Go to main content

SPARC Assembly Language Reference Manual

Exit Print View

Updated: November 2020
 
 

5.3 Global Object Table (GOT) Code Models

On SPARC processors, position independent code (PIC) uses a global object table (GOT) for loading addresses, so that the addresses can be determined at run-time by the dynamic linker.

For some data items, a faster access is possible by using the GOTdata relocations.

There are two different code models for GOTdata, plain GOTdata, and GOTdata_op.

Here is the code for the GOTdata_op code model.

add:
.L900000105:
        rd      %pc,%o1
        sethi   %pc22(_GLOBAL_OFFSET_TABLE_-(.L900000105-.)),%g1
        add     %g1,%pc10(_GLOBAL_OFFSET_TABLE_-(.L900000105-.)),%g1
        add     %g1,%o1,%o1
        sethi   %gdop_hix22(sum),%o3
        xor     %o3,%gdop_lox10(sum),%o2
        ldx     [%o1+%o2],%g4,%gdop(sum)
        ld      [%g4],%g5
        add     %g5,%o0,%g3
        retl
        st      %g3,[%g4]
        .type   add,#function
        .size   add,(.-add)

There are four instructions to form a pointer to the GOT into register %o1. Then it takes two more instructions to form the offset of the address of sum in the GOT (in %o2), and another instruction to add those to the address of the GOT to form the address of the GOT slot for sum, and load that address into %g4.

At this point, the code looks much like the PIC32 code model.

The operators act like this:

%gdop_hix22(sum) --> R_SPARC_GOTDATA_OP_HIX22
%gdop_lox10(sum) --> R_SPARC_GOTDATA_OP_LOX10
%gdop(sum)       --> R_SPARC_GOTDATA_OP

The difference for the GOTdata_op code model is that the static linker, ld, can re-write the code sequence to avoid one load from the GOT. This can happen if the distance from the beginning of the GOT to the location of sum is less than 2 GB away.

So, then the following load is re-written into an add:

ldx     [%o1+%o2],%g4,%gdop(sum)
add     %o1,%o2,%g4

Here is the code for the plain GOTdata code model.

add:
.L900000105:
        rd      %pc,%o1
        sethi   %pc22(_GLOBAL_OFFSET_TABLE_-(.L900000105-.)),%g1
        add     %g1,%pc10(_GLOBAL_OFFSET_TABLE_-(.L900000105-.)),%g1
        add     %g1,%o1,%o1
        sethi   %gd_hix22(sum),%o3
        xor     %o3,%gd_lox10(sum),%o2
        ld      [%o1+%o2],%g5
        add     %g5,%o0,%g3
        retl
        st      %g3,[%o1+%o2]
        .type   add,#function
        .size   add,(.-add)

There are four instructions to form a pointer to the GOT into register %o1. Then it takes two more instructions to form the offset of the address of sum in the GOT (in %o2). Now the sum of %o1 and %o2 can be used directly to load the value of sum.

The operators act like this:

%gd_hix22(sum) --> R_SPARC_GOTDATA_HIX22
%gd_lox10(sum) --> R_SPARC_GOTDATA_LOX10

The plain GOTdata code is simpler than the GOTdata_op code, but it requires that the data be within 2 GB of the start of the GOT, otherwise a static link-time error will result.