Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

Porting VAX MACRO Code to OpenVMS Alpha


Previous Contents Index

1.4 Identifying Nonportable VAX MACRO Coding Practices

When examining a VAX MACRO module that you intend to compile to OpenVMS Alpha object code, look for any of the following coding constructs. The occurrence of these in a module can make porting take longer than it would otherwise. Although the compiler can identify many of these practices, recognizing them yourself will speed up the porting effort. For more information about nonportable MACRO coding practices, including some that occur less frequently and are less easy to detect, see Chapter 3.

  1. Removing the return address from the stack to return to the caller's caller, such as the following (see Section 3.3.4):


    TSTL    (SP)+               ; remove return address 
    RSB                         ; return to caller's caller 
    

  2. Temporarily removing the return address from the stack to allocate space on the stack using mechanisms such as the following (see Section 3.3.4):


    POPL    R0                  ; remove the return address 
    SUBL    #structure_size,SP  ; allocate stack space for caller 
    PUSHL   R0                  ; replace the return address 
    
    or


    POPL    R1                  ; hold return address 
    PUSHL   structure           ; build structure for caller 
    ; 
    ; code continues 
    ; 
    JMP     (R1)                ; return to caller 
    

  3. Pushing a label onto the stack, as in the following examples, often as an attempt to construct a return address for an RSB instruction (see Section 3.3.3):


    MOVAL   routine_label,-(SP) 
    RSB 
    
    or


    PUSHAL  routine_label 
    RSB 
    

  4. Modifying the frame pointer (FP) (see Section 3.1.1). VAX MACRO code typically modifies the frame pointer for one of two reasons:


    MOVL    SP,FP 
    SUBL    #data_area,SP 
    

  5. Constructing an REI target, as in the following examples (see Section 3.3.7):


    MOVL    #fake_psl,-(SP) 
    MOVAL   target_label,-(SP)      ; all three 
    REI 
    
    or


    MOVPSL  -(SP) 
    MOVAL   target_label,-(SP)      ; force AST delivery only 
    REI 
    
    or


            MOVL    #fake_psl,-(SP) 
            BSBW    DOREI 
            ; 
            ; code continues 
            ; 
    DOREI:  REI 
    

  6. Branching to a destination that consists of a label plus an offset as in the following example. The appearance of this practice in VAX MACRO code may indicate a branch past some data in the code stream, such as the register save mask at the top of a .CALL_ENTRY routine (see Section 3.2.1). Alternatively, it may be a sign that the code is familiar with and dependent upon the size of VAX instructions (see Section 3.2.3).


    BRx     label+offset 
    

  7. Moving an opcode to a location, usually the stack or a data area, as shown in the following example. This practice indicates either generated or self-modifying code and will require redesign as indicated in Section 3.2.2.


    MOVB    #OP$_opcode,(Rx) 
    
    or


    MOVZBL  #OP$_opcode,(Rx) 
    

  8. Jumping across modules. Because of architectural requirements, the compiler must handle jumps across modules as JSBs. Therefore, external branch targets as in the following example must be declared with the .JSB_ENTRY directive (see Section 2.2.3).


    JMP     G^external_routine 
    

1.5 Establishing Useful Coding Conventions

Section 1.3 describes a recommended process for porting VAX MACRO code to OpenVMS Alpha. Although this process may provide a mechanism for porting code efficiently, it cannot by itself guarantee that the porting effort will be consistent among the engineers who are performing the porting, or will be intelligible to the engineers who will later need to debug and test ported code. To ensure that the porting effort proceeds uniformly and that its effects on source code are well documented, an engineering group should establish coding conventions that are relevant to the goals of the effort.

Naturally, any methodology an engineering group may adopt should be shaped by that group's development environment, including those procedures the group follows for tool management, source code control, common code, and testing. The coding conventions an engineering group should evaluate include:

1.6 Maintaining Common Sources for VAX and Alpha Systems

When designing a VAX MACRO code porting effort, consider the benefits of maintaining common sources for VAX and Alpha systems. It is advantageous to an engineering group to have only one copy of its sources to maintain and enhance, and common sources help ensure common user interfaces. However, if you find that you are conditionalizing so much source code that it is no longer intelligible, take steps to restructure the code into architecture-specific and architecture-independent pieces. If the number of these pieces becomes unmanageable, create separate architecture-specific modules.

1.6.1 Including Compiler Directive Definitions

A successful compilation does not preclude VAX MACRO code in a source file from also processing successfully under the VAX MACRO assembler. If you added any compiler directives to your code, they will be resolved by the library SYS$LIBRARY:STARLET.MLB when the code is assembled. The assembler automatically searches this library for any undefined macros. After finding these definitions, the assembler will ignore occurrences of the compiler directives.

However, if you are using OpenVMS VAX Version 6.0 or earlier, you must first extract the directive definitions from ALPHA$LIBRARY:STARLET.MLB on Alpha and insert them into your SYS$LIBRARY:STARLET.MLB on OpenVMS VAX. For example:


LIB/EXTRACT=.JSB_ENTRY/OUT=JSB_ENTRY.MAR ALPHA$LIBRARY:STARLET.MLB 
. 
. 
. 
LIB/INSERT SYS$LIBRARY:STARLET.MLB JSB_ENTRY.MAR 

Note that many of the definitions of the compiler directives refer to other macros. Make sure to extract not only the definitions of all the compiler directives used in your code but also all the associated macros and insert them into SYS$LIBRARY:STARLET.MLB on your OpenVMS VAX system.

1.6.2 Removing VAX Dependencies

If you must make changes to source files because they contain certain coding practices that cannot be directly compiled into Alpha code, you may still be able to generate images for both VAX and Alpha systems from common VAX MACRO sources.

Removing such VAX dependencies so that the same code can run on both VAX and Alpha systems can yield great benefits during the porting process. You can debug single modules or groups of modules of the ported code by building and testing the modules in the VAX environment. This can greatly speed your debugging process.

In some cases, you must define and implement procedures for conditionalizing the source files (as described in Section 1.6.3) or for providing separate sources for VAX and Alpha systems.

If the code runs in an inner mode, it is unlikely that an effort to generate VAX and Alpha images from common VAX MACRO sources will be fully successful. Because inner-mode code interoperates with the executive, it is vulnerable to the differences between VAX and Alpha system interfaces and executive data structures. However, user-mode code is generally immune from architectural dependencies and may more easily serve as the basis for common code.

1.6.3 Using Architecture-Specific Symbols

Conditionalizing VAX MACRO code requires the use of two ARCH_DEFS.MAR files with architecture-specific symbols, one to be assembled with the VAX MACRO source code on a VAX processor, the other to be compiled with the VAX MACRO source code on an Alpha processor.

If you choose to make code in a common source module conditional on architecture type, include ARCH_DEFS.MAR in your assembly and compilation and use .IF DF,VAX or .IF DF,ALPHA.

An ARCH_DEFS.MAR file is provided with OpenVMS Alpha. You need to create a corresponding file for OpenVMS VAX. The following is an example of such a file:


; This is the VAX version of ARCH_DEFS.MAR, which contains 
; architectural definitions for compiling sources for 
; VAX systems. 
; 
VAX = 1 
VAXPAGE = 1 
ADDRESSBITS = 32 

The Alpha version exists in SYS$LIBRARY and contains definitions for the following symbols:

Warning

Any other symbols in ARCH_DEFS.MAR on OpenVMS Alpha are specific to OpenVMS Alpha source code and are not guaranteed to be included from release to release.


Chapter 2
How to Use the MACRO-32 Compiler

The MACRO-32 Compiler for OpenVMS Alpha has been designed to help you port VAX MACRO source code from OpenVMS VAX to OpenVMS Alpha. When operating on VAX MACRO code that complies with the restrictions and guidelines described in this manual, the compiler produces a valid OpenVMS Alpha object module that preserves the semantics of the original VAX MACRO source and adheres to the OpenVMS calling standard.

This chapter describes the following topics:

As discussed in Chapter 1, the compiler cannot transparently convert all VAX MACRO code. There are many coding practices that cannot be directly compiled into OpenVMS Alpha code. They must be removed or modified to guarantee a successful compilation. The compiler can detect and report many of these coding practices.

2.1 Using Alpha Registers

Alpha computers employ 32 integer registers, R0 through R31. Because code generated by the compiler uses Alpha registers R0 through R12 as if they were VAX registers, VAX MACRO code usage of these registers (for instance, as input to JSB routines) does not have to change to achieve a correct compilation. VAX MACRO instructions (such as MOVL and ADDL) use the lower 32 bits of the Alpha register involved in the operation. The compiler maintains a sign-extended 64-bit form of this value in the register.

Registers R13 and above are also available to VAX MACRO code that will be compiled to OpenVMS Alpha object format. If you decide to use these registers, review the following constraints:

2.2 Routine Calls and Declarations

The OpenVMS Calling Standard specifies very different calling conventions for VAX and Alpha systems.

On a VAX system, there are two different call formats, CALL and JSB, with five different instructions: CALLS, CALLG, JSB, BSBW, and BSBB. CALL instructions create a frame on the stack which contains return information, saved registers, and other routine information. Parameters to CALL instructions are passed in consecutive longword memory locations, either on the stack (CALLS) or elsewhere (CALLG). JSB instructions have the return address stored on the stack. For both call formats, the hardware processing of the calling instruction provides all of these functions.

On an Alpha system, there is only one call format and only one subroutine call instruction, JSR. For routines that expect parameters, the first six parameters are passed in R16 through R21, with the parameter count in R25 and subsequent parameters in quadwords on the stack. The hardware execution of the JSR instruction simply passes control to the subroutine and places the return address in a designated register. It neither allocates stack space, nor creates a call frame, nor provides any parameter manipulations. All of these functions must be done by the calling routine or the called routine.

The compiler must generate code that conforms to the OpenVMS Calling Standard yet emulates the function of the different VAX MACRO instructions. This requires special code both at the calling instruction to manipulate the input parameters and at the entry point of the routine itself to create a stack frame and other context.

The compiler generates code only for source instructions that are part of a declared routine. For the compiler to generate the proper linkage information and proper routine code, you must insert a compiler directive at the entry points in the VAX MACRO source.

2.2.1 Linkage Section

On Alpha systems, all external (out-of-module) references are made through a linkage section. The linkage section is a program section (psect) containing:

A linkage pair is a data structure used when making a call to an external module. The linkage pair contains the address of the callee's procedure descriptor, and the entry point address. The linkage pair resides in the caller's linkage section; therefore, there may be several linkage pairs for a particular routine, one in each caller's linkage section. Linkage pairs are not used for module-local calls, since the compiler can refer to the callee's frame descriptor directly.

A procedure descriptor is a data structure that provides basic information about a routine, such as register and stack usage. Each routine has one unique procedure descriptor, and it is located in its linkage section. The procedure descriptor is normally not accessed at run time. Its primary use is for interpreting the frame in case of exceptions, by the debugger, for example.

For more information about these and other Alpha data structures, see the OpenVMS Calling Standard.

2.2.2 Prologue and Epilogue Code

To mimic the behavior of VAX subroutines, the compiler must generate code at the entry and exit of each routine. This code emulates the functions that are done by the VAX hardware, and is called the prologue and epilogue code.

In the prologue code, the compiler must allocate stack space to save any necessary context. This includes saving any registers that will be preserved by the routine and saving the return address. If this is a CALL routine, it also includes establishing a new stack frame and changing the frame pointer (FP), and may include further manipulation and storage of the input parameters (see Section 2.3).

In the epilogue code, the compiler must restore any necessary registers, stack frame information, and the return address, and trim the stack back to its original position.

2.2.3 When to Declare Entry Points

Any code label that is a possible target of a CALLS, CALLG, JSB, BSBW, or BSBB instruction must be declared as an entry point. In addition, any code label must be declared as an entry point using a .JSB_ENTRY or .JSB32_ENTRY directive if:

The OpenVMS calling standard for Alpha computers does not provide a way to access indeterminate code addresses directly. All such accesses are accomplished using a procedure descriptor to describe the routine and the code address. When a code label address is stored, the compiler does not know if that address will be referenced only by the current module, or whether it may be accessed by another MACRO module or another module written in another language. Whenever a source instruction stores a code address, the MACRO-32 compiler instead stores the procedure descriptor address for that code address so that other code can access it correctly. For a procedure descriptor to exist, the label must be declared as an entry point.

Likewise, when a stored address is used as a branch destination, the compiler does not know where that address came from, so it always assumes that the stored address is the address of a procedure descriptor and uses that descriptor to pass control to the routine.

2.2.4 Directives for Designating Routine Entry Points

Macros in STARLET.MLB generate directives for designating the entry points to routines. (Appendix B describes the format of each of these macros.) When assembled for VAX systems, the macros are null, except for .CALL_ENTRY; when compiled for Alpha systems, the macros expand to verify the arguments and generate the compiler directives. Therefore, you can use the following macros in common source modules:


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5601PRO_001.HTML