S390: Ifunc resolver macro for vector instructions.
[glibc.git] / sysdeps / arm / dl-tlsdesc.S
blobe42ca68eda2ba78a5d9652e9600ded517a310e64
1 /* Thread-local storage handling in the ELF dynamic linker.  ARM version.
2    Copyright (C) 2006-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <arm-features.h>
21 #include <tls.h>
22 #include "tlsdesc.h"
24         .text
25         @ emit debug information with cfi
26         @ use arm-specific pseudos for unwinding itself
27         CFI_SECTIONS
28         .hidden _dl_tlsdesc_return
29         .global _dl_tlsdesc_return
30         .type   _dl_tlsdesc_return,#function
31         cfi_startproc
32         eabi_fnstart
33         .align 2
34 _dl_tlsdesc_return:
35         sfi_breg r0, \
36         ldr     r0, [\B]
37         BX      (lr)
38         eabi_fnend
39         cfi_endproc
40         .size   _dl_tlsdesc_return, .-_dl_tlsdesc_return
42         .hidden _dl_tlsdesc_undefweak
43         .global _dl_tlsdesc_undefweak
44         .type   _dl_tlsdesc_undefweak,#function
45         cfi_startproc
46         eabi_fnstart
47         .align 2
48 _dl_tlsdesc_undefweak:
49         GET_TLS (r1)
50         rsb     r0, r0, #0
51         BX      (lr)
52         cfi_endproc
53         eabi_fnend
54         .size   _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
56 #ifdef SHARED
57         .hidden _dl_tlsdesc_dynamic
58         .global _dl_tlsdesc_dynamic
59         .type   _dl_tlsdesc_dynamic,#function
63         The assembly code that follows is a rendition of the following
64         C code, hand-optimized a little bit.
66 ptrdiff_t
67 _dl_tlsdesc_dynamic(struct tlsdesc *tdp)
69        struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
70        dtv_t *dtv = (dtv_t *)THREAD_DTV();
71        if (__builtin_expect (td->gen_count <= dtv[0].counter
72                              && dtv[td->tlsinfo.ti_module].pointer.val
73                                 != TLS_DTV_UNALLOCATED,
74                              1))
75                return dtv[td->tlsinfo.ti_module].pointer.val +
76                        td->tlsinfo.ti_offset - __builtin_thread_pointer();
78        return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
82         cfi_startproc
83         eabi_fnstart
84         .align 2
85 _dl_tlsdesc_dynamic:
86         /* Our calling convention is to clobber r0, r1 and the processor
87            flags.  All others that are modified must be saved */
88         eabi_save ({r2,r3,r4,lr})
89         push    {r2,r3,r4,lr}
90         cfi_adjust_cfa_offset (16)
91         cfi_rel_offset (r2,0)
92         cfi_rel_offset (r3,4)
93         cfi_rel_offset (r4,8)
94         cfi_rel_offset (lr,12)
95         sfi_breg r0, \
96         ldr     r1, [\B] /* td */
97         GET_TLS (lr)
98         mov     r4, r0 /* r4 = tp */
99         sfi_breg r0, \
100         ldr     r0, [\B]
101         sfi_breg r1, \
102         ldr     r2, [\B, #8] /* gen_count */
103         sfi_breg r0, \
104         ldr     r3, [\B]
105         cmp     r2, r3
106         bhi     1f
107         sfi_breg r1, \
108         ldr     r3, [\B]
109 #ifndef ARM_NO_INDEX_REGISTER
110         ldr     r2, [r0, r3, lsl #3]
111 #else
112         add     lr, r0, r3, lsl #3
113         sfi_breg lr, \
114         ldr     r2, [\B]
115 #endif
116         cmn     r2, #1
117         ittt    ne
118         sfi_breg r1, \
119         ldrne   r3, [r1, #4]
120         addne   r3, r2, r3
121         rsbne   r0, r4, r3
122         bne     2f
123 1:      mov     r0, r1
124         bl      __tls_get_addr
125         rsb     r0, r4, r0
127 #if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
128      || defined (ARM_ALWAYS_BX))
129         pop     {r2,r3,r4, lr}
130         cfi_adjust_cfa_offset (-16)
131         cfi_restore (lr)
132         cfi_restore (r4)
133         cfi_restore (r3)
134         cfi_restore (r2)
135         bx      lr
136 #else
137         pop     {r2,r3,r4, pc}
138 #endif
139         eabi_fnend
140         cfi_endproc
141         .size   _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
142 #endif /* SHARED */
144 /* lazy resolved for tls descriptors.  */
145         .hidden _dl_tlsdesc_lazy_resolver
146         .global _dl_tlsdesc_lazy_resolver
147         .type   _dl_tlsdesc_lazy_resolver,#function
148         cfi_startproc
149         eabi_fnstart
150         .align 2
151 _dl_tlsdesc_lazy_resolver:
152         /* r0 points at the tlsdesc,
153            r1 points at the GOT
154            r2 was pushed by the trampoline and used as a temp,
155               we need to pop it here.
156           We push the remaining call-clobbered registers here, and also
157           R1 -- to keep the stack correctly aligned.  */
158         /* Tell the unwinder that r2 has already been pushed.  */
159         eabi_save ({r2})
160         cfi_adjust_cfa_offset (4)
161         cfi_rel_offset (r2, 0)
162         eabi_save ({r0,r1,r3,ip,lr})
163         push    {r0, r1, r3, ip, lr}
164         cfi_adjust_cfa_offset (20)
165         cfi_rel_offset (r0, 0)
166         cfi_rel_offset (r1, 4)
167         cfi_rel_offset (r3, 8)
168         cfi_rel_offset (ip, 12)
169         cfi_rel_offset (lr, 16)
170         bl      _dl_tlsdesc_lazy_resolver_fixup
171         pop     {r0, r1, r3, ip, lr}
172         cfi_adjust_cfa_offset (-20)
173         cfi_restore (lr)
174         cfi_restore (ip)
175         cfi_restore (r3)
176         cfi_restore (r1)
177         cfi_restore (r0)
178         pop     {r2}
179         cfi_adjust_cfa_offset (-4)
180         cfi_restore (r2)
181         sfi_breg r0, \
182         ldr     r1, [\B, #4]
183         BX      (r1)
184         eabi_fnend
185         cfi_endproc
186         .size   _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
188 /* Holder for lazy tls descriptors being resolve in another thread.
190    Our calling convention is to clobber r0, r1 and the processor
191    flags.  All others that are modified must be saved */
192         .hidden _dl_tlsdesc_resolve_hold
193         .global _dl_tlsdesc_resolve_hold
194         .type   _dl_tlsdesc_resolve_hold,#function
195         cfi_startproc
196         eabi_fnstart
197         .align 2
198 _dl_tlsdesc_resolve_hold:
199         eabi_save ({r2,r3,ip,lr})
200         push    {r2, r3, ip, lr}
201         cfi_adjust_cfa_offset (16)
202         cfi_rel_offset (r2, 0)
203         cfi_rel_offset (r3, 4)
204         cfi_rel_offset (ip, 8)
205         cfi_rel_offset (lr, 12)
206         adr     r1, _dl_tlsdesc_resolve_hold
207         bl      _dl_tlsdesc_resolve_hold_fixup
208         pop     {r2, r3, ip, lr}
209         cfi_adjust_cfa_offset (-16)
210         cfi_restore (lr)
211         cfi_restore (ip)
212         cfi_restore (r3)
213         cfi_restore (r2)
214         sfi_breg r0, \
215         ldr     r1, [\B, #4]
216         BX      (r1)
217         eabi_fnend
218         cfi_endproc
219         .size   _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold