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