More IA-64 removal
[platform/upstream/glibc.git] / elf / tls-macros.h
1 /* Macros to support TLS testing in times of missing compiler support.  */
2
3 #define COMMON_INT_DEF(x) \
4   asm (".tls_common " #x ",4,4")
5 /* XXX Until we get compiler support we don't need declarations.  */
6 #define COMMON_INT_DECL(x)
7
8 /* XXX This definition will probably be machine specific, too.  */
9 #define VAR_INT_DEF(x) \
10   asm (".section .tdata\n\t"                                                  \
11        ".globl " #x "\n"                                                      \
12        ".balign 4\n"                                                          \
13        #x ":\t.long 0\n\t"                                                    \
14        ".size " #x ",4\n\t"                                                   \
15        ".previous")
16 /* XXX Until we get compiler support we don't need declarations.  */
17 #define VAR_INT_DECL(x)
18
19 #include_next <tls-macros.h>
20
21   /* XXX Each architecture must have its own asm for now.  */
22 #ifdef __i386__
23 # define TLS_LE(x) \
24   ({ int *__l;                                                                \
25      asm ("movl %%gs:0,%0\n\t"                                                \
26           "subl $" #x "@tpoff,%0"                                             \
27           : "=r" (__l));                                                      \
28      __l; })
29
30 # ifdef PIC
31 #  define TLS_IE(x) \
32   ({ int *__l;                                                                \
33      asm ("movl %%gs:0,%0\n\t"                                                \
34           "subl " #x "@gottpoff(%%ebx),%0"                                    \
35           : "=r" (__l));                                                      \
36      __l; })
37 # else
38 #  define TLS_IE(x) \
39   ({ int *__l, __b;                                                           \
40      asm ("call 1f\n\t"                                                       \
41           ".subsection 1\n"                                                   \
42           "1:\tmovl (%%esp), %%ebx\n\t"                                       \
43           "ret\n\t"                                                           \
44           ".previous\n\t"                                                     \
45           "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"                            \
46           "movl %%gs:0,%0\n\t"                                                \
47           "subl " #x "@gottpoff(%%ebx),%0"                                    \
48           : "=r" (__l), "=&b" (__b));                                         \
49      __l; })
50 # endif
51
52 # ifdef PIC
53 #  define TLS_LD(x) \
54   ({ int *__l, __c, __d;                                                      \
55      asm ("leal " #x "@tlsldm(%%ebx),%%eax\n\t"                               \
56           "call ___tls_get_addr@plt\n\t"                                      \
57           "leal " #x "@dtpoff(%%eax), %%eax"                                  \
58           : "=a" (__l), "=&c" (__c), "=&d" (__d));                            \
59      __l; })
60 # else
61 #  define TLS_LD(x) \
62   ({ int *__l, __b, __c, __d;                                                 \
63      asm ("call 1f\n\t"                                                       \
64           ".subsection 1\n"                                                   \
65           "1:\tmovl (%%esp), %%ebx\n\t"                                       \
66           "ret\n\t"                                                           \
67           ".previous\n\t"                                                     \
68           "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"                            \
69           "leal " #x "@tlsldm(%%ebx),%%eax\n\t"                               \
70           "call ___tls_get_addr@plt\n\t"                                      \
71           "leal " #x "@dtpoff(%%eax), %%eax"                                  \
72           : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d));               \
73      __l; })
74 # endif
75
76 # ifdef PIC
77 #  define TLS_GD(x) \
78   ({ int *__l, __c, __d;                                                      \
79      asm ("leal " #x "@tlsgd(%%ebx),%%eax\n\t"                                \
80           "call ___tls_get_addr@plt\n\t"                                      \
81           "nop"                                                               \
82           : "=a" (__l), "=&c" (__c), "=&d" (__d));                            \
83      __l; })
84 # else
85 #  define TLS_GD(x) \
86   ({ int *__l, __b, __c, __d;                                                 \
87      asm ("call 1f\n\t"                                                       \
88           ".subsection 1\n"                                                   \
89           "1:\tmovl (%%esp), %%ebx\n\t"                                       \
90           "ret\n\t"                                                           \
91           ".previous\n\t"                                                     \
92           "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"                            \
93           "leal " #x "@tlsgd(%%ebx),%%eax\n\t"                                \
94           "call ___tls_get_addr@plt\n\t"                                      \
95           "nop"                                                               \
96           : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d));               \
97      __l; })
98 # endif
99
100 #elif defined __x86_64__
101
102 # define TLS_LE(x) \
103   ({ int *__l;                                                                \
104      asm ("movq %%fs:0,%0\n\t"                                                \
105           "leaq " #x "@tpoff(%0), %0"                                         \
106           : "=r" (__l));                                                      \
107      __l; })
108
109 # define TLS_IE(x) \
110   ({ int *__l;                                                                \
111      asm ("movq %%fs:0,%0\n\t"                                                \
112           "addq " #x "@gottpoff(%%rip),%0"                                    \
113           : "=r" (__l));                                                      \
114      __l; })
115
116 # define TLS_LD(x) \
117   ({ int *__l, __c, __d;                                                      \
118      asm ("leaq " #x "@tlsld(%%rip),%%rdi\n\t"                                \
119           "call __tls_get_addr@plt\n\t"                                       \
120           "leaq " #x "@dtpoff(%%rax), %%rax"                                  \
121           : "=a" (__l), "=&c" (__c), "=&d" (__d)                              \
122           : : "rdi", "rsi", "r8", "r9", "r10", "r11");                        \
123      __l; })
124
125 # define TLS_GD(x) \
126   ({ int *__l, __c, __d;                                                      \
127      asm (".byte 0x66\n\t"                                                    \
128           "leaq " #x "@tlsgd(%%rip),%%rdi\n\t"                                \
129           ".word 0x6666\n\t"                                                  \
130           "rex64\n\t"                                                         \
131           "call __tls_get_addr@plt"                                           \
132           : "=a" (__l), "=&c" (__c), "=&d" (__d)                              \
133           : : "rdi", "rsi", "r8", "r9", "r10", "r11");                        \
134      __l; })
135
136 #elif defined __sh__
137
138 # define TLS_LE(x) \
139   ({ int *__l; void *__tp;                                                    \
140      asm ("stc gbr,%1\n\t"                                                    \
141           "mov.l 1f,%0\n\t"                                                   \
142           "bra 2f\n\t"                                                        \
143           " add %1,%0\n\t"                                                    \
144           ".align 2\n\t"                                                      \
145           "1: .long " #x "@tpoff\n\t"                                         \
146           "2:"                                                                \
147           : "=r" (__l), "=r" (__tp));                                         \
148      __l; })
149
150 # ifdef PIC
151 #  define TLS_IE(x) \
152   ({ int *__l; void *__tp;                                                    \
153      register void *__gp __asm__("r12");                                      \
154      asm ("mov.l 1f,r0\n\t"                                                   \
155           "stc gbr,%1\n\t"                                                    \
156           "mov.l @(r0,r12),%0\n\t"                                            \
157           "bra 2f\n\t"                                                        \
158           " add %1,%0\n\t"                                                    \
159           ".align 2\n\t"                                                      \
160           "1: .long " #x "@gottpoff\n\t"                                      \
161           "2:"                                                                \
162           : "=r" (__l), "=r" (__tp) : "r" (__gp) : "r0");                     \
163      __l; })
164 # else
165 #  define TLS_IE(x) \
166   ({ int *__l; void *__tp;                                                    \
167      asm ("mov.l r12,@-r15\n\t"                                               \
168           "mova 0f,r0\n\t"                                                    \
169           "mov.l 0f,r12\n\t"                                                  \
170           "add r0,r12\n\t"                                                    \
171           "mov.l 1f,r0\n\t"                                                   \
172           "stc gbr,%1\n\t"                                                    \
173           "mov.l @(r0,r12),%0\n\t"                                            \
174           "bra 2f\n\t"                                                        \
175           " add %1,%0\n\t"                                                    \
176           ".align 2\n\t"                                                      \
177           "1: .long " #x "@gottpoff\n\t"                                      \
178           "0: .long _GLOBAL_OFFSET_TABLE_\n\t"                                \
179           "2: mov.l @r15+,r12"                                                \
180           : "=r" (__l), "=r" (__tp) : : "r0");                                \
181      __l; })
182 #endif
183
184 # ifdef PIC
185 #  define TLS_LD(x) \
186   ({ int *__l;                                                                \
187      register void *__gp __asm__("r12");                                      \
188      asm ("mov.l 1f,r4\n\t"                                                   \
189           "mova 2f,r0\n\t"                                                    \
190           "mov.l 2f,r1\n\t"                                                   \
191           "add r0,r1\n\t"                                                     \
192           "jsr @r1\n\t"                                                       \
193           " add r12,r4\n\t"                                                   \
194           "bra 4f\n\t"                                                        \
195           " nop\n\t"                                                          \
196           ".align 2\n\t"                                                      \
197           "1: .long " #x "@tlsldm\n\t"                                        \
198           "2: .long __tls_get_addr@plt\n\t"                                   \
199           "4: mov.l 3f,%0\n\t"                                                \
200           "bra 5f\n\t"                                                        \
201           " add r0,%0\n\t"                                                    \
202           ".align 2\n\t"                                                      \
203           "3: .long " #x "@dtpoff\n\t"                                        \
204           "5:"                                                                \
205           : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5",     \
206                                       "r6", "r7", "pr", "t");                 \
207      __l; })
208 # else
209 #  define TLS_LD(x) \
210   ({ int *__l;                                                                \
211      asm ("mov.l r12,@-r15\n\t"                                               \
212           "mova 0f,r0\n\t"                                                    \
213           "mov.l 0f,r12\n\t"                                                  \
214           "add r0,r12\n\t"                                                    \
215           "mov.l 1f,r4\n\t"                                                   \
216           "mova 2f,r0\n\t"                                                    \
217           "mov.l 2f,r1\n\t"                                                   \
218           "add r0,r1\n\t"                                                     \
219           "jsr @r1\n\t"                                                       \
220           " add r12,r4\n\t"                                                   \
221           "bra 4f\n\t"                                                        \
222           " nop\n\t"                                                          \
223           ".align 2\n\t"                                                      \
224           "1: .long " #x "@tlsldm\n\t"                                        \
225           "2: .long __tls_get_addr@plt\n\t"                                   \
226           "0: .long _GLOBAL_OFFSET_TABLE_\n\t"                                \
227           "4: mov.l 3f,%0\n\t"                                                \
228           "bra 5f\n\t"                                                        \
229           " add r0,%0\n\t"                                                    \
230           ".align 2\n\t"                                                      \
231           "3: .long " #x "@dtpoff\n\t"                                        \
232           "5: mov.l @r15+,r12"                                                \
233           : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",    \
234                            "pr", "t");                                        \
235      __l; })
236 #endif
237
238 # ifdef PIC
239 #  define TLS_GD(x) \
240   ({ int *__l;                                                                \
241      register void *__gp __asm__("r12");                                      \
242      asm ("mov.l 1f,r4\n\t"                                                   \
243           "mova 2f,r0\n\t"                                                    \
244           "mov.l 2f,r1\n\t"                                                   \
245           "add r0,r1\n\t"                                                     \
246           "jsr @r1\n\t"                                                       \
247           " add r12,r4\n\t"                                                   \
248           "bra 3f\n\t"                                                        \
249           " mov r0,%0\n\t"                                                    \
250           ".align 2\n\t"                                                      \
251           "1: .long " #x "@tlsgd\n\t"                                         \
252           "2: .long __tls_get_addr@plt\n\t"                                   \
253           "3:"                                                                \
254           : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5",     \
255                                       "r6", "r7", "pr", "t");                 \
256      __l; })
257 # else
258 #  define TLS_GD(x) \
259   ({ int *__l;                                                                \
260      asm ("mov.l r12,@-r15\n\t"                                               \
261           "mova 0f,r0\n\t"                                                    \
262           "mov.l 0f,r12\n\t"                                                  \
263           "add r0,r12\n\t"                                                    \
264           "mov.l 1f,r4\n\t"                                                   \
265           "mova 2f,r0\n\t"                                                    \
266           "mov.l 2f,r1\n\t"                                                   \
267           "add r0,r1\n\t"                                                     \
268           "jsr @r1\n\t"                                                       \
269           " add r12,r4\n\t"                                                   \
270           "bra 3f\n\t"                                                        \
271           " mov r0,%0\n\t"                                                    \
272           ".align 2\n\t"                                                      \
273           "1: .long " #x "@tlsgd\n\t"                                         \
274           "2: .long __tls_get_addr@plt\n\t"                                   \
275           "0: .long _GLOBAL_OFFSET_TABLE_\n\t"                                \
276           "3: mov.l @r15+,r12"                                                \
277           : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",    \
278                            "pr", "t");                                        \
279      __l; })
280 #endif
281
282 #elif defined __sparc__ && !defined __arch64__
283
284 # define TLS_LE(x) \
285   ({ int *__l;                                                                \
286      asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l));                      \
287      asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l));        \
288      asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l));                       \
289      __l; })
290
291 # ifdef __PIC__
292 #  define TLS_LOAD_PIC \
293   ({ register long pc __asm__ ("%o7");                                        \
294      long got;                                                                \
295      asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"                       \
296           "call .+8\n\t"                                                      \
297           "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"                     \
298           "add %1, %0, %1\n\t"                                                \
299           : "=r" (pc), "=r" (got));                                           \
300      got; })
301 # else
302 #  define TLS_LOAD_PIC \
303    ({ long got;                                                               \
304       asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t"                                \
305            "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t"                        \
306            "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0"                           \
307            : "=r" (got));                                                     \
308       got; })
309 # endif
310
311 # define TLS_IE(x) \
312   ({ int *__l;                                                                \
313      asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l));                       \
314      asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));         \
315      asm ("ld [%1 + %2], %0, %%tie_ld(" #x ")"                                \
316           : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l));                      \
317      asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l));    \
318      __l; })
319
320 # define TLS_LD(x) \
321   ({ int *__l; register void *__o0 asm ("%o0");                               \
322      long __o;                                                                \
323      asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l));                      \
324      asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));        \
325      asm ("add %1, %2, %0, %%tldm_add(" #x ")"                                \
326           : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                     \
327      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                       \
328           " nop"                                                              \
329           : "=r" (__o0) : "0" (__o0)                                          \
330           : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",       \
331             "o5", "o7", "cc");                                                \
332      asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o));                     \
333      asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o));       \
334      asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l)                   \
335           : "r" (__o0), "r" (__o));                                           \
336      __l; })
337
338 # define TLS_GD(x) \
339   ({ int *__l; register void *__o0 asm ("%o0");                               \
340      asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l));                       \
341      asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));         \
342      asm ("add %1, %2, %0, %%tgd_add(" #x ")"                                 \
343           : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                     \
344      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                       \
345           " nop"                                                              \
346           : "=r" (__o0) : "0" (__o0)                                          \
347           : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",       \
348             "o5", "o7", "cc");                                                \
349      __o0; })
350
351 #elif defined __sparc__ && defined __arch64__
352
353 # define TLS_LE(x) \
354   ({ int *__l;                                                                \
355      asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l));                      \
356      asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l));        \
357      asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l));                       \
358      __l; })
359
360 # ifdef __PIC__
361 #  define TLS_LOAD_PIC \
362   ({ long pc, got;                                                            \
363      asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"                       \
364           "rd %%pc, %0\n\t"                                                   \
365           "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"                     \
366           "add %1, %0, %1\n\t"                                                \
367           : "=r" (pc), "=r" (got));                                           \
368      got; })
369 # else
370 #  define TLS_LOAD_PIC \
371    ({ long got;                                                               \
372       asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t"                                \
373            "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t"                        \
374            "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0"                           \
375            : "=r" (got));                                                     \
376       got; })
377 # endif
378
379 # define TLS_IE(x) \
380   ({ int *__l;                                                                \
381      asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l));                       \
382      asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));         \
383      asm ("ldx [%1 + %2], %0, %%tie_ldx(" #x ")"                              \
384           : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l));                      \
385      asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l));    \
386      __l; })
387
388 # define TLS_LD(x) \
389   ({ int *__l; register void *__o0 asm ("%o0");                               \
390      long __o;                                                                \
391      asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l));                      \
392      asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));        \
393      asm ("add %1, %2, %0, %%tldm_add(" #x ")"                                \
394           : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                     \
395      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                       \
396           " nop"                                                              \
397           : "=r" (__o0) : "0" (__o0)                                          \
398           : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",       \
399             "o5", "o7", "cc");                                                \
400      asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o));                     \
401      asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o));       \
402      asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l)                   \
403           : "r" (__o0), "r" (__o));                                           \
404      __l; })
405
406 # define TLS_GD(x) \
407   ({ int *__l; register void *__o0 asm ("%o0");                               \
408      asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l));                       \
409      asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l));         \
410      asm ("add %1, %2, %0, %%tgd_add(" #x ")"                                 \
411           : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l));                     \
412      asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t"                       \
413           " nop"                                                              \
414           : "=r" (__o0) : "0" (__o0)                                          \
415           : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4",       \
416             "o5", "o7", "cc");                                                \
417      __o0; })
418
419 #elif defined __s390x__
420
421 # define TLS_LE(x) \
422   ({ unsigned long __offset;                                                  \
423      asm ("bras %0,1f\n"                                                      \
424           "0:\t.quad " #x "@ntpoff\n"                                         \
425           "1:\tlg %0,0(%0)"                                                   \
426           : "=a" (__offset) : : "cc" );                                       \
427      (int *) (__builtin_thread_pointer() + __offset); })
428
429 # ifdef PIC
430 #  define TLS_IE(x) \
431   ({ unsigned long __offset;                                                  \
432      asm ("bras %0,1f\n"                                                      \
433           "0:\t.quad " #x "@gotntpoff\n"                                      \
434           "1:\tlg %0,0(%0)\n\t"                                               \
435           "lg %0,0(%0,%%r12):tls_load:" #x                                    \
436           : "=&a" (__offset) : : "cc" );                                      \
437      (int *) (__builtin_thread_pointer() + __offset); })
438 # else
439 #  define TLS_IE(x) \
440   ({ unsigned long  __offset;                                                 \
441      asm ("bras %0,1f\n"                                                      \
442           "0:\t.quad " #x "@indntpoff\n"                                      \
443           "1:\t lg %0,0(%0)\n\t"                                              \
444           "lg %0,0(%0):tls_load:" #x                                          \
445           : "=&a" (__offset) : : "cc" );                                      \
446      (int *) (__builtin_thread_pointer() + __offset); })
447 # endif
448
449 # ifdef PIC
450 #  define TLS_LD(x) \
451   ({ unsigned long __offset, __save12;                                        \
452      asm ("bras %0,1f\n"                                                      \
453           "0:\t.quad " #x "@tlsldm\n\t"                                       \
454           ".quad " #x "@dtpoff\n"                                             \
455           "1:\tlgr %1,%%r12\n\t"                                              \
456           "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                              \
457           "lg %%r2,0(%0)\n\t"                                                 \
458           "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t"            \
459           "lg %0,8(%0)\n\t"                                                   \
460           "algr %0,%%r2\n\t"                                                  \
461           "lgr %%r12,%1"                                                      \
462           : "=&a" (__offset), "=&a" (__save12)                                \
463           : : "cc", "0", "1", "2", "3", "4", "5", "14" );                     \
464      (int *) (__builtin_thread_pointer() + __offset); })
465 # else
466 #  define TLS_LD(x) \
467   ({ unsigned long __offset;                                                  \
468      asm ("bras %0,1f\n"                                                      \
469           "0:\t.quad " #x "@tlsldm\n\t"                                       \
470           ".quad " #x "@dtpoff\n"                                             \
471           "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                          \
472           "lg %%r2,0(%0)\n\t"                                                 \
473           "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t"            \
474           "lg %0,8(%0)\n\t"                                                   \
475           "algr %0,%%r2"                                                      \
476           : "=&a" (__offset)                                                  \
477           : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" );               \
478      (int *) (__builtin_thread_pointer() + __offset); })
479 # endif
480
481 # ifdef PIC
482 #  define TLS_GD(x) \
483   ({ unsigned long __offset, __save12;                                        \
484      asm ("bras %0,1f\n"                                                      \
485           "0:\t.quad " #x "@tlsgd\n"                                          \
486           "1:\tlgr %1,%%r12\n\t"                                              \
487           "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                              \
488           "lg %%r2,0(%0)\n\t"                                                 \
489           "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t"            \
490           "lgr %0,%%r2\n\t"                                                   \
491           "lgr %%r12,%1"                                                      \
492           : "=&a" (__offset), "=&a" (__save12)                                \
493           : : "cc", "0", "1", "2", "3", "4", "5", "14" );                     \
494      (int *) (__builtin_thread_pointer() + __offset); })
495 # else
496 #  define TLS_GD(x) \
497   ({ unsigned long __offset;                                                  \
498      asm ("bras %0,1f\n"                                                      \
499           "0:\t.quad " #x "@tlsgd\n"                                          \
500           "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                          \
501           "lg %%r2,0(%0)\n\t"                                                 \
502           "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t"            \
503           "lgr %0,%%r2"                                                       \
504           : "=&a" (__offset)                                                  \
505           : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" );               \
506      (int *) (__builtin_thread_pointer() + __offset); })
507 # endif
508
509 #elif defined __s390__
510
511 # define TLS_LE(x) \
512   ({ unsigned long __offset;                                                  \
513      asm ("bras %0,1f\n"                                                      \
514           "0:\t.long " #x "@ntpoff\n"                                         \
515           "1:\tl %0,0(%0)"                                                    \
516           : "=a" (__offset) : : "cc" );                                       \
517      (int *) (__builtin_thread_pointer() + __offset); })
518
519 # ifdef PIC
520 #  define TLS_IE(x) \
521   ({ unsigned long __offset;                                                  \
522      asm ("bras %0,1f\n"                                                      \
523           "0:\t.long " #x "@gotntpoff\n"                                      \
524           "1:\tl %0,0(%0)\n\t"                                                \
525           "l %0,0(%0,%%r12):tls_load:" #x                                     \
526           : "=&a" (__offset) : : "cc" );                                      \
527      (int *) (__builtin_thread_pointer() + __offset); })
528 # else
529 #  define TLS_IE(x) \
530   ({ unsigned long  __offset;                                                 \
531      asm ("bras %0,1f\n"                                                      \
532           "0:\t.long " #x "@indntpoff\n"                                      \
533           "1:\t l %0,0(%0)\n\t"                                               \
534           "l %0,0(%0):tls_load:" #x                                           \
535           : "=&a" (__offset) : : "cc" );                                      \
536      (int *) (__builtin_thread_pointer() + __offset); })
537 # endif
538
539 # ifdef PIC
540 #  define TLS_LD(x) \
541   ({ unsigned long __offset, __save12;                                        \
542      asm ("bras %0,1f\n"                                                      \
543           "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t"                            \
544           ".long __tls_get_offset@plt-0b\n\t"                                 \
545           ".long " #x "@tlsldm\n\t"                                           \
546           ".long " #x "@dtpoff\n"                                             \
547           "1:\tlr %1,%%r12\n\t"                                               \
548           "l %%r12,0(%0)\n\t"                                                 \
549           "la %%r12,0(%%r12,%0)\n\t"                                          \
550           "l %%r1,4(%0)\n\t"                                                  \
551           "l %%r2,8(%0)\n\t"                                                  \
552           "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t"                        \
553           "l %0,12(%0)\n\t"                                                   \
554           "alr %0,%%r2\n\t"                                                   \
555           "lr %%r12,%1"                                                       \
556           : "=&a" (__offset), "=&a" (__save12)                                \
557           : : "cc", "0", "1", "2", "3", "4", "5" );                           \
558      (int *) (__builtin_thread_pointer() + __offset); })
559 # else
560 #  define TLS_LD(x) \
561   ({ unsigned long __offset;                                                  \
562      asm ("bras %0,1f\n"                                                      \
563           "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t"                               \
564           ".long __tls_get_offset@plt\n\t"                                    \
565           ".long " #x "@tlsldm\n\t"                                           \
566           ".long " #x "@dtpoff\n"                                             \
567           "1:\tl %%r12,0(%0)\n\t"                                             \
568           "l %%r1,4(%0)\n\t"                                                  \
569           "l %%r2,8(%0)\n\t"                                                  \
570           "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t"                           \
571           "l %0,12(%0)\n\t"                                                   \
572           "alr %0,%%r2"                                                       \
573           : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
574      (int *) (__builtin_thread_pointer() + __offset); })
575 # endif
576
577 # ifdef PIC
578 #  define TLS_GD(x) \
579   ({ unsigned long __offset, __save12;                                        \
580      asm ("bras %0,1f\n"                                                      \
581           "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t"                            \
582           ".long __tls_get_offset@plt-0b\n\t"                                 \
583           ".long " #x "@tlsgd\n"                                              \
584           "1:\tlr %1,%%r12\n\t"                                               \
585           "l %%r12,0(%0)\n\t"                                                 \
586           "la %%r12,0(%%r12,%0)\n\t"                                          \
587           "l %%r1,4(%0)\n\t"                                                  \
588           "l %%r2,8(%0)\n\t"                                                  \
589           "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t"                        \
590           "lr %0,%%r2\n\t"                                                    \
591           "lr %%r12,%1"                                                       \
592           : "=&a" (__offset), "=&a" (__save12)                                \
593           : : "cc", "0", "1", "2", "3", "4", "5" );                           \
594      (int *) (__builtin_thread_pointer() + __offset); })
595 # else
596 #  define TLS_GD(x) \
597   ({ unsigned long __offset;                                                  \
598      asm ("bras %0,1f\n"                                                      \
599           "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t"                               \
600           ".long __tls_get_offset@plt\n\t"                                    \
601           ".long " #x "@tlsgd\n"                                              \
602           "1:\tl %%r12,0(%0)\n\t"                                             \
603           "l %%r1,4(%0)\n\t"                                                  \
604           "l %%r2,8(%0)\n\t"                                                  \
605           "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t"                           \
606           "lr %0,%%r2"                                                        \
607           : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
608      (int *) (__builtin_thread_pointer() + __offset); })
609 # endif
610
611 #elif defined __powerpc__
612
613 # define __TLS_CALL_CLOBBERS                                                  \
614         "0", "4", "5", "6", "7", "8", "9", "10", "11", "12",                  \
615         "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7"
616
617 # ifndef __powerpc64__
618
619 #  include "config.h"
620
621 /* PowerPC32 Local Exec TLS access.  */
622 #  define TLS_LE(x)                                                           \
623   ({ int *__result;                                                           \
624      asm ("addi %0,2," #x "@tprel"                                            \
625           : "=r" (__result));                                                 \
626      __result; })
627
628 /* PowerPC32 Initial Exec TLS access.  */
629 #  ifdef HAVE_ASM_PPC_REL16
630 #   define TLS_IE(x)                                                          \
631   ({ int *__result;                                                           \
632      asm ("bcl 20,31,1f\n1:\t"                                                \
633           "mflr %0\n\t"                                                       \
634           "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t"                       \
635           "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t"                         \
636           "lwz %0," #x "@got@tprel(%0)\n\t"                                   \
637           "add %0,%0," #x "@tls"                                              \
638           : "=b" (__result) :                                                 \
639           : "lr");                                                            \
640      __result; })
641 #  else
642 #   define TLS_IE(x)                                                          \
643   ({ int *__result;                                                           \
644      asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t"                              \
645           "mflr %0\n\t"                                                       \
646           "lwz %0," #x "@got@tprel(%0)\n\t"                                   \
647           "add %0,%0," #x "@tls"                                              \
648           : "=b" (__result) :                                                 \
649           : "lr");                                                            \
650      __result; })
651 #  endif
652
653 /* PowerPC32 Local Dynamic TLS access.  */
654 #  ifdef HAVE_ASM_PPC_REL16
655 #   define TLS_LD(x)                                                          \
656   ({ int *__result;                                                           \
657      asm ("bcl 20,31,1f\n1:\t"                                                \
658           "mflr 3\n\t"                                                        \
659           "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t"                         \
660           "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t"                           \
661           "addi 3,3," #x "@got@tlsld\n\t"                                     \
662           "bl __tls_get_addr@plt\n\t"                                         \
663           "addi %0,3," #x "@dtprel"                                           \
664           : "=r" (__result) :                                                 \
665           : "3", __TLS_CALL_CLOBBERS);                                        \
666      __result; })
667 #  else
668 #   define TLS_LD(x)                                                          \
669   ({ int *__result;                                                           \
670      asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t"                              \
671           "mflr 3\n\t"                                                        \
672           "addi 3,3," #x "@got@tlsld\n\t"                                     \
673           "bl __tls_get_addr@plt\n\t"                                         \
674           "addi %0,3," #x "@dtprel"                                           \
675           : "=r" (__result) :                                                 \
676           : "3", __TLS_CALL_CLOBBERS);                                        \
677      __result; })
678 #  endif
679
680 /* PowerPC32 General Dynamic TLS access.  */
681 #  ifdef HAVE_ASM_PPC_REL16
682 #   define TLS_GD(x)                                                          \
683   ({ register int *__result __asm__ ("r3");                                   \
684      asm ("bcl 20,31,1f\n1:\t"                                                \
685           "mflr 3\n\t"                                                        \
686           "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t"                         \
687           "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t"                           \
688           "addi 3,3," #x "@got@tlsgd\n\t"                                     \
689           "bl __tls_get_addr@plt"                                             \
690           : "=r" (__result) :                                                 \
691           : __TLS_CALL_CLOBBERS);                                             \
692      __result; })
693 #  else
694 #   define TLS_GD(x)                                                          \
695   ({ register int *__result __asm__ ("r3");                                   \
696      asm ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t"                              \
697           "mflr 3\n\t"                                                        \
698           "addi 3,3," #x "@got@tlsgd\n\t"                                     \
699           "bl __tls_get_addr@plt"                                             \
700           : "=r" (__result) :                                                 \
701           : __TLS_CALL_CLOBBERS);                                             \
702      __result; })
703 #  endif
704
705 # else
706
707 /* PowerPC64 Local Exec TLS access.  */
708 #  define TLS_LE(x)                                                           \
709   ({ int * __result;                                                          \
710      asm ("addis %0,13," #x "@tprel@ha\n\t"                                   \
711           "addi  %0,%0," #x "@tprel@l"                                        \
712           : "=b" (__result) );                                                \
713      __result;                                                                \
714   })
715 /* PowerPC64 Initial Exec TLS access.  */
716 #  define TLS_IE(x)                                                           \
717   ({ int * __result;                                                          \
718      asm ("ld  %0," #x "@got@tprel(2)\n\t"                                    \
719           "add %0,%0," #x "@tls"                                              \
720           : "=r" (__result) );                                                \
721      __result;                                                                \
722   })
723 #  ifdef HAVE_ASM_GLOBAL_DOT_NAME
724 #   define __TLS_GET_ADDR ".__tls_get_addr"
725 #  else
726 #   define __TLS_GET_ADDR "__tls_get_addr"
727 #  endif
728 /* PowerPC64 Local Dynamic TLS access.  */
729 #  define TLS_LD(x)                                                           \
730   ({ int * __result;                                                          \
731      asm ("addi  3,2," #x "@got@tlsld\n\t"                                    \
732           "bl    " __TLS_GET_ADDR "\n\t"                                      \
733           "nop   \n\t"                                                        \
734           "addis %0,3," #x "@dtprel@ha\n\t"                                   \
735           "addi  %0,%0," #x "@dtprel@l"                                       \
736           : "=b" (__result) :                                                 \
737           : "3", __TLS_CALL_CLOBBERS);                                        \
738      __result;                                                                \
739   })
740 /* PowerPC64 General Dynamic TLS access.  */
741 #  define TLS_GD(x)                                                           \
742   ({ register int *__result __asm__ ("r3");                                   \
743      asm ("addi  3,2," #x "@got@tlsgd\n\t"                                    \
744           "bl    " __TLS_GET_ADDR "\n\t"                                      \
745           "nop   "                                                            \
746           : "=r" (__result) :                                                 \
747           : __TLS_CALL_CLOBBERS);                                             \
748      __result;                                                                \
749   })
750 # endif
751
752 #elif !defined TLS_LE || !defined TLS_IE \
753       || !defined TLS_LD || !defined TLS_GD
754 # error "No support for this architecture so far."
755 #endif