Document revision date: 19 July 1999 | |
Previous | Contents | Index |
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.
TSTL (SP)+ ; remove return address RSB ; return to caller's caller |
POPL R0 ; remove the return address SUBL #structure_size,SP ; allocate stack space for caller PUSHL R0 ; replace the return address |
POPL R1 ; hold return address PUSHL structure ; build structure for caller ; ; code continues ; JMP (R1) ; return to caller |
MOVAL routine_label,-(SP) RSB |
PUSHAL routine_label RSB |
MOVL SP,FP SUBL #data_area,SP |
MOVL #fake_psl,-(SP) MOVAL target_label,-(SP) ; all three REI |
MOVPSL -(SP) MOVAL target_label,-(SP) ; force AST delivery only REI |
MOVL #fake_psl,-(SP) BSBW DOREI ; ; code continues ; DOREI: REI |
BRx label+offset |
MOVB #OP$_opcode,(Rx) |
MOVZBL #OP$_opcode,(Rx) |
JMP G^external_routine |
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:
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:
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. |
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:
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:
Since the .ENTRY directive is converted to an Alpha .CALL_ENTRY directive, any registers modified in the routine declared by .ENTRY will be automatically preserved. This is different from VAX MACRO behavior. See Section 2.3.2. |
Previous | Next | Contents | Index |
privacy and legal statement | ||
5601PRO_001.HTML |