HP OpenVMS Systems Documentation
HP OpenVMS Programming Concepts Manual
18.104.22.168.2 Output Registers
Up to eight output registers are used for passing parameters. If a procedure call requires fewer than eight general registers for its parameters, the calling procedure does not need to allocate more than are needed. If the called procedure expects more parameters, it will allocate extra input registers; these registers will be uninitialized.
A procedure may also allocate more than eight registers in the output
region. While the extra registers may not be used for passing
parameters, they can be used as extra scratch registers. On a procedure
call, they will show up in the called procedure's output area as excess
registers, and may be modified by that procedure. The called procedure
may also allocate few enough total registers in its stack frame that
the top of the called procedure's frame is lower than the caller's
top-of-frame, but those registers will become available again when
control returns to the caller.
A subset of the registers in the procedure frame may be designated as rotating registers. The rotating register region always starts with R32, and may be any multiple of eight registers in number, up to a maximum of 96 rotating registers. The renaming is under control of the Register Rename Base (RRB).
If the rotating registers include any or all of the output registers,
software must be careful when using the output registers for passing
parameters, because a non-zero RRB will change the virtual register
numbers that are part of the output region. In general, software should
ensure either that the rotating region does not overlap the output
region, or that the RRB is cleared to zero before setting output
The current application-visible state of the register stack is stored in an architecturally inaccessible register called the current frame marker. On a procedure call, this register is automatically saved by copying it to an application register, the previous function state (AR.PFS). The current frame marker is modified to describe a new stack frame whose input and local area is initially zero size, and whose output area is equal in size to the previous output area. On return, the previous frame state register is used to restore the current frame marker to its earlier value, and the base of the register stack is adjusted accordingly.
It is the responsibility of a procedure to save the previous function
state register before issuing any procedure calls of its own, and to
restore it before returning.
When the depth of the procedure call stack exceeds the capacity of the physical register file, the hardware frees physical registers by saving them into a memory stack. This backing store is distinct from the memory stack described in Section 22.214.171.124.
As returns unwind the procedure call stack, the hardware also restores previously-saved physical registers from the backing store.
The operation of this register stack engine (RSE) is mostly transparent to application software. While the RSE is running, application software may not examine the contents of the backing store, and may not make any assumptions about how much of the register stack is still in physical registers or in the backing store. In order to examine previous stack frames, application software must synchronize the RSE with the FLUSHRS instruction. Synchronizing the RSE forces all stack frames up to, but not including, the current frame to be saved in backing store, allowing the software to examine the contents of the backing store without asynchronous operations modifying the memory. Modifications to the backing store require setting the RSE to enforced lazy mode after synchronizing it, which prevents the RSE from doing any operations other than those required by calls and returns. The procedure for synchronizing the RSE and setting the mode is described in the Intel® Itanium® Software Conventions and Runtime Architecture Guide.
The backing store grows towards higher addresses. The top of the stack, which corresponds to the top of the previous procedure frame, is available in the Backing Store Pointer (BSP) application register. The BSP must always point to a valid backing store address, because the operating system may need to start the RSE to process an exception.
Backing store overflow is automatically detected by the OpenVMS operating system, which will either extend the backing store to allow continued operation or will raise an exception. Unlike for the memory stack (see Section 126.96.36.199), there are no specific rules or requirements that must be satisfied to facilitate detection of backing store overflow.
A NaT collection register is stored into the backing store following
each group of 63 physical registers. The NaT bit of each register
stored is shifted into the collection register. When the BSP reaches
the quadword just before a 64-quadword boundary, the RSE stores the
collection register. Software can determine the position of the NaT
collection registers in the backing store by examining the memory
address. This process is described in greater detail in the
Intel® Itanium® Architecture Software Developer's
A procedure value is an address value that represents a procedure.
On VAX systems, the procedure value is the address of the procedure entry mask that begins the actual code sequence of the procedure.
On Alpha systems, the procedure value in R27 is the address of the procedure descriptor that describes that procedure. So any OpenVMS Alpha procedure can be invoked by calling the stored address at offset 8 from the procedure descriptor (PDSC) starting address (procedure value).
For OpenVMS I64, a procedure value is the address of a function descriptor, which consists of at least two quadword fields: the address of the entry point and the GP value required by that procedure.
Every procedure whose address is taken, or might be taken, must have a unique official function descriptor. The address of this function descriptor is used for the procedure value that is passed as a parameter or when two procedure values are compared. For other purposes, additional local function descriptors may be used for efficiency (notably in images other than the image that contains the procedure).
An official function descriptor for any procedure which might be callable from a VAX or Alpha translated image must include signature information. A local function descriptor used to call a procedure that might be part of a VAX or Alpha translated image must also include additional fields to facilitate the call. Both of these cases are described in the HP OpenVMS Calling Standard.
A function descriptor for a bound procedure uses a special pseudo-GP value and includes an uplevel frame pointer. Such function descriptors are described in HP OpenVMS Calling Standard.
The several kinds of function descriptors are summarized in Table 18-8.
Note that the different kinds of function descriptor are not
self-identifying (that is, they do not contain any form of tag or kind
The calling standard defines a data structure called the argument list. An argument list is a sequence of locations in memory that represents a routine parameter list and possibly includes a function value. You use an argument list to pass information to a routine and receive results.
On VAX systems, the first longword in an argument list (see Figure 18-6) stores the number of arguments (the argument count, n) as an unsigned integer value. The maximum argument count is 255. The remaining 24 bits of the first longword are reserved for use by HP and must be 0.
Figure 18-6 Structure of a VAX Argument List
On Alpha systems, arguments are quadwords, and the calling program passes arguments in an argument item sequence. Each quadword in the sequence specifies a single argument. The argument item sequence is formed using R16--21 or F16--21 (a register for each argument). The argument item sequence can have a mix of integer and floating-point items that use both register types but must not repeat the same number. For example, an argument list might use R16, R17, F18, and R19. If there are more than six arguments, the argument items overflow to the end of the stack, as shown in Figure 18-7.
Figure 18-7 Alpha Argument List Format
The calling procedure must pass to the called procedure information about the argument list. For high-level languages, this is performed by the language processor. In the argument information (AI) register (R25), the quadword format is the structure shown in Figure 18-8. The AI register contains the argument count in the first byte. Table 18-9 describes the argument information fields in detail.
Figure 18-8 Argument Information (AI) Register (R25) Format
For I64, parameters are passed in a combination of general registers, floating-point registers, and memory, as illustrated in Figure 18-9.
The parameter list is formed by placing each individual parameter into fixed-size elements of the parameter list, referred to as parameter slots. Each parameter slot is 64 bits wide; parameters larger than 64 bits are placed in as many consecutive parameter slots as are needed to contain the entire parameter. The rules for allocation and alignment of parameter slots are described in Section 188.8.131.52.
The contents of the first eight parameter slots are always passed in registers, while the remaining parameters are always passed on the memory stack, beginning at the caller's stack pointer plus 16 bytes. The caller uses up to eight of the registers in the output region of its register stack for integer and VAX floating-point parameters, and up to eight floating-point registers for IEEE floating-point parameters. The maximum number of registers used is eight.
Figure 18-9 Parameter Passing in Registers and Memory
To accommodate variable argument lists in the C language, there is a fixed correspondence between parameter slots; the first parameter slot is always in either the first general output register or the first floating-point register (never both), the second parameter slot is always in the second general output register or the second floating-point register (never both), and so on. This allows a procedure to spill its register parameters easily to memory to form the argument home area before stepping through the parameter list with a pointer. The Argument Information register (AI) makes this possible, as explained in Section 18.5.6.
A procedure can assume that the NaT bits on its incoming general
register arguments are clear, and that the incoming floating-point
register arguments are not NaTVals. A procedure making a call must
ensure only that registers containing actual parameters are clear of
NaT bits or NaTVals; registers not used for actual parameters are
Each high-level language supported by OpenVMS provides a mechanism for passing arguments to a procedure. The specifics of the mechanism and the terminology used, however, vary from one language to another. For specific information, refer to the appropriate high-level language user's guide.
OpenVMS system routines are external procedures that accept arguments. The argument list contains the parameters that are passed to the routine. Depending on the passing mechanisms for these parameters, the forms of the arguments contained in the argument list vary. As shown in Figures 18-10 and 18-11, argument entries labeled arg1 through argn are the actual parameters, which can be any of the following addresses or value:
Figure 18-10 Alpha Procedure Argument-Passing Mechanisms
Figure 18-11 VAX Procedure Argument-Passing Mechanisms
OpenVMS programming reference manuals provide a description of each
OpenVMS system routine that indicates how each argument is to be
passed. Phrases such as "an address" and "address of a
character string descriptor" identify reference and descriptor
arguments, respectively. Terms like "Boolean value,"
"number," "value," and "mask" indicate an
argument that is passed by value.
When your program passes an argument using the by value mechanism, the argument list entry contains either the actual uninterpreted 32-bit VAX value or a 64-bit Alpha or I64 value (zero- or sign-extended) of the argument. For example, to pass the constant 100 by value, the calling program puts 100 directly in the argument list or sequence. For more information about passing 64-bit Alpha and I64 values, refer to Chapter 11.
All high-level languages (except C) require you to specify the by-value mechanism explicitly when you call a procedure that accepts an argument by value. For example, FORTRAN uses the %VAL built-in function, while COBOL uses the BY VALUE qualifier on the CALL [USING] statement.
A FORTRAN program calls a procedure using the by-value mechanism as follows:
A BLISS program calls this procedure as follows:
The equivalent VAX MACRO code is as follows:
A C language program calls a procedure using the by-value mechanism as follows:
18.5.2 Passing Arguments by Reference
When your program passes arguments using the by reference mechanism, the argument list entry contains the address of the location that contains the value of the argument. For example, if variable x is allocated at location 1000, the argument list entry will contain 1000, the address of the value of x.
On Alpha processors and I64, the address is sign-extended from 32 bits to 64 bits.
Most languages (but not C) pass scalar data by reference by default. Therefore, if you simply specify x in the CALL statement or function invocation, the language automatically passes the value stored at the location allocated to x to the OpenVMS system routine.
The equivalent VAX MACRO code is as follows:
A C language program calls a procedure using the by-reference mechanism as follows:
18.5.3 Passing Arguments by Descriptor
When a procedure specifies that an argument is passed by descriptor, the argument list entry must contain the address of a descriptor for the argument. For more information about OpenVMS Alpha 64-bit descriptors, refer to Chapter 11.
On Alpha and I64 processors, the address is sign-extended from 32 bits to 64 bits.
This mechanism is used to pass more complicated data. For both Alpha and VAX systems, a descriptor includes at least the following fields:
The HP OpenVMS Calling Standard describes these fields in greater detail.
OpenVMS high-level languages include extensions for passing arguments by descriptor. When you specify by descriptor in these languages, the compiler creates the descriptor, defines its fields, and passes the address of the descriptor to the OpenVMS system routine. In some languages, by descriptor is the default passing mechanism for certain types of arguments, such as character strings. For example, the default mechanism for passing strings in BASIC is by descriptor.
The default mechanism for passing strings in COBOL, however, is by reference. Therefore, when passing a string argument to an OpenVMS system routine from a COBOL program, you must specify BY DESCRIPTOR for the string argument in the CALL statement.
In VAX MACRO or BLISS, you must define the descriptor's fields explicitly and push its address onto the stack. Following is the VAX MACRO code that corresponds to the previous examples.
The equivalent BLISS code looks like this:
A C language program calls a procedure using the by-descriptor mechanism as follows: