[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Calling Standard


Previous Contents Index

4.9.6.5 Jump Tables

High-level language constructs such as case and switch statements, where there are several possible local targets of a branch, may use a number of different code generation strategies, ranging from sequential conditional branches to a direct-lookup branch table.

Two branch table methods are described: The first places the branch table in a read-only segment separate from the code segment. The second places the branch table in the code segment. The advantage of the first is that it allows the code segment to have execute-only access, while the second may require the code segment to allow read access as well. The advantage of the second is that it does not require addressing the branch table via the GP and hence may be slightly faster. Both methods avoid the need for relocation during image activation.

The branch table method descriptions that follow include examples that use 64-bit entries. It is also valid to use 32-bit, 16-bit or even 8-bit entries providing it is known that the smaller entry size is sufficient to allow the required displacement to be represented (without overflow).

4.9.6.5.1 Preferred Method

If a branch table is placed in a data segment separate from the code, each entry should be a byte displacement from a dispatch address located in the code segment to the branch target for that entry.

The following is a sample branch table and its associated code segment:


    //
    // Assume case index in loc0
    //
          addl    loc1=@ltoff($DSPTBL1), gp // addr of GOT entry
          ld8     loc2=[loc1]               // load addr of dsp table
          shladd  loc3=loc0,3,loc2          // calc addr of dsp entry
          ld8     loc4=[loc3]               // load dsp table entry
    $DA1: mov     loc5=ip                   // get "dispatch address"
          add     loc6=loc5,loc4            // calc target address
          mov     b6=loc6
          br.cond b6                        // perform dispatch

    $L1:  {target for case 1}
          ...
    $L2:  {target for case 2}
          ...
    ...   etc

    // The dispatch table is in the linkage section. It consists
    // of only constants (no relocations involved)
    //
    $DSPTBL1:
          .data8  $L1-$DA1
          .data8  $L2-$DA1
           .
           .
           .

4.9.6.5.2 Alternative Method

If a branch table is placed in the same segment as the code, each table entry should be a 64-bit byte displacement from the base of the branch table to the branch target for that entry.

A sample indirect branch is shown below. The branch table is assumed to be an array of entries, each of which is an offset relative to the beginning of the branch table to the branch target. The branch table index is assumed to have been computed or loaded into register LOC0.


        addl loc1=@ltoff(brtab),gp      // calc. address of
        ;;                              // linkage table entry
        ld8 loc2=[loc1] ;;              // load addr. of br. table
        shladd loc3=loc0,3,loc2 ;;      // calc. address of branch
                                        // table entry
        ld8 loc4=[loc3] ;;              // load branch table entry
        add loc5=loc4,loc2 ;;           // calc. target address
        mov b6=loc5 ;;                  // move address to B6...
        br.cond b6 ;;                   // ...and branch


Chapter 5
Signature Information and Translated Images (Alpha and I64 Systems Only)

To support interoperation between images built from native OpenVMS Alpha code and images translated from OpenVMS VAX code, native Alpha compilers can optionally generate information that describes the parameters and result of a procedure. Similarly, for interoperation between images built from native OpenVMS I64 code and images translated from VAX or Alpha code, I64 compilers can also optionally generate information that describes the parameters and result of a procedure. This auxiliary information is called signature information.

Translated VAX code on Alpha and I64 systems uses VAX argument list and function return conventions as described in Section 2.4 and Section 2.5.

Translated Alpha code on I64 systems uses Alpha argument list and function return conventions as described in Chapter 3.

The following sections describe the conventions for using signature information to control the passing of arguments and returning a function value when a native procedure passes control to a translated procedure and vice versa.

The Translated Image Executive (TIE) is the user-mode support facility (itself a sharable image) that performs the following functions:

  • Mediates calls between native and translated code
  • Controls execution of translated code
  • Performs interpretation where necessary

5.1 Overview

OpenVMS compilers for Alpha and I64 provide a compilation option that causes signature information to be included in the resulting object file. To support interoperation between OpenVMS native and translated code, the native code must contain signature information.

With one exception related to indirect calls (see Section 5.1.1.3 and Section 5.1.2.3), code generation is not affected by the presence or absence of translated code support.

The operation of translated images on OpenVMS Alpha and I64 systems is very similar, though different in certain details.

5.1.1 Translated VAX Images on Alpha Systems

When a VAX image is translated to an Alpha image, the VAX registers R0--15 are represented using the lower half of the corresponding Alpha registers R0--15 at call interface boundaries. No "type conversion" is performed in making parameters from either native or translated code available to each other.

5.1.1.1 Direct Calls From Translated to Native Code

When the TIE encounters a call in translated code that passes control to native Alpha code, it obtains signature information for the target procedure using the PDSC$W_SIGNATURE_OFFSET field of the target procedure descriptor (see Section 3.4.1).

If the value in the PDSC$W_SIGNATURE_OFFSET is zero, then no signature information is available, the call cannot be performed, and the TIE signals an error.

Otherwise, the TIE uses the signature information to create an appropriate Alpha argument list (in the integer registers and stack as appropriate), then calls the native procedure. When control returns, the TIE obtains the returned result (if any), makes it available to translated code, and resumes translated code execution.

5.1.1.2 Direct Calls From Native to Translated Code

Calls from native Alpha code to a routine in a translated image depend on special linker and image activator support. If the linker can confirm that the target of the call is also in native code (because the target is local to the same image), then the call is resolved normally. Otherwise, the linker passes the compiler generated signature information for use by the image activator.

If the image activator can determine that the target of the call is also in native code, then the call is resolved normally. Otherwise, the image activator creates a bound procedure descriptor (see Section 3.6.4) and resolves the procedure value to that descriptor. This descriptor is setup to pass control to a special TIE entry point which obtains the target VAX procedure value and signature information from that same descriptor.

5.1.1.3 Indirect Calls From Native to Translated Code

If interoperation with translated images is not required, then an indirect call is made as described in Section 3.6.3. If interoperation with translated images must be considered, the procedure value (in R4 in the following example) might be the address of a VAX entry point or the address of an Alpha procedure descriptor.

A VAX entry point can be dynamically distinguished from an Alpha procedure descriptor by examining bits 12 and 13 of a VAX entry call mask, which are required to be 0 by the VAX architecture. For an Alpha procedure, bit 12 corresponds to the PDSC$V_NATIVE flag, which is required to be set in all Alpha procedure descriptors. Bit 13 corresponds to the PDSC$V_NO_JACKET flag, which is currently required to be set but reserved for enhancements to this standard in all Alpha procedure descriptors.

If the procedure value is determined to correspond to an Alpha procedure, then the call can be completed as discussed. If the procedure value is determined to correspond to a VAX procedure, then the call must be completed using system TIE facilities that will effect the transition into and out of the code of the translated image.

Example 5-1 illustrates a code sequence for examining the procedure value.

Example 5-1 Code for Examining the Procedure Value


        LDL     R28,0(R4)             ;Load the flags field of the target PDSC
        MOV     #AI_LITERAL,R25       ;Load Argument Information register
        SRL     R28,#PDSC$V_NO_JACKET,R26 ;Position jacket flag
        BLBC    R26,CALL_JACKET       ;If clear then jacket needed
        LDQ     R26,8(R4)             ;Entry address to scratch register
        MOV     R4,R27                ;Procedure value to R27
        JSR     R26,(R26)             ;Call entry address.
back_in_line:
        ...                           ;Rest of procedure code goes here

TRANSLATED:                           ;Generated out of line, R2 contains a
        LDQ     R26,N_TO_T_LKP(R2)    ;Entry address to scratch register
        LDQ     R27,N_TO_T_LKP+8(R2)  ;Load procedure value
        MOV     R4,R23                ;Address of routine to call to R23
        JSR     R26,(R26)             ;Call jacket routine
        BR      back_in_line          ;Return to normal code path

CALL_JACKET:                          ;
        SRL     R28,#PDSC$V_NATIVE,R28;Jacketing for translated or native?
        LDA     R24,PSIG_OUT(R2)      ;Pass address of our argument
                                      ; signature information in R24
        BLBC    R28,TRANSLATED        ;If clear, then translated jacketing
        (Native Jacketing Reserved for Future Use)
        BR      back_in_line          ;Return to normal code path

In Example 5-1, TIE jacketing functionality is provided by the SYS$NATIVE_TO_TRANSLATED routine. This system procedure is called with the actual arguments for the target procedure in their normal locations (as though the target procedure were an Alpha procedure) and with two additional, nonstandard arguments:

  • R23 contains the procedure value for the target VAX procedure.
  • R24 contains the address of a signature information block for the call, as described in Section 5.2. There are two special address values:
    • The value zero (null) indicates that no signature information is available. As a result, if the call is to a translated image, then the call will fail.
    • The value one indicates a default signature applies, based on information in the argument information register (see Section 5.2.5).

The conventions just described are normally accomplished using the special service routine OTS$CALL_PROC. The actual parameters to the target function are passed to OTS$CALL_PROC as though the target routine is native code that is being invoked directly. In addition, OTS$CALL_PROC receives two additional parameters in registers R23 and R24 as described above for SYS$NATIVE_TO_TRANSLATED.

5.1.2 Translated Images on I64 Systems

When a VAX or Alpha image is translated to an I64 image, the VAX or Alpha registers become associated with I64 registers for the purpose of making a call according to the following mapping:

VAX/Alpha Register I64 Register
R0 R8
R1 R9

In the case of a VAX image, the lower half of the corresponding I64 register is used.

For example, at the time of a call from an Alpha to an I64 image, the contents of the Alpha R1 register become the initial contents of the I64 R9 register when native execution begins. Similarly, at the time of a call from an I64 image to a VAX image, the contents of the lower half of the I64 R8 register become the initial contents of the VAX R0 register.

For calls between a translated VAX and a translated Alpha image on I64 systems, the rules for calls between translated VAX and native Alpha images apply and make use of signature information in the translated Alpha image.

OpenVMS I64 implements a static mapping that:

  • Allows an address corresponding to a translated image to be identified
  • Specifies whether it is an Alpha or VAX translated image

However, the means for creating and accessing this mapping is not part of this calling standard.

It is not possible for dynamically generated non-native code to be reflected in this mapping. As a result, OpenVMS does not support translated images that dynamically generate non-native code and call the in-memory result.

5.1.2.1 Calls From Translated to Native I64 Code

When the TIE encounters a call in translated code that passes control to native I64 code, it obtains signature information for the target routine from the function descriptor for that routine.

If the value in the signature information field is zero, then no signature information is available, the call cannot be performed, and the TIE signals an exception.

Otherwise, the TIE uses the signature information to create an appropriate I64 argument list (in the stacked registers and memory stack as appropriate), then calls the target native function. When control returns, the TIE obtains the returned result (if any), makes it available to the translated code, and resumes translated code execution.

To assure that any routine that can potentially be called from translated code has either signature information or a zero indicating the lack of signature information, it is necessary that every official function descriptor be allocated with room for the signature information field.

5.1.2.2 Direct Calls From Native I64 Code to Translated Code

Calls from native I64 code to a routine in a translated image depend on special linker and image activator support. If the linker can confirm that the target of a call is also in native code (because the target is local to the same image), then the call is resolved normally. Otherwise, the linker creates an import stub and an associated local function descriptor in the linkage table in the normal way. However, in this case the local function descriptor must be a jacket function descriptor, as described in the following paragraphs.

The linker also passes through the compiler generated signature information for use by the image activator. If the image activator can determine that the target of a call is also in native code, then the jacket function descriptor is initialized as for a simple function descriptor (the extra space in the jacket descriptor is unused). Otherwise, the image activator initializes the jacket function descriptor so that the call using that descriptor will transfer control into the TIE.

A jacket function descriptor is similar to a bound function descriptor (see Section 4.7.7) except that it initially transfers control to an entry point in the TIE. The TIE uses the signature information field together with other information in the descriptor to construct an appropriate parameter list for the translated code and effects the transfer of control into that code. When the call completes, control returns to the TIE, which sets up the return value for the native code and returns to normal execution.

A jacket function descriptor consists of the following fields:

  • Entry (code) address of the TIE entry point that handles transfers of control into translated code
  • Pseudo-GP value, which is the address of the jacket function descriptor
  • Signature information for the call (see Section 5.1.3)
  • Function pointer to the official function descriptor for the entry point in the translated image (or other unique identification that can be interpreted by the TIE)

More complete details are beyond the scope of this Standard.

Calls made by translated code to other entry points in translated code are not visible to the OpenVMS I64 calling standard. From the outside, a call from native I64 code to translated code looks like a single call to the TIE entry point, regardless of how many calls are made within the translated image.

5.1.2.3 Indirect Calls From Native to Translated Code

When translated code support is not requested, the code generated for calling a dynamic function value follows the I64 conventions. In particular, the target code address and target global pointer value are obtained from the function pointer and used in the standard way ( Section 4.7.3.2.)

When translated code support is requested, the compiled code must instead call a special service routine, OTS$CALL_PROC. The actual parameters to the target function are passed to OTS$CALL_PROC as though the target routine is native code that is being invoked directly. In addition, OTS$CALL_PROC receives two additional parameters in special registers:

  • R17 contains the address of a signature information block for the call (see Section 5.1.3).
  • R18 contains the function pointer for the target of the call.

OTS$CALL_PROC first determines whether the target routine is part of a translated image or not using the static mapping mentioned earlier.

If the target is in native code, then OTS$CALL_PROC completes the call in a way that makes its mediation transparent (that is, control need not pass back through it for the return). The native parameters are used without modification.

If the target is in translated code, then OTS$CALL_PROC passes control to the TIE which handles the call as described in Section 5.1.2.2.

5.1.3 Signature Information Fields in Function Descriptors

The signature information field of the function descriptor is encoded using the low three bits of the field as a tag that specifies the interpretation of the rest of the field. Table 5-1 contains the meaning of the values specified by the tag value.

Table 5-1 Signature Information Field Tag Values
Tag Value
(low 3 bits)
Meaning
0 The signature information field as a whole (including the tag bits) is the address of a signature information block (see Section 5.2). However, if the address is null, no signature information is available.
1 Default signature information applies, which is based on the information in the argument information register (see Section 5.2.5). In this case the rest of the field must be zero.
2 The field as a whole is a signature information block (see Section 5.2) that is immediately contained in the function descriptor. This can only be used for a signature information block whose size is less than or equal to 64 bits (which can represent up to 12 arguments).
3---7 Reserved.

5.2 Signature Information Blocks

Signature information blocks on Alpha and I64 systems are nearly identical in content and interpretation. However, they differ in the following ways:
  • Signature information blocks are associated with the corresponding Alpha procedure descriptor or I64 function descriptor differently (see Section 5.1).
  • Signature information fields are arranged in different orders.
  • An I64 signature information block includes control information that is not present in an Alpha signature information block (see Section 5.1.3).

5.2.1 Signature Information on Alpha Systems

If a procedure is compiled with signature information, PDSC$W_SIGNATURE_OFFSET contains a byte offset from the procedure descriptor to the start of a signature information block. The maximum size of the signature information block is 72 bytes (defined by constant PSIG$K_MAX_SIZE). The fields defined in the signature information block are illustrated in Figure 5-1 and described in Table 5-2.

Figure 5-1 Alpha Signature Information Block (PSIG)


5.2.2 Signature Information on I64 Systems

Signature information is represented in Figure 5-2, and is explained in Table 5-2, Table 5-3, and Table 5-4.

Signature information is defined only for standard calls, that is, for normal parameters passed using standard mechanisms and locations as defined in this calling standard. For all other cases, the signature information will be null so that an attempted call between native and translated code will fail.

Figure 5-2 I64 Signature Information Block (PSIG)


5.2.3 Signature Information Block Content

The content of Alpha and I64 signature information blocks is described in Table 5-2, Table 5-3, and Table 5-4. Table 5-2 omits reference to particular bit positions. In these tables and subsequence sections, the following logical names are used to refer to corresponding Alpha and Intel Itanium registers:

Name Interpretation Alpha Register Itanium Register
RetVal First (or only) integer return register R0 R8
RetVal2 Second integer return register R1 R9
RetFlt First (or only) floating-point return register F0 F8 for S_ and T_floating
R8 for F_, D_ and G_floating
RetFlt2 Second floating-point return register F1 F9 for S_ and T_floating
R9 for F_, D_ and G_floating

Table 5-2 Contents of the Signature Information Block (PSIG)
Field Name Contents
PSIG$V_CTRL (I64 systems only) A 3-bit control information field. Not used in a signature information block. Contents are unspecified. Allows a signature information block to occur as an immediate value in the signature information field of a function descriptor (see Section 5.1.3).
PSIG$V_X (I64 systems only) A 5-bit unused field. Must be zero.
PSIG$V_FUNC_RETURN A 4-bit field that describes which registers are used for the function value return (if there is one) and what format is used for those registers.

Table 5-4 lists and describes the possible encoded values of PSIG$V_FUNC_RETURN.

PSIG$V_REG_ARG_INFO A field that is divided into groups of 4 bits that correspond to the arguments that can be passed in registers. There are six groups for a total of 24 bits on Alpha systems and eight groups for a total of 32 bits on I64 systems. The first group (lowest order bits) describes the first register argument, the second group (next lowest order bits) describes the second register argument, and so on. Table 5-3 lists the possible codes.
PSIG$V_SUMMARY A 4-bit field that contains coded argument signature information as follows:
Bit Name Meaning
0, 1 PSIG$M_SU_ASUM On Alpha, summary of arguments 7 through PSIG$B_ARG_COUNT.
On Itanium, summary of arguments 9 through PSIG$B_ARG_COUNT:
00 = All arguments are 64-bit or not used
01 = All arguments are 32-bit sign extended or not used
10 = Reserved
11 = Other (not 00 or 01)
2 PSIG$M_SU_VLIST VAX formatted argument list expected
3   Must be 0 (reserved)

PSIG$M_SU_ASUM values of 00 and 01 (binary) allow a quick test for the occurrence of either an all 32-bit or an all 64-bit argument list. The values for the PSIG$V_MEMORY_ARG_INFO field must be valid even when these occurrences apply.

PSIG$B_ARG_COUNT Unsigned byte (bits 0--7) that specifies the number of 64-bit argument items described in the argument signature information. This count includes the initial arguments that are passed in registers.
PSIG$V_MEMORY_ARG_INFO Array of 2-bit values that describe each of the arguments through PSIG$B_ARG_COUNT that are passed in memory (rather than registers). PSIG$S_MEMORY_ARG_INFO data is only defined for the arguments described by PSIG$B_ARG_COUNT. These memory argument signature bits are defined as follows:
Value Name Meaning1
0 MASE$K_MA_Q 64-bit argument
1   Reserved
2 MASE$K_MA_I32 32-bit sign-extended argument
3   Reserved

1For a more detailed description of these conversions, see Section 5.2.4.
2The X_floating and X_floating complex data types do not appear in this table because these types are not passed using the by value mechanism (see Section 3.7.5.1).


Previous Next Contents Index