HP-UX Linker and Libraries User's Guide
An opportunity for optimization in both cases is to share a single label (L) throughout a procedure,
and let the result of BL become a common sub-expression. Thus, only the first literal reference
within a procedure is expanded to three instructions. The rest remain two instructions.
Global and Static Variable References
References to global or static variables currently require two instructions either to form the address
of a variable, or to load or store the contents of the variable:
; to form the address of a variable
ADDIL L'var-$global$+x,%dp
LDO R'var-$global$+x(%r1),tmp
; to load the contents of a variable
ADDIL L'var-$global$+x,%dp
LDW R'var-$global$+x(%r1),tmp
These sequences must be converted to equivalent sequences using the linkage table pointer in
%r19:
; to form the address of a variable
LDW T'var(%r19),tmp1
LDO x(tmp1),tmp2 ; omit if x == 0
; to load the contents of a variable
LDW T'var(%r19),tmp1
LDW x(tmp1),tmp2
Note that the T' fixup on the LDW instruction allows for a 14-bit signed offset, which restricts the
DLT to be 16Kb. Because %r19 points to the middle of the DLT, we can take advantage of both
positive and negative offsets. The T' fixup specifier must generate a DLT_REL fixup proceeded by
an FSEL override fixup. If the FSEL override fixup is not generated, the linker assumes that the fixup
mode is LD/RD for DLT_REL fixups. In order to support larger DLT table sizes, the following long
form of the above data reference must be generated to reference tables that are larger. If the DLT
table grows beyond the 16Kb limit, the linker emits an error indicating that the user must recompile
using the +Z option, which produces the following long-load sequences for data reference:
; form the address of a variable
ADDIL LT'var,%r19
LDW RT'var(%r1),tmp1
LDO x(tmp1),tmp2 ; omit if x == 0
; load the contents of a variable
ADDIL LT'var,%r19
LDW RT'var(%r1),tmp1
LDW x(tmp1),tmp2
Procedure Labels
The compilers already mark procedure label constructs so that the linker can process them properly.
No changes are needed to the compilers.
When building shared libraries and incomplete executables, the linker modifies the plabel calculation
(produced by the compilers in both shared libraries and incomplete executables) to load the contents
of a DLT entry, which is built for each symbol associated with a CODE_PLABEL fixup.
In shared libraries and incomplete executables, a plabel value is the address of a PLT entry for the
target routine, rather than a procedure address. Hence, $$dyncall must be used when calling
a routine with a procedure label. The linker sets the second-to-last bit in the procedure label to flag
this as a special PLT procedure label. The $$dyncall routine checks this bit to determine which
type of procedure label has been passed, and calls the target procedure accordingly.
In order to generate a procedure label that can be used for shared libraries and incomplete
executables, assembly code must specify that a procedure address is being taken (and that a
plabel is wanted) by using the P' assembler fixup mode. For example, to generate an assembly
plabel, the following sequence must be used:
Generating Position-Independent Code 189