Porting VAX macro

To determine the arguments passed to a routine, VAX is easy: the first thing to do is to call a routine that will look back one level, using the frame pointer, to examine the number of arguments, and next traverse the call frame (on stack) to see if any entry is zeroed out (no parameter), or contains a value (parameter present), updating a mask.
Written in VAX MACRO, obviously. And incompilable on Alpha (because the reference of FP).
Nor very useful, either. On Alpha (and Itanium) it’s not that straight forward.
I asked Hoff whether he knows something to solve it – and he gave me some clues, and I went on from there and tried this:


program A
integer*4 x1,x2,x3,4

x1 = 1
x2 = 2
x3 = 3
x4 = 4

Call B (x1,x2,x3,x4) ! ---> R16..r19 (1)

end

Subroutine b (D,E,F,G) ! < --- R16..R19 integer*4 D,E,F,G integer*4 n,m call numarg (n,m) ! ---> R16..R17 (2)

end

subroutine numarg (nmb, msk) ! < ---- r16..R17 integer*4 nmb, msk integer*4 s integer*4 lib$get_curr_inco_context integer*4 lib$get_prev_inco_context external lib$get_curr_inco_context external lib$get_prev_inco_context C invoctxt defined according Calling Standfard manual record /incoctxt/ invo C initilaze invo to be all zeros C get current conetxt (==> numarg itself)

s = lib$get_curr_invo_context (invo) (A)

C get previous context (==> numarg caller)
C (B, in this case)

s = lib$get_prev_invo_conetxt (invo) (B)

after (1), R16..R19 refer to X1, X2, X3 and X4.
After (2), r16..R17 refer to nmb and msk, R18..R19 refer to X3 and X4

At call (A), invo.procedure_descriptor refers numarg, R29 and R30 are the correspionding FP and SP, and R16 and r17 refer to nbr and Msk – quite obvious, because that has been the present call (2)

At call (B), invo.procedure_descriptor refers to B, and R29 and R30 to corresponding FP and SP, which is correct. However, the other registers are unchnaged. Ovious as well, since references to x1 and X2 (in R16 and R17) have been overwitten by call (2) – these have not been saved in memory.

A simple solution: do NOT overwrite the registers, that is: do NOT pass any arguments. It’s not needed since the routine rertrieves data from the sytem without other data than it’s own invokation. It can pass the data in a structure:

Include the following code where numarg is called:

structure /numargdata/
integer*4 nmbr
integer*4 mask
end structure

record /numargdata/ args

record /numargdata/ numarg
external numarg

Change the caller:


args = numarg ()
nmbr = args.nmbr
mask = args.msk

and numrag itself should be changed accordingly. I expect R16..R21 be unchanged.

Or even simpler: just return the mask and forget about the number. Even simpler:


integer*4 numarg
external numarg

msk = numarg ()

Do I need the number ? It is known by design…- and if I really need it, it is at least the highest bit set in the mask – the rest isn’t present anyway and should not be accessed.

Though rework of the code, using OPTIONAL and PRESENT (due to new standards) is preferable, it’s fine for undertanding what goes on in the system.

(To Be Continued)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.