Fix sigpause namespace (bug 21554).
[glibc.git] / sysdeps / arm / dl-tlsdesc.S
blobe7bed02188d71e2abeeb9ddf5054f36ea186ccdf
1 /* Thread-local storage handling in the ELF dynamic linker.  ARM version.
2    Copyright (C) 2006-2017 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         ldr     r0, [r0]
36         BX      (lr)
37         eabi_fnend
38         cfi_endproc
39         .size   _dl_tlsdesc_return, .-_dl_tlsdesc_return
41         .hidden _dl_tlsdesc_undefweak
42         .global _dl_tlsdesc_undefweak
43         .type   _dl_tlsdesc_undefweak,#function
44         cfi_startproc
45         eabi_fnstart
46         .align 2
47 _dl_tlsdesc_undefweak:
48         GET_TLS (r1)
49         rsb     r0, r0, #0
50         BX      (lr)
51         cfi_endproc
52         eabi_fnend
53         .size   _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
55 #ifdef SHARED
56         .hidden _dl_tlsdesc_dynamic
57         .global _dl_tlsdesc_dynamic
58         .type   _dl_tlsdesc_dynamic,#function
62         The assembly code that follows is a rendition of the following
63         C code, hand-optimized a little bit.
65 ptrdiff_t
66 _dl_tlsdesc_dynamic(struct tlsdesc *tdp)
68        struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
69        dtv_t *dtv = (dtv_t *)THREAD_DTV();
70        if (__builtin_expect (td->gen_count <= dtv[0].counter
71                              && dtv[td->tlsinfo.ti_module].pointer.val
72                                 != TLS_DTV_UNALLOCATED,
73                              1))
74                return dtv[td->tlsinfo.ti_module].pointer.val +
75                        td->tlsinfo.ti_offset - __builtin_thread_pointer();
77        return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
81         cfi_startproc
82         eabi_fnstart
83         .align 2
84 _dl_tlsdesc_dynamic:
85         /* Our calling convention is to clobber r0, r1 and the processor
86            flags.  All others that are modified must be saved */
87         eabi_save ({r2,r3,r4,lr})
88         push    {r2,r3,r4,lr}
89         cfi_adjust_cfa_offset (16)
90         cfi_rel_offset (r2,0)
91         cfi_rel_offset (r3,4)
92         cfi_rel_offset (r4,8)
93         cfi_rel_offset (lr,12)
94         ldr     r1, [r0] /* td */
95         GET_TLS (lr)
96         mov     r4, r0 /* r4 = tp */
97         ldr     r0, [r0]
98         ldr     r2, [r1, #8] /* gen_count */
99         ldr     r3, [r0]
100         cmp     r2, r3
101         bhi     1f
102         ldr     r3, [r1]
103 #ifndef ARM_NO_INDEX_REGISTER
104         ldr     r2, [r0, r3, lsl #3]
105 #else
106         add     lr, r0, r3, lsl #3
107         ldr     r2, [lr]
108 #endif
109         cmn     r2, #1
110         ittt    ne
111         ldrne   r3, [r1, #4]
112         addne   r3, r2, r3
113         rsbne   r0, r4, r3
114         bne     2f
115 1:      mov     r0, r1
116         bl      __tls_get_addr
117         rsb     r0, r4, r0
119 #if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
120      || defined (ARM_ALWAYS_BX))
121         pop     {r2,r3,r4, lr}
122         cfi_adjust_cfa_offset (-16)
123         cfi_restore (lr)
124         cfi_restore (r4)
125         cfi_restore (r3)
126         cfi_restore (r2)
127         bx      lr
128 #else
129         pop     {r2,r3,r4, pc}
130 #endif
131         eabi_fnend
132         cfi_endproc
133         .size   _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
134 #endif /* SHARED */
136 /* lazy resolved for tls descriptors.  */
137         .hidden _dl_tlsdesc_lazy_resolver
138         .global _dl_tlsdesc_lazy_resolver
139         .type   _dl_tlsdesc_lazy_resolver,#function
140         cfi_startproc
141         eabi_fnstart
142         .align 2
143 _dl_tlsdesc_lazy_resolver:
144         /* r0 points at the tlsdesc,
145            r1 points at the GOT
146            r2 was pushed by the trampoline and used as a temp,
147               we need to pop it here.
148           We push the remaining call-clobbered registers here, and also
149           R1 -- to keep the stack correctly aligned.  */
150         /* Tell the unwinder that r2 has already been pushed.  */
151         eabi_save ({r2})
152         cfi_adjust_cfa_offset (4)
153         cfi_rel_offset (r2, 0)
154         eabi_save ({r0,r1,r3,ip,lr})
155         push    {r0, r1, r3, ip, lr}
156         cfi_adjust_cfa_offset (20)
157         cfi_rel_offset (r0, 0)
158         cfi_rel_offset (r1, 4)
159         cfi_rel_offset (r3, 8)
160         cfi_rel_offset (ip, 12)
161         cfi_rel_offset (lr, 16)
162         bl      _dl_tlsdesc_lazy_resolver_fixup
163         pop     {r0, r1, r3, ip, lr}
164         cfi_adjust_cfa_offset (-20)
165         cfi_restore (lr)
166         cfi_restore (ip)
167         cfi_restore (r3)
168         cfi_restore (r1)
169         cfi_restore (r0)
170         pop     {r2}
171         cfi_adjust_cfa_offset (-4)
172         cfi_restore (r2)
173         ldr     r1, [r0, #4]
174         BX      (r1)
175         eabi_fnend
176         cfi_endproc
177         .size   _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
179 /* Holder for lazy tls descriptors being resolve in another thread.
181    Our calling convention is to clobber r0, r1 and the processor
182    flags.  All others that are modified must be saved */
183         .hidden _dl_tlsdesc_resolve_hold
184         .global _dl_tlsdesc_resolve_hold
185         .type   _dl_tlsdesc_resolve_hold,#function
186         cfi_startproc
187         eabi_fnstart
188         .align 2
189 _dl_tlsdesc_resolve_hold:
190         /* r0 is saved so its original value can be used after the call and
191            r1 is saved only to keep the stack aligned.  (r0 points to the tls
192            descriptor, it is passed to _dl_tlsdesc_resolve_hold_fixup which
193            is a void function that may clobber r0, later r0 is used to load
194            the new resolver.)  */
195         eabi_save ({r0,r1,r2,r3,ip,lr})
196         push    {r0, r1, r2, r3, ip, lr}
197         cfi_adjust_cfa_offset (24)
198         cfi_rel_offset (r0, 0)
199         cfi_rel_offset (r1, 4)
200         cfi_rel_offset (r2, 8)
201         cfi_rel_offset (r3, 12)
202         cfi_rel_offset (ip, 16)
203         cfi_rel_offset (lr, 20)
204         adr     r1, _dl_tlsdesc_resolve_hold
205         bl      _dl_tlsdesc_resolve_hold_fixup
206         pop     {r0, r1, r2, r3, ip, lr}
207         cfi_adjust_cfa_offset (-24)
208         cfi_restore (lr)
209         cfi_restore (ip)
210         cfi_restore (r3)
211         cfi_restore (r2)
212         cfi_restore (r1)
213         cfi_restore (r0)
214         ldr     r1, [r0, #4]
215         BX      (r1)
216         eabi_fnend
217         cfi_endproc
218         .size   _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold