Back to index

glibc  2.9
tls-macros.h
Go to the documentation of this file.
00001 /* Macros to support TLS testing in times of missing compiler support.  */
00002 
00003 #define COMMON_INT_DEF(x) \
00004   asm (".tls_common " #x ",4,4")
00005 /* XXX Until we get compiler support we don't need declarations.  */
00006 #define COMMON_INT_DECL(x)
00007 
00008 /* XXX This definition will probably be machine specific, too.  */
00009 #define VAR_INT_DEF(x) \
00010   asm (".section .tdata\n\t"                                                \
00011        ".globl " #x "\n"                                             \
00012        ".balign 4\n"                                                 \
00013        #x ":\t.long 0\n\t"                                           \
00014        ".size " #x ",4\n\t"                                          \
00015        ".previous")
00016 /* XXX Until we get compiler support we don't need declarations.  */
00017 #define VAR_INT_DECL(x)
00018 
00019 #include_next <tls-macros.h>
00020 
00021   /* XXX Each architecture must have its own asm for now.  */
00022 #ifdef __i386__
00023 # define TLS_LE(x) \
00024   ({ int *__l;                                                              \
00025      asm ("movl %%gs:0,%0\n\t"                                              \
00026          "subl $" #x "@tpoff,%0"                                     \
00027          : "=r" (__l));                                              \
00028      __l; })
00029 
00030 # ifdef PIC
00031 #  define TLS_IE(x) \
00032   ({ int *__l;                                                              \
00033      asm ("movl %%gs:0,%0\n\t"                                              \
00034          "subl " #x "@gottpoff(%%ebx),%0"                            \
00035          : "=r" (__l));                                              \
00036      __l; })
00037 # else
00038 #  define TLS_IE(x) \
00039   ({ int *__l, __b;                                                  \
00040      asm ("call 1f\n\t"                                                     \
00041          ".subsection 1\n"                                           \
00042          "1:\tmovl (%%esp), %%ebx\n\t"                                      \
00043          "ret\n\t"                                                   \
00044          ".previous\n\t"                                             \
00045          "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"                           \
00046          "movl %%gs:0,%0\n\t"                                               \
00047          "subl " #x "@gottpoff(%%ebx),%0"                            \
00048          : "=r" (__l), "=&b" (__b));                                        \
00049      __l; })
00050 # endif
00051 
00052 # ifdef PIC
00053 #  define TLS_LD(x) \
00054   ({ int *__l, __c, __d;                                             \
00055      asm ("leal " #x "@tlsldm(%%ebx),%%eax\n\t"                             \
00056          "call ___tls_get_addr@plt\n\t"                              \
00057          "leal " #x "@dtpoff(%%eax), %%eax"                                 \
00058          : "=a" (__l), "=&c" (__c), "=&d" (__d));                           \
00059      __l; })
00060 # else
00061 #  define TLS_LD(x) \
00062   ({ int *__l, __b, __c, __d;                                               \
00063      asm ("call 1f\n\t"                                                     \
00064          ".subsection 1\n"                                           \
00065          "1:\tmovl (%%esp), %%ebx\n\t"                                      \
00066          "ret\n\t"                                                   \
00067          ".previous\n\t"                                             \
00068          "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"                           \
00069          "leal " #x "@tlsldm(%%ebx),%%eax\n\t"                              \
00070          "call ___tls_get_addr@plt\n\t"                              \
00071          "leal " #x "@dtpoff(%%eax), %%eax"                                 \
00072          : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d));              \
00073      __l; })
00074 # endif
00075 
00076 # ifdef PIC
00077 #  define TLS_GD(x) \
00078   ({ int *__l, __c, __d;                                             \
00079      asm ("leal " #x "@tlsgd(%%ebx),%%eax\n\t"                              \
00080          "call ___tls_get_addr@plt\n\t"                              \
00081          "nop"                                                              \
00082          : "=a" (__l), "=&c" (__c), "=&d" (__d));                           \
00083      __l; })
00084 # else
00085 #  define TLS_GD(x) \
00086   ({ int *__l, __b, __c, __d;                                               \
00087      asm ("call 1f\n\t"                                                     \
00088          ".subsection 1\n"                                           \
00089          "1:\tmovl (%%esp), %%ebx\n\t"                                      \
00090          "ret\n\t"                                                   \
00091          ".previous\n\t"                                             \
00092          "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"                           \
00093          "leal " #x "@tlsgd(%%ebx),%%eax\n\t"                               \
00094          "call ___tls_get_addr@plt\n\t"                              \
00095          "nop"                                                              \
00096          : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d));              \
00097      __l; })
00098 # endif
00099 
00100 #elif defined __x86_64__
00101 
00102 # define TLS_LE(x) \
00103   ({ int *__l;                                                              \
00104      asm ("movq %%fs:0,%0\n\t"                                              \
00105          "leaq " #x "@tpoff(%0), %0"                                        \
00106          : "=r" (__l));                                              \
00107      __l; })
00108 
00109 # define TLS_IE(x) \
00110   ({ int *__l;                                                              \
00111      asm ("movq %%fs:0,%0\n\t"                                              \
00112          "addq " #x "@gottpoff(%%rip),%0"                            \
00113          : "=r" (__l));                                              \
00114      __l; })
00115 
00116 # define TLS_LD(x) \
00117   ({ int *__l, __c, __d;                                             \
00118      asm ("leaq " #x "@tlsld(%%rip),%%rdi\n\t"                              \
00119          "call __tls_get_addr@plt\n\t"                                      \
00120          "leaq " #x "@dtpoff(%%rax), %%rax"                                 \
00121          : "=a" (__l), "=&c" (__c), "=&d" (__d)                      \
00122          : : "rdi", "rsi", "r8", "r9", "r10", "r11");                       \
00123      __l; })
00124 
00125 # define TLS_GD(x) \
00126   ({ int *__l, __c, __d;                                             \
00127      asm (".byte 0x66\n\t"                                           \
00128          "leaq " #x "@tlsgd(%%rip),%%rdi\n\t"                               \
00129          ".word 0x6666\n\t"                                          \
00130          "rex64\n\t"                                                 \
00131          "call __tls_get_addr@plt"                                   \
00132          : "=a" (__l), "=&c" (__c), "=&d" (__d)                      \
00133          : : "rdi", "rsi", "r8", "r9", "r10", "r11");                       \
00134      __l; })
00135 
00136 #elif defined __sh__
00137 
00138 # define TLS_LE(x) \
00139   ({ int *__l; void *__tp;                                           \
00140      asm ("stc gbr,%1\n\t"                                           \
00141          "mov.l 1f,%0\n\t"                                           \
00142          "bra 2f\n\t"                                                       \
00143          " add %1,%0\n\t"                                            \
00144          ".align 2\n\t"                                              \
00145          "1: .long " #x "@tpoff\n\t"                                        \
00146          "2:"                                                        \
00147          : "=r" (__l), "=r" (__tp));                                        \
00148      __l; })
00149 
00150 # ifdef PIC
00151 #  define TLS_IE(x) \
00152   ({ int *__l; void *__tp;                                           \
00153      register void *__gp __asm__("r12");                             \
00154      asm ("mov.l 1f,r0\n\t"                                          \
00155          "stc gbr,%1\n\t"                                            \
00156          "mov.l @(r0,r12),%0\n\t"                                    \
00157          "bra 2f\n\t"                                                       \
00158          " add %1,%0\n\t"                                            \
00159          ".align 2\n\t"                                              \
00160          "1: .long " #x "@gottpoff\n\t"                              \
00161          "2:"                                                        \
00162          : "=r" (__l), "=r" (__tp) : "r" (__gp) : "r0");                    \
00163      __l; })
00164 # else
00165 #  define TLS_IE(x) \
00166   ({ int *__l; void *__tp;                                           \
00167      asm ("mov.l r12,@-r15\n\t"                                             \
00168          "mova 0f,r0\n\t"                                            \
00169          "mov.l 0f,r12\n\t"                                          \
00170          "add r0,r12\n\t"                                            \
00171          "mov.l 1f,r0\n\t"                                           \
00172          "stc gbr,%1\n\t"                                            \
00173          "mov.l @(r0,r12),%0\n\t"                                    \
00174          "bra 2f\n\t"                                                       \
00175          " add %1,%0\n\t"                                            \
00176          ".align 2\n\t"                                              \
00177          "1: .long " #x "@gottpoff\n\t"                              \
00178          "0: .long _GLOBAL_OFFSET_TABLE_\n\t"                               \
00179          "2: mov.l @r15+,r12"                                               \
00180          : "=r" (__l), "=r" (__tp) : : "r0");                               \
00181      __l; })
00182 #endif
00183 
00184 # ifdef PIC
00185 #  define TLS_LD(x) \
00186   ({ int *__l;                                                              \
00187      register void *__gp __asm__("r12");                             \
00188      asm ("mov.l 1f,r4\n\t"                                          \
00189          "mova 2f,r0\n\t"                                            \
00190          "mov.l 2f,r1\n\t"                                           \
00191          "add r0,r1\n\t"                                             \
00192          "jsr @r1\n\t"                                                      \
00193          " add r12,r4\n\t"                                           \
00194          "bra 4f\n\t"                                                       \
00195          " nop\n\t"                                                  \
00196          ".align 2\n\t"                                              \
00197          "1: .long " #x "@tlsldm\n\t"                                       \
00198          "2: .long __tls_get_addr@plt\n\t"                                  \
00199          "4: mov.l 3f,%0\n\t"                                               \
00200          "bra 5f\n\t"                                                       \
00201          " add r0,%0\n\t"                                            \
00202          ".align 2\n\t"                                              \
00203          "3: .long " #x "@dtpoff\n\t"                                       \
00204          "5:"                                                        \
00205          : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5",     \
00206                                   "r6", "r7", "pr", "t");                   \
00207      __l; })
00208 # else
00209 #  define TLS_LD(x) \
00210   ({ int *__l;                                                              \
00211      asm ("mov.l r12,@-r15\n\t"                                             \
00212          "mova 0f,r0\n\t"                                            \
00213          "mov.l 0f,r12\n\t"                                          \
00214          "add r0,r12\n\t"                                            \
00215          "mov.l 1f,r4\n\t"                                           \
00216          "mova 2f,r0\n\t"                                            \
00217          "mov.l 2f,r1\n\t"                                           \
00218          "add r0,r1\n\t"                                             \
00219          "jsr @r1\n\t"                                                      \
00220          " add r12,r4\n\t"                                           \
00221          "bra 4f\n\t"                                                       \
00222          " nop\n\t"                                                  \
00223          ".align 2\n\t"                                              \
00224          "1: .long " #x "@tlsldm\n\t"                                       \
00225          "2: .long __tls_get_addr@plt\n\t"                                  \
00226          "0: .long _GLOBAL_OFFSET_TABLE_\n\t"                               \
00227          "4: mov.l 3f,%0\n\t"                                               \
00228          "bra 5f\n\t"                                                       \
00229          " add r0,%0\n\t"                                            \
00230          ".align 2\n\t"                                              \
00231          "3: .long " #x "@dtpoff\n\t"                                       \
00232          "5: mov.l @r15+,r12"                                               \
00233          : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",    \
00234                         "pr", "t");                                         \
00235      __l; })
00236 #endif
00237 
00238 # ifdef PIC
00239 #  define TLS_GD(x) \
00240   ({ int *__l;                                                              \
00241      register void *__gp __asm__("r12");                             \
00242      asm ("mov.l 1f,r4\n\t"                                          \
00243          "mova 2f,r0\n\t"                                            \
00244          "mov.l 2f,r1\n\t"                                           \
00245          "add r0,r1\n\t"                                             \
00246          "jsr @r1\n\t"                                                      \
00247          " add r12,r4\n\t"                                           \
00248          "bra 3f\n\t"                                                       \
00249          " mov r0,%0\n\t"                                            \
00250          ".align 2\n\t"                                              \
00251          "1: .long " #x "@tlsgd\n\t"                                        \
00252          "2: .long __tls_get_addr@plt\n\t"                                  \
00253          "3:"                                                        \
00254          : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5",     \
00255                                   "r6", "r7", "pr", "t");                   \
00256      __l; })
00257 # else
00258 #  define TLS_GD(x) \
00259   ({ int *__l;                                                              \
00260      asm ("mov.l r12,@-r15\n\t"                                             \
00261          "mova 0f,r0\n\t"                                            \
00262          "mov.l 0f,r12\n\t"                                          \
00263          "add r0,r12\n\t"                                            \
00264          "mov.l 1f,r4\n\t"                                           \
00265          "mova 2f,r0\n\t"                                            \
00266          "mov.l 2f,r1\n\t"                                           \
00267          "add r0,r1\n\t"                                             \
00268          "jsr @r1\n\t"                                                      \
00269          " add r12,r4\n\t"                                           \
00270          "bra 3f\n\t"                                                       \
00271          " mov r0,%0\n\t"                                            \
00272          ".align 2\n\t"                                              \
00273          "1: .long " #x "@tlsgd\n\t"                                        \
00274          "2: .long __tls_get_addr@plt\n\t"                                  \
00275          "0: .long _GLOBAL_OFFSET_TABLE_\n\t"                               \
00276          "3: mov.l @r15+,r12"                                               \
00277          : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",    \
00278                         "pr", "t");                                         \
00279      __l; })
00280 #endif
00281 
00282 #elif defined __alpha__
00283 
00284 register void *__gp __asm__("$29");
00285 
00286 # define TLS_LE(x) \
00287   ({ int *__l;                                                              \
00288      asm ("call_pal 158\n\tlda $0," #x "($0)\t\t!tprel" : "=v"(__l));       \
00289      __l; })
00290 
00291 # define TLS_IE(x) \
00292   ({ char *__tp; unsigned long __o;                                         \
00293      asm ("call_pal 158\n\tldq %1," #x "($gp)\t\t!gottprel"                 \
00294          : "=v"(__tp), "=r"(__o) : "r"(__gp));                              \
00295      (int *)(__tp + __o); })
00296 
00297 # define TLS_LD(x) \
00298   ({ extern void *__tls_get_addr(void *); int *__l; void *__i;              \
00299      asm ("lda %0," #x "($gp)\t\t!tlsldm" : "=r" (__i) : "r"(__gp));        \
00300      __i = __tls_get_addr(__i);                                             \
00301      asm ("lda %0, " #x "(%1)\t\t!dtprel" : "=r"(__l) : "r"(__i));          \
00302      __l; })
00303 
00304 # define TLS_GD(x) \
00305   ({ extern void *__tls_get_addr(void *); void *__i;                        \
00306      asm ("lda %0," #x "($gp)\t\t!tlsgd" : "=r" (__i) : "r"(__gp));         \
00307      (int *) __tls_get_addr(__i); })
00308 
00309 
00310 #elif defined __ia64__
00311 
00312 # define TLS_LE(x) \
00313   ({ void *__l;                                                             \
00314      asm ("mov r2=r13\n\t"                                           \
00315          ";;\n\t"                                                    \
00316          "addl %0=@tprel(" #x "),r2\n\t"                             \
00317          : "=r" (__l) : : "r2"  ); __l; })
00318 
00319 # define TLS_IE(x) \
00320   ({ void *__l;                                                             \
00321      register long __gp asm ("gp");                                         \
00322      asm (";;\n\t"                                                   \
00323         "addl r16=@ltoff(@tprel(" #x ")),gp\n\t"                     \
00324          ";;\n\t"                                                    \
00325          "ld8 r17=[r16]\n\t"                                                \
00326          ";;\n\t"                                                    \
00327          "add %0=r13,r17\n\t"                                               \
00328          ";;\n\t"                                                    \
00329          : "=r" (__l) : "r" (__gp) : "r16", "r17" ); __l; })
00330 
00331 # define __TLS_CALL_CLOBBERS \
00332   "r2", "r3", "r8", "r9", "r10", "r11", "r14", "r15", "r16", "r17",         \
00333   "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",            \
00334   "r27", "r28", "r29", "r30", "r31",                                        \
00335   "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",         \
00336   "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",         \
00337   "b6", "b7",                                                        \
00338   "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7"
00339 
00340 # define TLS_LD(x) \
00341   ({ void *__l;                                                             \
00342      register long __gp asm ("gp");                                         \
00343      asm (";;\n\t"                                                   \
00344         "mov loc0=gp\n\t"                                            \
00345          "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t"                          \
00346          "addl out1=@dtprel(" #x "),r0\n\t"                                 \
00347          ";;\n\t"                                                    \
00348          "ld8 out0=[r16]\n\t"                                               \
00349          "br.call.sptk.many b0=__tls_get_addr"                              \
00350          ";;\n\t"                                                    \
00351          "mov gp=loc0\n\t"                                           \
00352          "mov %0=r8\n\t"                                             \
00353          ";;\n\t"                                                    \
00354          : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS);          \
00355      __l; })
00356 
00357 # define TLS_GD(x) \
00358   ({ void *__l;                                                             \
00359      register long __gp asm ("gp");                                         \
00360      asm (";;\n\t"                                                   \
00361         "mov loc0=gp\n\t"                                            \
00362          "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t"                          \
00363          "addl r17=@ltoff(@dtprel(" #x ")),gp\n\t"                          \
00364          ";;\n\t"                                                    \
00365          "ld8 out0=[r16]\n\t"                                               \
00366          "ld8 out1=[r17]\n\t"                                               \
00367          "br.call.sptk.many b0=__tls_get_addr"                              \
00368          ";;\n\t"                                                    \
00369          "mov gp=loc0\n\t"                                           \
00370          "mov %0=r8\n\t"                                             \
00371          ";;\n\t"                                                    \
00372           : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS);         \
00373      __l; })
00374 
00375 #elif defined __sparc__ && !defined __arch64__
00376 
00377 # define TLS_LE(x) \
00378   ({ int *__l;                                                              \
00379      asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l));                    \
00380      asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l));             \
00381      asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l));                     \
00382      __l; })
00383 
00384 # ifdef __PIC__
00385 #  define TLS_LOAD_PIC \
00386   ({ register long pc __asm__ ("%o7");                                      \
00387      long got;                                                              \
00388      asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"                     \
00389          "call .+8\n\t"                                              \
00390          "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"                    \
00391          "add %1, %0, %1\n\t"                                               \
00392          : "=r" (pc), "=r" (got));                                   \
00393      got; })
00394 # else
00395 #  define TLS_LOAD_PIC \
00396    ({ long got;                                                             \
00397       asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t"                              \
00398           "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t"                       \
00399           "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0"                          \
00400           : "=r" (got));                                             \
00401       got; })
00402 # endif
00403 
00404 # define TLS_IE(x) \
00405   ({ int *__l;                                                              \
00406      asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l));                     \
00407      asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));       \
00408      asm ("ld [%1 + %2], %0, %%tie_ld(" #x ")"                              \
00409          : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l));              \
00410      asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l));    \
00411      __l; })
00412 
00413 # define TLS_LD(x) \
00414   ({ int *__l; register void *__o0 asm ("%o0");                             \
00415      long __o;                                                              \
00416      asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l));                    \
00417      asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));             \
00418      asm ("add %1, %2, %0, %%tldm_add(" #x ")"                              \
00419          : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                    \
00420      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                     \
00421          " nop"                                                      \
00422          : "=r" (__o0) : "0" (__o0)                                         \
00423          : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",             \
00424            "o5", "o7", "cc");                                               \
00425      asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o));                   \
00426      asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o));            \
00427      asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l)                 \
00428          : "r" (__o0), "r" (__o));                                   \
00429      __l; })
00430 
00431 # define TLS_GD(x) \
00432   ({ int *__l; register void *__o0 asm ("%o0");                             \
00433      asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l));                     \
00434      asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));       \
00435      asm ("add %1, %2, %0, %%tgd_add(" #x ")"                               \
00436          : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                    \
00437      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                     \
00438          " nop"                                                      \
00439          : "=r" (__o0) : "0" (__o0)                                         \
00440          : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",             \
00441            "o5", "o7", "cc");                                               \
00442      __o0; })
00443 
00444 #elif defined __sparc__ && defined __arch64__
00445 
00446 # define TLS_LE(x) \
00447   ({ int *__l;                                                              \
00448      asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l));                    \
00449      asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l));             \
00450      asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l));                     \
00451      __l; })
00452 
00453 # ifdef __PIC__
00454 #  define TLS_LOAD_PIC \
00455   ({ long pc, got;                                                   \
00456      asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"                     \
00457          "rd %%pc, %0\n\t"                                           \
00458          "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"                    \
00459          "add %1, %0, %1\n\t"                                               \
00460          : "=r" (pc), "=r" (got));                                   \
00461      got; })
00462 # else
00463 #  define TLS_LOAD_PIC \
00464    ({ long got;                                                             \
00465       asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t"                              \
00466           "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t"                       \
00467           "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0"                          \
00468           : "=r" (got));                                             \
00469       got; })
00470 # endif
00471 
00472 # define TLS_IE(x) \
00473   ({ int *__l;                                                              \
00474      asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l));                     \
00475      asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));       \
00476      asm ("ldx [%1 + %2], %0, %%tie_ldx(" #x ")"                     \
00477          : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l));              \
00478      asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l));    \
00479      __l; })
00480 
00481 # define TLS_LD(x) \
00482   ({ int *__l; register void *__o0 asm ("%o0");                             \
00483      long __o;                                                              \
00484      asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l));                    \
00485      asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));             \
00486      asm ("add %1, %2, %0, %%tldm_add(" #x ")"                              \
00487          : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                    \
00488      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                     \
00489          " nop"                                                      \
00490          : "=r" (__o0) : "0" (__o0)                                         \
00491          : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",             \
00492            "o5", "o7", "cc");                                               \
00493      asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o));                   \
00494      asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o));            \
00495      asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l)                 \
00496          : "r" (__o0), "r" (__o));                                   \
00497      __l; })
00498 
00499 # define TLS_GD(x) \
00500   ({ int *__l; register void *__o0 asm ("%o0");                             \
00501      asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l));                     \
00502      asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));       \
00503      asm ("add %1, %2, %0, %%tgd_add(" #x ")"                               \
00504          : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                    \
00505      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                     \
00506          " nop"                                                      \
00507          : "=r" (__o0) : "0" (__o0)                                         \
00508          : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",             \
00509            "o5", "o7", "cc");                                               \
00510      __o0; })
00511 
00512 #elif defined __s390x__
00513 
00514 # define TLS_LE(x) \
00515   ({ unsigned long __offset;                                                \
00516      asm ("bras %0,1f\n"                                             \
00517          "0:\t.quad " #x "@ntpoff\n"                                        \
00518          "1:\tlg %0,0(%0)"                                           \
00519          : "=a" (__offset) : : "cc" );                                      \
00520      (int *) (__builtin_thread_pointer() + __offset); })
00521 
00522 # ifdef PIC
00523 #  define TLS_IE(x) \
00524   ({ unsigned long __offset;                                                \
00525      asm ("bras %0,1f\n"                                             \
00526          "0:\t.quad " #x "@gotntpoff\n"                              \
00527          "1:\tlg %0,0(%0)\n\t"                                              \
00528          "lg %0,0(%0,%%r12):tls_load:" #x                            \
00529          : "=&a" (__offset) : : "cc" );                              \
00530      (int *) (__builtin_thread_pointer() + __offset); })
00531 # else
00532 #  define TLS_IE(x) \
00533   ({ unsigned long  __offset;                                               \
00534      asm ("bras %0,1f\n"                                             \
00535          "0:\t.quad " #x "@indntpoff\n"                              \
00536          "1:\t lg %0,0(%0)\n\t"                                      \
00537          "lg %0,0(%0):tls_load:" #x                                         \
00538          : "=&a" (__offset) : : "cc" );                              \
00539      (int *) (__builtin_thread_pointer() + __offset); })
00540 # endif
00541 
00542 # ifdef PIC
00543 #  define TLS_LD(x) \
00544   ({ unsigned long __offset, __save12;                                      \
00545      asm ("bras %0,1f\n"                                             \
00546          "0:\t.quad " #x "@tlsldm\n\t"                                      \
00547          ".quad " #x "@dtpoff\n"                                     \
00548          "1:\tlgr %1,%%r12\n\t"                                      \
00549           "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                     \
00550           "lg %%r2,0(%0)\n\t"                                               \
00551          "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t"           \
00552          "lg %0,8(%0)\n\t"                                           \
00553          "algr %0,%%r2\n\t"                                          \
00554           "lgr %%r12,%1"                                             \
00555          : "=&a" (__offset), "=&a" (__save12)                               \
00556           : : "cc", "0", "1", "2", "3", "4", "5", "14" );                   \
00557      (int *) (__builtin_thread_pointer() + __offset); })
00558 # else
00559 #  define TLS_LD(x) \
00560   ({ unsigned long __offset;                                                \
00561      asm ("bras %0,1f\n"                                             \
00562          "0:\t.quad " #x "@tlsldm\n\t"                                      \
00563          ".quad " #x "@dtpoff\n"                                     \
00564          "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                         \
00565           "lg %%r2,0(%0)\n\t"                                               \
00566          "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t"           \
00567          "lg %0,8(%0)\n\t"                                           \
00568          "algr %0,%%r2"                                              \
00569          : "=&a" (__offset)                                          \
00570          : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" );              \
00571      (int *) (__builtin_thread_pointer() + __offset); })
00572 # endif
00573 
00574 # ifdef PIC
00575 #  define TLS_GD(x) \
00576   ({ unsigned long __offset, __save12;                                      \
00577      asm ("bras %0,1f\n"                                             \
00578          "0:\t.quad " #x "@tlsgd\n"                                         \
00579          "1:\tlgr %1,%%r12\n\t"                                      \
00580          "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                      \
00581           "lg %%r2,0(%0)\n\t"                                               \
00582          "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t"           \
00583           "lgr %0,%%r2\n\t"                                          \
00584           "lgr %%r12,%1"                                             \
00585          : "=&a" (__offset), "=&a" (__save12)                               \
00586           : : "cc", "0", "1", "2", "3", "4", "5", "14" );                   \
00587      (int *) (__builtin_thread_pointer() + __offset); })
00588 # else
00589 #  define TLS_GD(x) \
00590   ({ unsigned long __offset;                                                \
00591      asm ("bras %0,1f\n"                                             \
00592          "0:\t.quad " #x "@tlsgd\n"                                         \
00593          "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                         \
00594          "lg %%r2,0(%0)\n\t"                                                \
00595          "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t"           \
00596           "lgr %0,%%r2"                                                     \
00597          : "=&a" (__offset)                                          \
00598          : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" );              \
00599      (int *) (__builtin_thread_pointer() + __offset); })
00600 # endif
00601 
00602 #elif defined __s390__
00603 
00604 # define TLS_LE(x) \
00605   ({ unsigned long __offset;                                                \
00606      asm ("bras %0,1f\n"                                             \
00607          "0:\t.long " #x "@ntpoff\n"                                        \
00608          "1:\tl %0,0(%0)"                                            \
00609          : "=a" (__offset) : : "cc" );                                      \
00610      (int *) (__builtin_thread_pointer() + __offset); })
00611 
00612 # ifdef PIC
00613 #  define TLS_IE(x) \
00614   ({ unsigned long __offset;                                                \
00615      asm ("bras %0,1f\n"                                             \
00616          "0:\t.long " #x "@gotntpoff\n"                              \
00617          "1:\tl %0,0(%0)\n\t"                                               \
00618          "l %0,0(%0,%%r12):tls_load:" #x                             \
00619          : "=&a" (__offset) : : "cc" );                              \
00620      (int *) (__builtin_thread_pointer() + __offset); })
00621 # else
00622 #  define TLS_IE(x) \
00623   ({ unsigned long  __offset;                                               \
00624      asm ("bras %0,1f\n"                                             \
00625          "0:\t.long " #x "@indntpoff\n"                              \
00626          "1:\t l %0,0(%0)\n\t"                                              \
00627          "l %0,0(%0):tls_load:" #x                                   \
00628          : "=&a" (__offset) : : "cc" );                              \
00629      (int *) (__builtin_thread_pointer() + __offset); })
00630 # endif
00631 
00632 # ifdef PIC
00633 #  define TLS_LD(x) \
00634   ({ unsigned long __offset, __save12;                                      \
00635      asm ("bras %0,1f\n"                                             \
00636          "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t"                           \
00637          ".long __tls_get_offset@plt-0b\n\t"                                \
00638          ".long " #x "@tlsldm\n\t"                                   \
00639          ".long " #x "@dtpoff\n"                                     \
00640          "1:\tlr %1,%%r12\n\t"                                              \
00641           "l %%r12,0(%0)\n\t"                                               \
00642           "la %%r12,0(%%r12,%0)\n\t"                                        \
00643          "l %%r1,4(%0)\n\t"                                          \
00644          "l %%r2,8(%0)\n\t"                                          \
00645          "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t"                       \
00646          "l %0,12(%0)\n\t"                                           \
00647          "alr %0,%%r2\n\t"                                           \
00648           "lr %%r12,%1"                                                     \
00649          : "=&a" (__offset), "=&a" (__save12)                               \
00650           : : "cc", "0", "1", "2", "3", "4", "5" );                         \
00651      (int *) (__builtin_thread_pointer() + __offset); })
00652 # else
00653 #  define TLS_LD(x) \
00654   ({ unsigned long __offset;                                                \
00655      asm ("bras %0,1f\n"                                             \
00656          "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t"                              \
00657          ".long __tls_get_offset@plt\n\t"                            \
00658          ".long " #x "@tlsldm\n\t"                                   \
00659          ".long " #x "@dtpoff\n"                                     \
00660          "1:\tl %%r12,0(%0)\n\t"                                     \
00661          "l %%r1,4(%0)\n\t"                                          \
00662          "l %%r2,8(%0)\n\t"                                          \
00663          "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t"                          \
00664          "l %0,12(%0)\n\t"                                           \
00665          "alr %0,%%r2"                                                      \
00666          : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
00667      (int *) (__builtin_thread_pointer() + __offset); })
00668 # endif
00669 
00670 # ifdef PIC
00671 #  define TLS_GD(x) \
00672   ({ unsigned long __offset, __save12;                                      \
00673      asm ("bras %0,1f\n"                                             \
00674          "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t"                           \
00675          ".long __tls_get_offset@plt-0b\n\t"                                \
00676          ".long " #x "@tlsgd\n"                                      \
00677          "1:\tlr %1,%%r12\n\t"                                              \
00678           "l %%r12,0(%0)\n\t"                                               \
00679           "la %%r12,0(%%r12,%0)\n\t"                                        \
00680          "l %%r1,4(%0)\n\t"                                          \
00681          "l %%r2,8(%0)\n\t"                                          \
00682          "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t"                       \
00683           "lr %0,%%r2\n\t"                                           \
00684           "lr %%r12,%1"                                                     \
00685          : "=&a" (__offset), "=&a" (__save12)                               \
00686           : : "cc", "0", "1", "2", "3", "4", "5" );                         \
00687      (int *) (__builtin_thread_pointer() + __offset); })
00688 # else
00689 #  define TLS_GD(x) \
00690   ({ unsigned long __offset;                                                \
00691      asm ("bras %0,1f\n"                                             \
00692          "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t"                              \
00693          ".long __tls_get_offset@plt\n\t"                            \
00694          ".long " #x "@tlsgd\n"                                      \
00695          "1:\tl %%r12,0(%0)\n\t"                                     \
00696          "l %%r1,4(%0)\n\t"                                          \
00697          "l %%r2,8(%0)\n\t"                                          \
00698          "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t"                          \
00699           "lr %0,%%r2"                                                      \
00700          : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
00701      (int *) (__builtin_thread_pointer() + __offset); })
00702 # endif
00703 
00704 #elif defined __powerpc__ && !defined __powerpc64__
00705 
00706 #include "config.h"
00707 
00708 # define __TLS_CALL_CLOBBERS                                          \
00709        "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",      \
00710        "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7"
00711 
00712 /* PowerPC32 Local Exec TLS access.  */
00713 # define TLS_LE(x)                        \
00714   ({ int *__result;                       \
00715      asm ("addi %0,2," #x "@tprel"        \
00716          : "=r" (__result));                     \
00717      __result; })
00718 
00719 /* PowerPC32 Initial Exec TLS access.  */
00720 # ifdef HAVE_ASM_PPC_REL16
00721 #  define TLS_IE(x)                              \
00722   ({ int *__result;                              \
00723      asm ("bcl 20,31,1f\n1:\t"                          \
00724          "mflr %0\n\t"                                  \
00725          "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t"  \
00726          "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t"    \
00727          "lwz %0," #x "@got@tprel(%0)\n\t"              \
00728          "add %0,%0," #x "@tls"                  \
00729          : "=b" (__result) :                            \
00730          : "lr");                                \
00731      __result; })
00732 # else
00733 #  define TLS_IE(x)                              \
00734   ({ int *__result;                              \
00735      asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \
00736          "mflr %0\n\t"                                  \
00737          "lwz %0," #x "@got@tprel(%0)\n\t"              \
00738          "add %0,%0," #x "@tls"                  \
00739          : "=b" (__result) :                            \
00740          : "lr");                                \
00741      __result; })
00742 # endif
00743 
00744 /* PowerPC32 Local Dynamic TLS access.  */
00745 # ifdef HAVE_ASM_PPC_REL16
00746 #  define TLS_LD(x)                              \
00747   ({ int *__result;                              \
00748      asm ("bcl 20,31,1f\n1:\t"                          \
00749          "mflr 3\n\t"                                   \
00750          "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t"    \
00751          "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t"      \
00752          "addi 3,3," #x "@got@tlsld\n\t"         \
00753          "bl __tls_get_addr@plt\n\t"                    \
00754          "addi %0,3," #x "@dtprel"               \
00755          : "=r" (__result) :                            \
00756          : __TLS_CALL_CLOBBERS);                 \
00757      __result; })
00758 # else
00759 #  define TLS_LD(x)                              \
00760   ({ int *__result;                              \
00761      asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \
00762          "mflr 3\n\t"                                   \
00763          "addi 3,3," #x "@got@tlsld\n\t"         \
00764          "bl __tls_get_addr@plt\n\t"                    \
00765          "addi %0,3," #x "@dtprel"               \
00766          : "=r" (__result) :                            \
00767          : __TLS_CALL_CLOBBERS);                 \
00768      __result; })
00769 # endif
00770 
00771 /* PowerPC32 General Dynamic TLS access.  */
00772 # ifdef HAVE_ASM_PPC_REL16
00773 #  define TLS_GD(x)                              \
00774   ({ register int *__result __asm__ ("r3");             \
00775      asm ("bcl 20,31,1f\n1:\t"                          \
00776          "mflr 3\n\t"                                   \
00777          "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t"    \
00778          "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t"      \
00779          "addi 3,3," #x "@got@tlsgd\n\t"         \
00780          "bl __tls_get_addr@plt"                 \
00781          : :                                     \
00782          : __TLS_CALL_CLOBBERS);                 \
00783      __result; })
00784 # else
00785 #  define TLS_GD(x)                              \
00786   ({ register int *__result __asm__ ("r3");             \
00787      asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \
00788          "mflr 3\n\t"                                   \
00789          "addi 3,3," #x "@got@tlsgd\n\t"         \
00790          "bl __tls_get_addr@plt"                 \
00791          : :                                     \
00792          : __TLS_CALL_CLOBBERS);                 \
00793      __result; })
00794 # endif
00795 
00796 #elif defined __powerpc__ && defined __powerpc64__
00797 
00798 /* PowerPC64 Local Exec TLS access.  */
00799 # define TLS_LE(x) \
00800   ({  int * __result;  \
00801       asm ( \
00802         "  addis %0,13," #x "@tprel@ha\n"  \
00803         "  addi  %0,%0," #x "@tprel@l\n"   \
00804         : "=b" (__result) );  \
00805       __result;  \
00806   })
00807 /* PowerPC64 Initial Exec TLS access.  */
00808 #  define TLS_IE(x) \
00809   ({  int * __result;  \
00810       asm (  \
00811         "  ld  %0," #x "@got@tprel(2)\n"  \
00812         "  add %0,%0," #x "@tls\n"   \
00813         : "=b" (__result) );  \
00814       __result;  \
00815   })
00816 # ifdef HAVE_ASM_GLOBAL_DOT_NAME
00817 #  define __TLS_GET_ADDR ".__tls_get_addr"
00818 # else
00819 #  define __TLS_GET_ADDR "__tls_get_addr"
00820 # endif
00821 /* PowerPC64 Local Dynamic TLS access.  */
00822 #  define TLS_LD(x) \
00823   ({  int * __result;  \
00824       asm (  \
00825         "  addi  3,2," #x "@got@tlsld\n"  \
00826         "  bl    " __TLS_GET_ADDR "\n"  \
00827         "  nop   \n"  \
00828         "  addis %0,3," #x "@dtprel@ha\n"  \
00829         "  addi  %0,%0," #x "@dtprel@l\n"  \
00830         : "=b" (__result) :  \
00831         : "0", "3", "4", "5", "6", "7",    \
00832           "8", "9", "10", "11", "12",      \
00833           "lr", "ctr",  \
00834           "cr0", "cr1", "cr5", "cr6", "cr7");  \
00835       __result;  \
00836   })
00837 /* PowerPC64 General Dynamic TLS access.  */
00838 #  define TLS_GD(x) \
00839   ({  int * __result;  \
00840       asm (  \
00841         "  addi  3,2," #x "@got@tlsgd\n"  \
00842         "  bl    " __TLS_GET_ADDR "\n"  \
00843         "  nop   \n"  \
00844         "  mr    %0,3\n"  \
00845         : "=b" (__result) :  \
00846         : "0", "3", "4", "5", "6", "7",    \
00847           "8", "9", "10", "11", "12",      \
00848           "lr", "ctr",  \
00849           "cr0", "cr1", "cr5", "cr6", "cr7");  \
00850       __result;  \
00851   })
00852 
00853 #elif !defined TLS_LE || !defined TLS_IE \
00854       || !defined TLS_LD || !defined TLS_GD
00855 # error "No support for this architecture so far."
00856 #endif