[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Calling Standard


Previous Contents Index

4.8.5.5 The Write Register Routine

Place a function pointer for this routine in the LIBICB$PH_UO_WRITE_REG field of the invocation context block.

The write register routine is used to write a register in the target process. It is used by LIB$I64_PUT_INVO_REGISTERS for a register that has not been saved in memory.

This routine is optional, or subset of registers can be implemented, in this case LIB$I64_PUT_INVO_REGISTERS will return an error if this routine is not present, or is unable to write the desired register.


int (* write_reg) (int whichReg, uint64 value_1, uint64 value_2, uint64 ident);

Argument OpenVMS Usage Type Access Mechanism
whichReg enumeration longword read by value
value_1 register_value quadword read by value
value_2 register_value quadword read by value
ident user_value quadword read by value

Arguments:

  whichReg
Indicates the register to be written (see enum in libicb.h).
  value_1
Specifies the register contents, or lower quadword for a FR fill operation.
  value_2
Specifies the NaT bit for GRs, or upper quadword for a FR fill.
  ident
Specifies a user ident value from the invocation context block.

Function Value Returned:

  status
A value of 1 indicates success.
A value of 0 indicates failure.

4.8.5.6 The Memory Allocation Routine

The memory allocation routine is used to allocate heap storage required during the analysis of unwind descriptors. This routine should mimic the behavior of the C RTL routine malloc.


void * (* malloc) (size_t size, uint64 ident);

Argument OpenVMS Usage Type Access Mechanism
length size_t longword read by value
ident user_value quadword read by value

Arguments:

  length
The length in bytes of memory to be allocated. The returned memory block should be aligned on a 16-byte boundary.
  ident
Specifies a user ident value from the invocation context block.

Function Value Returned:

  ptr
Address of the memory block allocated, or 0 for failure.

In the case where local memory is being read, that is, you have not overridden the read memory routines, the malloc requests are reduced to:

  • One Unwind Context block of size LIBICB$K_CONTEXT_BLK_SIZE
  • One Unwind Descriptor block of size LIBICB$K_DESCRIPTOR_BLK_SIZE
  • Several Unwind region blocks of size LIBICB$K_REGION_BLK_SIZE
  • Several Unwind region label blocks of size LIBICB$K_REGIONLABEL_BLK_SIZE

The number of the last two required depends on the complexity of the unwind descriptors for a given procedure being traced.

4.8.5.7 The Memory Deallocation Routine

The memory deallocation routine is used to free heap storage allocated by the memory allocation routine (see Section 4.8.5.6). This routine should mimic the behavior of the C RTL routine free.


void (* free) (void * ptr, uint64 ident);

Argument OpenVMS Usage Type Access Mechanism
ptr address quadword read by value
ident user_value quadword read by value

Arguments:

  ptr
Address of a memory block previously allocated by a call to the user malloc routine.
  ident
Specifies a user ident value from the invocation context block.

Function Value Returned:

None.

4.9 Data Allocation

In order to make the most effective use of the addressing modes available to Intel Itanium processors, each image's data is partitioned into one or two short data segments and some number of long data segments. The short data segments, addressed by the GP register in each image, contain the following areas:

  • A linkage table, containing pointers to imported data and functions, and to data in the code segments and long data segments. This area is generally protected by OpenVMS against being written after image activation is complete.
  • A read-only short data area, containing small initialized own data items. This area is generally protected by OpenVMS against being written after image activation is complete. (This area is optional.)
  • A read-write short data area, containing small initialized own data items.
  • A read-write short bss area, containing small uninitialized own data items.

The long data segments contain either or both of the following areas:

  • One or more long data areas, which contain large initialized data items, and initialized non-own data items of any size.
  • One or more long bss areas, which contain large uninitialized data items, and uninitialized non-own data items of any size.

Own data items are those that are either local to an image, or are such that all references to these items from the same image will always refer to these items. Because non-own variables cannot be referenced directly, there is no benefit to placing them in the short data area or bss area. Small own data items are placed in the short bss area or short data areas, and are guaranteed to be within 2 megabytes (in either direction) of the GP address; this allows compilers to use a short direct addressing sequence (using the add with 22-bit immediate instruction) to access any data item allocated in these areas.

The compiler should place all own data items that are 8 bytes or less in size (regardless of structure) in one of the short data areas or the short bss area. All other data items, including items that are larger than 8 bytes in size, must be placed in one of the long data areas or long bss areas. The compiler must address these items indirectly, using a linkage table entry. Linkage table entries are typically allocated by the linker in response to a relocation request generated by the compiler; an entry in the linkage table is either a pointer to a data item, or a function descriptor. A function descriptor placed in the linkage table is a local copy of an official function descriptor that is generally allocated by the linker or image activator.

This design allows for a maximum size of 4 megabytes for the short data segment, because everything must be addressable via the GP register using the 22-bit add immediate instruction. This allows for up to 256,000 individually-named variables and functions. If an image requires more than this, linker options may be used to divide the image into multiple clusters (see Section 4.7.1).

4.9.1 Alignment

On Itanium hardware, memory references to data that is not naturally aligned can result in alignment faults, which can severely degrade the performance of all procedures that reference the unaligned data. To avoid such performance degradation, all data values should be naturally aligned, as shown in Table 4-18.

In addition, common blocks, dynamically allocated (heap) regions (for example from malloc ), and global data items greater than 8 bytes must be aligned on a 16-byte boundary.

Table 4-18 Natural Alignment Requirements
Data Type Alignment Starting Position
8-bit character string Byte boundary
16-bit integer Address that is a multiple of 2 (word alignment)
32-bit integer Address that is a multiple of 4 (longword alignment)
64-bit integer Address that is a multiple of 8 (quadword alignment)
F_floating
F_floating complex
Address that is a multiple of 4 (longword)
D_floating
D_floating complex
Address that is a multiple of 8 (quadword)
G_floating
G_floating complex
Address that is a multiple of 8 (quadword)
S_floating
S_floating complex
Address that is a multiple of 4 (longword alignment)
T_floating
T_floating complex
Address that is a multiple of 8 (quadword)
X_floating
X_floating complex
Address that is a multiple of 16 (octaword)

For aggregates such as strings, arrays, and records, the data type to be considered for purposes of alignment is not the aggregate itself, but rather the elements of which the aggregate is composed. The alignment requirement of an aggregate is that all elements of the aggregate be naturally aligned. For example, varying 8-bit character strings must start at addresses that are a multiple of at least 2 (word alignment) because of the 16-bit count at the beginning of the string; 32-bit integer arrays start at a longword boundary, irrespective of the extent of the array.

The rules for passing a record in an argument that is passed by immediate value (see Section 4.7.4) always provide quadword alignment of the record value independent of the normal alignment requirement of the record. If deemed appropriate by an implementation, normal alignment can be established within the called procedure by making a copy of the record argument at a suitably aligned location.

4.9.2 Global Data

Access to global variables that are not known (at compile time) to be defined in the same image must be indirect. Each image has a linkage table in its data segment, pointed to by the GP register; code must load a pointer to the global variable from the linkage table, then access the global variable through the pointer. Access to global variables known to be defined in the same image or to static locals that are placed in the short data area may be made with a GP-relative offset.

4.9.3 Local Static Data

Access to short local static data can be made with a GP-relative offset; access to long local static data must be indirect.

4.9.4 Constants and Literals

Constants and literals may be placed in the text segment or in the data segment. If placed in the text segment, the access must be PC-relative or indirect using a linkage table entry. Literals placed in the data segment may be placed in the short initialized data area if they are 8 bytes or less in size. Larger literals must be placed in the long initialized data area or in the text segment. Literals in the long initialized data area require an indirect access using a linkage table entry.

4.9.5 Record Layout Conventions

The OpenVMS I64 calling standard rules for record layout are designed to provide good run-time performance on all implementations of the Itanium architecture and to provide the required level of compatibility with conventional VAX and Alpha operating environments.

Therefore, this standard defines the following record layout conventions:

  • Those optimized for optimal access characteristics (referred to as aligned record layouts)
  • Those compatible with conventions that are traditionally used by VAX languages (referred to as VAX compatible record layouts)

Note

Although compiler implementers must make appropriate business decisions, Hewlett-Packard strongly recommends that all OpenVMS I64 high-level language compilers should support both record layouts.

Only these record layouts may be used across standard interfaces or between languages. Languages can support other language-specific record layout conventions, but such layouts are nonstandard.

The aligned record layout conventions should be used unless interchange is required with conventional VAX applications that use the OpenVMS VAX compatible record layouts.

4.9.5.1 Aligned Record Layout

The aligned record layout conventions ensure that:

  • All components of a record or subrecord are naturally aligned.
  • Layout and alignment of record elements and subrecords are independent of any record or subrecord in which they are embedded.
  • Layout and alignment of a subrecord is the same as if it were a top-level record.
  • Declaration in high-level languages of standard records for interlanguage use is straightforward and obvious, and meets the requirements for source-level compatibility between OpenVMS I64 languages and OpenVMS Alpha and VAX languages.

The aligned record layout is defined by the following conventions:

  • The components of a record must be laid out in memory corresponding to the lexical order of their appearance in the high-level language declaration of the record.
  • The first bit of a record or subrecord must be directly addressable (byte aligned).
  • Records and subrecords must be aligned according to the largest natural alignment requirements of the contained elements and subrecords.
  • Bit fields (packed subranges of integers) are characterized by an underlying integer type that is a byte, word, longword, or quadword in size together with an allocation size in bits. A bit field is allocated at the next available bit boundary, provided that the resulting allocation does not cross an alignment boundary of the underlying type. Otherwise, the field is allocated at the next byte boundary that is aligned as required for the underlying type. (In the later case, the space skipped over is left permanently not allocated.) In addition, if necessary, the alignment of the record as a whole is increased to that of the underlying integer type.
  • Unaligned bit strings, unaligned bit arrays, and elements of unaligned bit arrays must start at the next available bit in the record. No fill is ever supplied preceding an unaligned bit string, unaligned bit array, or unaligned bit array element.
  • All other components of a record must start at the next available naturally aligned address for the data type.
  • The length of a record must be a multiple of its alignment. (This includes the case when a record is a component of another record.)
  • Strings and arrays must be aligned according to the natural alignment requirements of the data type of which the string or array is composed.
  • The length of an array element is a multiple of its alignment, even if this leaves unused space at its end. The length of the whole array is the sum of the lengths of its elements.

4.9.5.2 OpenVMS VAX Compatible Record Layout

The OpenVMS VAX compatible record layout is defined by the following conventions:

  • The components of a record must be laid out in memory corresponding to the lexical order of their appearance in the high-level language declaration of the record.
  • Unaligned bit strings, unaligned bit arrays, and elements of unaligned bit arrays must start at the next available bit in the record. No fill is ever supplied preceding an unaligned bit string, unaligned bit array, or unaligned bit array element.
  • All other components of a record must start at the next available byte in the record. Any unused bits following the last-used bit in the last-used byte of each component must be filled out to the next byte boundary so that any following data starts on a byte boundary.
  • Subrecords must be aligned according to the largest alignment of the contained elements and subrecords. A subrecord always starts at the next available byte unless it consists entirely of unaligned bit data and it immediately follows an unaligned bit string, unaligned bit array, or a subrecord consisting entirely of unaligned bit data.
  • Records must be aligned on byte boundaries.

4.9.6 Sample Code Sequences

In the sample code sequences in this section, register names of the form t1, t2, and so on, are temporary registers, and may be assigned to any available scratch register. The code sequences show necessary cycle breaks, but no other scheduling considerations have been made. It is assumed that these code sequences will be scheduled with surrounding code to make best use of the processor resources.

4.9.6.1 Addressing Own Data in the Short Data Area

Own short data can be addressed with a simple direct reference relative to the GP register, as shown in the following example:


     addl   t1=@gprel(var),gp ;;          // calc. address of var
     ld8    loc0=[t1]                     // load contents of var

Own long data can be addressed either via the linkage table, as shown in Section 4.9.6.2, or directly as shown in the following example:


     movl   t1=@gprel(var) ;;             // form gp-relative offset of var
     add    t2=t1,gp ;;                   // calc. address of var
     ld8    loc0=[t2]                     // load contents of var

4.9.6.2 Addressing External Data or Data in a Long Data Area

When data is not known to be defined in the current image (that is, it is not own), or if it is too large for the short data region, it must be accessed indirectly through the linkage table, as shown in the following example:


     addl   t1=@ltoff(var),gp ;;          // calc. address of LT entry
     ld8    t2=[t1] ;;                    // load address of var
     ld8    loc0=[t2]                     // load contents of var

4.9.6.3 Addressing Literals in the Text Segment

Literals in the text segment may be addressed either through the linkage table, as in Section 4.9.6.2, or with PC-relative addressing, as shown in the following example:


 L1: mov    r3=ip ;;                      // get current IP
     addl   loc0=litbase-L1,r3 ;;         // calc. addr. of lit. area
     adds   t2=(lit-litbase),loc0 ;;      // calc. address of lit.
     ld8    loc1=[t2]                     // load value of literal

Note

The first two instructions can be moved towards the beginning of the procedure, and the base address of the literal area (in LOC0) can be shared by other literal references in the same procedure.

4.9.6.4 Materializing Function Pointers

Function pointers must always be obtained from the data segment, either as an initialized quadword or through the linkage table, as shown in the following examples:

Materializing function pointers through linkage table:


     addl   t1=@ltoff(@fptr(func)),gp ;;  // calc address of LT entry
     ld8    loc0=[t1]                     // load function pointer

Materializing function pointers in data:


 fptr:
     data8  @ftpr(func)                   // initialize function ptr


Previous Next Contents Index