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