HP OpenVMS Systems Documentation
HP OpenVMS Calling Standard
188.8.131.52 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
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:
184.108.40.206.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.
|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:
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
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|
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:
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.
220.127.116.11 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
18.104.22.168 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:
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.
22.214.171.124 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 126.96.36.199.)
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:
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 188.8.131.52.
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.
(low 3 bits)
|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).|
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:
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)
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)
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
|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.|
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
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.|
A 4-bit field that contains coded argument signature information as
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.|
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