|
OpenVMS MACRO-32 Porting and User's Guide
2.12.3.1 Additional Arguments That Are Easy to Locate
You can easily find additional arguments if:
- The argument list is not homed, and $ARGn symbols are
defined to $ARG7 or higher. If the argument list is not homed, the
$ARGn symbols $ARG7 and above always point into the list of
parameters passed as quadwords on the stack. Subsequent arguments will
be in quadwords following the last defined $ARGn symbol.
- The argument list is homed, and you want to examine an argument
that is less than or equal to the maximum number detected by the
compiler (either by automatic detection or as specified by MAX_ARGS).
If the argument list is homed, $ARGn symbols always point into
the homed argument list. Subsequent arguments will be in longwords
following the last defined $ARGn symbol.
For example, you can examine arguments beyond the eighth argument in a
JSB routine (where the argument list must be homed in the caller), as
follows:
DBG> EX $ARG8 ; highest defined $ARGn
.
.
.
DBG> EX .+4 ; next arg is in next longword
.
.
.
DBG> EX .+4 ; and so on
|
This example assumes that the caller detected at least 10 arguments
when homing the argument list.
To find arguments beyond the last $ARGn symbol in a routine
that did not home the arguments, proceed exactly as in the previous
example except substitute EX .+8 for EX .+4.
2.12.3.2 Additional Arguments That Are Not Easy to Locate
You cannot easily find additional arguments if:
- The argument list is not homed, and $ARGn symbols are
defined only as high as $ARG6. In this case, the existing
$ARGn symbols will either point to registers or to quadword
locations in the stack frame. In both cases, subsequent arguments
cannot be examined by looking at quadword locations beyond the defined
$ARGn symbols.
- The argument list is homed, and you want to examine arguments
beyond the number detected by the compiler. The $ARGn symbols
point to the longwords that are stored in the homed argument list. The
compiler only moves as many arguments as it can detect into this list.
Examining longwords beyond the last argument that was homed will result
in examining various other stack context.
The only way to find the additional arguments in these cases is to
examine the compiled machine code to determine where the arguments
reside. Both of these problems are eliminated if MAX_ARGS is specified
correctly for the maximum argument that you want to examine.
2.12.4 Debugging Code with Packed Decimal Data
The following list provides important information about debugging
compiled VAX MACRO code with packed decimal data on an Alpha system:
- When using the EXAMINE command to examine a location that was
declared with a .PACKED directive, the debugger automatically displays
the value as a packed decimal data type.
- You can deposit packed decimal data. The syntax is the same as it
is on VAX.
2.12.5 Debugging Code with Floating-Point Data
The following list provides important information about debugging
compiled VAX MACRO code with floating-point data on an Alpha system:
- You can use the EXAMINE/FLOAT command to examine an Alpha integer
register for a floating-point value.
Even though there is a set of
registers for floating-point operations on Alpha systems, those
registers are not used by compiled VAX MACRO code that contains
floating-point operations. Only the Alpha integer registers are used.
Floating-point operations in compiled VAX MACRO code are performed
by emulation routines that operate outside the compiler. Therefore,
performing VAX MACRO floating-point operations on, say, R7, has no
effect on Alpha floating-point Register 7.
- When using the EXAMINE command to examine a location that was
declared with a .FLOAT directive or other floating-point storage
directives, the debugger automatically displays the value as
floating-point data.
- When using the EXAMINE command to examine the G_FLOAT data type,
the debugger does not use the contents of two registers to build the
value for VAX data.
Consider the following example:
In this example, the lower longwords of R4 and R5 are not used to
build the value as is the case on VAX. Instead, the quadword contents
of R4 are used. The code the compiler generates for D_FLOAT and
G_FLOAT operations preserves the VAX format of the data in the low
longwords of two consecutive registers. Therefore, using
EXAMINE/G_FLOAT on either of these two registers will not give the true
floating-point value, and issuing DEPOSIT/G_FLOAT to one of these
registers will not give the desired results. You can manually combine
the two halves of such a value, however. For example, assume you
executed the following instruction:
You could then read the G_FLOAT value which now resides in R6 and
R7 with a sequence like the following:
DBG> EX R6
.MAIN.\%LINE 100\%R6: 0FFFFFFFF D8E640D1
DBG> EX R7
.MAIN.\%LINE 100\%R7: 00000000 2F1B24DD
DBG> DEP R0 = 2F1B24DDD8E640D1
DBG> EX/G_FLOAT R0
.MAIN.\%LINE 100\%R0: 4568.89900000000
|
- You can deposit floating-point data in an Alpha integer register
with the DEPOSIT command. The syntax is the same as it is on a VAX
system.
- H_FLOAT is unsupported.
Chapter 3 Recommended and Required Source Changes
This chapter describes the coding constructs you should examine when
porting VAX MACRO code to OpenVMS Alpha. The occurrence of any of these
in a module can make porting take longer than it would otherwise.
Although the compiler can identify many of these practices and flag
them with diagnostic messages, recognizing them yourself will speed up
the porting effort.
In most cases, it will be necessary to change your source code. The
exceptions are noted.
The coding constructs described in this chapter are:
3.1 Stack Usage
The OpenVMS calling standard defines a stack frame format for Alpha
systems substantially different from that defined for VAX systems. If
your code relies on the format of the VAX stack frame you will need to
change it when porting it to an Alpha system.
3.1.1 References to the Procedure Stack Frame
The compiler disallows references to positive stack offsets from FP,
and flags them as errors.
A single exception to this rule is the practice whereby VAX MACRO code
establishes a dynamic condition handler by moving a routine address to
the stack location pointed to by FP. The compiler detects this and
generates the appropriate Alpha code for establishing such a handler.
However, if the write to 0(FP) occurs inside a JSB routine, the
compiler will flag it as an error.
The compiler allows negative FP offsets, as used for referring to stack
storage allocated at procedure entry.
Recommended Change
If possible, remove stack frame references entirely, rather than
converting to the Alpha format. For example, if the offending code was
attempting to change saved register values, store the new value in a
stack temporary and set the register value on routine exit (removing
the register from the entry register mask).
3.1.2 References Outside the Current Stack Frame
By monitoring stack depth throughout a VAX MACRO module, the compiler
detects references in a routine to data pushed on the stack by its
caller and flags them as errors.
Recommended Change
You must eliminate references in a routine to data pushed on the stack
by its caller. Instead, pass the required data as parameters or pass a
pointer to the stack base from which the data can be read.
3.1.3 Nonaligned Stack References
At routine calls, the compiler octaword-aligns the stack, if the stack
is not already octaword-aligned. Some code, when building structures on
the stack, makes unaligned stack references or causes the stack pointer
to become unaligned. The compiler flags both of these with
information-level messages.
Recommended Change
Provide sufficient padding in data elements or structures pushed onto
the stack, or change data structure sizes. Because unaligned stack
references also have an impact on VAX performance, you should apply
these fixes to code designed for both the VAX and Alpha architectures.
3.1.4 Building Data Structures on the Stack
A common coding practice is to produce a structure on the stack by
pushing the elements and relying on auto decrement to move the stack
pointer to allocate space. The problems with this technique follow:
- If the SDL source for the structure being built is modified to pad
the structure in order to align fields, the code will be broken. If the
code does not contain assume statements this will not be detected at
compile time.
- If the size of a field is extended, the current instruction will
not access all the data and this will also go undetected.
Recommended Change
To correct the first problem and detect the second, use the coding
technique illustrated in this example. Consider the following code
example:
; Build a descriptor on the stack.
;
MOVW length, -(SP)
MOVB type, -(SP)
MOVB class, -(SP)
MOVAL buffer, -(SP)
|
Replace this code with the following:
SUBL2 DSC$S_DSCDEF, SP ; pre-allocate space on stack
MOVW length, DSC$W_LENGTH(SP)
MOVB type, DSC$B_DTYPE(SP)
MOVB size, DSC$B_CLASS(SP)
MOVAL buffer, DSC$A_POINTER(SP)
|
3.1.5 Quadword Moves Into the VAX SP and PC
Due to architectural differences between VAX and Alpha computers, it is
not possible to completely emulate quadword moves into the VAX stack
pointer (SP) and the program counter (PC) without programmer
intervention. The VAX architecture defines R14 as the SP and R15 as the
PC. A MOVQ instruction with SP as the target would simultaneously load
the VAX SP and PC, as shown in the following example:
MOVQ R0,SP ; Contents of R0 to SP, R1 to PC
MOVQ REGDATA, SP ; REGDATA to SP
; REGDATA+4 to PC
|
If the compiler encounters a MOVQ instruction with SP as the
destination, it generates a sign-extended longword load from the
supplied source into R30 (the Alpha stack pointer) and issues the
following informational message:
%AMAC-I-CODGENINF, (1) Longword update of Alpha SP, PC untouched
|
Recommended Change
If the intended use of the MOVQ instruction was to achieve the VAX
behavior, a MOVL instruction should be used, followed by a branch to
the intended address, as shown next:
MOVL REGDATA, SP ; Load the SP
MOVL REGDATA+4, R0 ; Get the new PC
JMP (R0) ; And Branch
|
If the intended use of the MOVQ instruction was to load the stack
pointer with an 8-byte value, the EVAX_LDQ built-in should be used
instead, as shown next:
3.2 Instruction Stream
The following VAX MACRO coding practices and VAX instructions either do
not work on OpenVMS Alpha or they can produce unexpected results.
3.2.1 Data Embedded in the Instruction Stream
The compiler detects data embedded in the instruction stream, and
reports it as an error.
Data in the instruction stream often takes the form of a JSB
instruction followed by a .LONG. This construct allows VAX MACRO code
to implicitly pass a parameter to a JSB routine which locates the data
by using the return address on the stack. Another occasional use of
data in the code stream is to make the data contiguous with the code in
memory, so that it can be relocated as a unit.
Recommended Change
For implicit JSB parameters, pass the parameter value in a register.
For values larger than a longword, put the data in another program
section (psect) and explicitly pass its address.
Because static data must reside in a separate data psect, any code that
tries to relocate code and data together must be rewritten.
3.2.2 Run-Time Code Generation
The compiler detects branches to stack locations and to static data
areas and flags them as errors.
Recommended Change
You must either remove or modify code that builds instructions for
later execution, branches to stack locations, or branches to static
data areas. If the code is absolutely necessary, you should
conditionalize it for VAX, and generate corresponding, suitable Alpha
code.
3.2.3 Dependencies on Instruction Size
Code that computes branch offsets based on instruction lengths, for
example, must be changed.
Recommended Change
Use a label and standard branch or a CASE instruction for computed
GOTOs.
3.2.4 Incomplete Instructions
Some CASE instructions in OpenVMS VAX code are not followed by offset
tables, but instead depend on psect placement by the linker to complete
the instruction. The compiler will flag the incomplete instruction as
an error.
Recommended Change
Complete the instruction in the module or build a table of addresses in
a data psect, and replace the CASE instruction with code to select a
destination address from the table and branch.
3.2.5 Untranslatable VAX Instructions
Because the compiler cannot translate the following VAX instructions,
it flags them as errors:
- LDPCTX and SVPCTX
- XFC
- ESCD, ESCE, and ESCF
- BUGx
Recommended Change
These instructions usually appear in code that is highly dependent on
the VAX architecture. You will need to rewrite such code to port it to
Alpha systems.
3.2.6 References to Internal Processor Registers
Pay special attention to the following instructions:
Recommended Change
Verify that they reference valid Alpha internal processor registers
(IPRs). If they do not, they will be flagged. For more information
about the Alpha internal processor registers, refer to the
Alpha Architecture Reference Manual.
3.2.7 Use of Z and N Condition Codes with the BICPSW Instruction
The BICPSW instruction is supported, but the Z and N condition codes
cannot be set at the same time. Setting the Z condition code will clear
the N condition code and vice versa.
Recommended Change
If you find that your code sets both condition codes at the same time,
modify the code.
3.2.8 Interlocked Memory Instructions
The Alpha Architecture Reference Manual, Third Edition
describes strict rules for using interlocked memory instructions. In
particular, branches within or into LDxL/STxC
sequences are not allowed. Branches out of interlocked sequences are
valid and need not change. The Alpha 21264 (EV6) processor and all
subsequent Alpha processors are
more stringent than their predecessors in their requirement that these
rules be followed. The Alpha 21264 processor was first supported by
OpenVMS Alpha Version 7.1-2.
The MACRO-32 compiler observes these rules in the code it generates
from MACRO-32 source code. However, the compiler provides
EVAX_LQxL and EVAX_STxC built-ins which enable
programmers to write these instructions directly in source code.
To help ensure that these instructions are used in conformance with the
rules for using interlocked memory instructions, additional checking
was added to the MACRO-32 compiler, starting in Version 3.1 of the
compiler for OpenVMS Alpha Version 7.1-2 and in Version 4.1 for OpenVMS
Alpha Version 7.2.
The compiler reports the following warning messages under the
circumstances described:
BRNDIRLOC, branch directive ignored in locked memory sequence
Explanation: The compiler found a .BRANCH_LIKELY
directive within an LDx_L/STx_C sequence.
User Action: None. The compiler will ignore the
.BRANCH_LIKELY directive and, unless other coding guidelines are
violated, the code will work as written.
BRNTRGLOC, branch target within locked memory sequence in routine
'routine_name'
Explanation: A branch instruction has a target that is
within an LDx_L/STx_C sequence.
User Action: To avoid this warning, rewrite the source
code to avoid branches within or into LDx_L/STx_C sequences. Branches
out of interlocked sequences are valid and are not flagged.
MEMACCLOC, memory access within locked memory sequence in routine
'routine_name'
Explanation: A memory read or write occurs within an
LDx_L/STx_C sequence. This can be either an explicit reference in the
source code, such as "MOVL data, R0", or an implicit reference to
memory. For example, fetching the address of a data label (e.g., "MOVAB
label, R0") is accomplished by a read from the linkage section, the
data area that is used to resolve external references.
User Action: To avoid this warning, move all memory
accesses outside the LDx_L/STx_C sequence.
RETFOLLOC, RET/RSB follows LDx_L instruction
Explanation: The compiler found a RET or RSB
instruction after an LDx_L instruction and before finding an STx_C
instruction. This indicates an ill-formed lock sequence.
User Action: Change the code so that the RET or RSB
instruction does not fall between the LDx_L instruction and the STx_C
instruction.
RTNCALLOC, routine call within locked memory sequence in routine
'routine_name'
Explanation: A routine call occurs within an
LDx_L/STx_C sequence. This can be either an explicit CALL/JSB in the
source code, such as "JSB subroutine", or an implicit call that occurs
as a result of another instruction. For example, some instructions such
as MOVC and EDIV generate calls to run-time libraries.
User Action: To avoid this warning, move the routine
call or the instruction that generates it, as indicated by the
compiler, outside the LDx_L/STx_C sequence.
STCMUSFOL, STx_C instruction must follow LDx_L instruction
Explanation: The compiler found an STx_C instruction
before finding an LDx_L instruction. This indicates an ill-formed lock
sequence.
User Action: Change the code so that the STx_C
instruction follows the LDx_L instruction.
Recommended Change
If the compiler detects any nonconformant use of interlocked memory
instructions, follow the recommended user actions described with these
warning messages.
3.2.9 Use of the MOVPSL Instruction
The MOVPSL instruction fetches the Alpha PS, whose contents differ from
the VAX PSL (processor status longword). For example, the Alpha PS does
not contain the condition code bits. For more information about the
Alpha PS, refer to the Alpha Architecture Reference Manual.
Recommended Change
The MOVSPL instruction is rarely used. If your code contains the MOVPSL
instruction, you will need to rewrite the code to port it to Alpha
systems.
3.3 Flow Control Mechanisms
Certain flow control mechanisms used with VAX MACRO do not produce the
desired results on Alpha systems. Therefore, some changes to your code
are either recommended or required.
Included in this category are several frequently used variations of
modifying the return address on the stack, from within a JSB routine,
to change the flow of control. All must be recoded.
3.3.1 Communication by Condition Codes
The compiler detects a JSB instruction followed immediately by a
conditional branch, or a conditional branch as the first instruction in
a routine, and generates an error message.
Recommended Change
Return a status value or a flag parameter to take the place of implicit
communication by means of condition codes.
For example:
BSBW GET_CHAR
BNEQ ERROR ; Or BEQL, or BLSS or BGTR, etc
|
can be replaced with:
BSBW GET_CHAR
BLBC R0, ERROR ; Or BLBS
|
If you are already using R0, you must push it onto the stack and
restore it later when you have handled the error.
|