VMS Help MACRO, /MIGRATION, Compiler Directives *Conan The Librarian (sorry for the slow response - running on an old VAX) |
The MACRO-32 Compiler for OpenVMS Alpha provides the following specialized directives: o .BRANCH_LIKELY o .BRANCH_UNLIKELY o .CALL_ENTRY o .DEFINE_PAL o .DISABLE o .ENABLE o .EXCEPTION_ENTRY o .GLOBAL_LABEL o .JSB_ENTRY o .JSB32_ENTRY o .LINKAGE_PSECT o .PRESERVE o .SET_REGISTERS o .SYMBOL_ALIGNMENT You can use certain arguments to these directives to indicate register sets. You express a register set by listing the registers, separated by commas, within angle brackets. For example: <R1,R2,R3> If only one register is in the set, no angle brackets are used. For example: R1
1 - .BRANCH LIKELY |
Instructs the compiler that the following branch will likely be taken. Therefore, the compiler generates code that incorporates that assumption. Format .BRANCH_LIKELY There are no parameters for this directive.
1.1 - Example
MOVL (R0),R1 .BRANCH_LIKELY BNEQ 10$ . . . 10$ The compiler will move the code between the BNEQ instruction and label 10$ to the end of the module, and change the BNEQ 10$ to a BEQL to the moved code. It will then continue immediately following the BEQL instruction with generation of the code starting at label 10$. This will eliminate the delay that occurs on Alpha systems for a mispredicted branch.
2 - .BRANCH UNLIKELY |
Instructs the compiler that the following branch will likely not be taken. Therefore, the compiler generates code that incorporates that assumption. Format .BRANCH_UNLIKELY There are no parameters for this directive.
2.1 - Description
The .BRANCH_UNLIKELY directive instructs the compiler that the following conditional branch will likely not be taken. The compiler then generates code that incorporates that assumption. Alpha system hardware predicts that forward conditional branches are not taken. Therefore, if a .BRANCH_UNLIKELY directive precedes a branch that will be in the forward direction, it has no effect. However, if it precedes a branch that would be backward, code is generated to force the branch to be forward, to an out-of-line branch back to the actual branch destination. .BRANCH_UNLIKELY should be used only in cases where the branch is very unlikely, not just less frequent than the fall-through case.
2.2 - Example
MOVL #QUEUE,R0 ;Get queue header 10$: MOVL (R0),R0 ;Get entry from queue BEQL 20$ ;Forward branch assumed unlikely . . ;Process queue entry . TSTL (R0) ;More than one entry (unlikely) .BRANCH_UNLIKELY BNEQ 10$ ;This branch made into forward 20$: ;conditional branch The .BRANCH_UNLIKELY directive is used here because the Alpha hardware would predict a backward branch to 10$ as likely to be taken. The programmer knows it is a rare case, so the directive is used to change the branch to a forward branch, which is predicted not taken.
3 - .CALL ENTRY |
Declares the entry point of a called routine to the compiler. This entry declaration will save and restore the full 64 bits of any registers (except R0 and R1) that are modified by the routine and are not declared as scratch or output. Format .CALL_ENTRY [max_args] [,home_args=TRUE|FALSE] [,quad_args=TRUE|FALSE] [,input] [,output] [,scratch] [,preserve] [,label]
3.1 - Parameters
max_args Maximum number of arguments the called procedure expects. The compiler uses this value as the number of longwords it allocates in the fixed temporary region of the stack frame, if the argument list must be homed. If homing is not necessary, the max_args count is not required. The compiler flags procedure entry points, where max_args has not been specified, that require homed argument lists. Note that, for .CALL_ENTRY routines in which max_args exceeds 14, the compiler uses the received argument count, or max_args, whichever is smaller, when homing the argument list. home_args=TRUE|FALSE Indication to the compiler that the called procedure's argument list should or should not be homed. The home_args argument overrides the compiler's default logicfor determining the circumstances under which an argument list must be homed. quad_args=TRUE|FALSE Indication to the compiler that the called procedure's argument list will have quadword references. input=<> Register set that indicates those registers from which the routine receives input values. This register set informs the compiler that the registers specified have meaningful values at routine entry and are unavailable for use as temporary registers even before the first compiler-detected use of the registers. Specifying registers in this register set affects compiler temporary register usage in two cases: o If you are using the VAXREGS optimization switch. This optimization allows the compiler to use as temporary registers any of the VAX registers which are not explicitly being used by the VAX MACRO code. o If you are explicitly using any of the Alpha registers (R13 and above). In either of these cases, if you do not specify a register that is being used as input in the input argument, the compiler may use the register as a temporary register, corrupting the input value. This register set has no effect on the compiler's default register preservation behavior. If you are not using the VAXREGS optimization switch or any of the Alpha registers, the input mask is used only to document your routine. output=<> Register set that indicates those registers to which the routine assigns values that are returned to the routine's caller. Registers included in this register set are not saved and restored by the compiler, even if they are modified by the routine. This register set also informs the compiler that the registers specified have meaningful values at routine exit and are unavailable for use as temporary registers even after the last compiler-detected use of the registers. Specifying registers in this register set affects compiler temporary register usage in two cases: o If you are using the VAXREGS optimization switch. This optimization allows the compiler to use as temporary registers any of the VAX registers which are not explicitly being used by the VAX MACRO code. o If you are explicitly using any of the Alpha registers (R13 and above). In either of these cases, if you do not specify a register that is being used as output in the output argument, the compiler may use the register as a temporary register, corrupting the output value. scratch=<> Register set that indicates registers that are used within the routine but which should not be saved and restored at routine entry and exit. The caller of the routine does not expect to receive output values nor does it expect the registers to be preserved. Registers included in this register set are not saved and restored by the compiler, even if they are modified by the routine. This also pertains to the compiler's temporary register usage. The compiler may use registers R13 and above as temporary registers if they are unused in the routine source code. Because R13 through R15 must be preserved, if modified, according to the OpenVMS Alpha calling standard, the compiler preserves those registers if it uses them. However, if they appear in the scratch register set declaration, the compiler will not preserve them if it uses them as temporary registers. As a result, these registers may be scratched at routine exit, even if they were not used in the routine source but are in the scratch set. If the VAXREGS optimization is used, this applies to registers R2 through R12, as well. preserve=<> Register set that indicates those registers that should be preserved over the routine call. This should include only those registers that are modified and whose full 64-bit contents should be saved and restored. This register set causes registers to be preserved whether or not they would have been preserved automatically by the compiler. Note that because R0 and R1 are scratch registers, by calling standard definition, the compiler never saves and restores them unless you specify them in this register set. This register set overrides the output and scratch register sets. If you specify a register both in the preserve register set and in the output or scratch register sets, the compiler will report the warning: %AMAC-W-REGDECCON, register declaration conflict in routine A label=name Optionally specify a label as in a VAX MACRO .ENTRY directive. This can be used if a module is to be common between VAX and Alpha, the VAX version needs to reference the entry with a .MASK directive, and the Alpha version needs to use one or more of the special .CALL_ENTRY parameters. When the label parameter is specified and the symbol VAX is defined, an .ENTRY directive is used. If the symbol VAX is not defined, it creates the label and does a normal .CALL_ENTRY. Note that label is not the first parameter. Therefore, you cannot simply replace .ENTRY with .CALL_ENTRY. You must use the label parameter declaration.
4 - .DEFINE PAL |
Defines an arbitrary PALcode function such that it can be called later in the MACRO source. Format .DEFINE_PAL name, pal_opcode, [,operand_descriptor_list]
4.1 - Parameters
name Name of the PALcode function. The compiler applies the prefix EVAX_ to the specified name (for instance, EVAX_MTPR_USP). pal_opcode Opcode value of the PALcode function. Be sure to use angle brackets around the function code when specifying it in hexadecimal format (^X). If you specify the function code in decimal format, angle brackets are not necessary. operand_descriptor_list A list of operand descriptors that specifies the number of operands and the type of each. Up to 6 operand descriptors are allowed in the list. Be careful to specify operands correctly so that the compiler can correctly track register and stack usage. The following table lists the operand descriptors. Access Type Data Type Byte Word Longword Octaword Address AB AW AL AQ Read-only RB RW RL RQ Modify MB MW ML MQ Write-only WB WW WL WQ
4.2 - Description
By default, the compiler defines many OpenVMS Alpha PALcode instructions as built-ins. If you need to use an OpenVMS Alpha PALcode instruction that is not available as a compiler built- in, you must define the built-in yourself using the .DEFINE_PAL directive.
4.3 - Example
.DEFINE_PAL MTPR_USP, <^X23>, RQ NOTE This is an example-the compiler compiles MTPR instructions directly to PAL calls.
5 - .DISABLE |
Disables compiler features over a range of source code. Format .DISABLE argument-list
5.1 - Parameters
argument-list You can use one or more of the symbolic arguments listed in the following table: Option Description DEBUG Excludes local symbol table information in the object file for use with the debugger. FLAGGING Deactivates compiler flagging. GLOBAL Disables the assumption that undefined symbols are external symbols. OVERFLOW Deactivates production of overflow trap code for the following opcodes: ADDx, ADWC, INCx, ADAWI, SUBx, SBWC, DECx, MNEGx, MULx, CVTxy (where x is greater than y, for example CVTLB), AOBxx, ACBL, and SOBxx. QUADWORD Disables support for quadword literal and address expressions. SUPPRESSION Stops the listing of unreferenced symbols in the symbol table. TRACEBACK Stops providing traceback information to the debugger.
6 - .ENABLE |
Enables compiler features over a range of source code. Format .ENABLE argument-list
6.1 - Parameters
argument-list You can use one or more of the symbolic arguments listed in the following table: Option Description DEBUG Includes local symbol table information in the object file for use with the debugger. For this to take effect, you must compile with /DEBUG or /ENABLE=DEBUG. FLAGGING Activates compiler flagging. GLOBAL Assumes undefined symbols are external symbols. OVERFLOW Activates production of overflow trap code for the following opcodes: ADDx, ADWC, INCx, ADAWI, SUBx, SBWC, DECx, MNEGx, MULx, CVTxy (where x is greater than y, for example CVTLB), AOBxx, ACBL, and SOBxx. QUADWORD Provides support for quadword literal and address expressions. SUPPRESSION Provides a listing of unreferenced symbols in the symbol table. TRACEBACK Provides traceback information to the debugger. For this to take effect, you must compile with /DEBUG or /ENABLE=TRACEBACK.
7 - .EXCEPTION ENTRY |
Declares the entry point of an exception service routine to the compiler. Format .EXCEPTION_ENTRY [,stack_base]
7.1 - Parameters
preserve=<> Register set that forces the compiler to save and restore across the routine call the contents of registers. By default, the compiler saves at routine entry and restores at routine exit the full 64-bit contents of any register that is modified by a routine. In the case of an .EXCEPTION_ENTRY routine, exception dispatching saves R2 through R7 on the stack (along with the PC and PSL) and the values of these registers are restored by the REI instruction executed by the routine itself. Other registers, if used, are saved in code generated by the compiler, and all other registers are saved if the routine issues a CALL or JSB instruction. stack_base Register into which the stack pointer (SP) value is moved at routine entry. At exception entry points, exception dispatching pushes onto the stack registers R2 through R7, the PC, and the PSL. Note that the Alpha counterpart for the VAX register known as the PSL is the processor status (PS) register. The value returned to the register specified in the stack_base helps an exception service routine locate the values of these registers. You can use the macro $INTSTKDEF in SYS$LIBRARY:LIB.MLB to define symbols for the area on the stack where R2-R7, the PC, and the PSL are stored. The symbols are: o INTSTK$Q_R2 o INTSTK$Q_R3 o INTSTK$Q_R4 o INTSTK$Q_R5 o INTSTK$Q_R6 o INTSTK$Q_R7 o INTSTK$Q_PC o INTSTK$Q_PS You can then use these symbols in the exception routine, as offsets to the stack_base value. By using the appropriate symbolic offset with the stack_base value, the exception routine can access the saved contents of any of these registers. For example, the exception routine could examine the PSL to see what access mode was in effect when the exception was taken.
7.2 - Description
The .EXCEPTION_ENTRY directive indicates the entry point of an exception service routine. At routine entry, R3 must contain the address of the procedure descriptor. The routine must exit with an REI instruction. You should declare with the .EXCEPTION_ENTRY directive all of the following interrupt service routines: o Interval clock o Interprocessor interrupt o System/processor correctable error o Power failure o System/processor machine abort o Software interrupt
8 - .GLOBAL LABEL |
Declares a global label in a routine that is not an entry point to the routine. Format Label: .GLOBAL_LABEL There are no parameters for this directive.
8.1 - Description
The .GLOBAL_LABEL directive declares a global label within a routine that is not a routine entry point. Unless declared with .GLOBAL_LABEL, global labels in code (specified with "::") are assumed to be entry point labels, which require declaration. If they are not declared, they are flagged as errors. The compiler also allows the address of a global label to be stored (for instance, by means of PUSHAL instruction). (The compiler flags as an error any attempt to store a label that has not been declared as a global label or an entry point.) By using the .GLOBAL_LABEL directive, the user is acknowledging that the stored code address will not be the target of a CALL or JSB instruction. Global labels must appear inside routine boundaries. Labels declared with the .GLOBAL_LABEL directive can be used as the newpc argument in calls to the $UNWIND (Unwind Call Stack) system service because it allows the address of the label to be stored. However, there is no provision in the compiler to automatically adjust the stack pointer at such labels to remove arguments passed on the stack or compensate for stack alignment. If the call stack is unwound back to an alternate PC in the calling routine, the stack may still contain arguments and alignment bytes, and any stack-based references that expect this adjustment to the caller's original stack depth (which happened automatically on VAX) will be incorrect. Code that contains labels declared with this directive that are to be used as alternate PC targets for $UNWIND must be examined carefully to ensure correct behavior, with particular emphasis on any references based on the stack pointer.
9 - .JSB ENTRY |
Declares the entry point of a JSB routine to the compiler. This entry declaration will save and restore the full 64 bits of any registers (except R0 and R1) that are modified by the routine and are not declared as scratch or output. See also .JSB32_ENTRY. Format .JSB_ENTRY [input] [,output] [,scratch] [,preserve]
9.1 - Parameters
input=<> Register set that indicates those registers from which the routine receives input values. This register set informs the compiler that the registers specified have meaningful values at routine entry and are unavailable for use as temporary registers even before the first compiler-detected use of the registers. Specifying registers in this register set affects compiler temporary register usage in two cases: o If you are using the VAXREGS optimization switch. This optimization allows the compiler to use as temporary registers any of the VAX registers which are not explicitly being used by the VAX MACRO code. o If you are explicitly using any of the Alpha registers (R13 and above). In either of these cases, if you do not specify a register that is being used as input in the input argument, the compiler may use the register as a temporary register, corrupting the input value. This register set has no effect on the compiler's default register preservation behavior. If you are not using the VAXREGS optimization switch or any of the Alpha registers, the input mask is used only to document your routine. output=<> Register set that indicates those registers to which the routine assigns values that are returned to the routine's caller. Registers included in this register set are not saved and restored by the compiler, even if they are modified by the routine. This register set also informs the compiler that the registers specified have meaningful values at routine exit and are unavailable for use as temporary registers even after the last compiler-detected use of the registers. Specifying registers in this register set affects compiler temporary register usage in two cases: o If you are using the VAXREGS optimization switch. This optimization allows the compiler to use as temporary registers any of the VAX registers which are not explicitly being used by the VAX MACRO code. o If you are explicitly using any of the Alpha registers (R13 and above). In either of these cases, if you do not specify a register that is being used as output in the output argument, the compiler may use the register as a temporary register, corrupting the output value. scratch=<> Register set that indicates registers that are used within the routine but which should not be saved and restored at routine entry and exit. The caller of the routine does not expect to receive output values nor does it expect the registers to be preserved. Registers included in this register set are not saved and restored by the compiler, even if they are modified by the routine. The compiler may use registers R13 and above as temporary registers if they are unused in the routine source code. Because R13 through R15 must be preserved, if modified, according to the OpenVMS Alpha calling standard, the compiler preserves those registers if it uses them. However, if they appear in the scratch register set declaration, the compiler will not preserve them if it uses them as temporary registers. As a result, these registers may be scratched at routine exit, even if they were not used in the routine source but are in the scratch set. If the VAXREGS optimization is used, this applies to registers R2 through R12, as well. preserve=<> Register set that indicates those registers that should be preserved over the routine call. This should include only those registers that are modified and whose full 64-bit contents should be saved and restored. This register set causes registers to be preserved whether or not they would have been preserved automatically by the compiler. Note that because R0 and R1 are scratch registers, by calling standard definition, the compiler never saves and restores them unless you specify them in this register set. This register set overrides the output and scratch register sets. If you specify a register both in the preserve register set and in the output or scratch register sets, the compiler will report the following warning: %AMAC-W-REGDECCON, register declaration conflict in routine A NOTE For procedures declared with the .JSB_ENTRY directive, the MACRO-32 compiler automatically generates a null frame procedure descriptor. Because no new context is set up by a null frame procedure, a side effect is that there is no guarantee of completely accurate debugger information about such procedures in response to SHOW CALLS and SHOW STACK commands. For example, the line number in the called null procedure (to which a JSB is done) may be reported as the line number in the calling procedure from which the JSB is issued.
10 - .JSB32 ENTRY |
Declares the entry point of a JSB routine to the compiler. This directive does not preserve any VAX register values (R2 through R12) unless the PRESERVE parameter is specified. The routine itself may save and restore registers by pushing them on the stack, but this will not preserve the upper 32 bits of the registers. See also .JSB_ENTRY. WARNING The .JSB32_ENTRY directive can be a great time-saver if you are sure that you can use it. If you use .JSB32_ENTRY in a situation where the upper 32 bits of a register are being used, it may cause very obscure and difficult-to-track bugs by corrupting a 64-bit value that may be several calling levels above the offending routine. .JSB32_ENTRY should never be used in an AST routine, condition handler, or any other code that can be executed asynchronously. Format .JSB32_ENTRY [input] [,output] [,scratch] [,preserve]
10.1 - Parameters
input=<> Register set that indicates those registers from which the routine receives input values. For the .JSB32_ENTRY directive, this register set is used only to document your code. output=<> Register set that indicates those registers to which the routine assigns values that are returned to the routine's caller. For the .JSB32_ENTRY directive, this register set is used only to document your code. scratch=<> Register set that indicates registers that are used within the routine but which should not be saved and restored at routine entry and exit. The caller of the routine does not expect to receive output values nor does it expect the registers to be preserved. The scratch argument also pertains to the compiler's temporary register usage. The compiler may use registers R13 and above as temporary registers if they are unused in the routine source code. Because R13 through R15 must be preserved, if modified, according to the OpenVMS Alpha calling standard, the compiler preserves those registers if it uses them. However, if they appear in the scratch register set declaration, the compiler will not preserve them if it uses them as temporary registers. As a result, these registers may be scratched at routine exit, even if they were not used in the routine source but are in the scratch set. Because R2 through R12 are not preserved by default, their inclusion in the scratch is for documentation purposes only. preserve=<> Register set that indicates those registers that should be preserved over the routine call. This should include only those registers that are modified and whose full 64-bit contents should be saved and restored. This register set causes registers to be preserved by the compiler. By default, no registers are preserved by the .JSB32_ ENTRY directive. This register set overrides the output and scratch register sets. If you specify a register both in the preserve register set and in the output or scratch register sets, the compiler will report the warning: %AMAC-W-REGDECCON, register declaration conflict in routine A
10.2 - Description
The .JSB32_ENTRY directive is an alternative way of declaring a JSB entry point. It is designed to streamline the declaration of VAX MACRO routines that operate within a well-defined, bounded application environment, such as that of a single application or a self-contained subsystem. For any routine declared with the .JSB32_ENTRY directive, the compiler does not automatically save or restore any VAX registers (R2 through R12), therefore leaving the current 32-bit operation untouched. When you use the .JSB32_ ENTRY directive to declare a JSB entry point, you are responsible for declaring and saving registers which must be preserved. If the externally visible entry points of a subsystem can be called from the 64-bit environment, those entry points should not be declared with .JSB32_ENTRY. Instead, .JSB_ENTRY (or .CALL_ ENTRY) should be used so that the full 64-bit register values are saved, if necessary.
11 - .LINKAGE PSECT |
Allows the name of the linkage section psect to be changed. Format .LINKAGE_PSECT program-section-name
11.1 - Parameters
program_section_name Name of the program section. The name can contain up to 31 characters, including any alphanumeric character and the special characters underline (_), dollar sign ($), and period (.).
11.2 - Description
The .LINKAGE_PSECT directive allows you to locate a routine's linkage section by reference to other psects within the routine. This facilitates such operations as locking code within memory and forcing code location. An example of forcing code location is to explicitly place the psect in the image created by the linker, using linker options. This would let you use adjacent psects to find their bounds. You can use the .LINKAGE_PSECT directive multiple times within a single source module to set different linkage sections for different routines. However, note that a routine's linkage section remains the same for the entire routine. The name of the routine's linkage section is the one specified in the last .LINKAGE_PSECT directive before the routine's entry point directive. The compiler reports a fatal error if different linkage sections are specified for routines that share code paths. The .LINKAGE_PSECT directive sets the psect attributes to be the same as the default linkage psect $LINKAGE. The attributes are the same as the normal psect default attributes except the linkage psect is set NOEXE NOWRT. You can change the linkage section psect attributes using the .PSECT directive after declaring the psect with .LINKAGE_PSECT.
11.3 - Example
.LINKAGE_PSECT LINK_001 .PSECT LINK_000 LS_START: .PSECT LINK_002 LS_END: This code allows a program to use LS_START and LS_END in computations to determine the location and size of the linkage section (LINK_001) of the routine.
12 - .PRESERVE |
Directs the compiler to generate special Alpha assembly code for VAX MACRO instructions, within portions of the source module, that rely on VAX guarantees of operation atomicity or granularity. Format .[NO]PRESERVE argument-list
12.1 - Parameters
argument-list One or more of the symbolic arguments listed in the following table: Option Description GRANULARITY Preserves the rules of VAX granularity of writes. Specifying .PRESERVE GRANULARITY causes the compiler to use Alpha Load-locked and Store- conditional instruction sequences in code it generates for VAX instructions that perform byte, word, or unaligned longword writes. ATOMICITY Preserves atomicity of VAX modify operations. Specifying .PRESERVE ATOMICITY causes the compiler to use Load-locked and Store-conditional instruction sequences in code it generates for instructions with modify operands.
12.2 - Description
The .PRESERVE and .NOPRESERVE directives cause the compiler to generate special Alpha assembly code for VAX MACRO instructions, within portions of the source module, that rely on VAX guarantees of operation atomicity or granularity. Use of .PRESERVE or .NOPRESERVE without specifying GRANULARITY or ATOMICITY will affect both options. When preservation of both granularity and atomicity is enabled, and the compiler encounters a VAX coding construct that requires both granularity and atomicity guarantees, it enforces atomicity over granularity. Alternatively, you can use the /PRESERVE and /NOPRESERVE compiler qualifiers to affect the atomicity and granularity in generated code throughout an entire MACRO source module. Atomicity is guaranteed for multiprocessing systems as well as uniprocessing systems when you specify .PRESERVE ATOMICITY. When the .PRESERVE directive is present, you can use the /RETRY_ COUNT qualifier on the command line to control the number of times the compiler-generated code retries a granular or atomic update. WARNING If .PRESERVE ATOMICITY is turned on, any unaligned data references will result in a fatal reserved operand fault. If .PRESERVE GRANULARITY is turned on, unaligned word references to addresses assumed aligned will also cause a fatal reserved operand fault.
12.3 - Example
INCW 1(R0) This instruction, when compiled with .PRESERVE GRANULARITY, retries the insertion of the new word value, if it is interrupted. However, when compiled with .PRESERVE ATOMICITY, it will also refetch the initial value and increment it, if interrupted. If both options are specified, it will do the latter.
13 - .SET REGISTERS |
This directive allows the user to override the compiler's alignment assumptions, and also allows implicit reads/writes of registers to be declared. Format .SET_REGISTERS argument-list
13.1 - Parameters
argument-list One or more of the arguments listed in the following table. For each argument, you can specify one or more registers. Option Description aligned=<> Declares one or more registers to be aligned on longword boundaries. unaligned=<> Declares one or more registers to be unaligned. Because this is an explicit declaration, this unaligned condition will not produce a fault at run time. read=<> Declares one or more registers, which otherwise the compiler could not detect as input registers, to be read. written=<> Declares one or more registers, which otherwise the compiler could not detect as output registers, to be written to.
13.2 - Description
The aligned and unaligned qualifiers to this directive allow the user to override the compiler's alignment assumptions. Using the directive for this purpose in certain cases can produce more efficient code. The read and written qualifiers to this directive allow implicit reads and writes of registers to be declared. They are generally used to declare the register usage of called routines and are useful for documenting your program. With one exception, the .SET_REGISTERS directive remains in effect (ensuring proper alignment processing) until the routine ends, unless you change the value in the register. The exception can occur under certain conditions when a flow path joins the code following a .SET_REGISTERS directive. The following example illustrates such an exception. R2 is declared aligned, and at a subsequent label, 10$, which is before the next write access to the register, a flow path joins the code. R2 will be treated as unaligned following the label, because it is unaligned from the other path. INCL R2 ; R2 is now unaligned . . . BLBC R0, 10$ . . . MOVL R5, R2 .SET_REGISTERS ALIGNED=R2 MOVL R0, 4(R2) 10$: MOVL 4(R2), R3 ; R2 considered unaligned ; due to BLBC branch The .SET_REGISTERS directive and its read and written qualifiers are required on every routine call that passes or returns data in any register from R2 through R12, if you specify the command line qualifier and option /OPTIMIZE=VAXREGS. That is because the compiler allows the use of unused VAX registers as temporary registers when you specify /OPTIMIZE=VAXREGS.
13.3 - Examples
1.DIVLR0,R1 .SET_REGISTERS ALIGNED=R1 MOVL 8(R1), R2 ; Compiler will use aligned load. In this example, the compiler would normally consider R1 unaligned after the division. Any memory references using R1 as a base register (until it is changed again) would use unaligned load/stores. If it is known that the actual value will always be aligned, performance could be improved by adding a .SET_ REGISTERS directive, as shown. 2.MOV1 4(R0), R1 ; Stored memory addresses assumed .SET_REGISTERS UNALIGNED=R1 ; aligned so explicitly set it unaligned MOVL 4(R1), R2 ; to avoid run-time fault. In this example, R1 would be considered longword aligned after the MOVL. If it is actually unaligned, an alignment fault would occur on memory reference that follows at run time. To prevent this, the .SET_REGISTERS directive can be used, as shown. 3..SET_REGISTERS READ=<R3,R4>, WRITTEN=R5 JSB DO_SOMETHING_USEFUL In this example, the read/written attributes are used to explicitly declare register uses which the compiler cannot detect. R3 and R4 are input registers to the JSB target routine, and R5 is an output register. This is particularly useful if the routine containing this JSB does not use these registers itself, or if the SET_REGISTERS directive and JSB are embedded in a macro. When compiled with /FLAG=HINTS, routines which use the macro would then have R3 and R4 listed as possible input registers, even if they are not used in that routine.
14 - .SYMBOL ALIGNMENT |
This directive associates an alignment attribute with a symbol definition for a register offset. You can use this directive when you know the alignment of the base register. This attribute guarantees to the compiler that the base register has the same alignment, which enables the compiler to generate optimal code. Format .SYMBOL_ALIGNMENT argument-list
14.1 - Parameters
argument-list One of the arguments listed in the following table. Option Description long Declares longword alignment for any symbol that you declare after this directive. quad Declares quadword alignment for any symbol that you declare after this directive. none Turns off the alignment specified by the preceding .SYMBOL_ALIGNMENT directive.
14.2 - Description
The .SYMBOL_ALIGNMENT directive is used to associate an alignment attribute with the fields in a structure when you know the base alignment. It is used in pairs. The first .SYMBOL_ALIGNMENT directive associates either longword (long) or quadword (quad) alignment with the symbol or symbols that follow. The second directive, .SYMBOL_ALIGNMENT none, turns it off. Any time a reference is made with a symbol with an alignment attribute, the base register of that reference, in effect, inherits the symbol's alignment. The compiler also resets the base register's alignment to longword for subsequent alignment tracking. This alignment guarantee enables the compiler to produce more efficient code sequences.
14.3 - Example
OFFSET1 = 4 .SYMBOL_ALIGNMENT LONG OFFSET2 = 8 OFFSET3 = 12 .SYMBOL_ALIGNMENT QUAD OFFSET4 = 16 .SYMBOL_ALIGNMENT NONE OFFSET5 = 20 . . . CLR1 OFFSET2(R8) . . . MOVL R2, OFFSET4(R6) For OFFSET1 and OFFSET5, the compiler will use only its tracking information for deciding if Rn in OFFSET1(Rn) is aligned or not. For the other references, the base register will be treated as longword (OFFSET2 and OFFSET3) or quadword (OFFSET4) aligned. After each use of OFFSET2 or OFFSET4, the base register in the reference is reset to longword alignment. In this example, the alignment of R8 and R6 will be reset to longword, although the reference to OFFSET4 will use the stronger quadword alignment.
|