VMS Help  —  MACRO  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.

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.

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

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.

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

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.

1.3  –  $PAGES TO BYTES

    Converts a page count to a byte count.

    Format

      $PAGES_TO_BYTES  source_pagcnt, dest_bytcnt, leftshift,

                       quad=YES

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.

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

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.

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

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

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

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.

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.

2.1  –  $POP64

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

    Format

      $POP64  reg

2.1.1  –  Parameters

 reg

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

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.

2.2  –  $PUSH64

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

    Format

      $PUSH64  reg

2.2.1  –  Parameters

 reg

    Register to be pushed onto the stack.

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.

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

       For OpenVMS I64 systems, these macros are still under
       development and additional OpenVMS routines are being
       provided to lock working sets. See the OpenVMS I64 Release
       Notes for more information.

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]

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.

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.

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]

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.

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.

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.

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.

3.4  –  $LOCK PAGE

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

    Format

      $LOCK_PAGE  [error]

3.4.1  –  Parameters

 [error]

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

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.

3.5  –  $UNLOCK PAGE

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

    Format

      $UNLOCK_PAGE  [error][,LINK_SECT]

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.

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