[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS Alpha Guide to 64-Bit Addressing and VLM Features


Previous Contents Index

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, as shown in the following list:

  • $BYTES_TO_PAGES
  • $NEXT_PAGE
  • $PAGES_TO_BYTES
  • $PREVIOUS_PAGE
  • $START_OF_PAGE

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 64 KB

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

For moves longer than 64 KB, use OTS$MOVE3 and OTS$MOVE5. OTS$MOVE3 and OTS$MOVE5 accept longword-sized lengths. (LIB$MOVC3 and LIB$MOVC5 have the same 64 KB 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
  • $is_desc64
  • $is_32bits

DESCRIPTOR64

Constructs a 64-bit string descriptor.

Format

$DESCRIPTOR64 name, string


Description

  • name is Name of variable
  • string is Address of string

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

  • desc is address of 32-bit or 64-bit descriptor

Returns:

  • 0 if descriptor is 32-bit descriptor
  • 1 if descriptor is 64-bit descriptor

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:

  • 1 if arg is 32-bit sign-extended
  • 0 if arg is not 32-bit sign-extended

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
  • $PUSH_ARG64
  • $CALL64

$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.

If there are more than six arguments, there can be no references to AP or SP between a $SETUP_CALL64 and the matching $CALL64, because the $CALL64 code may be in a separate JSB routine. In addition, temporary registers (R16 and above) may not survive the $SETUP_CALL64. However, they can be used within the range, except where R16 through R21 interfere with the argument registers already set up. In such cases, higher temporary registers should be used instead.

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.

$PUSH_ARG64

Does the equivalent of argument pushes for a call.

Format

$PUSH_ARG64 argument


Parameters

argument

The argument to be pushed.

Description

This macro pushes a 64-bit argument for a 64-bit call. The macro $SETUP_CALL64 must be used before you can use $PUSH_ARG64.

Arguments will be read as aligned quadwords. That is, $PUSH_ARG64 4(R0) will read the quadword at 4(R0), and push the quadword. Any indexed operations will be done in quadword mode.

To push a longword value from memory as a quadword, first move it into a register with a longword instruction, and then use $PUSH_ARG64 on the register. Similarly, to push a quadword value that you know is not aligned, move it to a temporary register first, and then use $PUSH_ARG64.

If the call contains more than six arguments, this macro checks for SP or AP references in the argument. If the call contains more than six arguments, SP references are not allowed, and AP references are allowed only if the inline option is used.

The macro also checks for references to argument registers that have already been set up for the current $CALL64. If it finds such references, a warning is reported to advise the user to be careful not to overwrite an argument register before it is used as the source in a $PUSH_ARG64.

The same checking is done for AP references when there are six or fewer arguments; they are allowed, but the compiler cannot prevent you from overwriting one before you use it. Therefore, if such references are found, an informational message is reported.

Note that if the operand uses a symbol whose name includes one of the strings R16 through R21, not as a register reference, this macro might report a spurious error. For example, if the invocation $PUSH_ARG64 SAVED_R21 is made after R21 has been set up, this macro will unnecessarily report an informational message about overwriting argument registers.

Also note that $PUSH_ARG64 cannot be in conditional code. $PUSH_ARG64 updates several symbols, such as the remaining argument count. Attempting to write code that branches around a $PUSH_ARG64 in the middle of a $SETUP_CALL64/$CALL64 sequence will not work properly.


$CALL64

Invokes the target routine.

Format

$CALL64 call_target


Parameters

call_target

The routine to be invoked.

Description

This macro calls the specified routine, assuming $SETUP_CALL64 has been used to specify the argument count, and $PUSH_ARG64 has been used to push the quadword arguments. This macro checks that the number of pushes matches what was specified in the setup call.

The call_target operand must not be AP- or SP-based.

B.2 Macros for Checking Sign Extension and Descriptor Format

The macros in this section are used for checking certain values and directing program flow based on the outcome of the check.


$IS_32BITS

Checks the sign extension of the low 32 bits of a 64-bit value and directs the program flow based on the outcome of the check.

Format

$IS_32BITS quad_arg, leq_32bits, gtr_32bits, temp_reg=22


Parameters

quad_arg

A 64-bit quantity, either in a register or in an aligned quadword memory location.

leq_32bits

Label to branch to if quad_arg is a 32-bit sign-extended value.

gtr_32bits

Label to branch to if quad_arg is greater than 32 bits.

temp_reg=22

Register to use as a temporary register for holding the low longword of the source value---R22 is the default.

Description

$IS_32BITS checks the sign extension of the low 32 bits of a 64-bit value and directs the program flow based on the outcome of the check.

Examples

#1

$is_32bits  R9, 10$
      

In this example, the compiler checks the sign extension of the low 32 bits of the 64-bit value at R9 using the default temporary register, R22. Depending on the type of branch and the outcome of the test, the program either branches or continues in line.

#2

$is_32bits  4(R8), 20$, 30$, R28
      

In this example, the compiler checks the sign extension of the low 32 bits of the 64-bit value at 4(R8) using R28 as a temporary register and, based on the check, branches to either 20$ or 30$.


$IS_DESC64

Tests the specified descriptor to determine if it is a 64-bit format descriptor, and directs the program flow based on the outcome of the test.

Format

$IS_DESC desc_addr, target, size=long or quad


Parameters

desc_addr

The address of the descriptor to test.

target

The label to branch to if the descriptor is in 64-bit format.

size=long

The size of the address pointing to the descriptor. Acceptable values are "long" (the default) and "quad".

Description

$IS_DESC64 tests the fields which distinguish a 64-bit descriptor from a 32-bit descriptor. If it is in 64-bit form, a branch is taken to the specified target. The address to be tested is read as a longword, unless SIZE=QUAD is specified.

Examples

#1

$is_desc64 r9, 10$

      

In this example, the descriptor pointed to by R9 is tested, and if it is in 64-bit form, a branch to 10$ is taken.

#2

$is_desc64 8(r0), 20$, size=quad
      

In this example, the quadword at 8(R0) is read, and the descriptor it points to is tested. If it is in 64-bit form, a branch to 20$ is taken.


Previous Next Contents Index