Document revision date: 30 March 2001

## OpenVMS MACRO-32 Porting and User's Guide

Previous | Contents | Index

## C.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:

- 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.
- 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-32 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 Table C-2.

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. See Appendix B for additional information.

Table C-2 Alpha PALcode Built-Ins
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

## Appendix D
Macros for Porting to OpenVMS Alpha

This appendix describes macros designed to facilitate the porting of VAX MACRO code to an OpenVMS Alpha system. They are grouped according to their function, as follows:

- Page-related calculations (see Section D.1)
- Saving and restoring Alpha registers (see Section D.2)
- Locking pages into a working set (see Section D.3)

Note that you can use certain arguments to the macros described in this appendix to indicate register sets. To express a register set, list the registers, separated by commas, within angle brackets. For instance:

> <R1,R2,R3>

If the set contains only one register, omit the angle brackets:

> R1

## D.1 Page-Related Calculations

This section describes the following macros that provide a standard, architecture-independent means for calculating page-size dependent values:

- $BYTES_TO_PAGES
- $NEXT_PAGE
- $PAGES_TO_BYTES
- $PREVIOUS_PAGE
- $ROUND_RETADR
- $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, the user 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 Table D-1.

Table D-1 Shift Values
Page size | rightshift | leftshift
--- | --- | ---
512 bytes (VAX) | -9 | 9
8K (Alpha) | -13 | 13
16K 1 | -14 | 14
32K 1 | -15 | 15
64K 1 | -16 | 16

1If a future Alpha system implements this architecturally-permitted larger page size.

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:

- If the destination operand is blank, the source operand is used as the destination.
- All macros conditionalize code on the symbols VAXPAGE and BIGPAGE.
- 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.

## $BYTES_TO_PAGES

> Converts a byte count to a page count.

### Format

> $BYTES_TO_PAGES source_bytcnt, dest_pagcnt, rightshift, roundup=YES, quad=YES

### 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 Table D-1.

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

## $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

### 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 one 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.

## $PAGES_TO_BYTES

> Converts a page count to a byte count.

### Format

> $PAGES_TO_BYTES source_pagcnt, dest_bytcnt, leftshift, quad=YES

### 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 Table D-1.

> #### quad=YES

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

## $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

### 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 one 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.

## $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

### 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 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

## $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

### 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 in OpenVMS Alpha systems and MMG$C-VAX-PAGE-SIZE - 1 (defined in $pagedef) in OpenVMS VAX systems.

> #### quad=YES

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

## D.2 Saving and Restoring Alpha Registers

Frequently, VAX MACRO source code must save and restore register values, either because that is part of the defined interface or the code requires work registers. On OpenVMS VAX, code may invoke any number of macros to do this. On OpenVMS Alpha, 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.

## $POP64

> Pops the 64-bit value on the top of the stack into an Alpha register.

### Format

> $POP64 reg

### Parameters

> #### reg

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

### Description

> $POP64 takes the 64-bit value at the top of the stack and places it in an Alpha 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.

Previous | Next | Contents | Index

| privacy and legal statement |
5601PRO_013.HTML