Reputation: 109
I am a long time assembler programmer, moving into the world of Metal C. I am very much a C novice, so my terminology may reflect the stuff that I know vs. the stuff that I am learning. It will certainly color how I understand things.
I am trying to insert new Metal C code into some old components that don't necessarily follow standard entry linkage conventions.
For example, a service routine takes, as input in R1, the address of a control block to process. I've looked at the Metal C User's Guide at the discussion about parameter passing and the #pragma linkage discussion in the language reference and there doesn't seem to be a means to cause the compiler to do this.
In essence, I want to declare a routine that is invoked by the following assembler:
L R1,MyParm@ Put pointer to Parm into R1
L R15,Routine@ Get address of service routine
BASR R14,R15 Branch to service routine
I realize that I can take the above, parameterize it and put it into an __asm() block, but I would like to keep the program as "clean" as possible.
Thanks, Scott
Addendum - 26 September 2019
To respond to Mark Hiscock's answer below, such an __asm() block would look like:
#define CallwithR1(ParmPtr,RoutinePtr,RC,Rsn) \
__asm( \
" L R1,%2 Get ParmPtr into R1 \n" \
" L R15,%3 Get RoutinePtr into R15 \n" \
" BALR R14,R15 Call the routine \n" \
" ST R15,%0 Save the return code \n" \
" ST R0,%1 Save the reason code \n" \
/* Output variables */ \
: "=m"(RC) /* %0, output only, in-memory */ \
,"=m"(Rsn) /* %1, output only, in memory */ \
/* Input variables */ \
: "m"(ParmPtr) /* %2, input, in-memory */ \
,"m"(RoutinePtr) /* %3, input, in-memory */ \
/* Register clobber list */ \
: "r0" /* R0 clobbered by reason code */ \
,"r1" /* R1 clobbered by linkage code */ \
,"r14" /* R14 clobbered by return addr */ \
,"r15" /* R15 clobbered by return code */ \
);
and would be far simpler to deal with (fewer instructions, no bind time issues). I'm really looking for something that allows the compiler to "do the right thing."
Scott
Upvotes: 2
Views: 158
Reputation: 1
You could try something like this in the C program:
#pragma linkage(MYHLASM,OS)
And then call the function like this:
MYHLASM(&pointerToParmWhichBecomesR1);
Then the assembler would look like this:
MYHLASM CSECT ,
MYHLASM AMODE 64
MYHLASM RMODE 31
STG 14,12(13)
LG 2,0(,1)
USING *,15
DO SOMETHING WITH THE PARM ADDR WHICH IS NOW IN R2
LG 14,12(13)
BR 14
LTORG
END
This is a 64bit example and MYHLASM would have to be available at the bind time of the C program.
Hope this helps,
Mark
Upvotes: 0