SPRAB89A September 2011 – March 2014
In the Initial Exec model, the thread-local variable is accessed as follows:
callp __c6xabi_get_tp() ;Returns TP in A4; Can be CSEed
LDW *+DP($GOT_TPR_byte(x)), A5 ;reloc R_C6000_SBR_GOT_U15_W_TPR_B
LDB *A4[A5], B4 ;
LDW *+DP($GOT_TPR_hword(x)), A5 ;reloc R_C6000_SBR_GOT_U15_W_TPR_H
LDH *A4[A5], B4 ;
LDW *+DP($GOT_TPR_word(x)), A5 ;reloc R_C6000_SBR_GOT_U15_W_TPR_W
LDW *A4[A5], B4 ;
LDW *+DP($GOT_TPR_dword(x)), A5 ;reloc R_C6000_SBR_GOT_U15_W_TPR_D
LDDW *A4[A5], B4 ;
The relocation R_C6000_SBR_GOT_U15_W_TPR_[B|H|W] causes the linker to create a GOT entry for x’s TPR offset:
GOT[m] ;reloc R_C6000_TPR_U32_B (symbol x)
GOT[n] ;reloc R_C6000_TPR_U32_H (symbol y)
GOT[o] ;reloc R_C6000_TPR_U32_W (symbol z)
GOT[p] ;reloc R_C6000_TPR_U32_D (symbol z)
The _TPR_U32_[B|H|W|DW] relocations are resolved by the dynamic loader with the offset of x from the thread pointer. These relocations are scaled as per the access width.
If the GOT must be accessed using far-DP addressing, the sequence is as follows:
callp __c6xabi_get_tp() ;Returns TP in A4; Can be CSEed
MVKL $DPR_GOT_TPR_byte(x), A5 ;reloc R_C6000_SBR_GOT_L16_W_TPR_B
MVKH $DPR_GOT_TPR_byte(x), A5 ;reloc R_C6000_SBR_GOT_H16_W_TPR_B
ADD DP, A5, A5
LDW *A5, A5
LDB *A4[A5], A6
MVKL $DPR_GOT_TPR_hword(x), A5 ;reloc R_C6000_SBR_GOT_L16_W_TPR_H
MVKH $DPR_GOT_TPR_hword(x), A5 ;reloc R_C6000_SBR_GOT_H16_W_TPR_H
ADD DP, A5, A5
LDW *A5, A5
LDH *A4[A5], A6
MVKL $DPR_GOT_TPR_word(x), A5 ;reloc R_C6000_SBR_GOT_L16_W_TPR_W
MVKH $DPR_GOT_TPR_word(x), A5 ;reloc R_C6000_SBR_GOT_H16_W_TPR_W
ADD DP, A5, A5
LDW *A5, A5
LDW *A4[A5], A6
MVKL $DPR_GOT_TPR_dword(x), A5 ;reloc R_C6000_SBR_GOT_L16_W_TPR_D
MVKH $DPR_GOT_TPR_dword(x), A5 ;reloc R_C6000_SBR_GOT_H16_W_TPR_D
ADD DP, A5, A5
LDW *A5, A5
LDDW *A4[A5], A6