[Digital logo]
[HR]

OpenVMS Alpha Guide to 64-Bit Addressing and VLM Features


Previous | Contents

If there are more than six arguments, 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 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.


$PUSH_ARG64

Does the equivalent of argument pushes for a call.

Format

$PUSH_ARG64 argument


PARAMETERS

argument

The argument to be pushed.

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, this macro checks for SP or AP references in the argument. If the call contains more than six arguments, SP references are not allowed, and AP references are allowed only if the inline option is used.

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.

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.

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.


$CALL64

Invokes the target routine.

Format

$CALL64 call_target


PARAMETERS

call_target

The routine to be invoked.

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.

B.2 Macros for Checking Sign Extension and Descriptor Format

The macros in this section are used for checking certain values and directing program flow based on the outcome of the check.


$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


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.

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.

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


$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 or quad


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

The size of the address pointing to the descriptor. Acceptable values are "long" (the default) and "quad".

DESCRIPTION

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

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.


Appendix C
64-Bit Example Program

This example program demonstrates the 64-bit region creation and deletion system services. It uses SYS$CREATE_REGION_64 to create a region and then uses SYS$EXPREG_64 to allocate virtual addresses within that region. The virtual address space and the region are deleted by calling SYS$DELETE_REGION_64.

 
/* 
 ***************************************************************************** 
 * 
 * Copyright © Digital Equipment Corporation, 1995 All Rights Reserved. 
 * Unpublished rights reserved under the copyright laws of the United States. 
 * 
 * The software contained on this media is proprietary to and embodies the 
 * confidential technology of Digital Equipment Corporation.  Possession, use, 
 * duplication or dissemination of the software and media is authorized only 
 * pursuant to a valid written license from Digital Equipment Corporation. 
 * 
 * RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure by the U.S. 
 * Government is subject to restrictions as set forth in Subparagraph 
 * (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. 
 * 
 ***************************************************************************** 
/* 
    This program creates a region in P2 space using the region creation 
    service and then creates VAs within that region.  The intent is to 
    demonstrate the use of the region services and how to allocate virtual 
    addresses within a region.  The program also makes use of 64-bit 
    descriptors and uses them to format return values into messages with the 
    aid of SYS$GETMSG. 
 
    To build and run this program type: 
 
    $ CC/POINTER_SIZE=32/STANDARD=RELAXED/DEFINE=(__NEW_STARLET=1) - 
        REGIONS.C 
    $ LINK REGIONS.OBJ 
    $ RUN REGIONS.EXE 
*/ 
 
#include    <descrip.h>             /* Descriptor Definitions               */ 
#include    <far_pointers.h>        /* Long Pointer Definitions             */ 
#include    <gen64def.h>            /* Generic 64-bit Data Type Definition  */ 
#include    <iledef.h>              /* Item List Entry Definitions          */ 
#include    <ints.h>                /* Various Integer Typedefs             */ 
#include    <iosbdef.h>             /* I/O Status Block Definition          */ 
#include    <psldef.h>              /* PSL$ Constants                       */ 
#include    <ssdef.h>               /* SS$_ Message Codes                   */ 
#include    <starlet.h>             /* System Service Prototypes            */ 
#include    <stdio.h>               /* printf                               */ 
#include    <stdlib.h>              /* malloc, free                         */ 
#include    <string.h>              /* memset                               */ 
#include    <syidef.h>              /* $GETSYI Item Code Definitions        */ 
#include    <vadef.h>               /* VA Creation Flags and Constants      */ 
 
 
/*  Module-wide constants and macros.                                       */ 
 
#define     BUFFER_SIZE         132 
#define     HW_NAME_LENGTH       32 
#define     PAGELET_SIZE        512 
#define     REGION_SIZE         128 
 
#define     good_status(code)   ((code) & 1) 
 
 
/*  Module-wide Variables                                                   */ 
 
int 
    page_size; 
 
$DESCRIPTOR64 (msgdsc, ""); 
 
 
/*  Function Prototypes                                                    */ 
 
int get_page_size (void); 
static void print_message (int code, char *string); 
 
main (int argc, char **argv) 
{ 
    int 
        i, 
        status; 
 
    uint64 
        length_64, 
        master_length_64, 
        return_length_64; 
 
    GENERIC_64 
        region_id_64; 
 
    VOID_PQ 
        master_va_64, 
        return_va_64; 
 
 
/*  Get system page size, using SYS$GETSYI.                                 */ 
 
    status = get_page_size (); 
    if (!good_status (status)) 
        return (status); 
 
 
/*  Get a buffer for the message descriptor.                                */ 
 
    msgdsc.dsc64$pq_pointer = malloc (BUFFER_SIZE); 
    printf ("Message Buffer Address = %016LX\n\n", msgdsc.dsc64$pq_pointer); 
 
 
/*  Create a region in P2 space.                                            */ 
 
    length_64 = REGION_SIZE*page_size; 
    status = sys$create_region_64 ( 
        length_64,                  /* Size of Region to Create             */ 
        VA$C_REGION_UCREATE_UOWN,   /* Protection on Region                 */ 
        0,                          /* Allocate in Region to Higher VAs     */ 
        &region_id_64,              /* Region ID                            */ 
        &master_va_64,              /* Starting VA in Region Created        */ 
        &master_length_64);         /* Size of Region Created               */ 
    if (!good_status (status)) 
    { 
        print_message (status, "SYS$CREATE_REGION_64"); 
        return (status); 
    } 
 
    printf ("\nSYS$CREATE_REGION_64 Created this Region:  %016LX - %016LX\n", 
        master_va_64, 
        (uint64) master_va_64 + master_length_64 - 1); 
 
 
/*  Create virtual address space within the region.                         */ 
 
    for (i = 0; i < 3; ++i) 
    { 
        status = sys$expreg_64 ( 
            &region_id_64,      /* Region to Create VAs In                  */ 
            page_size,          /* Number of Bytes to Create                */ 
            PSL$C_USER,         /* Access Mode                              */ 
            0,                  /* Creation Flags                           */ 
            &return_va_64,      /* Starting VA in Range Created             */ 
            &return_length_64); /* Number of Bytes Created                  */ 
        if (!good_status (status)) 
        { 
            print_message (status, "SYS$EXPREG_64"); 
            return status; 
        } 
        printf ("Filling %016LX - %16LX with %0ds.\n", 
            return_va_64, 
            (uint64) return_va_64 + return_length_64 - 1, 
            i); 
        memset (return_va_64, i, page_size); 
    } 
 
 
/*  Return the virtual addresses created within the region, as well as the 
    region itself.                                                          */ 
 
    printf ("\nReturning Master Region:  %016LX - %016LX\n", 
        master_va_64, 
        (uint64) master_va_64 + master_length_64 - 1); 
 
    status = sys$delete_region_64 ( 
        &region_id_64,      /* Region to Delete                             */ 
        PSL$C_USER,         /* Access Mode                                  */ 
        &return_va_64,      /* VA Deleted                                   */ 
        &return_length_64); /* Length Deleted                               */ 
 
    if (good_status (status)) 
        printf ("SYS$DELETE_REGION_64 Deleted VAs Between:  %016LX - %016LX\n", 
            return_va_64, 
            (uint64) return_va_64 + return_length_64 - 1); 
    else 
    { 
        print_message (status, "SYS$DELTE_REGION_64"); 
        return (status); 
    } 
 
/*  Return message buffer.                                                  */ 
 
    free (msgdsc.dsc64$pq_pointer); 
} 
 
 
/*  This routine obtains the system page size using SYS$GETSYI.  The return 
    value is recorded in the module-wide location, page_size.               */ 
 
int get_page_size () 
{ 
int 
    status; 
 
IOSB 
    iosb; 
 
ILE3 
    item_list [2]; 
 
 
/* Fill in SYI item list to retrieve the system page size.                  */ 
 
    item_list[0].ile3$w_length       = sizeof (int); 
    item_list[0].ile3$w_code         = SYI$_PAGE_SIZE; 
    item_list[0].ile3$ps_bufaddr     = &page_size; 
    item_list[0].ile3$ps_retlen_addr = 0; 
    item_list[1].ile3$w_length       = 0; 
    item_list[1].ile3$w_code         = 0; 
 
 
/* Get the system page size.                                                */ 
 
    status = sys$getsyiw ( 
                0,                              /* EFN                      */ 
                0,                              /* CSI address              */ 
                0,                              /* Node name                */ 
                &item_list,                     /* Item list                */ 
                &iosb,                          /* I/O status block         */ 
                0,                              /* AST address              */ 
                0);                             /* AST parameter            */ 
 
    if (!good_status (status)) 
    { 
        print_message (status, "SYS$GETJPIW"); 
        return (status); 
    } 
    if (!good_status (iosb.iosb$w_status)) 
    { 
        print_message (iosb.iosb$w_status, "SYS$GETJPIW IOSB"); 
        return (iosb.iosb$w_status); 
    } 
 
    return SS$_NORMAL; 
} 
 
 
/*  This routine takes the message code passed to the routine and then uses 
    SYS$GETMSG to obtain the associated message text.  That message is then 
    printed to stdio along with a user-supplied text string.                */ 
 
#pragma inline (print_message) 
static void print_message (int code, char *string) 
{ 
    msgdsc.dsc64$q_length = BUFFER_SIZE; 
    sys$getmsg ( 
        code,                                       /* Message Code         */ 
        (unsigned short *) &msgdsc.dsc64$q_length,  /* Returned Length      */ 
        &msgdsc,                                    /* Message Descriptor   */ 
        15,                                         /* Message Flags        */ 
        0);                                         /* Optional Parameter   */ 
    *(msgdsc.dsc64$pq_pointer+msgdsc.dsc64$q_length) = '\0'; 
     printf ("Call to %s returned:  %s\n", 
        string, 
        msgdsc.dsc64$pq_pointer); 
} 
 


Appendix D
VLM Example Program

This example program demonstrates the memory management VLM features described in Chapter 4.

/* 
 ***************************************************************************** 
 * 
 * Copyright © Digital Equipment Corporation, 1996 All Rights Reserved. 
 * Unpublished rights reserved under the copyright laws of the United States. 
 * 
 * The software contained on this media is proprietary to and embodies the 
 * confidential technology of Digital Equipment Corporation.  Possession, use, 
 * duplication or dissemination of the software and media is authorized only 
 * pursuant to a valid written license from Digital Equipment Corporation. 
 * 
 * RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure by the U.S. 
 * Government is subject to restrictions as set forth in Subparagraph 
 * (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. 
 * 
 ***************************************************************************** 
/* 
    This program creates and maps to a memory resident global section using 
    shared page tables.  The program requires a reserved memory entry 
    (named In_Memory_Database) in the Reserved Memory Registry. 
 
    The entry in the registry is created using SYSMAN as follows: 
 
    $ MCR SYSMAN 
    SYSMAN> RESERVED_MEMORY ADD "In_Memory_Database"/ALLOCATE/PAGE_TABLES - 
        /ZERO/SIZE=64/GROUP=100 
 
    The above command creates an entry named In_Memory_Database that is 
    64 Mbytes in size and requests that the physical memory be allocated 
    during system initialization.  This enables the physcial memory to 
    be mapped with granularity hints by the SYS$CRMPSC_GDZRO_64 system 
    service.  It also requests that physical memory be allocated for 
    page tables for the named entry, requests the allocated memory be 
    zeroed, and requests that UIC group number 100 be associated with 
    the entry. 
 
 
    Once the entry has been created with SYSMAN, the system must be 
    re-tuned with AUTOGEN.  Doing so allows AUTOGEN to re-calculate 
    values for SYSGEN parameters that are sensitive to changes in 
    physical memory sizes.  (Recall that the Reserved Memory Registry 
    takes physical pages away from the system.)  Once AUTOGEN has 
    been run, the system must be rebooted. 
 
 
    Using the following commands to compile and link this program: 
 
    $ CC/POINTER_SIZE=32 shared_page_tables_example 
    $ LINK shared_page_tables_example 
 
    Since 64-bit virtual addresses are used by this program, a Version 
    5.2 DEC C compiler or later is required to compile it. 
*/ 
#define     __NEW_STARLET   1 
 
#include    <DESCRIP>
#include    <FAR_POINTERS>
#include    <GEN64DEF>
#include    <INTS>
#include    <PSLDEF>
#include    <SECDEF>
#include    <SSDEF>
#include    <STARLET>
#include    <STDIO>
#include    <STDLIB>
#include    <STRING>
#include    <VADEF>
 
#define     bad_status(status) (((status) & 1) != 1) 
#define     ONE_MEGABYTE    0x100000 
 
 
main () 
{ 
    int 
        status; 
 
    $DESCRIPTOR (section_name, "In_Memory_Database"); 
 
    uint32 
        region_flags = VA$M_SHARED_PTS,   /* Shared PT region. */ 
        section_flags = SEC$M_EXPREG; 
 
    uint64 
        mapped_length, 
        requested_size = 64*ONE_MEGABYTE, 
        section_length = 64*ONE_MEGABYTE, 
        region_length; 
 
    GENERIC_64 
        region_id; 
 
    VOID_PQ 
        mapped_va, 
        region_start_va; 
 
 
    printf ("Shared Page Table Region Creation Attempt:  Size = %0Ld\n", 
        requested_size); 
 
 
/*  Create a shared page table region. */ 
 
    status = sys$create_region_64 ( 
        requested_size,                 /* Size in bytes of region */ 
        VA$C_REGION_UCREATE_UOWN,       /* Region VA creation and owner mode */ 
        region_flags,                   /* Region Flags:  shared page tables */ 
        &region_id,                     /* Region ID */ 
        &region_start_va,               /* Starting VA for region */ 
        &region_length);                /* Size of created region */ 
 
    if (bad_status (status)) 
    { 
        printf ("ERROR:  Unable to create region of size %16Ld\n\n", 
            requested_size); 
        return; 
    } 
 
    printf ("Shared Page Table Region Created:  VA = %016LX, Size = %0Ld\n\n", 
        region_start_va, 
        region_length); 
 
 
/* Create and map a memory resident section with shared page tables 
       into the shared page table region. */ 
 
    printf ("Create and map to section %s\n", section_name.dsc$a_pointer); 
    status = sys$crmpsc_gdzro_64 ( 
            &section_name,              /* Section name */ 
            0,                          /* Section Ident */ 
            0,                          /* Section protection */ 
            section_length,             /* Length of Section */ 
            &region_id,                 /* RDE */ 
            0,                          /* Section Offset; map entire section */ 
            PSL$C_USER,                 /* Access Mode */ 
            section_flags,              /* Section Creation Flags */ 
            &mapped_va,                 /* Return VA */ 
            &mapped_length);            /* Return Mapped Length */ 
 
    if (bad_status (status)) 
        printf ("ERROR:  Unable to Create and Map Section %s, status = %08x\n\n", 
                section_name.dsc$a_pointer, 
                status); 
    else 
    { 
        printf ("Section %s created, Section Length = %0Ld\n", 
                section_name.dsc$a_pointer, 
                section_length); 
        printf ("    Mapped VA = %016LX, Mapped Length = %0Ld\n\n", 
                mapped_va, 
                mapped_length); 
    } 
 
    /* Delete the shared page table.  This will cause the mapping to the 
       section and the section itself to be deleted. */ 
 
    printf ("Delete the mapping to the memory resident global section"); 
    printf (" and the shared\n    page table region.\n"); 
    status = sys$delete_region_64 ( 
            &region_id, 
            PSL$C_USER, 
            &region_start_va, 
            &region_length); 
 
    if (bad_status (status)) 
        printf ("ERROR:  Unable to delete shared page table region, status = %08x\n\n", status); 
    else 
        printf ("Region Deleted, Start VA = %016LX, Length = %016LX\n\n", 
                region_start_va, 
                region_length); 
    printf ("\n"); 
} 
 

This example program displays the following output:

Shared Page Table Region Creation Attempt:  Size = 67108864 
Shared Page Table Region Created:  VA = FFFFFFFBFC000000, Size = 67108864 
 
Create and map to section In_Memory_Database 
Section In_Memory_Database created, Section Length = 67108864 
    Mapped VA = FFFFFFFBFC000000, Mapped Length = 67108864 
 
Delete the mapping to the memory resident global section and the shared 
    page table region. 
Region Deleted, Start VA = FFFFFFFBFC000000, Length = 0000000004000000 


Index | Contents | [Home] | [Comments] | [Ordering info] | [Help]

[HR]

  6467P007.HTM
  OSSG Documentation
  22-NOV-1996 13:12:06.27

Copyright © Digital Equipment Corporation 1996. All Rights Reserved.

Legal