This chapter describes some fundamental concepts of the Tru64 UNIX calling standard. The topics discussed are as follows:
Address representation
Procedure representation
Register usage conventions
Register names
Values that represent addresses are 64 bits in size.
2.2 Procedure Representation
One of the distinguishing characteristics of any calling standard is how procedures are represented. The term used to denote the value that uniquely identifies a procedure is a procedure value. If the value identifies a bound procedure, it is called a bound procedure value.
In the Tru64 UNIX calling standard, a simple (not bound) procedure value is defined as the address of the first instruction of that procedure's entry code. (See Section 3.2.6.)
A bound procedure value is defined as the address of the first instruction of an instruction sequence that establishes the correct execution context for the bound procedure.
Procedures in the Tru64 UNIX calling standard are associated with
a set of information called a procedure descriptor.
This information describes
various aspects of the procedure's code that are required for correct and
robust exception handling.
The exception processing described by this standard
is based on the assumption that any given program counter value can be mapped
to an associated procedure descriptor that describes the currently active
procedure.
2.3 Register Usage Conventions
This section describes the
usage of the Alpha hardware integer and floating-point registers.
2.3.1 Integer Registers
Table 2-1
describes the Alpha
hardware integer registers.
Table 2-1: General-Purpose Integer Registers
Register | Description |
$0 | Function value register. In a standard call that returns a nonfloating-point function result in a register, the result must be returned in this register. In a standard call, this register can be modified by the called procedure without being saved and restored. |
$1 - $8 | Conventional scratch registers. In a standard call, these registers can be modified by the called procedure without being saved and restored. |
$9 - $14 | Conventional saved registers. If a standard-conforming procedure modifies one of these registers, it must save and restore it. |
$15 | Stack frame base (FP) register. For procedures with a run-time variable amount of stack, this register is used to point at the base of the stack frame (fixed part of the stack). For all other procedures, this register has no special significance. If a standard-conforming procedure modifies this register, it must save and restore it. |
$16 - $21 | Argument registers. In a standard call, up to six nonfloating-point items of the argument list are passed in these registers. In a standard call, these registers can be modified by the called procedure without being saved and restored. |
$22 - $25 | Conventional scratch registers. In a standard call, these registers can be modified by the called procedure without being saved and restored. |
$26 | Return address (RA) register. In a standard call, the return address must be passed and returned in this register. |
$27 | Procedure value (PV) register. In a standard call, the procedure value of the procedure being called is passed in this register. (See Section 2.2.) In a standard call, this register can be modified by the called procedure without being saved and restored. |
$28 | Volatile scratch register. The contents of this register are always unpredictable after any external transfer of control to or from a procedure. This unpredictable nature applies to both standard and nonstandard calls. This register can be used by the operating system for external call fixing, autoloading, and exit sequences. |
$29 | Global pointer (GP) register. For a standard-conforming procedure, this register must contain the calling procedure's global offset table (GOT) segment pointer value at the time of a call and must contain the calling procedure's GOT segment pointer value or the called procedure's GOT segment pointer value upon return. This register must be treated as scratch by the calling procedure. (See Section 2.5 and Section 3.2.2 for details.) |
$30 | Stack pointer (SP) register. This register contains a pointer to the top of the current operating stack. Aspects of its usage and alignment are defined by the hardware architecture. See Section 3.2.1 for details about its usage and alignment. |
$31 | ReadAsZero/Sink register. This register is defined in the hardware to be binary zero as a source operand or sink (no effect) as a result operand. |
2.3.2 Floating-Point Registers
Table 2-2
describes the Alpha hardware
floating-point registers.
Table 2-2: Floating-Point Registers
Register | Description |
$f0 | Floating-point function value register. In a standard call that returns a floating-point result in a register, this register is used to return the real part of the result. In a standard call, this register can be modified by the called procedure without being saved and restored. |
$f1 | Floating-point function value register. In a standard call that returns a complex floating-point result in registers, this register is used to return the imaginary part of the result. In a standard call, this register can be modified by the called procedure without being saved and restored. |
$f2 - $f9 | Conventional saved registers. If a standard-conforming procedure modifies one of these registers, it must save and restore it. |
$f10 - $f15 | Conventional scratch registers. In a standard call, these registers can be modified by the called procedure without being saved and restored. |
$f16 - $f21 | Argument registers. In a standard call, up to six floating-point arguments can be passed by value in these registers. In a standard call, these registers can be modified by the called procedure without being saved and restored. |
$f22 - $f30 | Conventional scratch registers. In a standard call, these registers can be modified by the called procedure without being saved and restored. |
$f31 | ReadAsZero/Sink register. This register is defined in the hardware to be binary zero as a source operand or sink (no effect) as a result operand. |
A few special register names appear in uppercase letters. This register naming convention is not necessarily followed by compiler or assembler tools that are used on Tru64 UNIX systems. However, a simple name substitution can convert from the notation used here to the appropriate convention. For example, the following code fragment might be used in conjunction with the standard C preprocessor as a prelude to the examples in this text:
#define FP $15 #define RA $26 #define PV $27 #define GP $29 #define SP $30
The Tru64 UNIX calling standard defines only some aspects of an executable image. One basic concept that is defined involves program image layout, which permits optimal access to static data.
A hardware architecture in which instructions cannot contain full virtual addresses can be referred to as a base register architecture. The Alpha architecture is such an architecture. In a base register architecture, normal memory references within a limited range from a given address are expressed by using displacements relative to the contents of some register which contains that address (usually referred to as a base register). Base registers for external program segments, either data or code, are usually loaded indirectly through a program segment of address constants.
To optimize this base register access method, this standard requires each image that makes up an executable program to have zero or one global offset table (GOT). This global offset table can be further divided into multiple GOT segments. Together, the linker and the compilers arrange for various static data to be collected together into a minimal number of these GOT segments (typically one per image). During program execution, the GP (global pointer) register will contain a pointer into the appropriate GOT segment so that all references therein can utilize a single base register. (For more information, see Section 3.2.2.)
During the compilation process, a compiler generates object language to designate data as belonging in a GOT segment. No single procedure is allowed to provide more than 64KB of data to a GOT segment. The linker pools these contributions to form the GOT segments. Typically, routines in several compilation units can share the same pointer into the GOT. In fact, if only one GOT segment is needed and will not exceed the 64KB addressing maximum, all routines within an image can use the same GOT pointer. Consequently, the GP register can be loaded once and then used by many routines to improve performance.