This section describes the steps that must be executed in procedure entry and exit sequences. These conventions must be followed in order for the call chain to be well defined at every point during thread execution.
Since the value of the PC defines the currently executing procedure, it must be possible using the procedure descriptor associated with that PC, as well as the instructions of the procedure itself, to recover the identity (PC) and environment of the caller. This leads to the following restriction: A standard call cannot be made from the prologue.
Note If an exception is raised or an exception occurs in the prologue of a procedure, that procedure's exception handler (if any) will not be invoked since the procedure is not current yet. This implies that if a procedure has an exception handler then compilers may not move code into the procedure prologue that might cause an exception that would be handled by that handler.
When a procedure is called, the code at the entry address must synchronize (as needed) any pending exceptions caused by instructions issued by the caller, save the caller's context, and make the called procedure current (by executing the last instruction of the procedure prologue).
This is done by performing the following actions in the order given:
After any necessary calculations and stack limit checks, this step must be completed by exactly one instruction that modifies SP.
Note If the locations allocated for saving the registers must be more than 32768 bytes away from the top of stack (for example, because the procedure contains an actual parameter list whose size exceeds 32768 bytes), then it is not possible to allocate the entire stack in a single step. In this case, the variable stack size form of stack frame must be used. (Recall that memory reference instructions in the Alpha architecture can address at most 32768 bytes relative to the contents of some general register.)
This step must be completed by exactly one instruction that modifies FP.
When the above steps have been completed, the executing procedure is said to become current for the purposes of exception handling. The handler for a procedure will not be called except when that procedure is current.
It is possible for a single routine to have more than one entry point, hence more than one entry code sequence of instructions. When this occurs, all of the entry code sequences must be equivalent in the sense that after execution leaves each prologue, any one of the entry code sequences can be used for exception-handling purposes regardless of which entry code sequence was actually used to enter the routine. The fixed-size stack allocation, where specific registers are saved in the stack frame, and so on, are all properties of the routine as a whole, not a particular entry point, and every entry point must establish the same run-time frame before completing the prologue. (In general, after execution completes one of the prologues, control passes into code that is common to all entry points and it is not possible to tell which entry was actually called.)
For each of the steps described above, there are specific instructions or sequences of instructions that must be used. These are the only instructions that are interpreted when unwinding a stack frame for purposes of exception dispatching or stack walking. (Such prologue interpretation is sometimes called reverse execution. See Getting a Procedure Invocation Context with a Routine for related discussion.)
Let N be the number of bytes to allocate for the fixed part of the stack. The simpler case occurs when the size of the extension does not exceed the value of MAX_NOCHK_EXTEND, 4096, and can therefore be represented in the 16-bit offset field of an LDA instruction. In this case, use
LDA SP, -N(SP)
If the previous case does not apply, then use the sequence
load Rx, N
...
SUBQ SP, Rx, SP
where Rx is a scratch register for the procedure and load stands for one of a number of alternatives for loading the constant N into register Rx. The load of Rx and update of the stack pointer are separated by instructions that check that the stack limit is not exceeded by the allocation as described in Section 6.1, Stack Limit Checking.
The following instructions may be used to load a constant value N into a register Rx:
BIS R31, N, Rx ; 0 ≤? N ≤? 255
or
ADDQ R31, N, Rx ; 0 ≤? N ≤? 255
or
LDA Rx, N(R31) ; 0 ≤? N ≤? 32767
or
LDAH Rx, Hi(R31) ; 0 ≤? Hi ≤? 32767, N = Hi*65536
or
LDAH Rx, Hi(R31) ; 0 ≤? Hi ≤? 32767
LDA Rx, Lo(Rx) ; -32768 ≤? Lo ≤? 32767
; N = Hi*65536 + Lo
In the last case, the LDAH and LDA instructions need not be contiguous.
General-purpose registers that are saved on the stack must be saved using
STQ Rx, n(SP)
where Rx is the register being saved (including the return address register) and n is the offset in the stack for saving that register. Similarly, floating-point registers that are saved on the stack must be saved using
STT Fx, n(SP)
where Fx is the register being saved and n is the offset in the stack for saving that register. (Note that floating-point registers are never saved using STF, STD, STG, or STS because the called routine has no a priori information about the type of the variable contained in the register. Similarly, LDT is always used to restore a floating register.)
Preservation of registers in this manner is not limited to just the standard preserved integer and floating-point registers.
A register that is preserved may also be saved by moving it to a scratch register in the case of a register frame procedure.
There are no requirements concerning the order in which registers are saved or the position within the stack frame where they are saved.
The first use of a register that is preserved within a prologue must be to save it. The save operation may consist of a sequence of moves that start with a given register, copy the contents to other registers, and optionally store the register in the stack. (This may be necessary, for example, to temporarily preserve the return address if a routine is called in the prologue to perform stack limit checking. Note that such a called routine is necessarily nonstandard.) The last location in this sequence (whether a register or a stack location) must thereafter not be modified during the execution of the procedure. The registers involved in such a sequence (other than the last if the contents is not stored in the stack) can be used for other purposes provided, either
In the case of the return address register (R26), the occurrence of more than one of the above instructions that reads that register in a prologue is reserved for use by the kernel. The occurrence of more than one such instruction is used in kernel routine prologues that are invoked by exceptions and traps to indicate that the associated frame is an exception frame (as defined in the Alpha System Reference Manual); see Section 7.3 for further discussion. If there is a need to use the return address value in the prologue in addition to saving it in the normal manner, then the return address value must be read from the saved location rather than directly from R26.
The TRAPB instruction is used to ensure that any pending exceptions occur prior to the end of the prologue (prior to the routine becoming current).
The frame pointer must be set using
MOV SP, FP
A general register Rx must be moved (MOV) to another general register Ry using
BIS R31, Rx, Ry
or
BIS Rx, Rx, Ry
or
BIS Rx, R31, Ry
A floating-point register Fx must be moved to another general register Fy using
CPYS Fx, Fx, Fy
Note The SP register is normally "saved" and "restored" by adjusting its contents by a fixed value that is part of the instruction stream rather than by copying its contents to another register or to a location on the stack. However, a STx SP,n(SP) or MOV SP,Rx instruction is reverse executed as just described in paragraphs 2 and 5 above. It follows that these instructions can be included in a procedure prologue only if their reverse execution is in fact intended as part of restoring the SP contents. In particular, code scheduling must not allow such instructions, whose use of the SP contents is unrelated to SP maintenance, to be moved into the prologue of a procedure.
As a general rule, it is valid to include instructions in the prologue in addition to those required above in order to take advantage of available processor cycles that are not otherwise used. However, to avoid undesirable reverse execution overhead during exception, dispatching or unwinding the length of the prologue should not be increased in ways that do not exploit such available cycles except possibly to include instructions that have an unusually long latency. In any case, it must not be possible for such additional instructions to cause an exception that would be handled by that procedure if that exception were raised after the procedure became current. (An exception may be considered to be not handled by a procedure if it is known a priori that the handler will always resignal that exception.)
It follows from these considerations that the length of the prologue of a procedure should typically be no larger than two instructions times the number of registers that are preserved in that procedure, in addition to those instructions that perform stack limit checking (if any). In Windows NT for Alpha Systems, there must not be more than 1024 instructions in a prologue. If a larger number is detected, then the containing program may be aborted.
After procedure prologue completion, the register indicated by BASE_REG_IS_FP must contain the frame pointer of the stack frame, which is the address of the lowest-addressed byte of the fixed portion of the stack frame allocated by the procedure prologue. The value of the frame pointer is the value of FRAME_SIZE subtracted from the value of the stack pointer upon procedure entry.
For fixed frame procedures, the frame pointer is the stack pointer, which is not modified by that procedure after the instruction in that procedure prologue specified by SP_SET.
This example assumes that this is a stack frame procedure, that registers R9..R11 and F2..F3 are saved and restored, that the procedure has a static exception handler that does not reraise arithmetic traps, and that the procedure uses a fixed amount of stack (BASE_REG_IS_FP is 0).
LDA SP,-SIZE(SP) ;Allocate space for new stack frame
STQ R26,16(SP) ;Save return address
STQ R9,24(SP) ;Save first integer register
STQ R10,32(SP) ;Save next integer register
STQ R11,40(SP) ;Save next integer register
STT F2,48(SP) ;Save first floating-point register
STT F3,56(SP) ;Save last floating-point register
TRAPB ;Force any pending hardware exceptions
; to be raised
;Called procedure is now the current procedure
The following entry code example is for a called procedure that has no static exception handler. Both SAVE_RA and ENTRY_RA specify R26 and the procedure utilizes a fixed amount of stack storage (BASE_REG_IS_FP is 0).
LDA SP,-SIZE(SP) ;Allocate space for new stack frame
;Called procedure is now the current procedure
The end of procedure entry code can be determined easily given a PC value together with the ENTRY_LENGTH value. Since there may be multiple return points from a procedure, detecting that a procedure exit sequence is being executed is not quite as straightforward. Unwind support routines must be able to detect if the stack pointer has been reset or not and, if not, how to reset it. This is done by using a reserved instruction sequence.
To allow the stack to be properly restored during an unwind, a reserved instruction or sequence of instructions must be used. None of these sequences may be used in any other way.
The following reserved instruction must appear at every exit point from any procedure that uses stack (FRAME_SIZE ¹ 0):
RET R31,(Rn),0001 ;Return to caller with usage hint 0001
Note Usage hint refers to the value of the branch prediction bits encoded in the RET instruction. The Alpha System Reference Manual documents that these bits, <13:0> of the instruction longword, are reserved to software when the instruction is RET or JSR_COROUTINE. (See Section 4.3 of the Alpha System Reference Manual.) This calling standard further requires that these bits contain the value 0001 (hex) for procedure returns and 0000 otherwise. It is the occurrence of the usage hint value 0001 that identifies a RET instruction as one that is reserved for use only as described in this section. RET instructions may be used for other purposes provided they contain a usage hint of 0000. Such RET instructions will not be recognized and treated in a special way for the purposes of exception handling or unwinding.
Furthermore, for any such procedure that does not return a value on the stack, the above instruction must be directly preceded by one of the two reserved stack resetting instructions, as in:
LDA SP,* ;Reset stack
RET R31,(*),0001 ;Return to caller with usage hint
or
ADDQ *,*,SP ;Reset stack
RET R31,(*),0001 ;Return to caller with usage hint
That is, any LDA instruction whose destination is the SP register or any ADDQ instruction whose destination is the SP register is interpreted as part of a procedure exit sequence when immediately followed by the reserved procedure return instruction. The LDA instruction must have the form LDA SP,n(Rx) if the amount by which the stack is being adjusted can be represented as the offset n. Otherwise, the latter form is used, in which case the ADDQ instruction must have the form ADDQ Rx, Ry, SP where, in particular, Ry is the name of a register rather than a literal operand.
A stack resetting instruction may not be present (in the case of a procedure that returns a result on the top of the stack). However, if present, it will occur immediately preceding the reserved RET instruction.
Furthermore, for any such procedure that has BASE_REG_IS_FP set to 1, the resulting sequence must be directly preceded by the FP reloading instruction, as in:
LDQ FP,* ;Restore FP
LDA SP,* ;Or ADDQ *,*,SP to Reset stack
RET R31,(*),0001 ;Return to caller with usage hint
That is, any LDQ instruction whose destination is the FP register (R15) is interpreted as part of a procedure exit sequence when it is immediately followed by the reserved procedure return instruction or by a stack resetting instruction as described above that is immediately followed by the reserved procedure return instruction.
Procedures that do not use the stack need not use these reserved instruction sequences.
The unwind support code uses the above sequences to make the following assumptions about an interrupted PC value:
Otherwise, the registers must be restored, SP reset, and the unwind can proceed.
When a procedure has executed the first instruction of one of the reserved sequences just described, the procedure becomes no longer current for the purposes of exception handling. The handler for a procedure will not be called in the midst of one of these reserved instruction sequences in that procedure.
When a procedure returns, the exit code must restore the caller's context, synchronize any pending hardware exceptions, and make the calling procedure current by returning control to it.
This is done by performing the following actions:
Perform step 1, followed by steps 2 - 4 in any order, followed by steps 5 - 7 in that order.
After any necessary calculations, this step must be completed by exactly one instruction as described above.
After any necessary calculations, this step must be completed by exactly one instruction as described above.
Note that the called routine does not adjust the stack to remove any arguments passed in memory. This responsibility falls to the calling routine, which may choose to defer their removal due to optimizations or other considerations.
The following is the return code sequence for the stack frame example above:
LDQ R26,16(SP) ;Get return address
LDQ R9,24(SP) ;Restore first integer register
LDQ R10,32(SP) ;Restore next integer register
LDQ R11,40(SP) ;Restore next integer register
LDT F2,48(SP) ;Restore first floating-point register
LDT F3,56(SP) ;Restore last floating-point register
TRAPB ;Force any pending hardware exceptions
; to be raised
LDA SP,SIZE(SP) ;Restore SP
RET R31,(R26),0001 ;Return to caller with usage hint
The following is the return code sequence for the register frame example above:
LDA SP,SIZE(SP) ;Restore the SP
RET R31,(R26),0001 ;Return to caller with usage hint