1 /* Thread-local storage handling in the ELF dynamic linker. ARM version.
2 Copyright (C) 2006-2014 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/>. */
20 #include <arm-features.h>
25 @ emit debug information with cfi
26 @ use arm-specific pseudos for unwinding itself
28 .hidden _dl_tlsdesc_return
29 .global _dl_tlsdesc_return
30 .type _dl_tlsdesc_return,#function
40 .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
42 .hidden _dl_tlsdesc_undefweak
43 .global _dl_tlsdesc_undefweak
44 .type _dl_tlsdesc_undefweak,#function
48 _dl_tlsdesc_undefweak:
54 .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
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.
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,
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();
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})
90 cfi_adjust_cfa_offset (16)
94 cfi_rel_offset (lr,12)
98 mov r4, r0 /* r4 = tp */
102 ldr r2, [\B, #8] /* gen_count */
109 #ifndef ARM_NO_INDEX_REGISTER
110 ldr r2, [r0, r3, lsl #3]
112 add lr, r0, r3, lsl #3
127 #if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
128 || defined (ARM_ALWAYS_BX))
130 cfi_adjust_cfa_offset (-16)
141 .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
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
151 _dl_tlsdesc_lazy_resolver:
152 /* r0 points at the tlsdesc,
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. */
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)
179 cfi_adjust_cfa_offset (-4)
186 .size _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
188 /* Holder for lazy tls descriptors being resolve in another thread.
189 Same ABI as the lazy resolver itself. */
190 .hidden _dl_tlsdesc_resolve_hold
191 .global _dl_tlsdesc_resolve_hold
192 .type _dl_tlsdesc_resolve_hold,#function
196 _dl_tlsdesc_resolve_hold:
197 /* Tell the unwinder that r2 has already been pushed. */
199 cfi_adjust_cfa_offset (4)
200 cfi_rel_offset (r2, 0)
201 eabi_save ({r0,r1,r3,ip,lr})
202 push {r0, r1, r3, ip, lr}
203 cfi_adjust_cfa_offset (20)
204 cfi_rel_offset (r0, 0)
205 cfi_rel_offset (r1, 4)
206 cfi_rel_offset (r3, 8)
207 cfi_rel_offset (ip, 12)
208 cfi_rel_offset (lr, 16)
209 adr r2, _dl_tlsdesc_resolve_hold
210 bl _dl_tlsdesc_resolve_hold_fixup
211 pop {r0, r1, r3, ip, lr}
212 cfi_adjust_cfa_offset (-20)
219 cfi_adjust_cfa_offset (-4)
226 .size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold