[Digital logo]
[HR]

OpenVMS Alpha Guide to 64-Bit Addressing and VLM Features


Previous | Contents

Before declaring function prototypes that support 64-bit pointers, the pointer context is changed (2) from 32-bit pointers to 64-bit pointers.

Functions restricted to 32-bit pointers are placed in the 32-bit pointer context section (1) of the header file. All other functions are placed in the 64-bit context section (3) of the header file.

Functions that have no pointer-size impact ( (4) and (5) ) are located in the 64-bit section. Functions that have no pointer-size impact, except for a 32-bit address return value (5) , are also in the 64-bit section, and use the 32-bit specific typedefs previously discussed. #4

: 
#if __INITIAL_POINTER_SIZE 
#   pragma __pointer_size 64 
#endif 
: 
: 
#if __INITIAL_POINTER_SIZE == 32 (1)
#   pragma __pointer_size 32 
#endif 
: 
char *strcat (char *__s1, __const_char_ptr64 __s2); (2)
: 
#if __INITIAL_POINTER_SIZE 
#   pragma __pointer_size 32 
    : 
    char *_strcat32  (char *__s1, __const_char_ptr64 __s2); (3)
    : 
#   pragma __pointer_size 64 
    : 
    char *_strcat64  (char *__s1, const char *__s2); (4)
    : 
#endif 
: 
 
 

This example shows declarations of functions that have both a 32-bit and 64-bit implementation. These declarations are located in the 64-bit section of the header file.

The normal interface to the function (2) is declared using the pointer size specified on the /POINTER_SIZE qualifier. Because the header file is in 64-bit pointer context and because of the statements at (1) , the declaration at (2) is made using the same pointer size context as the /POINTER_SIZE qualifier.

The 32-bit specific interface (3) and the 64-bit specific interface (4) are declared in 32-bit and 64-bit pointer-size context, respectively.


Chapter 12
MACRO--32 Programming Support for 64-Bit Addressing

This chapter describes the new 64-bit addressing support provided by the MACRO--32 compiler and associated components. The changes are primarily for argument passing and receiving and for address computations.

12.1 Guidelines for 64-Bit Addressing

The following guidelines pertain to using 64-bit addressing in VAX MACRO code that is compiled for OpenVMS Alpha:

12.2 New and Changed Components for 64-Bit Addressing

The new and changed components that provide MACRO--32 programming support for 64-bit addressing are shown in Table 12-1.

Table 12-1 New and Changed Components for 64-Bit Addressing
Component Description
$SETUP_CALL64 New macro that initializes the call sequence.
$PUSH_ARG64 New macro that does the equivalent of argument pushes.
$CALL64 New macro that invokes the target routine.
$IS_32BITS New macro for checking the sign extension of the low 32 bits of a 64-bit value.
$IS_DESC64 New macro for determining if descriptor is a 64-bit format descriptor.
QUAD=NO/YES New parameter for page macros to support 64-bit virtual addresses.
/ENABLE=QUADWORD The QUADWORD parameter was extended to include 64-bit address computations.
.CALL_ENTRY QUAD_ARGS=TRUE|FALSE QUAD_ARGS=TRUE|FALSE is a new parameter that indicates the presence (or absence) of quadword references to the argument list.
.ENABLE QUADWORD/.DISABLE QUADWORD The QUADWORD parameter was extended to include 64-bit address computations.
EVAX_SEXTL New built-in for sign extending the low 32 bits of a 64-bit value into a destination.
EVAX_CALLG_64 New built-in to support 64-bit calls with variable-size argument lists.
$RAB64 and $RAB64_STORE New RMS macros for using buffers in 64-bit address space.

12.3 Passing 64-Bit Values

The method that you use for passing 64-bit values depends on whether the size of the argument list is fixed or variable. These methods are described in the following sections.

12.3.1 Calls With a Fixed-Size Argument List

For calls with a fixed-size argument list, use the new macros as shown in Table 12-2.

Table 12-2 Passing 64-Bit Values with a Fixed-Size Argument List
Step Use...
1. Initialize the call sequence $SETUP_CALL64
2. "Push" the call arguments $PUSH_ARG64
3. Invoke the target routine $CALL64

An example of using these macros follows. Note that the arguments are pushed in reverse order, which is the same way a 32-bit PUSHL instruction is used.

MOVL           8(AP), R5         ; fetch a longword to be passed 
$SETUP_CALL64  3                 ; Specify three arguments in call 
$PUSH_ARG64    8(R0)             ; Push argument #3 
$PUSH_ARG64    R5                ; Push argument #2 
$PUSH_ARG64    #8                ; Push argument #1 
$CALL64        some_routine      ; Call the routine 

The $SETUP_CALL64 macro initializes the state for a 64-bit call. It is required before $PUSH_ARG64 or $CALL64 can be used. If the number of arguments is greater than six, this macro creates a local JSB routine, which is invoked to perform the call. Otherwise, the argument loads and call are inline and very efficient. Note that the argument count specified in the $SETUP_CALL64 does not include a pound sign (#). (The standard call sequence requires octaword alignment of the stack with its arguments at the top. The JSB routine facilitates this alignment.)

The inline option can be used to force a call with greater than six arguments to be done without a local JSB routine. However, there are restrictions on its use (see Appendix B).

The $PUSH_ARG64 macro moves the argument directly to the correct argument register or stack location. It is not actually a stack push, but it is the analog of the PUSHL instructions used in a 32-bit call.

The $CALL64 macro sets up the argument count register and invokes the target routine. If a JSB routine was created, it ends the routine. It reports an error if the number of arguments pushed does not match the count specified in $SETUP_CALL64. Both $CALL64 and $PUSH_ARG64 check that $SETUP_CALL64 has been invoked prior to their use.

12.3.1.1 Usage Notes for $SETUP_CALL64, $PUSH_ARG64, and $CALL64

Keep these points in mind when using $SETUP_CALL64, $PUSH_ARG64, and $CALL64:


Note

The $SETUP_CALL64, $PUSH_ARG64, and $CALL64 macros are intended to be used in an inline sequence. That is, you cannot branch into the middle of a $SETUP_CALL64/$PUSH_ARG64/$CALL64 sequence, nor can you branch around $PUSH_ARG64 macros or branch out of the sequence to avoid the $CALL64.

For more information about $SETUP_CALL64, $PUSH_ARG64, and $CALL64, see Appendix B.

12.3.2 Calls With a Variable-Size Argument List

For calls with a variable-size argument list, use the new EVAX_CALLG_64 built-in, as shown in the following steps:

  1. Create an in-memory argument list.
  2. Call a routine, passing the in-memory argument list. For example:
    EVAX_CALLG_64 (Rn), routine
    

The argument list in the EVAX_CALLG_64 built-in is read as a series of quadwords, beginning with a quadword argument count.

12.4 Declaring 64-Bit Arguments

You can use QUAD_ARGS=TRUE, a new .CALL_ENTRY parameter, to declare the use of quadword arguments in a routine's argument list. With the presence of the QUAD_ARGS parameter, the compiler behaves differently when a quadword reference to the argument list occurs. First, it does not force argument-list homing, which such a reference normally requires. (An argument list containing a quadword value cannot be homed because homing, by definition, packs the arguments into longword slots.) Second, "unaligned memory reference" will not be reported on these quadword references to the argument list.

Note that the actual code generated for the argument-list reference itself is not changed by the presence of the QUAD_ARGS clause, except when the reference is in a VAX quadword instruction, such as MOVQ. For the most part, QUAD_ARGS only prevents argument-list homing due to a quadword reference and suppresses needless alignment messages. This suppression applies to both EVAX_ built-ins and VAX quadword instructions such as MOVQ.

For VAX quadword instructions, the QUAD_ARGS clause causes the compiler to read the quadword argument as it does for EVAX_ built-ins---as an actual quadword. Consider the following example:

MOVQ    4(AP), 8(R2) 

If the QUAD_ARGS clause is specified, MOVQ stores the entire 64 bits of argument 1 into the quadword at 8(R2). If the QUAD_ARGS clause is not specified, MOVQ stores the low longwords of arguments 1 and 2 into the quadword at 8(R2).

QUAD_ARGS also affects the code generated for deferred mode operands that are AP-based. If the effective address must be loaded from an argument in memory, it will be read as a quadword, rather than a longword, if QUAD_ARGS is in effect.

12.4.1 Usage Notes for QUAD_ARGS

Keep these points in mind when using QUAD_ARGS:

12.5 Specifying 64-Bit Address Arithmetic

There are no explicit pointer-type declarations in MACRO--32. You can create a 64-bit pointer value in a register in a variety of ways. The most common are the EVAX_LDQ built-in for loading an address stored in memory and the MOVAx for getting the address of the specified operand.

After a 64-bit pointer value is in a register, an ordinary instruction will access the 64-bit address. The amount of data read from that address depends on the instruction used. Consider the following example:

MOVL     4(R1), R0 

The MOVL instruction reads the longword at offset 4 from R1, regardless of whether R1 contains a 32- or 64-bit pointer.

However, certain addressing modes require the generation of arithmetic instructions to compute the effective address. For VAX compatibility, the compiler computes these as longword operations. For example, 4 +<1@33> yields the value 4, because the shifted value exceeds 32 bits. If quadword mode is enabled, the upper bit will not be lost.

In compilers shipping with previous versions of OpenVMS Alpha, the /ENABLE=QUADWORD qualifier (and the corresponding .ENABLE QUADWORD and .DISABLE QUADWORD directives) only affected the mode in which constant expression evaluations were performed. For OpenVMS Alpha Version 7.0, these have been extended to affect address computations. They will result in addresses being computed with quadword instructions, such as SxADDQ and ADDQ.

To have quadword operations used throughout a module, specify /ENABLE=QUADWORD on the command line. If you want quadword operations applied only to certain sections, use the .ENABLE QUADWORD and .DISABLE QUADWORD directives to enclose those sections.

There is no performance penalty when using /ENABLE=QUADWORD.

12.5.1 Dependence on Wrapping Behavior of Longword Operations

The compiler cannot use quadword arithmetic for all addressing computations, because existing code may rely on the wrapping behavior of the 32-bit operations. That is, code may perform addressing operations that actually overflow 32 bits, knowing that the upper bits are discarded. Doing the calculation in quadword mode causes an incompatibility.

Before using /ENABLE to set quadword evaluation for an entire module, check the existing code for dependence on longword wrapping. There is no simple way to do this, but as a programming technique, it should be rare and may be called out in the code.

The following example shows the wrapping problem:

MOVAL   (R1)[R0], R2 

Suppose R1 contains the value 7FFFFFFF and R0 contains 1. The MOVAL instruction generates an S4ADDL instruction. The shift and add result exceeds 32 bits, but the stored result is the low 32 bits, sign extended.

If quadword arithmetic were used (S4ADDQ), the true quadword value would result, as shown in the following example:

S4ADDL  R0, R1, R2   =>  FFFFFFFF 80000003 
S4ADDQ  R0, R1, R2   =>  00000000 80000003 

The wrapping problem is not limited to indexed-mode addressing. Consider the following example:

MOVAB   offset(R1), R0 

If the symbol offset is not a compile-time constant, this instruction causes a value to be read from the linkage section and added (using an ADDL instruction) to the value in R1. Changing this to ADDQ may change the result if the value exceeds 32 bits.

12.6 Sign Extending and Checking

A new built-in, EVAX_SEXTL (sign-extend longword), is available for sign extending the low 32 bits of a 64-bit value into a destination. This built-in makes explicit the sign extension of the low longword of the source into the destination.

EVAX_SEXTL takes the low 32 bits of the 64-bit value, fills the upper 32 bits with the sign extension (whatever is in bit 31 of the value) and writes the 64-bit result to the destination.

The following examples are all legal uses:

evax_sextl r1,r2 
evax_sextl r1,(r2) 
evax_sextl (r2), (r3)[r4] 

As shown by these examples, the operands are not required to be registers.

A new macro, $IS_32BITS, is available for checking the sign extension of the low 32 bits of a 64-bit value. It is described in Appendix B.

12.7 Alpha Instruction Built-ins

The compiler supports many Alpha instructions as built-ins. Many of these built-ins (available since the compiler first shipped) can be used to operate on 64-bit quantities. The function of each built-in and its valid operands are documented in Porting VAX MACRO Code to OpenVMS Alpha. A full description of each Alpha instruction is documented in the MACRO--64 Assembler for OpenVMS AXP Systems Reference Manual.

12.8 Calculating Page-Size Dependent Values

A new parameter, QUAD=NO/YES, for supporting 64-bit virtual addresses is available for each of the page macros, shown in the following list:

These macros provide a standard, architecture-independent means for calculating page-size dependent values. For more information about these macros, see Porting VAX MACRO Code to OpenVMS Alpha.

12.9 Creating and Using Buffers in 64-Bit Address Space

The $RAB and $RAB_STORE control block macros have been extended for creating and using data buffers in 64-bit address space. The 64-bit versions are named $RAB64 and $RAB64_STORE, respectively. The rest of the RMS interface is restricted to 32 bits at this time. For more information about $RAB64 and $RAB64_STORE, see Chapter 5.

12.10 Coding for Moves Longer Than 64K Bytes

The MACRO--32 instructions MOVC3 and MOVC5 properly handle 64-bit addresses but the moves are limited to a 64K byte length. This limitation is because MOVC3 and MOVC5 accept word-sized lengths.

For moves longer than 64K bytes, use OTS$MOVE3 and OTS$MOVE5. OTS$MOVE3 and OTS$MOVE5 accept longword-sized lengths. (LIB$MOVC3 and LIB$MOVC5 have the same 64K byte length restriction as MOVC3 and MOVC5.) An example of replacing MOVC3 with OTS$MOVE3 follows.

Code using MOVC3:

MOVC3      BUF$W_LENGTH(R5), (R6), OUTPUT(R7)   ; Old code, word length 

The equivalent 64-bit code with longword length:

$SETUP_CALL64  3              ; Specify three arguments in call 
EVAX_ADDQ      R7, #OUTPUT, R7 
$PUSH_ARG64    R7             ; Push destination, arg #3 
$PUSH_ARG64    R6             ; Push source, arg #2 
MOVL           BUF$L_LENGTH(R5), R16 
$PUSH_ARG64    R16            ; Push length, arg #1 
$CALL64        OTS$MOVE3 
 
MOVL           BUF$L_LENGTH(R5), R16 
EVAX_ADDQ      R6, R16, R1    ; MOVC3 returns address past source 
EVAX_ADDQ      R7, R16, R3    ; MOVC3 returns address past destination 

Because MOVC3 clears R0, R2, R4, and R5, make sure that these side effects are no longer needed.

OTS$MOVE3 and OTS$MOVE5 are documented with other LIBOTS routines in the OpenVMS RTL General Purpose (OTS$) Manual.

12.11 Using the MACRO--32 Compiler

In order to take advantage of OpenVMS Alpha 64-bit addressing features, you must use the MACRO--32 compiler included with OpenVMS Alpha Version 7.0.

When you use the latest version of the compiler, regardless of whether you use the 64-bit addressing features, you must also use the latest version of ALPHA$LIBRARY:STARLET.MLB. Make sure that the latest version is installed on your system and that the logical name points to the correct directory.


Appendix A
C Macros for 64-Bit Addressing

This appendix describes the following C macros for manipulating 64-bit addresses, for checking the sign extension of the low 32 bits of 64-bit values, and for checking descriptors for the 64-bit format.


DESCRIPTOR64

Constructs a 64-bit string descriptor.

Format

$DESCRIPTOR64 name, string


DESCRIPTION

Example:

 
        int status; 
        $DESCRIPTOR64 (gblsec, "GBLSEC_NAME"); 
 
        ... 
 
        /* Create global page file section */ 
        status = sys$create_gpfile (&gblsec, 0, 0, section_size, 0, 0); 
 
        ... 
 

This macro resides in descrip.h in SYS$LIBRARY:DECC$RTLDEF.TLB.


$is_desc64

Distinguishes a 64-bit descriptor.

Format

$is_desc64 desc


DESCRIPTION

Returns:

Example:

#include <descrip.h> 
#include <far_pointers.h> 
... 
        if ($is_desc64 (user_desc)) 
        { 
                /* Get 64-bit address and 64-bit length from descriptor */ 
                ... 
        } 
        else 
        { 
               /* Get 32-bit address and 16-bit length from descriptor */ 
               ... 
        } 
 

This macro resides in descrip.h in SYS$LIBRARY:DECC$RTLDEF.TLB.


$is_32bits

Tests if a quadword is 32-bit sign-extended.

Format

$is_32bits arg


DESCRIPTION

Input: arg is 64-bit value

Output:

Example:

        #include <starlet_bigpage.h> 
        ... 
        if ($is_32bits(user_va)) 
                counter_32++;   /* Count number of 32-bit references */ 
        else 
                counter_64++;  /* Count number of 64-bit references */ 
 

This macro resides in starlet_bigpage.h in SYS$LIBRARY:SYS$STARLET_C.TLB.


Appendix B
MACRO-32 Macros for 64-Bit Addressing

This appendix describes the MACRO-32 macros for manipulating 64-bit addresses, for checking the sign extension of the low 32 bits of 64-bit values, and for checking descriptors for the 64-bit format.

These macros reside in the directory ALPHA$LIBRARY:STARLET.MLB (generally synonymous with SYS$LIBRARY:STARLET.MLB) and can be used by both application code and system code. The page macros have also been enhanced for 64-bit addresses. The support is provided by a new parameter, QUAD=NO/YES.

Note that you can use certain arguments to the macros described in this appendix to indicate register sets. To express a register set, list the registers, separated by commas, within angle brackets. For example:

<R1,R2,R3> 

If the set contains only one register, the angle brackets are not required.

B.1 Macros for Manipulating 64-Bit Addresses

This section describes the following macros, designed to manipulate 64-bit addresses:


$SETUP_CALL64

Initializes the call sequence.

Format

$SETUP_CALL64 arg_count, inline=true or false


PARAMETERS

arg_count

The number of arguments in the call.

inline

Forces inline expansion, rather than creation of a JSB routine, when set to TRUE. If there are six or fewer arguments, the default is INLINE=FALSE.

DESCRIPTION

This macro initializes the state for a 64-bit call. It must be used before using $PUSH_ARG64 and $CALL64.

If there are six or fewer arguments, the code is always in line.

By default, if there are more than six arguments, this macro creates a JSB routine that is invoked to perform the actual call. However, if the inline option is specified as INLINE=TRUE, the code is generated in line. This option should be enabled only if the code in which it appears has a fixed stack depth. A fixed stack depth can be assumed if no RUNTIMSTK or VARSIZSTK messages have been reported. Otherwise, if the stack alignment is not at least quadword, there might be many alignment faults in the called routine and in anything the called routine calls. The default behavior (INLINE=FALSE) does not have this problem.


Previous | Next | Contents | [Home] | [Comments] | [Ordering info] | [Help]

[HR]

  6467P006.HTM
  OSSG Documentation
  22-NOV-1996 13:12:04.74

Copyright © Digital Equipment Corporation 1996. All Rights Reserved.

Legal