[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Calling Standard


Previous Contents Index

3.9.1.2 Stack Reserve Region

In some cases, it is desirable to maintain a stack reserve region, which is a minimum-sized region that is immediately above a thread's guard region. A reserve region may be desirable to ensure that exceptions or asynchronous system faults (ASTs) have stack space to execute on a thread's stack, or to ensure that the exception dispatcher and any exception handler that it might call have stack space to execute after detection of an invalid attempt to extend the stack.

This standard does not require a reserve region.

3.9.1.3 Methods for Stack Limit Checking

Because accessible memory may be available at addresses lower than those occupied by the guard region, compilers must generate code that never extends the stack past the guard pages into accessible memory that is not allocated to the thread's stack.

A general strategy is to access each page of memory down to and possibly including the page corresponding to the intended new value for the SP. If the stack is to be extended by an amount larger than the size of a memory page, then a series of accesses is required that works from higher to lower addressed pages. If any access results in a memory access violation, then the code has made an invalid attempt to extend the stack of the current thread.

Note

An access can be performed by using either a load or a store operation; however, be sure to use an instruction that is guaranteed to make an access to memory. For example, do not use an LDQ R31,* instruction, because the Alpha architecture does not allow any memory access, even a read access, whose result is discarded because of the R31 destination.

This standard defines two methods for stack limit checking: implicit and explicit.

Implicit Stack Limit Checking

The following are two mutually exclusive strategies for implicit stack limit checking:

  • If the lowest addressed byte of the new stack region is guaranteed to be accessed prior to any further stack extension, then the stack can be extended by an increment that is equal in size to the guard region (without any further accesses).
  • If some byte (not necessarily the lowest) of the new stack region is guaranteed to be accessed prior to any further stack extension, then the stack can be extended by an increment that is equal in size to one-half the guard region (without any further accesses).

The stack frame format (see Section 3.4.3) and entry code rules (see Section 3.6.5) generally do not ensure access to the lowest address of a new stack region without introducing an extra access solely for that purpose. Consequently, this standard uses the second strategy. While the amount of implicit stack extension that can be achieved is smaller, the check is achieved at no additional cost.

This standard requires that the minimum guard region size is 8192 bytes, the size of the smallest memory protection granularity allowed by the Alpha architecture.

If the stack is being extended by an amount less than or equal to 4096 and a reserve region is not required, then explicit stack limit checking is not required. However, because asynchronous interrupts and calls to other procedures may also cause stack extension without explicit stack limit checking, stack extension with implicit limit checking must adhere to a strict set of conventions as follows:

  • Explicit stack limit checking must be performed unless the amount by which the SP is decremented is known to be less than or equal to 4096 and a reserve region is not required.
  • Some byte in the new stack region must be accessed before the SP can be decremented for a subsequent stack extension.
    This access can be performed either before or after the SP is decremented for this stack extension, but it must be done before the SP can be decremented again.
  • No standard procedure call can be made before some byte in the new stack region is accessed.
  • The system exception dispatcher ensures that the lowest addressed byte in the new stack region is accessed if any kind of asynchronous interrupt occurs after the SP is decremented, but before the access in the new stack region occurs.

These conventions ensure that the stack pointer is not decremented so that it points to accessible storage beyond the stack limit without this error being detected (either by the guard region being accessed by the thread or by an explicit stack limit check failure).

As a matter of practice, the system can provide multiple guard pages in the guard region. When a stack overflow is detected as a result of access to the guard region, one or more guard pages can be unprotected for use by the exception-handling facility, and one or more guard pages can remain protected to provide implicit stack limit checking during exception processing. However, the size of the guard region and the number of guard pages is system defined and is not defined by this standard.

Explicit Stack Limit Checking

If the stack is being extended by an amount of unknown size or by a known size greater than the maximum implicit check size (4096), then a code sequence that follows the rules for implicit stack limit checking can be executed in a loop to access the new stack region incrementally in segments lesser than or equal to the minimum page size (8192 bytes). At least one access must occur in each such segment.

The first access must occur between SP and SP - 4096 because, in the absence of more specific information, the previous guaranteed access relative to the current stack pointer may be as much as 4096 bytes greater than the current stack pointer address.

The last access must be within 4096 bytes of the intended new value of the stack pointer. These accesses must occur in order, starting with the highest addressed segment and working toward the lowest addressed segment.

A more optimal strategy is:

  1. Perform a read access using the intended new value of the stack pointer. This is nondestructive, even if the read is beyond the stack guard region, and may facilitate OS mapping of new stack pages, if appropriate, in a single operation.
  2. Proceed with sequential accesses as just described.

Note

A simple algorithm that is consistent with this requirement (but achieves up to twice the minimum number of accesses) is to perform a sequence of accesses in a loop starting with the previous value of SP, decrementing by the minimum no-check extension size (4096) to, but not including, the first value that is less than the new value for the stack pointer.

The stack must not be extended incrementally in procedure prologues. A procedure prologue that needs to extend the stack by an amount of unknown size or known size greater than the minimum implicit check size must test new stack segments as just described in a loop that does not modify SP, and then update the stack with one instruction that copies the new stack pointer value into the SP.

Note

An explicit stack limit check can be performed either by inline code that is part of a prologue or by a run-time support routine that is tailored to be called from a procedure prologue.

Stack Reserve Region Checking

The size of the reserve region must be included in the increment size used for stack limit checks, after which it is not included in the amount by which the stack is actually extended. (Depending on the size of the reserve region, this may partially or even completely eliminate the ability to use implicit stack limit checking.)

3.9.1.4 Stack Overflow Handling

If a stack overflow is detected, one of the following results:

  • Exception SS$_ACCVIO may be raised.
  • The system may transparently extend the thread's stack, reset the TEB stack limit value appropriately, and continue execution of the thread.

Note that if a transparent stack extension is performed, a stack overflow that occurs in a called procedure might cause the stack to be extended. Therefore, the TEB stack limit value must be considered volatile and potentially modified by external procedure calls and by handling of exceptions.


Chapter 4
OpenVMS I64 Conventions

This chapter describes the fundamental concepts and conventions for calling a procedure in an OpenVMS I64 environment.

4.1 Register Usage

This section describes the register conventions for OpenVMS I64. OpenVMS uses the following register types:

  • General
  • Floating-point
  • Predicate
  • Branch
  • Application

4.1.1 Partitioning

Registers are partitioned into the following classes that define the way a register can be used within a procedure:

  • Scratch registers -- may be modified by a procedure call; the caller must save these registers before a call if needed (caller save).
  • Preserved registers -- must not be modified by a procedure call; the callee must save and restore these registers if used (callee save). A procedure using one of the preserved general registers must save and restore the caller's original contents, including the NaT bits associated with the registers, without generating a NaT consumption fault.
    One way to preserve a register is not to use it at all.
  • Automatic registers -- saved and restored automatically by the hardware call/return mechanism.
  • Constant or Read-only registers -- contain a fixed value that cannot be changed by the program.
  • Special registers -- used in the calling standard call/return mechanism.
  • Global registers -- shared across a set of cooperating routines as global static storage that happens to be allocated in a register. (Details regarding the dynamic lifetime of such storage are not addressed here.)

OpenVMS further defines the way that static registers can be used between routines:

  • Special registers -- used in the calling standard call/return mechanism. (These are the same as the set of special registers in the preceding list of registers used within a procedure.)
  • Input registers -- may be used to pass information into a procedure (in addition to the normal stacked input registers).
  • Output registers -- may be used to pass information back from a called procedure to its caller (in addition to the normal return value registers).
  • Volatile registers -- may be used as scratch registers within a procedure and are not preserved across a call; may not be used to pass information between procedures either as input or output.

4.1.2 I64 General Register Usage

This standard defines the usage of the OpenVMS general registers as listed in Table 4-1. General registers R0 through R31 are termed the static general registers. General registers R32 through R127 are termed the stacked general registers.

Table 4-1 I64 General Register Usage
Register Class Usage
R0 Constant Always 0.
R1 Special Global data pointer (GP). Designated to hold the address of the currently addressable global data segment. Its use is subject to the following conventions:
  1. On entry to a procedure, GP is guaranteed valid for that procedure.
  2. At any direct procedure call, GP must be valid (for the caller). This guarantees that an import stub (see Section 4.7.3) can access the caller's linkage table.
  3. Any procedure call (indirect or direct) may modify GP unless the call is known to be local to the image.
  4. At procedure return, GP must be valid (for the returning procedure). This allows the compiler to optimize calls known to be local (an exception to convention 3).

The effect of these rules is that GP must be treated as a scratch register at a point of call (that is, it must be saved by the caller), and it must be preserved from entry to exit.

R2 Volatile May not be used to pass information between procedures, either as inputs or outputs. See also Section 4.1.9.
R3 Scratch May be used within and between procedures in any mutually consistent combination of ways under explicit user control. See also Section 4.1.9.
R4-R7 Preserved General-purpose preserved registers. Used for any value that needs to be preserved across a procedure call.
May be used within and between procedures in any mutually consistent combination of ways under explicit user control. See also Section 4.1.9.
R8-R9 Scratch Return Value. Can also be used as input (whether or not the procedure has a return value), but not in any additional ways. In addition, R9 is the preferred and recommended register to use when passing the environment value when calling a bound procedure. (See Section 4.7.7 and Section 5.1.2.)
R10-R11 Scratch May be used within and between procedures in any mutually consistent combination of ways under explicit user control. See also Section 4.1.9.
R12 Special Memory stack pointer (SP). Holds the lowest address of the current stack frame. At a call, the stack pointer must point to a 0 mod 16 aligned area. The stack pointer is also used to access any memory arguments upon entry to a function. Except in the case of dynamic stack allocation, code can use the stack pointer to reference stack items without having to set up a frame pointer for this purpose.
R13 Special Reserved as a thread pointer (TP).
R14-R18 Volatile May not be used to pass information between procedures, either as inputs or outputs. See also Section 4.1.9.
R19-R24 Scratch May be used within and between procedures in any mutually consistent combination of ways under explicit user control. See also Section 4.1.9.
R25 Special Argument information (see Section 4.7.5.3).
R26-R31 Scratch May be used within and between procedures in any mutually consistent combination of ways under explicit user control. See also Section 4.1.9.
IN0-IN7 Automatic Stacked input registers. Code may allocate a register stack frame of up to 96 registers with the ALLOC instruction, and partition this frame into three regions: input registers (IN0, IN1, ...), local registers (LOC0, LOC1, ...), and output registers (OUT0, OUT1, ...). R32--R39 (IN0--IN7) are used as incoming argument registers. Arguments beyond these registers appear in memory, as explained in Section 4.7.4.
LOC0-LOC95 Automatic Stacked local registers. Code may allocate a register stack frame of up to 96 registers with the ALLOC instruction, and partition this frame into three regions: input registers (IN0, IN1, ...), local registers (LOC0, LOC1, ...), and output registers (OUT0, OUT1, ...). LOC0-LOC95 are used for local storage. See Section 4.7.4 for more information.
OUT0-OUT7 Scratch Stacked output registers. Code may allocate a register stack frame of up to 8 registers with the ALLOC instruction, and partition this frame into three regions: input registers (IN0, IN1, ...), local registers (LOC0, LOC1, ...), and output registers (OUT0, OUT1, ...). OUT0-OUT7 are used to pass the first eight arguments in calls. See Section 4.7.4 for more information.

4.1.3 I64 Floating-Point Register Usage

This standard defines the usage of the OpenVMS floating-point registers as listed in Table 4-2. Floating-point registers F0 through F31 are termed the static floating-point registers. Floating-point registers F32 through F127 are termed the rotating floating-point registers.

Table 4-2 I64 Floating-Point Register Usage
Register Class Usage
F0 Constant Always 0.0.
F1 Constant Always 1.0.
F2-F5 Preserved Can be used for any value that needs to be preserved across a procedure call. A procedure using one of the preserved floating-point registers must save and restore the caller's original contents without generating a NaT consumption fault.
F6-F7 Scratch May be used within and between procedures in any mutually consistent combination of ways under explicit user control.
F8-F9 Scratch Argument/Return values. See Sections 4.7.4 and 4.7.6 for the OpenVMS specifications for use of these registers.
F10-F15 Scratch Argument values. See Section 4.7.4 for the OpenVMS specifications for use of these registers.
F16--F31 Preserved Can be used for any value that needs to be preserved across a procedure call. A procedure using one of the preserved floating-point registers must save and restore the caller's original contents without generating a NaT consumption fault.
F32-F127 Scratch Rotating registers or scratch registers.

Note

VAX floating-point data are never loaded or manipulated in the Itanium floating-point registers. However, VAX floating-point values may be converted to IEEE floating-point values, which are then manipulated in the I64 floating-point registers.

4.1.4 I64 Predicate Register Usage

Predicate registers are single-bit-wide registers used for controlling the execution of predicated instructions. Predicate registers P0 through P15 are termed the static predicate registers. Predicate registers P16 through P127 are termed the rotating predicate registers. This standard defines the usage of the OpenVMS predicate registers as listed in Table 4-3.

Table 4-3 I64 Predicate Register Usage
Register Class Usage
P0 Constant Always 1.
P1-P5 Preserved Can be used for any predicate value that needs to be preserved across a procedure call. A procedure using one of the preserved predicate registers must save and restore the caller's original contents.
P6-P13 Scratch Can be used within a procedure as a scratch register.
P14-P15 Volatile May not be used to pass information between procedures, either as input or output. See also Section 4.1.9.
P16-P63 Preserved Rotating registers.

4.1.5 I64 Branch Register Usage

Branch registers are used for making indirect branches. This standard defines the usage of the OpenVMS branch registers as listed in Table 4-4.

Table 4-4 I64 Branch Register Usage
Register Class Usage
B0 Scratch Contains the return address on entry to a procedure; otherwise a scratch register.
B1-B5 Preserved Can be used for branch target addresses that need to be preserved across a procedure call.
B6-B7 Volatile May not be used to pass information between procedures, either as input or output. See also Section 4.1.9.


Previous Next Contents Index