| # An external tdata symbol |
| .globl tdata_ext[TL] |
| .csect tdata_ext[TL] |
| .long 1 |
| |
| .csect tdata_int_csect[TL] |
| # A first internal tdata symbol |
| tdata_int1: |
| .long 2 |
| # A second internal tdata symbol |
| tdata_int2: |
| .long 3 |
| |
| # Two external tbss symbols. |
| # XCOFF doesn't seem to allow internal tbss |
| # (or bss) symbols. |
| .comm tbss_ext[UL],8 |
| |
| .toc |
| # TC entries targeting the external tdata symbol |
| # Their value should be "tdata_ext" address, |
| # except TLSM value which must be 0. |
| # Their relocations should target it. |
| .tc tdata_ext_gd[TC],tdata_ext[TL] |
| .tc .tdata_ext_gd[TC],tdata_ext[TL]@m |
| .tc tdata_ext_ld[TC],tdata_ext[TL]@ld |
| .tc tdata_ext_ie[TC],tdata_ext[TL]@ie |
| .tc tdata_ext_le[TC],tdata_ext[TL]@le |
| |
| # TC entries targeting internal tdata symbols. |
| # Their value should be "tdata_int1" or "tdata_int2" |
| # addresses, except TLSM value which must be 0. |
| # Their relocations should target "tdata_int_csect". |
| .tc tdata_int1_gd[TC],tdata_int1 |
| .tc .tdata_int1_gd[TC],tdata_int1@m |
| .tc tdata_int1_ld[TC],tdata_int1@ld |
| .tc tdata_int1_ie[TC],tdata_int1@ie |
| .tc tdata_int1_le[TC],tdata_int1@le |
| .tc tdata_int2_gd[TC],tdata_int2 |
| .tc .tdata_int2_gd[TC],tdata_int2@m |
| .tc tdata_int2_ld[TC],tdata_int2@ld |
| .tc tdata_int2_ie[TC],tdata_int2@ie |
| .tc tdata_int2_le[TC],tdata_int2@le |
| |
| # TC entries targeting the external tdata symbol |
| # Their value should be "tbss_ext" address, |
| # except TLSM value which must be 0. |
| # Their relocations should target "tbss_ext". |
| .tc tbss_ext_gd[TC],tbss_ext[UL] |
| .tc .tbss_ext_gd[TC],tbss_ext[UL]@m |
| .tc tbss_ext_ld[TC],tbss_ext[UL]@ld |
| .tc tbss_ext_ie[TC],tbss_ext[UL]@ie |
| .tc tbss_ext_le[TC],tbss_ext[UL]@le |
| |
| # Module entry |
| .tc mh[TC],mh[TC]@ml |
| .rename mh[TC], "_$TLSML" # Symbol for the module handle |
| |
| # Macros |
| .macro gd_macro,sym |
| .if size == 32 |
| lwz 4, \sym\()[TC](2) |
| lwz 3, .\sym\()[TC](2) |
| .else |
| ld 4, \sym\()[TC](2) |
| ld 3, .\sym\()[TC](2) |
| .endif |
| bla __tls_get_addr |
| .endm |
| |
| .macro ld_macro, sym |
| .if size == 32 |
| lwz 4, \sym\()[TC](2) |
| .else |
| ld 4, \sym\()[TC](2) |
| .endif |
| add 5,3,4 |
| .endm |
| |
| .macro ie_macro, sym |
| .if size == 32 |
| bla __get_tpointer |
| lwz 4, \sym\()[TC](2) |
| add 5,3,4 |
| .else |
| ld 4, \sym\()[TC](2) |
| add 5,4,13 |
| .endif |
| .endm |
| |
| .macro le_macro, sym |
| .if size == 32 |
| bla __get_tpointer |
| lwz 4, \sym\()[TC](2) |
| add 5,3,4 |
| .else |
| ld 4, \sym\()[TC](2) |
| add 5,3,13 |
| .endif |
| .endm |
| |
| |
| # As TLS relocations are made in for TC symbols, |
| # this function only aims to avoid garbage collection |
| # of these symbols, especially hidden ones. |
| .globl foo |
| .globl .foo |
| .csect foo[DS],3 |
| foo: |
| .if size == 32 |
| .long .foo, TOC[tc0], 0 |
| .else |
| .llong .foo, TOC[tc0], 0 |
| .endif |
| |
| .csect foo[PR] |
| .foo: |
| # External syms |
| #GD |
| gd_macro tdata_ext_gd |
| gd_macro tdata_int1_gd |
| gd_macro tdata_int2_gd |
| gd_macro tbss_ext_gd |
| |
| #LD |
| .if size == 32 |
| lwz 3, mh[TC](2) |
| .else |
| ld 3, mh[TC](2) |
| .endif |
| bla __tls_get_mod |
| ld_macro tdata_ext_ld |
| ld_macro tdata_int1_ld |
| ld_macro tdata_int2_ld |
| ld_macro tbss_ext_ld |
| |
| #IE |
| ie_macro tdata_ext_ie |
| ie_macro tdata_int1_ie |
| ie_macro tdata_int2_ie |
| ie_macro tbss_ext_ie |
| |
| #LE |
| le_macro tdata_ext_le |
| le_macro tdata_int1_le |
| le_macro tdata_int2_le |
| le_macro tbss_ext_le |