HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Programming Concepts Manual

Previous Contents Index

18.5.4 Parameter Passing Mechanisms for I64

The parameter passing mechanisms for I64 are generally the same as for Alpha and are included here for completeness. Two notable difference between Alpha and I64 are that the first six parameter slots are passed in registers for Alpha, while for I64 the first eight parameter slots are passed in registers; and that I64 passes VAX floating-point parameters in general registers. Allocation of Parameter Slots

Parameter slots are allocated for each parameter, based on the parameter passing mechanism, type, and size, treating each parameter in sequence, from left to right. The rules for allocating parameter slots and placing the contents within the slot are given in Table 18-10. The allocation column of the table indicates how parameter slots are allocated to each type of parameter.

Table 18-10 Rules for Allocating Parameter Slots
Type Size (Bits) Number of Slots
Integer, small set 1-64 1
Address/pointer (including all types passed by reference or descriptor) 64 1
IEEE single-precision floating-point (S_floating) 32 1
IEEE single-precision floating-point complex (S_floating) 64 2
IEEE double-precision floating-point (T_floating) 64 1
IEEE double-precision floating-point complex (T_floating) 128 2
IEEE quad-precision floating-point (X_floating) 64 (by reference) 1
IEEE quad-precision floating-point complex (X_floating) 64 (by reference) 1
Aggregates (noncomplex) any (size+63)/64
VAX single-precision floating-point (F_floating) 32 1
VAX single-precision floating-point complex (F_floating) 64 2
VAX double-precision floating-point (D_ & G_floating) 64 1
VAX double-precision floating-point complex (D_ & G_floating) 128 2


These rules are applied based on the type of the parameter after any type-promotion rules specified by the language have been applied. For example, a short integer passed without a function prototype in C is promoted to the int type, and is then passed according to the rules for the int type.

OpenVMS does not support passing the I64 double-precision extended floating-point type (__float80), although that type may be used from time to time in code generation sequences.

This placement policy does not ensure that parameters greater than 64 bits in size will fall on a natural alignment boundary if passed in memory. Such parameters may need to be copied by the called procedure into an aligned temporary prior to use, or accessed in a way that does not depend on natural alignment.

18.5.5 Normal Register Parameters

The first eight parameter slots (64 bytes) are passed in registers, according to the rules in this section.

  • These eight argument slots are associated, one-to-one, with the stacked output general registers, as shown in Figure 18-9.
  • Integral scalar parameters, (including addresses and pointers), VAX floating-point parameters, and aggregate parameters in these slots are passed only in the corresponding output general registers.
  • Aggregate parameters in these slots are passed by value only in the corresponding output general registers. The aggregate is treated as a sequence of 64-bit integral values, with each value allocated into the next available slot in aggregate memory address order. If the size of the aggregate is not an even multiple of 64 bits, then the unused bits in the last slot are undefined.
  • If an aggregate or VAX floating-point complex parameter straddles the boundary between slot 7 and slot 8, the part that lies within the first eight slots is passed in general registers, and the remainder is passed in memory, as described in Table 18-11.
    Complex values (other than IEEE quad-precision floating-point complex), in those languages that include complex types, are passed as a pair of floating-point values (either single-precision or double-precision as appropriate). It is possible for the first of the two floating-point values in a complex value to occupy the last output register slot; in this case, the second floating-point value is passed in memory. IEEE quad-precision floating-point complex values are passed by reference.
  • IEEE single-precision and double-precision floating-point scalar parameters are passed in the corresponding floating-point register slot. IEEE quad-precision floating point scalar parameters are passed by reference in the corresponding output general registers.

When IEEE floating-point parameters are passed in floating-point registers, they are passed in the register format, rounded to the appropriate precision. They are never passed in the general registers unless part of an aggregate, in which case they are passed in the aggregate memory format. When VAX floating-point parameters are passed in general registers, they are passed in memory format.

Parameters allocated beyond the eighth parameter slot are never passed in registers.

Unsigned integral (except unsigned 32-bit), set, and VAX floating-point values passed in registers are zero-filled; signed integral values as well as unsigned 32-bit integral values are sign-extended to 64 bits. For all other types passed in the general registers, unused bits are undefined.


Bit 31 is replicated in bits 32--63, even for unsigned 32-bit integers.

The rules contained in this section are summarized in Tables 18-11 and 18-12.

Table 18-11 Data Types and the Unused Bits in Passed Data
Data Type ( OpenVMS Names) Type Designator1 Data Size (bytes) Register Extension Type Memory Extension Type
Byte logical DSC$K_DTYPE_BU 1 Zero64 Zero64
Word logical DSC$K_DTYPE_WU 2 Zero64 Zero64
Longword logical DSC$K_DTYPE_LU 4 Sign64 Sign64
Quadword logical DSC$K_DTYPE_QU 8 Data64 Data64
Byte integer DSC$K_DTYPE_B 1 Sign64 Sign64
Word integer DSC$K_DTYPE_W 2 Sign64 Sign64
Longword integer DSC$K_DTYPE_L 4 Sign64 Sign64
Quadword integer DSC$K_DTYPE_Q 8 Data64 Data64
F_floating DSC$K_DTYPE_F 4 VAXF64 Data32
D_floating DSC$K_DTYPE_D 8 VAXDG64 Data64
G_floating DSC$K_DTYPE_G 8 VAXDG64 Data64
F_floating complex DSC$K_DTYPE_FC 2 * 4 2*VAXF64 2 * Data32
D_floating complex DSC$K_DTYPE_DC 2 * 8 2*VAXDG64 2 * Data64
G_floating complex DSC$K_DTYPE_GC 2 * 8 2*VAXDG64 2 * Data64
S_floating DSC$K_DTYPE_FS 4 Hard Data32
T_floating DSC$K_DTYPE_FT 8 Hard Data64
X_floating DSC$K_DTYPE_FX 16 N/A N/A
S_floating complex DSC$K_DTYPE_FSC 2 * 4 2 * Hard 2 * Data32
T_floating complex DSC$K_DTYPE_FTC 2 * 8 2 * Hard 2 * Data64
X_floating complex DSC$K_DTYPE_FXC 2 * 16 N/A N/A
Small structures of 8 bytes or less N/A <=8 Nostd Nostd
Small arrays of 8 bytes or less N/A <=8 Nostd Nostd
32-bit address N/A 4 Sign64 Sign64
64-bit address N/A 8 Data64 Data64

1OpenVMS also provides symbols of the form DSC64$K_DTYPE_xxx for each type designator.

Table 18-12 contains the defined meanings for the memory extension type symbols used in Table 18-11.

Table 18-12 Extension Type Codes
Sign Extension Type Defined Function
Sign64 Sign-extended to 64 bits.
Zero64 Zero-extended to 64 bits.
Data32 Data is 32 bits. The state of bits <63:32> is unpredictable.
2 * Data32 Two single-precision parts of the complex value are stored in memory as independent floating-point values (each handled as Data32).
Data64 Data is 64 bits.
2 * Data64 Two double-precision parts of the complex value are stored in memory as independent floating-point values (each handled as Data64).
VAXF64 Data is 64 bits. Low-order 32 bits are the same as the F_floating memory format and the high-order 32 bits are zero. (Used only in a general register, never in a floating-point register.)
VAXDG64 Data is 64 bits. Uses the corresponding D_floating or G_floating memory format. (Used only in a general register, never in a floating-point register.)
2*VAXF64 Two single-precision parts of the complex value are stored in memory as independent floating-point values (each handled as VAXF64).
2*VAXDG64 Two double-precision parts of the complex value are stored in memory as independent floating-point values (each handled as VAXDG64).
Hard Passed in the layout defined by the hardware SRM.
2 * Hard Two floating-point parts of the complex value are stored in a pair of registers as independent floating-point values (each handled as Hard).
Nostd State of all high-order bits not occupied by the data is unpredictable across a call or return.

18.5.6 Argument Information (AI) Register

In addition to the normal parameters, an implicit argument information value is passed in register R25, the Argument Information (AI) register. This value is shown in Figure 18-12. Note that I64 passes eight arguments in registers, while Alpha passes six arguments in registers.

Figure 18-12 Argument Information Register Representation

Argument Count is an unsigned byte that specifies the number of 64-bit argument slots used for the argument list. (Note that single- and double-precision complex values use two slots, which is reflected in this count.)

Argument Register Information is a contiguous group of eight 3-bit fields that correspond to the eight arguments passed in registers. The first group, bits <10:8>, describes the first argument; the second group, bits <13:11>, describes the second argument; and so on. The encoding for each group is described in Table 18-13.

Table 18-13 Argument Information Register Codes
Value OpenVMS Name Meaning
0 AI$K_AR_I64 64-bit or 32-bit sign-extended to 64-bit argument passed in an integer register (including addresses)
Argument is not present
1 AI$K_AR_FF F_floating (also known as VAX single-precision floating-point) argument passed in a general register
2 AI$K_AR_FD D_floating (also known as VAX double-precision floating-point) argument passed in a general register
3 AI$K_AR_FG G_floating (also known as VAX double-precision floating-point) argument passed in a general register
4 AI$K_AR_FS S_floating (also known as IEEE single-precision floating-point) argument passed in a floating-point register
5 AI$K_AR_FT T_floating (also known as IEEE double-precision floating-point) argument passed in a floating-point register
6,7   Reserved

18.5.7 Memory Stack Parameters

The remainder of the parameter list, beginning with slot 8, is passed in the outgoing parameter area of the memory stack frame, as described in the HP OpenVMS Calling Standard. Parameters are mapped directly to memory, with slot 8 placed at location SP+16, slot 9 placed at location SP+24, and so on. Each argument is stored in memory as a series of one or more 64-bit storage units, with unused bits in the last unit undefined.

18.5.8 Variable Argument Lists

The rules above support variable-argument list functions in both the K&R and the ANSI dialects of the C language. (Note that argument location is independent of whether a prototype is in scope.)

The nth argument is in either Rn or Fn regardless of the type of parameter in the preceding register slot. Therefore, a function with variable arguments may assume that the variable arguments that lie within the first eight argument slots can be found in either the stacked input integer registers (IN0-IN7), or in the floating-point parameter registers (F8-F15). Using the information codes from the the AI (Argument Information) register (see Table 18-13), the function can then store these registers to memory using the 16-byte scratch area for IN6/F14 and IN7/F15, and up to 48 bytes at the base of its own stack frame for IN0/F8-IN5/F13, as necessary. This arrangement places all of the variable parameters in one contiguous block of memory.

18.5.9 Pointers to Formal Parameters

Whenever the address is formed of a formal parameter that is passed in a register, the compiler must store the parameter to the stack, as it would for a variable argument list. Languages Other than C

The placement of arguments in general registers versus floating-point registers does not depend on any notion or concept of a prototype being in scope. It is therefore applicable to all languages at all times.

18.5.10 Rounding Floating-Point Values

There must be no difference in behavior between a floating-point parameter passed directly in a register and a floating-point parameter that has been stored to memory and reloaded. In either case, the floating-point value must be the same. This implies that floating-point parameters passed in floating-point registers must be explicitly rounded to the proper precision by the caller.

18.6 Passing Scalars as Arguments

When you are passing an input scalar value to an OpenVMS system routine, you usually pass it either by reference or by value. You usually pass output scalar arguments by reference to OpenVMS system routines. An output scalar argument is the address of a location where some scalar output of the routine will be stored.

18.7 Passing Arrays as Arguments

Arrays are passed to OpenVMS system routines by reference or by descriptor.

Sometimes the routine knows the length and dimensions of the array to be received, as in the case of the table passed to LIB$CRC_TABLE. Arrays such as this are normally passed by reference.

In other cases, the routine actually analyzes and operates on the input array. The routine does not necessarily know the length or dimensions of such an input array, so a descriptor is necessary to provide the information the routine needs to describe the array accurately.

18.8 Passing Strings as Arguments

Strings are passed by descriptor to OpenVMS system routines. Table 18-14 lists the string-passing descriptors recognized by a system routine.

Table 18-14 String-Passing Descriptors
Descriptor Function Descriptor Class Code Numeric Value
Fixed length (string/scalar) DSC$K_CLASS_S 1
Dynamic DSC$K_CLASS_D 2
Scaled decimal DSC$K_CLASS_SD 9
Noncontiguous array DSC$K_CLASS_NCA 10
Varying length DSC$K_CLASS_VS 11

An OpenVMS system routine writes strings according to the following types of semantics:

  • Fixed length --- Characterized by an address and a constant length
  • Varying length --- Characterized by an address, a current length, and a maximum length
  • Dynamic --- Characterized by a current address and a current length

18.9 Combinations of Descriptor Class and Data Type

Some combinations of descriptor class and data type are not permitted, either because they are not meaningful or because the calling standard does not recognize them. Possibly, the same function can be performed with more than one combination. This section describes the restrictions on the combinations of descriptor classes and data types. These restrictions help to keep procedure interfaces simple by allowing a procedure to accept a limited set of argument formats without sacrificing functional flexibility.

The tables in Figures 18-13, 18-14, and 18-15 show all possible combinations of descriptor classes and data types. For example, Figure 18-13 shows that your program can pass an argument to an OpenVMS system routine whose descriptor class is DSC$K_CLASS_A (array descriptor) and whose data type is unsigned byte (DSC$K_DTYPE_BU). The calling standard does not permit your program to pass an argument whose descriptor class is DSC$K_CLASS_D (dynamic string) and whose data type is unsigned byte.

A descriptor with data type DSC$K_DTYPE_DSC (24) points to a descriptor that has class DSC$K_CLASS_D (2) and data type DSC$K_DTYPE_T (14). All other class and data type combinations in the target descriptor are reserved for future definition in the standard.

The scale factor for DSC$K_CLASS_SD is always a decimal data type. It does not vary with the data type of the data described by the descriptor.

For DSC$K_CLASS_UBS and DSC$K_CLASS_UBA, the length field specifies the length of the data field in bits. For example, if the data type is unsigned word (DSC$K_DTYPE_WU), DSC$W_LENGTH equals 16.

Figure 18-13 Atomic Data Types and Descriptor Classes

Figure 18-14 String Data Types and Descriptor Classes

Figure 18-15 Miscellaneous Data Types and Descriptor Classes

Previous Next Contents Index