VMS Help  —  MACRO  /MIGRATION
    The MACRO/MIGRATION command invokes the MACRO Compiler for
    OpenVMS Systems to compile one or more VAX MACRO assembly
    language source files into native OpenVMS Alpha object code.

    Format

      MACRO/MIGRATION  filespec[+...]

1  –  Parameters

 filespec[+...]

    Specifies a VAX MACRO assembly language source file to be
    compiled. If you specify more than one file, separate the
    file specifications with plus signs (+).  File specifications
    separated by plus signs are concatenated into one input file and
    produce a single object file and, if indicated, a listing file.

                                   NOTE

       Unlike the VAX assembler, the MACRO compiler does not
       support the creation of separate object files when the
       source files are separated by a comma (,).

    You cannot include a wildcard character in a file specification.
    For each file specification, the compiler command supplies a
    default file type of MAR.

    The compiler creates output files of one version higher than the
    highest version existing in the target directory.

2  –  Description

    The qualifiers to the MACRO/MIGRATION command serve as either
    command (global) qualifiers or positional qualifiers. A command
    qualifier affects all the files specified in the command. A
    positional qualifier affects only the file that it qualifies.
    All MACRO/MIGRATION qualifiers except /LIBRARY are usable as
    either command or positional qualifiers. The /LIBRARY qualifier
    is a positional qualifier only.

    Many of the qualifiers take one or more arguments. If you specify
    only one argument, you can omit the parentheses.

    The compiler supports most of the standard MACRO qualifiers.
    Some of these qualifiers have additional options unique to the
    compiler and some of them are missing one or more VAX MACRO
    options. The compiler also supports several qualifiers unique to
    the compiler. All of these qualifiers are shown in the following
    table:

    Standard MACRO Qualifiers           Unique Qualifiers

    /DEBUG (with additional options)    /FLAG
    /DIAGNOSTICS                        /MACHINE
    /DISABLE (with additional options)  /OPTIMIZE
    /ENABLE (with additional options)   /PRESERVE
    /LIBRARY                            /RETRY_COUNT
    /LIST                               /SYMBOLS
    /OBJECT                             /TIE
    /SHOW                               /UNALIGNED
                                        /WARN

3  –  Qualifiers

3.1    /DEBUG

       /DEBUG=(option[,...])
       /NODEBUG

    Includes or excludes local symbols in the symbol table or
    traceback information in the object module. You can specify one
    or more of the following options:

    Option      Description

    ALL         Makes local symbols and traceback information in
                the object module available to the debugger. This
                qualifier is equivalent to /ENABLE=(DEBUG,TRACEBACK).

    NONE        Makes local symbols and traceback information
                in the object module unavailable to the
                debugger. This qualifier is equivalent to
                /DISABLE=(DEBUG,TRACEBACK).

    SYMBOLS     Makes all local symbols in the object module
                available and all traceback information unavailable
                to the debugger. This qualifier is equivalent to
                /ENABLE=SYMBOLS.

    TRACEBACK   Makes traceback information in the object module
                available and local symbols unavailable to
                the debugger. This qualifier is equivalent to
                /ENABLE=TRACEBACK.

    The default value for /DEBUG is ALL. The /DEBUG
    qualifier overrides /ENABLE=(DEBUG,TRACEBACK) or
    /DISABLE=(DEBUG,TRACEBACK), regardless of their order on the
    command line.

                                   NOTE

       Debugging can be simplified by specifying /NOOPTIMIZE. This
       qualifier prevents the movement of generated code across
       source line boundaries.

    For more information about debugging, see the OpenVMS Debugger
    Manual.

3.2    /DIAGNOSTICS

       /DIAGNOSTICS[=filespec]
       /NODIAGNOSTICS (default)

    Creates a file containing assembler messages and diagnostic
    information. If you omit the file specification, the default file
    name is the same as the source program; the default file type is
    DIA.

    No wildcard characters are allowed in the file specification.

    The diagnostics file is reserved for use with layered products,
    such as the VAX Language-Sensitive Editor (LSE).

3.3    /DISABLE

       /DISABLE=(option[,...])
       /NODISABLE

    Provides initial settings for the compiler functions that can be
    controlled by the .DISABLE and .ENABLE MACRO directives.

    You can specify one or more of the following functions:

    Option      Description

    DEBUG       Excludes local symbol table information in
                the object file for use with the debugger.
                If the /DEBUG qualifier is also specified,
                it overrides /DISABLE=(DEBUG,TRACEBACK) or
                /ENABLE=(DEBUG,TRACEBACK), regardless of their order
                on the command line.

    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 Prevents the listing of unreferenced symbols in the
                symbol table.

    TRACEBACK   Disables the provision of traceback information
                to the debugger. If the /DEBUG qualifier is also
                specified, it overrides /DISABLE=(DEBUG,TRACEBACK) or
                /ENABLE=(DEBUG,TRACEBACK), regardless of their order
                on the command line.

    By default, at compiler activation, FLAGGING, GLOBAL, and
    SUPPRESSION are enabled, and DEBUG, OVERFLOW, QUADWORD, and
    TRACEBACK are disabled.

    The /NODISABLE qualifier has the same effect as omitting the
    /DISABLE qualifier. It can also be used to negate the effects of
    any /DISABLE qualifiers specified earlier in the command line.

                                   NOTE

       If /DISABLE is used two or more times in the command line,
       the last /DISABLE will override all previous uses of
       /DISABLE. The options not specified in the final /DISABLE
       will revert to their default values.

       Furthermore, if /ENABLE and /DISABLE are used in the same
       command line for the same option, /DISABLE will always
       prevail, regardless of its position in the command line.

       Workaround: If you want to disable two or more options,
       specify them in the following way:

       /DISABLE=(xxxx, yyyy)

3.4    /ENABLE

       /ENABLE=(option[,...])
       /NOENABLE

    Provides initial settings for the compiler functions that can be
    controlled by the .DISABLE and .ENABLE MACRO directives.

    You can specify one or more of the following functions:

    Option      Description

    DEBUG       Includes local symbol table information in
                the object file for use with the debugger.
                If the /DEBUG qualifier is also specified,
                it overrides /ENABLE=(DEBUG,TRACEBACK) or
                /DISABLE=(DEBUG,TRACEBACK), regardless of their order
                on the command line.

    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 listing of unreferenced symbols in the
                symbol table.

    TRACEBACK   Provides traceback information to the debugger.
                If the /DEBUG qualifier is also specified,
                it overrides /ENABLE=(DEBUG,TRACEBACK) or
                /DISABLE=(DEBUG,TRACEBACK), regardless of their order
                on the command line.

    By default, at compiler activation, FLAGGING, GLOBAL, TRACEBACK,
    and SUPPRESSION are enabled, and DEBUG, OVERFLOW, and QUADWORD
    are disabled.

    The /NOENABLE qualifier has the same effect as not specifying the
    /ENABLE qualifier. It can also be used to negate the effects of
    any /ENABLE qualifiers specified earlier in the command line.

                                   NOTE

       For every option of the /ENABLE qualifier, if /ENABLE and
       /DISABLE are used in the same command line for the same
       option, /DISABLE will always prevail, regardless of its
       position in the command line.

       You may want to enable an option previously disabled through
       the use of a symbol. For example, you may have incorporated
       the following frequently used options into the DCL symbol
       MAC, as follows:

       MAC::== MACRO/MIGRATION/NOTIE/DISABLE=FLAGGING

       To enable FLAGGING using the symbol MAC, issue the following
       command:

       $ MAC /NODISABLE/ENABLE=FLAGGING

3.5    /FLAG

       /FLAG=(option[,...])
       /NOFLAG

    Specifies which classes of informational messages the compiler
    reports. The options are:

    Option          Description

    ALIGNMENT       Reports unaligned stack and memory references.

    ALL             Enables all options.

    ARGLIST         Reports that the argument list has been homed.

    CODEGEN         Reports run-time code generation, such as self-
                    modifying code.

    DIRECTIVES      Reports unsupported directives.

    HINTS           Reports input/output/auto-preserved register
                    hints.

    INSTRUCTIONS    Reports instructions that use absolute addresses
                    that might compile correctly, but should be
                    examined anyway, because the desired absolute
                    address might be different on the system.

    JUMPS           Reports branches between routines.

    NONE            Disables all options.

    STACK           Reports all messages caused by user stack
                    manipulation.

    At compiler activation, the default is /FLAG=(ALIGNMENT, ARGLIST,
    CODEGEN, DIRECTIVES, INSTRUCTIONS, JUMPS, STACK).

                                   NOTE

       Use of the /NOFLAG and /FLAG qualifiers together to
       activate a specific subset of cross-compiler messages
       does not work as expected. When used together, as in
       /NOFLAG/FLAG=(keyword,keyword), instead of activating only
       the messages specified by the keywords, all cross-compiler
       messages are activated. However, use of /FLAG=(none,keyword)
       activates only those messages specified by the keyword.

    Note that specifying /NOFLAG or /FLAG=NONE does not disable the
    reporting of coding constructs that would prevent a successful
    compilation. The compiler continues to report code that you must
    change, such as an up-level stack reference.

3.6    /LIBRARY

       /LIBRARY
       /NOLIBRARY

    Positional qualifier.

    The associated input file to the /LIBRARY qualifier must be a
    macro library. The default file type is MLB. The /NOLIBRARY
    qualifier has the same effect as not specifying the /LIBRARY
    qualifier, or negates the effects of any /LIBRARY qualifiers
    specified earlier in the command line.

    The compiler can search up to 16 libraries, one of which
    is always STARLET.MLB. This number applies to a particular
    compilation, not necessarily to a particular MACRO command. If
    you enter the MACRO command so that more than one source file is
    compiled, but the source files are compiled separately, you can
    specify up to 16 macro libraries for each separate compilation.
    More than one macro library in a compilation causes the libraries
    to be searched in reverse order of their specification.

    A macro call in a source program causes the compiler to begin the
    following sequence of searches if the macro is undefined:

    1. The libraries specified with the .LIBRARY directive are
       searched first, in reverse order of the order in which they
       were declared.

    2. If the macro definition is not found in any of the libraries
       specified with the .LIBRARY directive, a search of the
       libraries specified in the MACRO command line (in the reverse
       order in which they were specified).

    3. If the macro definition is not found in any of the libraries
       specified in the command line, a search of STARLET.MLB.

3.7    /LIST

       /LIST[=filespec]
       /NOLIST

    Creates or omits an output listing, and optionally provides an
    output file specification for it. The default file type for the
    listing file is LIS. No wildcard characters are allowed in the
    file specification.

    An interactive MACRO command does not produce a listing file
    by default. The /NOLIST qualifier, present either explicitly or
    by default, causes errors to be reported on the current output
    device.

    The /LIST qualifier is the default for a MACRO command in a batch
    job. The /LIST qualifier allows you to control the defaults
    applied to the output file specification by the placement of
    the qualifier in the command line.

3.8    /MACHINE

       /MACHINE
       /NOMACHINE (default)

    Enables machine code listing, if it and the /LIST qualifier are
    both specified in the command line.

3.9    /OBJECT

       /OBJECT[=filespec]
       /NOOBJECT

    Creates or omits an object module. It also defines the file
    specification. By default, the compiler creates an object module
    with the same file name as the first input file. The default file
    type for object files is OBJ. No wildcard characters are allowed
    in the file specification.

    The /OBJECT qualifier controls the defaults applied to the output
    file specification by the placement of the qualifier in the
    command line.

3.10    /OPTIMIZE

       /OPTIMIZE[=(option[,...])]
       /NOOPTIMIZE

    Enables or disables optimization options. All options are enabled
    by default except VAXREGS.

    The options are:

    Option         Description

    [NO]PEEPHOLE   Peephole optimization
    [NO]SCHEDULE   Code scheduling
    [NO]ADDRESSES  Common base address loading
    [NO]REFERENCES Common data referencing
    [NO]VAXREGS    OpenVMS Alpha systems only: Allow the use of VAX
                   registers (R0 through R12) as temporary registers
                   when they appear to be unused
    ALL            All optimizations
    NONE           No optimizations

    Note that, on OpenVMS Alpha systems, /OPTIMIZE=ALL turns on
    VAXREGS, which may generate incorrect code unless all register
    usage of all routines in the module have been correctly declared.

3.11    /PRESERVE

       /PRESERVE[=(option[,...])]
       /NOPRESERVE (default)

    Directs the compiler to generate special OpenVMS Alpha or OpenVMS
    I64 code throughout a module for all VAX MACRO instructions that
    rely on VAX guarantees of operation atomicity or granularity.

    The options are:

    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 or the Itanium
                   compare-exchange (cmpxchg) instruction 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 Alpha Load-locked and Store-
                   conditional instruction sequences or the Itanium
                   compare-exchange (cmpxchg) instruction in code
                   it generates for VAX instructions with modify
                   operands.

    /PRESERVE and /PRESERVE=(GRANULARITY,ATOMICITY) are equivalent.
    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.

    If you are aware of specific sections of VAX MACRO code that
    require VAX granularity and atomicity guarantees, you may not
    need the compiler to enforce these guarantees for the entire
    module. Instead, you can use the .PRESERVE and .NOPRESERVE
    directives to apply the guarantees only to those sections.
    Because the compiler does not need to generate expanded code
    for the entire module, these these directives can help optimize
    the code.

    Atomicity is guaranteed on multiprocessing systems as well as
    uniprocessing systems when you specify /PRESERVE=ATOMICITY.

    When the /PRESERVE qualifier is present, you can control the
    number of times compiler-generated code retries a granular or
    atomic update by specifying the /RETRY_COUNT qualifier.

                                 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.

3.12    /RETRY_COUNT

       /RETRY_COUNT=count

    Specifies to the compiler the number of times the following
    operations should be performed in generated code:

    o  Retries of operations performed in source by a VAX interlocked
       instruction

    o  Retries of atomic or granular updates if the /PRESERVE
       qualifier or .PRESERVE directive is present

    If the /RETRY_COUNT qualifier is not present, the compiler
    generates code that performs an infinite number of retries of
    these operations.

3.13    /SHOW

       /SHOW[=(function[,...])]
       /NOSHOW[=(function[,...])]

    Provides initial settings for the functions controlled by the
    compiler directives .SHOW and .NOSHOW.

    You can specify one or more of the following functions:

    Option        Description

    CONDITIONALS  Lists unsatisfied conditional code associated with
                  .IF and .ENDC MACRO directives.

    CALLS         Lists macro calls and repeat range expansions.

    DEFINITIONS   Lists macro definitions.

    EXPANSIONS    Lists macro expansions.

    BINARY        Lists binary code generated by the expansion of
                  macro calls.

3.14    /SYMBOLS

       /SYMBOLS
       /NOSYMBOLS (default)

    Generates a symbol table and psect synopsis table for the listing
    file if it and the /LIST qualifier are both specified in the
    command line.

3.15    /TIE

       /TIE (default)
       /NOTIE

    Ensures that proper external callouts are generated for
    translated images. Translated images are images that were
    translated with the DECMigrate (also known as VEST) facility.
    The Translated Image Environment (TIE) allows translated images
    to execute as if on an OpenVMS VAX system. Use /NOTIE for better
    performance if you do not make calls to translated images.

3.16    /UNALIGNED

       /UNALIGNED
       /NOUNALIGNED (default)

    Forces the compiler to use unaligned loads and stores for all
    register-based memory references (except those that are FP-based
    or SP-based or are references to local aligned static data).

    By default, the compiler assumes that addresses in registers used
    as base pointers (except those that are FP-based or SP-based)
    are longword-aligned at routine entry, and generates code to load
    BYTE, WORD, and LONG data accordingly. This can result in run-
    time alignment faults, with significant performance impact, if
    the assumption is incorrect. Specifying /UNALIGNED causes the
    compiler to generate code assuming pointers are unaligned. This
    code is significantly larger, but is more efficient than handling
    an alignment fault.

                                   NOTE

       The compiler does not track quadword register alignment.
       For quadword memory references (such as in VAX MOVQ
       instructions), the compiler assumes the base address is
       quadword aligned, unless it has determined the address
       may not be longword-aligned in its register tracking code.
       Quadword references in OpenVMS Alpha and OpenVMS I64 built-
       in uses are always assumed to be quadword aligned. Since
       these must be in new code, the data should be properly
       aligned.

    The /UNALIGNED qualifier is generally appropriate only for
    modules where data is often unaligned, but which are not
    sufficiently performance sensitive to merit the correction of
    the data alignment in the source.

3.17    /WARN

       /WARN=[[option]...]
       /NOWARN

    Turns off all informational level or warning level messages. Both
    are on by default. The options are:

    Option     Description

    INFO       Turns on all informational level messages
    NOINFO     Turns off all informational level messages
    WARN       Turns on all informational and warning level messages
    NOWARN     Turns off all informational and warning level messages

4  –  VAX MACRO Assembler Directives

    The MACRO Compiler for OpenVMS Systems supports most of the
    standard VAX MACRO assembler directives discussed in the VAX
    MACRO and Instruction Set Reference Manual. However, some
    directives that are supported by the VAX MACRO assembler do not
    make sense for compiled code. Consequently, the compiler flags
    them and continues execution. You can disable the flagging of
    these directives by specifying /NOFLAG=DIRECTIVES.

    The directives that you can disable are:

    o  .ENABLE and .DISABLE ABSOLUTE-for forcing absolute addressing
       modes

    o  .ENABLE and .DISABLE TRUNCATION-for enabling floating point
       truncation

    o  .LINK-for specifying linker options in a linker options file

    o  .DEFAULT-for setting displacement lengths

    o  .OPDEF and .REFn-for defining opcodes

    o  Alignment directives (.ALIGN, .EVEN, and .ODD) in code psects

    o  .TRANSFER

    o  .MASK

                                   NOTE

       The length of the argument to a .ASCID directive is limited
       to 996 characters when using the MACRO Compiler for OpenVMS
       Systems. No such restriction exists in the VAX MACRO
       Assembler.

5  –  MACRO Compiler Directives

    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 needed.
    For example:

    R1

5.1  –  .BRANCH LIKELY

    Instructs the compiler that the following branch will likely be
    taken.

    Format

      .BRANCH_LIKELY

    There are no parameters for this directive.

5.1.1  –  Description

    The Alpha hardware predicts that forward conditional branches
    are not taken and that backwards conditional branches are taken.
    Based on the Alpha architecture, those assumptions are built into
    the compiler and influences the code generated for conditional
    branches.

    When .BRANCH_LIKELY precedes a forward conditional branch, the
    compiler will change the conditional branch and reorder the code
    such that the unlikely path will be a forward branch instead of
    the likely branch.

    The Itanium architecture includes branch prediction explicitly on
    each branch instruction. However, the compiler will still reorder
    the code to conform to the assumption that forward branches are
    not taken and backward branches are taken. The compiler will set
    the branch prediction flags as appropriate.

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

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

5.2.1  –  Description

    See the description of the .BRANCH_LIKELY directive for the
    assumptions used by the compiler when predicting branches.

    On OpenVMS Alpha systems, when .BRANCH_UNLIKELY precedes a
    conditional backwards branch, the compiler will change the
    conditional branch and the code such that the branch is a forward
    branch to an unconditional backwards branch. .BRANCH_UNLIKELY
    should only be used in cases where the branch is very unlikely,
    not just less frequent than the fall-through case.

    .BRANCH_UNLIKELY has no effect if it precedes a conditional
    forwards branch.

5.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 (known to be 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.

5.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=number] [,home_args=TRUE|FALSE]

                   [,quad_args=TRUE|FALSE] [,input] [,output]

                   [,scratch] [,preserve] [,label]

5.3.1  –  Parameters

 max_args=number

    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 logic for 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 (OpenVMS Alpha only) optimization
       option. 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 or Itanium
       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 (OpenVMS Alpha only) 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 or Itanium
       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.
    On OpenVMS Alpha systems, 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, on OpenVMS Alpha systems, 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 (OpenVMS Alpha only)
    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. Registers R16 and
    above are not allowed.

    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 OpenVMS
    VAX and OpenVMS Alpha or OpenVMS I64, if the OpenVMS VAX version
    needs to reference the entry with a .MASK directive, and if the
    OpenVMS Alpha or OpenVMS I64 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.

5.4  –  .DEFINE PAL

    OpenVMS Alpha only.

    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]

5.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 six 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

5.4.2  –  Description

    By default, the compiler defines many Alpha PALcode instructions
    as built-ins. If you need to use an Alpha PALcode instruction
    that is not available as a compiler built-in, you must define the
    built-in yourself using the .DEFINE_PAL directive.

5.4.3  –  Example

  .DEFINE_PAL MTPR_USP, <^X23>, RQ

                                   NOTE

       This is an example-the compiler compiles MTPR instructions
       directly to PAL calls.

5.5  –  .DISABLE

    Disables compiler features over a range of source code.

    Format

      .DISABLE  argument-list

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

5.6  –  .ENABLE

    Enables compiler features over a range of source code.

    Format

      .ENABLE  argument-list

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

5.7  –  .EXCEPTION ENTRY

    OpenVMS Alpha only.

    Declares the entry point of an exception service routine to the
    compiler.

    Format

      .EXCEPTION_ENTRY  [preserve] [,stack_base]

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

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

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

5.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, you are 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.

5.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]

5.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 (OpenVMS Alpha only) optimization
       option. 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 or Itanium
       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 (OpenVMS Alpha only) optimization
       option. 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 or Itanium
       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.

    On OpenVMS Alpha systems, 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, on OpenVMS Alpha systems, 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 (OpenVMS Alpha only)
    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 compiler automatically generates a null frame
       procedure descriptor on OpenVMS Alpha.

       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.

5.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]

5.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. On OpenVMS Alpha sytems, 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, on Alpha systems, 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

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

5.11  –  .LINKAGE PSECT

    OpenVMS Alpha only.

    Allows the name of the linkage section psect to be changed.

    Format

      .LINKAGE_PSECT  program-section-name

5.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 (.).

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

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

5.12  –  .PRESERVE

    Directs the compiler to generate special OpenVMS Alpha or OpenVMS
    I64 code throughout a module for all VAX MACRO instructions that
    rely on VAX guarantees of operation atomicity or granularity.

    Format

      .[NO]PRESERVE  argument-list

5.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 or the Itanium
                   compare-exchange (cmpxchg) instruction 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 Alpha Load-locked and Store-
                   conditional instruction sequences or the Itanium
                   compare-exchange (cmpxchg) instruction in code
                   it generates for VAX instructions with modify
                   operands.

5.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, though this is not
    recommended, because the overhead of the extra code where it is
    not needed can slow the program down considerably.

    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.

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

5.13  –  .SET REGISTERS

    This directive allows you to override the compiler's alignment
    assumptions, and also allows implicit reads/writes of registers
    to be declared.

    Format

      .SET_REGISTERS  argument-list

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

5.13.2  –  Description

    The aligned and unaligned qualifiers to this directive allow
    you 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 (OpenVMS Alpha only). That
    is because the compiler allows the use of unused VAX registers as
    temporary registers when you specify /OPTIMIZE=VAXREGS.

5.13.3  –  Examples

    1.DIVL R0,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 un-
      MOVL     4(R1), R2          ;aligned 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.

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

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

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

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

6  –  MACRO Compiler Built-Ins

    On OpenVMS Alpha systems, the compiler provides two sets of
    built-ins:

    o  Alpha instruction built-ins that are used to access Alpha
       instructions for which there are no VAX equivalents.

    o  Alpha PALcode built-ins that are used to emulate the VAX
       instructions for which there are no Alpha equivalents and to
       perform other functions such as quadword queue manipulations.

    Both sets of built-ins are presented in tables. The second column
    of each table specifies the operands the built-in expects, where:

       WL = write longword
       ML = modify longword
       AL = address of longword
       WQ = write quadword
       RQ = read quadword
       MQ = modify quadword
       AQ = address of quadword
       AB = address of byte
       AW = address of word
       WB = write byte
       WW = write word

                                   NOTE

       Be careful when mixing built-ins with VAX MACRO instructions
       on the same registers. The code generated by the compiler
       expects registers to contain 32-bit sign-extended values,
       but it is possible to create 64-bit register values that are
       not in this format. Subsequent longword operations on these
       registers could produce incorrect results.

       Therefore, make sure to return registers to 32-bit sign-
       extended format before using them in VAX MACRO instructions
       as source operands. Note that loading the register with
       a new value using a VAX MACRO instruction (such as MOVL)
       returns it to this format.

6.1  –  Alpha Instruction Built-Ins

    Ported VAX MACRO code sometimes requires access to Alpha
    native instructions to deal directly with a 64-bit quantity
    or to include an Alpha instruction that has no VAX equivalent.
    The compiler provides built-ins to allow you access to these
    instructions.

    The following byte and word built-ins are included in the MACRO
    compiler:

    o  EVAX_LDBU

    o  EVAX_LDWU

    o  EVAX_STB

    o  EVAX_STW

    o  EVAX_SEXTB

    o  EVAX_SEXTW

    You use these built-ins in the same way that you use native VAX
    instructions, using any VAX operand mode. For example, EVAX_
    ADDQ 8(R0),(SP)+,R1 is legal. The only exception is that the
    first operand of any Alpha load/store built-in (EVAX_LD*, EVAX_
    ST*) must be a register.

    On OpenVMS Alpha, the best environment in which to run code
    that contains the byte and word built-ins is on a system that
    implements these instructions in hardware. If you run such code
    on an Alpha system that implements them by software emulation,
    the following limitations exist:

    o  Significant performance loss

       The overhead of handling the exception to trigger the software
       emulation causes a significant performance loss. If software
       emulation is in effect, you will see this message:

       %SYSTEM-I-EMULATED,
        an instruction not implemented on this processor was emulated

    o  Some capabilities not present in the software emulation

       The software emulation is not capable of providing all
       the capabilities that would be present on a system that
       implemented the the instructions in hardware. Code that
       executes in inner access modes and at elevated IPL is allowed
       to use these instructions. For example, activation of the
       software emulator above IPL 2 will not cause a bug check.
       However, certain applications where these instructions
       might be useful, such as direct writes to hardware control
       registers, will be impossible, because such applications
       require the presence of address lines whose function cannot
       be emulated.

    Furthermore, if the code with these built-ins executes on a
    system without either the byte and word software emulator or
    a processor that implements the byte and word instructions in
    hardware, it will incur a fatal exception, such as the following:

    %SYSTEM-F-OPCDEC, opcode reserved to Digital fault at
    PC=00000000000020068,PS=0000001B

                                   NOTE

       Memory references in the MACRO compiler built-ins are always
       assumed to be quadword aligned except in EVAX_SEXTB, EVAX_
       SEXTW, EVAX_LDBU, EVAX_LDWU, EVAX_STB, EVAX_STW, EVAX_LDQU,
       and EVAX_STQU.

    The following table summarizes the Alpha built-ins supported by
    the compiler. The built-ins that are Alpha-only (cannot be used
    to generate or access Itanium instructions) are noted in the
    table.

                                                     Functional on
    Built-in      Operands   Description             OpenVMS I64?

    EVAX_SEXTB    <RQ,WB>    Sign-extend byte        Yes
    EVAX_SEXTW    <RQ,WW>    Sign-extend word        Yes
    EVAX_SEXTL    <RQ,WL>    Sign-extend longword    Yes

    EVAX_LDBU     <WQ,AB>    Load zero-extended      Yes
                             byte from memory
    EVAX_LDWU     <WQ,AQ>    Load zero-extended      Yes
                             word from memory
    EVAX_LDLL     <WL,AL>    Load longword locked    Yes
    EVAX_LDAQ     <WQ,AQ>    Load address of         Yes
                             quadword
    EVAX_LDQ      <WQ,AQ>    Load quadword           Yes
    EVAX_LDQL     <WQ,AQ>    Load quadword locked    Yes
    EVAX_LDQU     <WQ,AQ>    Load unaligned          Yes
                             quadword

    EVAX_STB      <RQ,AB>    Store byte from         Yes
                             register to memory
    EVAX_STW      <RQ,AW>    Store word from         Yes
                             register to memory
    EVAX_STLC     <ML,AL>    Store longword          Yes
                             conditional
    EVAX_STQ      <RQ,AQ>    Store quadword          Yes
    EVAX_STQC     <MQ,AQ>    Store quadword          Yes
                             conditional
    EVAX_STQU     <RQ,AQ>    Store unaligned         Yes
                             quadword

    EVAX_ADDQ     <RQ,RQ,WQ> Quadword add            Yes
    EVAX_SUBQ     <RQ,RQ,WQ> Quadword subtract       Yes
    EVAX_MULQ     <RQ,RQ,WQ> Quadword multiply       Yes
    EVAX_UMULH    <RQ,RQ,WQ> Unsigned quadword       Yes
                             multiply high

    EVAX_AND      <RQ,RQ,WQ> Logical product         Yes
    EVAX_OR       <RQ,RQ,WQ> Logical sum             Yes
    EVAX_XOR      <RQ,RQ,WQ> Logical difference      Yes
    EVAX_BIC      <RQ,RQ,WQ> Bit clear               Yes
    EVAX_ORNOT    <RQ,RQ,WQ> Logical sum with        Yes
                             complement
    EVAX_EQV      <RQ,RQ,WQ> Logical equivalence     Yes
    EVAX_SLL      <RQ,RQ,WQ> Shift left logical      Yes
    EVAX_SRL      <RQ,RQ,WQ> Shift right logical     Yes
    EVAX_SRA      <RQ,RQ,WQ> Shift right             Yes
                             arithmetic

    EVAX_EXTBL    <RQ,RQ,WQ> Extract byte low        Yes
    EVAX_EXTWL    <RQ,RQ,WQ> Extract word low        Yes
    EVAX_EXTLL    <RQ,RQ,WQ> Extract longword low    Yes
    EVAX_EXTQL    <RQ,RQ,WQ> Extract quadword low    Yes
    EVAX_EXTBH    <RQ,RQ,WQ> Extract byte high       Yes
    EVAX_EXTWH    <RQ,RQ,WQ> Extract word high       Yes
    EVAX_EXTLH    <RQ,RQ,WQ> Extract longword high   Yes
    EVAX_EXTQH    <RQ,RQ,WQ> Extract quadword high   Yes

    EVAX_INSBL    <RQ,RQ,WQ> Insert byte low         Yes
    EVAX_INSWL    <RQ,RQ,WQ> Insert word low         Yes
    EVAX_INSLL    <RQ,RQ,WQ> Insert longword low     Yes
    EVAX_INSQL    <RQ,RQ,WQ> Insert quadword low     Yes
    EVAX_INSBH    <RQ,RQ,WQ> Insert byte high        Yes
    EVAX_INSWH    <RQ,RQ,WQ> Insert word high        Yes
    EVAX_INSLH    <RQ,RQ,WQ> Insert longword high    Yes
    EVAX_INSQH    <RQ,RQ,WQ> Insert quadword high    Yes

    EVAX_TRAPB    <>         Trap barrier            No
    EVAX_MB       <>         Memory barrier          Yes
    EVAX_RPCC     <WQ>       Read process cycle      No
                             counter

    EVAX_CMPEQ    <RQ,RQ,WQ> Integer signed          Yes
                             compare, equal
    EVAX_CMPLT    <RQ,RQ,WQ> Integer signed          Yes
                             compare, less than
    EVAX_CMPLE    <RQ,RQ,WQ> Integer signed          Yes
                             compare, less equal
    EVAX_CMPULT   <RQ,RQ,WQ> Integer unsigned        Yes
                             compare, less than
    EVAX_CMPULE   <RQ,RQ,WQ> Integer unsigned        Yes
                             compare, less equal

    EVAX_BEQ      <RQ,AQ>    Branch equal            Yes
    EVAX_BLT      <RQ,AQ>    Branch less than        Yes
    EVAX_BNE      <RQ,AQ>    Branch not equal        Yes

    EVAX_CMOVEQ   <RQ,RQ,WQ> Conditional             Yes
                             move/equal
    EVAX_CMOVNE   <RQ,RQ,WQ> Conditional move/not    Yes
                             equal
    EVAX_CMOVLT   <RQ,RQ,WQ> Conditional move/less   Yes
                             than
    EVAX_CMOVLE   <RQ,RQ,WQ> Conditional move/less   Yes
                             or equal
    EVAX_CMOVGT   <RQ,RQ,WQ> Conditional             Yes
                             move/greater than
    EVAX_CMOVGE   <RQ,RQ,WQ> Conditional             Yes
                             move/greater or equal
    EVAX_CMOVLBC  <RQ,RQ,WQ> Conditional move/low    Yes
                             bit clear
    EVAX_CMOVLBS  <RQ,RQ,WQ> Conditional move/low    Yes
                             bit set

    EVAX_MF_FPCR  <WQ>       Move from floating-     No
                             point control
                             register
    EVAX_MT_FPCR  <WQ,RQ>    Move to floating-       No
                             point control
                             register
    EVAX_ZAP      <RQ,RQ,WQ> Zero bytes              Yes
    EVAX_ZAPNOT   <RQ,RQ,WQ> Zero bytes with NOT     Yes
                             mask

6.2  –  Alpha PALcode Built-Ins

    Alpha PALcode built-ins, primarily for privileged code, are used
    in the same way that Alpha instruction built-ins are used with
    two exceptions:

    o  For the queue PAL functions, the compiler does not move the
       input arguments to the Alpha registers before issuing the PAL
       call as it does for all other functions. Therefore, you must
       supply the code to do that.

    o  When using a built-in for a PAL call that returns a value, the
       source code must explicitly read R0 for the return value.

    Certain Alpha PALcode built-ins, EVAX_INSQHIQR, EVAX_INSQTIQR,
    EVAX_REMQHIQR, and EVAX_REMQHITR, support the manipulation of
    quadword queues, a function that VAX MACRO does not support. If
    you use these built-ins, you must supply the code to move the
    input arguments to R16 (and R17, for EVAX_INSQxxxx), as shown in
    the following example:

    MOVAB  Q_header, R16  ; Set up address of queue header for PAL call
    EVAX_REMQHIQR         ; Remove quadword queue entry
    EVAX_STQ  R0, entry   ; Save entry address returned in R0

    The Alpha PALcode built-ins are listed in the following table.

                                   NOTE

       You can use the .DEFINE_PAL compiler directive to custom-
       define a built-in for an Alpha PALcode operation that is not
       listed in this table.

    Built-in         Operands  Description

    EVAX_CFLUSH      <RQ>      Cache flush
    EVAX_DRAINA      <>        Drain aborts
    EVAX_LDQP        <AQ>      Load quadword physical
    EVAX_STQP        <AQ,RQ>   Store quadword physical
    EVAX_SWPCTX      <AQ>      Swap privileged context
    EVAX_BUGCHK      <RQ>      Bugcheck
    EVAX_CHMS        <>        Change mode supervisor
    EVAX_CHMU        <>        Change mode user
    EVAX_IMB         <>        Instruction memory barrier
    EVAX_SWASTEN     <RQ>      Swap AST enable
    EVAX_WR_PS_SW    <RQ>      Write processor status software field

    EVAX_MTPR_ASTEN  <RQ>      Move to processor register ASTEN
    EVAX_MTPR_ASTSR  <RQ>      Move to processor register ASTSR
    EVAX_MTPR_AT     <RQ>      Move to processor register AT
    EVAX_MTPR_FEN    <RQ>      Move to processor register FEN
    EVAX_MTPR_IPIR   <RQ>      Move to processor register IPIR
    EVAX_MTPR_IPL    <RQ>      Move to processor register IPL
    EVAX_MTPR_PRBR   <RQ>      Move to processor register PRBR
    EVAX_MTPR_SCBB   <RQ>      Move to processor register SCBB
    EVAX_MTPR_SIRR   <RQ>      Move to processor register SIRR
    EVAX_MTPR_TBIA   <>        Move to processor register TBIA
    EVAX_MTPR_TBIAP  <>        Move to processor register TBIAP
    EVAX_MTPR_TBIS   <AQ>      Move to processor register TBIS
    EVAX_MTPR_TBISD  <AQ>      Move to processor register, TB
                               invalidate single DATA
    EVAX_MTPR_TBISI  <AQ>      Move to processor register, TB
                               invalidate single ISTREAM
    EVAX_MTPR_ESP    <AQ>      Move to processor register ESP
    EVAX_MTPR_SSP    <AQ>      Move to processor register SSP
    EVAX_MTPR_USP    <AQ>      Move to processor register USP

    EVAX_MFPR_ASN    <>        Move from processor register ASN
    EVAX_MFPR_AT     <>        Move from processor register AT
    EVAX_MFPR_FEN    <>        Move from processor register FEN
    EVAX_MFPR_IPL    <>        Move from processor register IPL
    EVAX_MFPR_MCES   <>        Move from processor register MCES
    EVAX_MFPR_PCBB   <>        Move from processor register PCBB
    EVAX_MFPR_PRBR   <>        Move from processor register PRBR
    EVAX_MFPR_PTBR   <>        Move from processor register PTBR
    EVAX_MFPR_SCBB   <>        Move from processor register SCBB
    EVAX_MFPR_SISR   <>        Move from processor register SISR
    EVAX_MFPR_TBCHK  <AQ>      Move from processor register TBCHK
    EVAX_MFPR_ESP    <>        Move from processor register ESP
    EVAX_MFPR_SSP    <>        Move from processor register SSP
    EVAX_MFPR_USP    <>        Move from processor register USP
    EVAX_MFPR_WHAMI  <>        Move from processor register WHAMI

    EVAX_INSQHILR    <>        Insert entry into longword queue at
                               head interlocked-resident
    EVAX_INSQTILR    <>        Insert entry into longword queue at
                               tail interlocked-resident
    EVAX_INSQHIQR    <>        Insert entry into quadword queue at
                               head interlocked-resident
    EVAX_INSQTIQR    <>        Insert entry into quadword queue at
                               tail interlocked-resident
    EVAX_REMQHILR    <>        Remove entry from longword queue at
                               head interlocked-resident
    EVAX_REMQTILR    <>        Remove entry from longword queue at
                               tail interlocked-resident
    EVAX_REMQHIQR    <>        Remove entry from quadword queue at
                               head interlocked-resident
    EVAX_REMQTIQR    <>        Remove entry from quadword queue at
                               tail interlocked-resident

    EVAX_GENTRAP     <>        Generate trap exception

    EVAX_READ_UNQ    <>        Read unique context
    EVAX_WRITE_UNQ   <RQ>      Write unique context

7  –  Macros for Porting from VAX to Alpha or I64

    The following macros facilitate the porting of VAX MACRO code to
    an OpenVMS Alpha or OpenVMS I64 system. The macros are grouped
    according to their function.

7.1  –  Calculating Page-Size Values

    The following macros provide a standard, architecture-independent
    means for calculating page-size dependent values:

    o  $BYTES_TO_PAGES

    o  $NEXT_PAGE

    o  $PAGES_TO_BYTES

    o  $PREVIOUS_PAGE

    o  $ROUND_RETADR

    o  $START_OF_PAGE

    These macros reside in the directory SYS$LIBRARY:STARLET.MLB and
    can be used by both application code and system code. Because
    application code does not have access to SYSTEM_DATA_CELLS, you
    must supply the relevant masks, shift values, and so on.

    The shift values are correlated with the page size of the
    processor. The rightshift values are negative; the leftshift
    values are positive, as shown in Shift Values.

    Table D-1 Shift Values

    Page size                 rightshift leftshift

    512 bytes (VAX)            -9         9
    8K (OpenVMS Alpha or      -13        13
    OpenVMS I64)
    16K                       -14        14
    32K                       -15        15
    64K                       -16        16

    Typically, the application issues a call to $GETSYI (specifying
    the SYI$_PAGESIZE item descriptor) to obtain the CPU-specific
    page size and then compute other values from the page size that
    is returned.

    The following conventions apply to the macros described in this
    section:

    o  If the destination operand is blank, the source operand is
       used as the destination.

    o  All macros conditionalize code on the symbols VAXPAGE and
       BIGPAGE.

    o  Several macros allow for page-size-independent code on VAX
       systems with the independent=YES argument. These macros
       generate code in which I-stream fetches are changed to memory
       accesses. Because this is inherently slower on a VAX system,
       the default value of the independent argument is NO.

7.1.1  –  $BYTES TO PAGES

    Converts a byte count to a page count.

    Format

      $BYTES_TO_PAGES  source_bytcnt, dest_pagcnt, rightshift,

                       roundup=YES, quad=YES

7.1.1.1  –  Parameters

 source_bytcnt

    Source byte count.

 dest_pagcnt

    Destination of page count.

 rightshift

    Location of application-provided value to shift (in place of
    multiply). This value is a function of the page size, as shown in
    the table on shift values.

 roundup=YES

    If YES, page-size-1 is added to byte count before shifting;
    if NO, page count is truncated. Any other value is treated as
    the user-specified address of the page-size-1 value. Note that
    roundup=YES is incompatible with the presence of the rightshift
    argument; invoking the macro with both these arguments generates
    a compile-time warning.

 quad=YES

    If YES, the conversion supports 64-bit addressing. If NO, the
    conversion does not support 64-bit addressing.

7.1.2  –  $NEXT PAGE

    Computes the virtual address of the first byte in the next page.

    Format

      $NEXT_PAGE  source_va, dest_va, clearbwp=NO,

                  user_pagesize_addr, user_mask_addr, quad=YES

7.1.2.1  –  Parameters

 source_va

    Source virtual address.

 dest_va

    Destination of virtual address within next page.

 clearbwp=NO

    If YES, masks the byte-within-page portion of the source virtual
    address. The clearbwp=NO option is a performance enhancement,
    avoiding unnecessary instructions if you know you are starting
    on a page boundary or you are intending to divide by page-size
    anyway.

 user_pagesize_addr

    Location of the page-size value (returned by a call to the
    $GETSYI system service specifying the SYI$_PAGESIZE item
    descriptor) in the application data area. If this argument is
    blank, the macro uses MMG$GL_PAGESIZE (bigpage) or MMG$C_VAX_
    PAGE_SIZE (vaxpage).

 user_mask_addr

    Location of the application-provided byte-within-page mask. If
    this argument is blank, the macro uses MMG$GL_BWP_MASK if user_
    pagesize_addr is also blank. Otherwise, it subtracts 1 from the
    contents of the user_pagesize_addr and uses that value.

 quad=YES

    If YES, the conversion supports 64-bit addressing. If NO, the
    conversion does not support 64-bit addressing.

7.1.3  –  $PAGES TO BYTES

    Converts a page count to a byte count.

    Format

      $PAGES_TO_BYTES  source_pagcnt, dest_bytcnt, leftshift,

                       quad=YES

7.1.3.1  –  Parameters

 source_pagcnt

    Source page count.

 dest_bytcnt

    Destination of byte count.

 leftshift

    Location of application-provided value to shift (in place of
    multiply). This value is a function of the page size, as shown in
    the table on shift values.

 quad=YES

    If YES, the conversion supports 64-bit addressing. If NO, the
    conversion does not support 64-bit addressing.

7.1.4  –  $PREVIOUS PAGE

    Computes the virtual address of the first byte in the previous
    page.

    Format

      $PREVIOUS_PAGE  source_va, dest_va, clearbwp=NO,

                      user_pagesize_addr, user_mask_addr,

                      quad=YES

7.1.4.1  –  Parameters

 source_va

    Source virtual address.

 dest_va

    Destination of virtual address within previous page.

 clearbwp=NO

    If YES, masks the byte-within-page portion of the source virtual
    address. The clearbwp=NO option is a performance enhancement,
    avoiding unnecessary instructions if you know you are starting
    on a page boundary or you are intending to divide by page-size
    anyway.

 user_pagesize_addr

    Location of the page-size value (returned by a call to the
    $GETSYI system service specifying the SYI$_PAGESIZE item
    descriptor) in the application data area. If this argument is
    blank, the macro uses MMG$GL_PAGESIZE (bigpage) or MMG$C_VAX_
    PAGE_SIZE (vaxpage).

 user_mask_addr

    Location of the application-provided byte-within-page mask. If
    this argument is blank, the macro uses MMG$GL_BWP_MASK if user_
    pagesize_addr is also blank. Otherwise, it subtracts 1 from the
    contents of the user_pagesize_addr and uses that value.

 quad=YES

    If YES, the conversion supports 64-bit addressing. If NO, the
    conversion does not support 64-bit addressing.

7.1.5  –  $ROUND RETADR

    Rounds the range implied by the virtual addresses in a retadr
    array returned from a memory management system service to a range
    that is the factor of CPU-specific pages. The return value can be
    supplied as an inadr array in a subsequent call to another memory
    management system service.

    Format

      $ROUND_RETADR  retadr, full_range, user_mask_addr,

                     direction=ASCENDING

7.1.5.1  –  Parameters

 retadr

    Address of array of two 32-bit addresses, typically returned from
    $CRMPSC or a similar service. This value can be in the form of
    either "label" or "(Rx)".

 full_range

    Output array of two longwords. FULL_RANGE[0] is retadr[0]
    rounded down to a CPU-specific page boundary, and FULL_RANGE[1]
    is retadr[1] rounded up to one less than a CPU-specific page
    boundary (that is, to the last byte in the page).

 user_mask_addr

    Location of application-provided byte-within-page mask. If this
    argument is blank, the macro uses MMG$GL_BWP_MASK on an OpenVMS
    Alpha or OpenVMS I64 system and VA$M_BYTE on an OpenVMS VAX
    system.

 direction=ASCENDING

    Direction of rounding. The keywords are defined in the following
    table:

    ASCENDING          retadr[0] < retadr[1]
    DESCENDING         retadr[1] < retadr[0]
    UNKNOWN            Values are compared at run time, then proper
                       rounding is performed

7.1.6  –  $START OF PAGE

    Converts a virtual address to the address of the first byte
    within that page.

    Format

      $START_OF_PAGE  source_va, dest_va, user_mask_addr, quad=YES

7.1.6.1  –  Parameters

 source_va

    Source virtual address.

 dest_va

    Destination of virtual address of first byte within page.

 user_mask_addr

    Location of application-provided byte-within-page mask. If this
    argument is blank, the macro uses MMG$GL_BWP_MASK on an OpenVMS
    Alpha or OpenVMS I64 system and MMG$C_VAX_PAGE_SIZE - 1 (defined
    in $pagedef) on an OpenVMS VAX system.

 quad=YES

    If YES, the conversion supports 64-bit addressing. If NO, the
    conversion does not support 64-bit addressing.

7.2  –  Saving and Restoring 64-Bit Registers

    Frequently, VAX MACRO source code must save and restore register
    values, because that is part of the defined interface or because
    the code requires work registers.

    On OpenVMS VAX, code can invoke any number of macros to do
    this. On OpenVMS Alpha and OpenVMS I64, you cannot simply
    replace these macros with 64-bit pushes and pops to and from
    the stack, because there is no guarantee that the macro caller
    has a quadword-aligned stack. Instead, you should replace such
    macro invocations with $PUSH64 and $POP64 macros. These macros,
    located in STARLET.MLB, preserve all 64 bits of a register but
    use longword references to do so.

7.2.1  –  $POP64

    Pops the 64-bit value on the top of the stack into a register.

    Format

      $POP64  reg

7.2.1.1  –  Parameters

 reg

    Register into which the macro places the 64-bit value from the
    top of the stack.

7.2.1.2  –  Description

    $POP64 takes the 64-bit value at the top of the stack and places
    it in a register using longword instructions. This is to avoid
    using quadword instructions when an alignment fault should be
    avoided, but restoring all 64 bits is necessary.

7.2.2  –  $PUSH64

    Pushes the contents of a 64-bit register onto the stack.

    Format

      $PUSH64  reg

7.2.2.1  –  Parameters

 reg

    Register to be pushed onto the stack.

7.2.2.2  –  Description

    $PUSH64 takes a 64-bit register and puts it on the stack
    using longword instructions. This is to avoid using quadword
    instructions when an alignment fault should be avoided, but
    saving all 64 bits is necessary.

7.3  –  Locking Pages into a Working Set

    Five macros are provided for locking pages into a working set.
    These macros reside in SYS$LIBRARY:LIB.MLB. For a description
    of how to use these macros, see the HP OpenVMS MACRO Compiler
    Porting and User's Guide.

    Three macros are used for image initialization-time lockdown, and
    two macros are used for on-the-fly lockdown.

                                   NOTE

       If the code is being locked because the IPL will be raised
       above 2, where page faults cannot occur, make sure that
       the delimited code does not call run-time library or other
       procedures. The VAX MACRO compiler generates calls to
       routines to emulate certain VAX instructions. An image that
       uses these macros must link against the system base image so
       that references to these routines are resolved by code in a
       nonpageable executive image.

7.3.1  –  $LOCK PAGE INIT

    Required in the initialization routines of an image that is using
    $LOCKED_PAGE_START and $LOCKED_PAGE_END to delineate areas to be
    locked at initialization time.

    Format

      $LOCK_PAGE_INIT  [error]

7.3.1.1  –  Parameters

 [error]

    Address to which to branch if one of the $LKWSET calls fail. If
    this address is reached, R0 reflects the status of the failed
    call, and R1 contains 0 if the call to lock the code failed, or 1
    if that call succeeded but the call to lock the linkage section
    failed.

7.3.1.2  –  Description

    $LOCK_PAGE_INIT creates the necessary psects and issues the
    $LWKSET calls to lock into the working set the code and linkage
    sections that were declared by $LOCKED_PAGE_START and $LOCKED_
    PAGE_END. R0 and R1 are destroyed by this macro.

    The psects locked by this macro are $LOCK_PAGE_2 and $LOCK_
    LINKAGE_2. If code sections in other modules, written in other
    languages, use these psects, they will be locked by an invocation
    of this macro in a VAX MACRO module.

7.3.2  –  $LOCKED PAGE END

    Marks the end of a section of code that may be locked at image
    initialization time by the $LOCK_PAGE_INIT macro.

    Format

      $LOCKED_PAGE_END  [link_sect]

7.3.2.1  –  Parameters

 [link_sect]

    Psect to return to if the linkage psect in effect when the
    $LOCKED_PAGE_START macro was executed was not the default linkage
    psect, $LINKAGE.

7.3.2.2  –  Description

    $LOCKED_PAGE_END is used with $LOCKED_PAGE_START to delineate
    code that may be locked at image initialization time by the
    $LOCK_PAGE_INIT macro. The code delineated by these macros must
    contain complete routines-execution cannot fall through either
    macro, nor can you branch into or out of the locked code. Any
    attempt to branch into or out of the locked code section or to
    fall through the macros will be flagged by the compiler with an
    error.

7.3.3  –  $LOCKED PAGE START

    Marks the start of a section of code that may be locked at image
    initialization time by the $LOCK_PAGE_INIT macro.

    Format

      $LOCKED_PAGE_START

    There are no parameters for this macro.

7.3.3.1  –  Description

    $LOCKED_PAGE_START is used with $LOCKED_PAGE_END to delineate
    code that may be locked at image initialization time by the
    $LOCK_PAGE_INIT macro. The code delineated by these macros must
    contain complete routines-execution may not fall through either
    macro, nor may the locked code be branched into or out of. Any
    attempt to branch into or out of the locked code section or to
    fall through the macros will be flagged by the compiler with an
    error.

7.3.4  –  $LOCK PAGE

    Marks the beginning of a section of code to be locked on-the-fly.

    Format

      $LOCK_PAGE  [error]

7.3.4.1  –  Parameters

 [error]

    Address to branch to if one of the $LKWSET calls fail.

7.3.4.2  –  Description

    This macro is placed inline in executable code and must be
    followed by the $UNLOCK_PAGE macro. The $LOCK_PAGE/$UNLOCK_PAGE
    macro pair creates a separate routine in a separate psect. $LOCK_
    PAGE locks the pages and linkage section of this separate routine
    into the working set and JSRs to it. All code between this macro
    and the matching $UNLOCK_PAGE macro is included in the locked
    routine and is locked down.

    All registers are preserved by this macro unless the error
    address parameter is present and one of the calls fail. If that
    happens, R0 reflects the status of the failed call. R1 then
    contains 0 if the call to lock the code failed or 1 if that call
    succeeded but the call to lock the linkage section failed.

    If the ERROR parameter is used, the ERROR label must be placed
    outside the scope of the $LOCK_PAGE and $UNLOCK_PAGE pair. This
    is because the error routine is branched to before calling the
    subroutine that the $LOCK_PAGE and $UNLOCK_PAGE routines create.

    Note that since the locked code is made into a separate routine,
    any references to local stack storage within the routine will
    have to be changed, as the stack context is no longer the same.
    Also, you cannot branch into or out of the locked code from the
    rest of the routine.

7.3.5  –  $UNLOCK PAGE

    Marks the end of a section of code to be locked on-the-fly.

    Format

      $UNLOCK_PAGE  [error][,LINK_SECT]

7.3.5.1  –  Parameters

 [error]

    An error address to which to branch if one of the $ULKWSET calls
    fail.

 [link_sect]

    Linkage psect to return to if the linkage psect in effect when
    the $LOCK_PAGE macro was executed was not the default linkage
    psect, $LINKAGE.

7.3.5.2  –  Description

    $UNLOCK_PAGE returns from the locked routine created by the
    $LOCK_PAGE and $UNLOCK_PAGE macro pair and then unlocks the pages
    and linkage section from the working set. This macro is placed
    inline in executable code after a $LOCK_PAGE macro.

    All registers are preserved by this macro unless the error
    address parameter is present and one of the calls fail. If that
    happens, R0 reflects the status of the failed call. R1 then
    contains 0 if the call to unlock the code failed or 1 if that
    call succeeded but the call to unlock the linkage section failed.

    If the error parameter is used, the error label must be placed
    outside the scope of the $LOCK_PAGE and $UNLOCK_PAGE pair. This
    is because the error routine is branched to after returning
    from the subroutine created by the $LOCK_PAGE and $UNLOCK_PAGE
    routines.

8  –  Macros for 64-Bit Addressing

    These macros reside in the directory SYS$LIBRARY:STARLET.MLB and
    can be used by both application code and system code.

    The page macros accommodate for 64-bit addresses. The support is
    provided by the QUAD=NO/YES parameter.

    You can use certain arguments to these macros 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.

8.1  –  $SETUP CALL64

    Initializes the call sequence.

    Format

      $SETUP_CALL64  arg_count, inline=true | false

8.1.1  –  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 on
    OpenVMS Alpha, or eight or fewer on OpenVMS I64, the default
    is inline=false.

8.1.2  –  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 on OpenVMS Alpha, or eight or
    fewer on OpenVMS I64, the code is always in line.

    By default, if there are more than six arguments on OpenVMS
    Alpha or eight arguments on OpenVMS I64, 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 on OpenVMS Alpha or eight
    arguments on OpenVMS I64, 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
    (on Alpha only) 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.

8.2  –  $PUSH ARG64

    Does the equivalent of argument pushes for a call.

    Format

      $PUSH_ARG64  argument

8.2.1  –  Parameters

 argument

    The argument to be pushed.

8.2.2  –  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 on OpenVMS Alpha or
    eight arguments on OpenVMS I64, this macro checks for SP or AP
    references in the argument.

    If the call contains more than six arguments on OpenVMS Alpha or
    eight arguments on OpenVMS I64, SP references are not allowed,
    and AP references are allowed only if the inline option is used.

    OpenVMS Alpha systems only: 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.

    OpenVMS Alpha systems only: 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.

    OpenVMS Alpha systems only: 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.

8.3  –  $CALL64

    Invokes the target routine.

    Format

      $CALL64  call_target

8.3.1  –  Parameters

 call_target

    The routine to be invoked.

8.3.2  –  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.

8.4  –  $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

8.4.1  –  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.

8.4.2  –  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.

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

8.5  –  $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 | quad

8.5.1  –  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|quad

    The size of the address pointing to the descriptor. The default
    value is size=long.

8.5.2  –  Description

    $IS_DESC64 tests the fields that 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.

8.5.3  –  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.
Close Help