]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/arm/dl-tlsdesc.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / arm / dl-tlsdesc.S
CommitLineData
3447f0d7 1/* Thread-local storage handling in the ELF dynamic linker. ARM version.
bfff8b1b 2 Copyright (C) 2006-2017 Free Software Foundation, Inc.
3447f0d7
NS
3 This file is part of the GNU C Library.
4
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.
9
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.
14
15 You should have received a copy of the GNU Lesser General Public
ab84e3ff
PE
16 License along with the GNU C Library. If not, see
17 <http://www.gnu.org/licenses/>. */
3447f0d7
NS
18
19#include <sysdep.h>
6bcae146 20#include <arm-features.h>
3447f0d7
NS
21#include <tls.h>
22#include "tlsdesc.h"
23
3447f0d7
NS
24 .text
25 @ emit debug information with cfi
26 @ use arm-specific pseudos for unwinding itself
f4564ff0 27 CFI_SECTIONS
3447f0d7
NS
28 .hidden _dl_tlsdesc_return
29 .global _dl_tlsdesc_return
30 .type _dl_tlsdesc_return,#function
31 cfi_startproc
7214d558 32 eabi_fnstart
3447f0d7
NS
33 .align 2
34_dl_tlsdesc_return:
6bcae146
RM
35 sfi_breg r0, \
36 ldr r0, [\B]
3447f0d7 37 BX (lr)
7214d558 38 eabi_fnend
3447f0d7
NS
39 cfi_endproc
40 .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
41
42 .hidden _dl_tlsdesc_undefweak
43 .global _dl_tlsdesc_undefweak
44 .type _dl_tlsdesc_undefweak,#function
45 cfi_startproc
7214d558 46 eabi_fnstart
3447f0d7
NS
47 .align 2
48_dl_tlsdesc_undefweak:
5232b909 49 GET_TLS (r1)
3447f0d7 50 rsb r0, r0, #0
3447f0d7 51 BX (lr)
3447f0d7 52 cfi_endproc
7214d558 53 eabi_fnend
3447f0d7
NS
54 .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
55
56#ifdef SHARED
57 .hidden _dl_tlsdesc_dynamic
58 .global _dl_tlsdesc_dynamic
59 .type _dl_tlsdesc_dynamic,#function
60
61
62/*
63 The assembly code that follows is a rendition of the following
64 C code, hand-optimized a little bit.
65
66ptrdiff_t
67_dl_tlsdesc_dynamic(struct tlsdesc *tdp)
68{
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();
77
78 return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
79}
80
81*/
82 cfi_startproc
7214d558 83 eabi_fnstart
3447f0d7
NS
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 */
7214d558 88 eabi_save ({r2,r3,r4,lr})
55668624 89 push {r2,r3,r4,lr}
3447f0d7
NS
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)
6bcae146
RM
95 sfi_breg r0, \
96 ldr r1, [\B] /* td */
5232b909 97 GET_TLS (lr)
3447f0d7 98 mov r4, r0 /* r4 = tp */
6bcae146
RM
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]
3447f0d7
NS
105 cmp r2, r3
106 bhi 1f
6bcae146
RM
107 sfi_breg r1, \
108 ldr r3, [\B]
109#ifndef ARM_NO_INDEX_REGISTER
3447f0d7 110 ldr r2, [r0, r3, lsl #3]
6bcae146
RM
111#else
112 add lr, r0, r3, lsl #3
113 sfi_breg lr, \
114 ldr r2, [\B]
115#endif
3447f0d7 116 cmn r2, #1
6ccd0107 117 ittt ne
12290c06 118 sfi_breg r1, \
3447f0d7
NS
119 ldrne r3, [r1, #4]
120 addne r3, r2, r3
121 rsbne r0, r4, r3
122 bne 2f
1231: mov r0, r1
124 bl __tls_get_addr
125 rsb r0, r4, r0
d137b6dc 1262:
6bcae146
RM
127#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
128 || defined (ARM_ALWAYS_BX))
d137b6dc 129 pop {r2,r3,r4, lr}
3447f0d7
NS
130 cfi_adjust_cfa_offset (-16)
131 cfi_restore (lr)
132 cfi_restore (r4)
133 cfi_restore (r3)
134 cfi_restore (r2)
d137b6dc
RH
135 bx lr
136#else
137 pop {r2,r3,r4, pc}
138#endif
7214d558 139 eabi_fnend
3447f0d7
NS
140 cfi_endproc
141 .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
142#endif /* SHARED */
143
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
7214d558 149 eabi_fnstart
3447f0d7
NS
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. */
7214d558 159 eabi_save ({r2})
3447f0d7
NS
160 cfi_adjust_cfa_offset (4)
161 cfi_rel_offset (r2, 0)
7214d558 162 eabi_save ({r0,r1,r3,ip,lr})
55668624 163 push {r0, r1, r3, ip, lr}
3447f0d7
NS
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
55668624 171 pop {r0, r1, r3, ip, lr}
3447f0d7
NS
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)
55668624 178 pop {r2}
3447f0d7
NS
179 cfi_adjust_cfa_offset (-4)
180 cfi_restore (r2)
6bcae146
RM
181 sfi_breg r0, \
182 ldr r1, [\B, #4]
3447f0d7 183 BX (r1)
7214d558 184 eabi_fnend
3447f0d7
NS
185 cfi_endproc
186 .size _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
187
188/* Holder for lazy tls descriptors being resolve in another thread.
36ffe739
WN
189
190 Our calling convention is to clobber r0, r1 and the processor
191 flags. All others that are modified must be saved */
3447f0d7
NS
192 .hidden _dl_tlsdesc_resolve_hold
193 .global _dl_tlsdesc_resolve_hold
194 .type _dl_tlsdesc_resolve_hold,#function
195 cfi_startproc
7214d558 196 eabi_fnstart
3447f0d7
NS
197 .align 2
198_dl_tlsdesc_resolve_hold:
1fae5a68
SN
199 /* r0 is saved so its original value can be used after the call and
200 r1 is saved only to keep the stack aligned. (r0 points to the tls
201 descriptor, it is passed to _dl_tlsdesc_resolve_hold_fixup which
202 is a void function that may clobber r0, later r0 is used to load
203 the new resolver.) */
204 eabi_save ({r0,r1,r2,r3,ip,lr})
205 push {r0, r1, r2, r3, ip, lr}
206 cfi_adjust_cfa_offset (24)
207 cfi_rel_offset (r0, 0)
208 cfi_rel_offset (r1, 4)
209 cfi_rel_offset (r2, 8)
210 cfi_rel_offset (r3, 12)
211 cfi_rel_offset (ip, 16)
212 cfi_rel_offset (lr, 20)
36ffe739 213 adr r1, _dl_tlsdesc_resolve_hold
3447f0d7 214 bl _dl_tlsdesc_resolve_hold_fixup
1fae5a68
SN
215 pop {r0, r1, r2, r3, ip, lr}
216 cfi_adjust_cfa_offset (-24)
3447f0d7
NS
217 cfi_restore (lr)
218 cfi_restore (ip)
219 cfi_restore (r3)
3447f0d7 220 cfi_restore (r2)
1fae5a68
SN
221 cfi_restore (r1)
222 cfi_restore (r0)
6bcae146
RM
223 sfi_breg r0, \
224 ldr r1, [\B, #4]
3447f0d7 225 BX (r1)
7214d558 226 eabi_fnend
3447f0d7
NS
227 cfi_endproc
228 .size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold