The original code had an entry point which did the STM for the save area and then loaded a function code into a register. Unfortunately, this does not work well with LE because the CEEENTRY macro has the STM in it. So I came up with this interesting implementation to get the function code and have only one CEEENTRY macro. Here is a very simple example, without the required CEEPPA, CEEDSA, CEECAA, and CEETERM macros:
API CSECT
ENTRY INIT,READ,WRITE,TERM
INIT DC 0H
J LEENTRY
READ DC 0H
J LEENTRY
WRITE DC 0H
J LEENTRY
TERM DC 0H
J LEENTRY
LEENTRY DC 0H
API CEEENTRY MAIN=NO,BASE=R11 (default base)
L R15,4(,R13) Backchain save area
L R15,16(,R15) Get R15 at call
* R15 now is the address of the entry point
LA R14,0(,R11) Clear out HOB just in case (SEE BELOW)
LA R15,4(,R15) Clear out HOB and make 1-based
SR R14,R15 Calculate offset from beginning of CSECT
SRA R14,2 Divide by 4, preserving sign (allows use of JM BAD)
* R14 now has a function code ranging from 1 to 4
* Obviously we add some additional checking of R14 to make sure
* it is valid for our purposes.
So now GPR14 has a value ranging from 1 to 4, with 1 being INIT, 2 being READ, etc.. Good programmers will test GPR14 for falling within the required boundaries. You could also forgo the SRA and use the value of 4, 8, 12, or 16. In current releases of z/OS, CEEENTRY uses LARL to load the base register with the address of API, so the LA of GPR14 from GPR11 could just be an LR. This also works with non-LE assembler code; if you have a base register use LA, and if "baseless" use an LARL of the CSECT name. Just make sure that if you have a standard entry macro (most shops do) that generates a CSECT, the CSECT name used at the beginning of the module has to match that generated by your macro.
No comments:
Post a Comment
Feel free to leave a comment or ask questions.