  | 
		
HP OpenVMS Calling Standard
 
 
4.7.3.2 Indirect Calls
Indirect procedure calls follow nearly the same sequence as direct
calls (see Section 4.7.3.1), except that the branch target is established
indirectly. This sequence is illustrated in Figure 4-4.
 
Figure 4-4 Indirect Procedure Calls
  
 
 
  -  Caller: Function Pointer. A function pointer is always the address
  of a function descriptor for the target procedure (see Section 4.3).
  An indirect call loads the GP value into the GP register before
  branching to the entry point address. 
 In order to guarantee the
  uniqueness of a function pointer, and because its value is determined
  at program invocation time, code must materialize function pointers
  only by loading a pointer from the data segment.
   -  Caller: Prepare call. Indirect calls are made by first loading the
  function pointer into a general register, loading the entry point
  address and the new GP value, and using the Move to Branch Register
  operation to move the address of the procedure entry point into the
  branch register to be used for the call. 
 Values in scratch
  registers that must be kept live across the call must be saved. They
  can be saved by copying them into local stacked registers, or by saving
  them on the memory stack. If the NaT bits associated with any live
  scratch registers must be saved, the compiler should use ST8.SPILL or
  STF.SPILL instructions. The User NaT collection register itself is
  preserved by the call, so the NaT bits need no further treatment at
  this point.  Unless the call is known (at compile time) to be within
  the same image, the GP register must be saved before the new GP value
  is loaded.  The parameters must be set up in registers and memory as
  described in Section 4.7.4
   -  Caller: Call. All indirect calls are made with the indirect form
  of the BR.CALL instruction, specifying B0 for the return link. 
 The
  BR.CALL instruction saves the return link in the return branch
  register, saves the current frame marker in the AR.PFS register, and
  sets the base of the new register stack frame to the beginning of the
  output region of the old frame. Because the indirect call sequence
  obtains the entry point address and new GP value from the function
  descriptor, control flows directly to the target procedure, without the
  need for any intervening stubs.
   -  Callee: Entry; Exit. The remainder of the calling sequence is the
  same as for direct calls ( Section 4.7.3.1).
  
4.7.4 Parameter Passing
Parameters are passed in a combination of general registers,
floating-point registers, and memory, as described below, and as
illustrated in Figure 4-5.
 
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 4.7.5.1.
 
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 4-5 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 4.7.5.3.
 
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
undefined.
4.7.5 Parameter Passing Mechanisms
 
This OpenVMS calling standard defines three classes of argument items
according to the mechanism used to pass the argument:
 
  - Immediate value
  
 - Reference
  
 - Descriptor
  
Argument items are not self-defining; interpretation of each argument
item depends on agreement between the calling and called procedures.
 
This standard does not dictate which passing mechanism must be used by
a given language compiler. Language semantics and interoperability
considerations might require different mechanisms in different
situations.
 
Immediate value
 
 
An immediate value argument item contains the value of
the data item. The argument item, or the value contained in it, is
directly associated with the parameter.
 
Reference
 
 
A reference argument item contains the address of a
data item such as a scalar, string, array, record, or procedure. This
data item is associated with the parameter.
 
Descriptor
 
 
A descriptor argument item contains the address of a
descriptor, which contains structural information about the argument's
type (such as array bounds) and the address of a data item. This data
item is associated with the parameter.
 
 Requirements for using the argument passing mechanisms follow:
 
  - By immediate value. An argument may be passed by
  immediate value only if the argument is one of the following:
  
    - One of the noncomplex scalar data types with a size known (at
    compile time) to be <= 64 bits
    
 - Either single or double precision complex
    
 - A record with a known size (at compile time)
    
 - A set, implemented as a bit vector, with a size known (at compile
    time) to be <= 64 bits
  
  
     No form of string or array data type may be passed by immediate
    value in a standard call.  Unused high-order bits must be zero or
    sign extended, as appropriate depending on the date type, to fill all
    bits of each argument list item (as specified in Table 4-10).
     A single-precision or double-precision complex value is passed as
    two single- or double-precision floating-point values, respectively.
    Note that the argument count reflects that two argument positions are
    used rather than just one actual argument.  A record value, which
    may be larger than 64 bits, is passed by immediate value as follows:
  
    - Allocate as many fully occupied argument item positions to the
    argument value as are needed to represent the argument.
    
 - If the final argument position is only partially occupied by the
    argument, the contents of the remaining bits are undefined.
    
 - If an argument position is passed in one of the registers, it can
    only be passed in an integer register (never in a floating-point
    register).
  
  
      Other argument values that are larger than 64 bits can be passed
    by immediate value using nonstandard conventions, typically using a
    method similar to those for passing records. Thus, for example, a
    26-byte string can be passed by value in four integer registers.
   - By reference. Nonparametric arguments (arguments
  for which associated information such as string size and array bounds
  are not required) can be passed by reference in a standard call. This
  includes extended precision floating and extended precision complex
  values.
  
 - By descriptor. Parametric arguments (arguments for
  which associated information such as string size and array bounds must
  be passed to the caller) are passed by a single descriptor in a
  standard call.
  
Note that extended floating values are not passed using the immediate
value mechanism; rather, they are passed using the by reference
mechanism. (However, when by value semantics is required, it may be
necessary to make a copy of the actual parameter and pass a reference
to that copy in order to avoid improper alias effects.)
 
Also note that when a record is passed by immediate value, the
component types are not material to how the argument is aligned; the
record will always be quadword aligned.
4.7.5.1 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 4-9.
The allocation column of the table indicates how parameter slots are
allocated to each type of parameter.  
 
  Table 4-9 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
     | 
   
 
 
  Note 
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 Itanium 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.
4.7.5.2 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 4-5.
  
 - 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 4-10. 
 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.
 
 
  Note 
Bit 31 is replicated in bits 32--63, even for unsigned 32-bit integers.
     | 
   
 
The rules contained in this section are summarized in Tables
4-10 and 4-11.
 
 
  Table 4-10 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 4-11 contains the defined meanings for the memory extension
type symbols used in Table 4-10.  
 
  Table 4-11 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.
     | 
   
 
  
  
		 |