SPRAB89A September 2011 – March 2014
This access model is an optimization of the General Dynamic Model to access a module's own data. If the compiler knows it is accessing a module’s own thread-local storage, then this access model can be used. If the thread-local variable is defined in the same module where it is accessed, then the TLS offset is known at static link time. However, the module-id is not known at static link time.
A call to __tls_get_addr() with an offset argument of zero returns the base address of that module’s TLS block. This base address can be used to access all the thread-local data belonging to that module.
At compile time, the thread's own data is identified using the symbol binding and visibility. Symbols with static scope or hidden/protected visibility are own data. In this model, thread-local x can be accessed as follows:
LDW *+DP($GOT_TLSMOD(x)), A4 ; reloc R_C6000_SBR_GOT_U15_W_TLSMOD
MVK $TBR_word(x), A5 ; reloc R_C6000_TBR_U15_W
|| CALLP __tls_get_addr,B3 ; A4 has the address of x at return
As mentioned previously, the own TLS base can be obtained once and reused to access other own thread-local variables as follows:
LDW *+DP($GOT_TLSMOD()), A4 ; reloc R_C6000_SBR_GOT_U15_W_TLSMOD w/ Symbol=0
MVK 0x0, A5 ;
|| CALLP __tls_get_addr,B3 ; A4 has the module’s own TLS base
MVK $TBR_byte(x), A5 ; reloc R_C6000_TBR_U15_B; Get x’s scaled TLS offset
LDB *A4[A5], A6 ; A6 has the value of thread-local char x
MVK $TBR_hword(y), A5 ; reloc R_C6000_TBR_U15_H; Get y’s scaled TLS offset
LDH *A4[A5], A6 ; A6 has the value of thread-local short y
MVK $TBR_word(z), A5 ; reloc R_C6000_TBR_U15_W; Get z’s scaled TLS offset
LDW *A4[A5], A6 ; A6 has the value of thread-local int z
MVK $TBR_dword(l), A5 ; reloc R_C6000_TBR_U15_D; Get l’s scaled TLS offset
LDDW *A4[A5], A7:A6 ; A7:A6 has the value of thread-local long long l
The relocation R_C6000_SBR_GOT_U15_W_TLSMOD resolves to the module’s own module-id when the symbol is zero. The TBR_U15 relocations encode a 15-bit unsigned offset from the module’s TLS Base for near TB (TLS Block Base) addressing. They are scaled according to the access width. The previous addressing can access a TLS block of size 32 KB. This specification limits the size of each module’s TLS block to 32 KB, a limit that is expected to be sufficient for most use cases. Hence the far TB relative address is not defined. Far TBR addressing may be defined, but it will use up 8 new relocations, and it is better to conserve the limited number of relocations (256) ELF allows.
The static linker resolves all the TBR relocations using static-only relocations. That is, these relocations cannot be in the dynamic relocation table.