Benchtests: Remove broken walk benchmarks
[glibc.git] / sysdeps / loongarch / dl-tlsdesc.S
bloba6627cc7547668ce69fbc70112e8837a7c713ba1
1 /* Thread-local storage handling in the ELF dynamic linker.
2    LoongArch version.
3    Copyright (C) 2024 Free Software Foundation, Inc.
5    This file is part of the GNU C Library.
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, see
19    <https://www.gnu.org/licenses/>.  */
21 #include <sysdep.h>
22 #include <tls.h>
23 #include "tlsdesc.h"
25         .text
27         /* Compute the thread pointer offset for symbols in the static
28            TLS block. The offset is the same for all threads.
29            Prototype:
30            _dl_tlsdesc_return (tlsdesc *);  */
31         .hidden _dl_tlsdesc_return
32         .global _dl_tlsdesc_return
33         .type   _dl_tlsdesc_return,%function
34         cfi_startproc
35         .align 2
36 _dl_tlsdesc_return:
37         REG_L  a0, a0, 8
38         RET
39         cfi_endproc
40         .size   _dl_tlsdesc_return, .-_dl_tlsdesc_return
42         /* Handler for undefined weak TLS symbols.
43            Prototype:
44            _dl_tlsdesc_undefweak (tlsdesc *);
46            The second word of the descriptor contains the addend.
47            Return the addend minus the thread pointer. This ensures
48            that when the caller adds on the thread pointer it gets back
49            the addend.  */
50         .hidden _dl_tlsdesc_undefweak
51         .global _dl_tlsdesc_undefweak
52         .type   _dl_tlsdesc_undefweak,%function
53         cfi_startproc
54         .align  2
55 _dl_tlsdesc_undefweak:
56         REG_L   a0, a0, 8
57         sub.d   a0, a0, tp
58         RET
59         cfi_endproc
60         .size   _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
63 #ifdef SHARED
65 #define FRAME_SIZE        (-((-14 * SZREG) & ALMASK))
66 #define FRAME_SIZE_LSX    (-((-32 * SZVREG) & ALMASK))
67 #define FRAME_SIZE_LASX   (-((-32 * SZXREG) & ALMASK))
68 #define FRAME_SIZE_FLOAT  (-((-24 * SZFREG) & ALMASK))
70         /* Handler for dynamic TLS symbols.
71            Prototype:
72            _dl_tlsdesc_dynamic (tlsdesc *) ;
74            The second word of the descriptor points to a
75            tlsdesc_dynamic_arg structure.
77            Returns the offset between the thread pointer and the
78            object referenced by the argument.
80            ptrdiff_t
81            _dl_tlsdesc_dynamic (struct tlsdesc *tdp)
82            {
83              struct tlsdesc_dynamic_arg *td = tdp->arg;
84              dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer - SIZE_OF_TCB);
85              if (__glibc_likely (td->gen_count <= dtv[0].counter
86                 && (dtv[td->tlsinfo.ti_module].pointer.val
87                     != TLS_DTV_UNALLOCATED),
88                 1))
89                return dtv[td->tlsinfo.ti_module].pointer.val
90                 + td->tlsinfo.ti_offset
91                 - __thread_pointer;
93              return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
94            }  */
95         .hidden _dl_tlsdesc_dynamic
96         .global _dl_tlsdesc_dynamic
97         .type   _dl_tlsdesc_dynamic,%function
98         cfi_startproc
99         .align 2
100 _dl_tlsdesc_dynamic:
101         /* Save just enough registers to support fast path, if we fall
102            into slow path we will save additional registers.  */
103         ADDI    sp, sp, -32
104         REG_S   t0, sp, 0
105         REG_S   t1, sp, 8
106         REG_S   t2, sp, 16
108 /* Runtime Storage Layout of Thread-Local Storage
109    TP point to the start of TLS block.
111                                       dtv
112 Low address     TCB ----------------> dtv0(counter)
113          TP --> static_block0  <----- dtv1
114                 static_block1  <----- dtv2
115                 static_block2  <----- dtv3
116                 dynamic_block0 <----- dtv4
117 Hign address    dynamic_block1 <----- dtv5  */
119         REG_L   t0, tp, -SIZE_OF_TCB      /* t0 = dtv */
120         REG_L   a0, a0, TLSDESC_ARG       /* a0(td) = tdp->arg */
121         REG_L   t1, a0, TLSDESC_GEN_COUNT /* t1 = td->gen_count */
122         REG_L   t2, t0, DTV_COUNTER       /* t2 = dtv[0].counter */
123         /* If dtv[0].counter < td->gen_count, goto slow path.  */
124         bltu    t2, t1, .Lslow
126         REG_L   t1, a0, TLSDESC_MODID /* t1 = td->tlsinfo.ti_module */
127         /* t1 = t1 * sizeof(dtv_t) = t1 * (2 * sizeof(void*)) */
128         slli.d  t1, t1, 4
129         add.d   t1, t1, t0  /* t1 = dtv[td->tlsinfo.ti_module] */
130         REG_L   t1, t1, 0   /* t1 = dtv[td->tlsinfo.ti_module].pointer.val */
131         li.d    t2, TLS_DTV_UNALLOCATED
132         /* If dtv[td->tlsinfo.ti_module].pointer.val is TLS_DTV_UNALLOCATED,
133            goto slow path.  */
134         beq     t1, t2, .Lslow
136         REG_L   t2, a0, TLSDESC_MODOFF  /* t2 = td->tlsinfo.ti_offset */
137         /* dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset */
138         add.d   a0, t1, t2
139 .Lret:
140         sub.d   a0, a0, tp
141         REG_L   t0, sp, 0
142         REG_L   t1, sp, 8
143         REG_L   t2, sp, 16
144         ADDI    sp, sp, 32
145         RET
147 .Lslow:
148         /* This is the slow path. We need to call __tls_get_addr() which
149            means we need to save and restore all the register that the
150            callee will trash.  */
152         /* Save the remaining registers that we must treat as caller save.  */
153         ADDI    sp, sp, -FRAME_SIZE
154         REG_S   ra, sp, 0 * SZREG
155         REG_S   a1, sp, 1 * SZREG
156         REG_S   a2, sp, 2 * SZREG
157         REG_S   a3, sp, 3 * SZREG
158         REG_S   a4, sp, 4 * SZREG
159         REG_S   a5, sp, 5 * SZREG
160         REG_S   a6, sp, 6 * SZREG
161         REG_S   a7, sp, 7 * SZREG
162         REG_S   t3, sp, 8 * SZREG
163         REG_S   t4, sp, 9 * SZREG
164         REG_S   t5, sp, 10 * SZREG
165         REG_S   t6, sp, 11 * SZREG
166         REG_S   t7, sp, 12 * SZREG
167         REG_S   t8, sp, 13 * SZREG
169 #ifndef __loongarch_soft_float
171         /* Save fcsr0 register.
172            Only one physical fcsr0 register, fcsr1-fcsr3 are aliases
173            of some fields in fcsr0.  */
174         movfcsr2gr  t0, fcsr0
175         st.w    t0, sp, FRAME_SIZE + 24 /* Use the spare slot above t2 */
177         /* Whether support LASX.  */
178         la.global   t0, _rtld_global_ro
179         REG_L   t0, t0, GLRO_DL_HWCAP_OFFSET
180         andi    t1, t0, HWCAP_LOONGARCH_LASX
181         beqz    t1, .Llsx
183         /* Save 256-bit vector registers.
184            FIXME: Without vector ABI, save all vector registers.  */
185         ADDI    sp, sp, -FRAME_SIZE_LASX
186         xvst    xr0, sp, 0*SZXREG
187         xvst    xr1, sp, 1*SZXREG
188         xvst    xr2, sp, 2*SZXREG
189         xvst    xr3, sp, 3*SZXREG
190         xvst    xr4, sp, 4*SZXREG
191         xvst    xr5, sp, 5*SZXREG
192         xvst    xr6, sp, 6*SZXREG
193         xvst    xr7, sp, 7*SZXREG
194         xvst    xr8, sp, 8*SZXREG
195         xvst    xr9, sp, 9*SZXREG
196         xvst    xr10, sp, 10*SZXREG
197         xvst    xr11, sp, 11*SZXREG
198         xvst    xr12, sp, 12*SZXREG
199         xvst    xr13, sp, 13*SZXREG
200         xvst    xr14, sp, 14*SZXREG
201         xvst    xr15, sp, 15*SZXREG
202         xvst    xr16, sp, 16*SZXREG
203         xvst    xr17, sp, 17*SZXREG
204         xvst    xr18, sp, 18*SZXREG
205         xvst    xr19, sp, 19*SZXREG
206         xvst    xr20, sp, 20*SZXREG
207         xvst    xr21, sp, 21*SZXREG
208         xvst    xr22, sp, 22*SZXREG
209         xvst    xr23, sp, 23*SZXREG
210         xvst    xr24, sp, 24*SZXREG
211         xvst    xr25, sp, 25*SZXREG
212         xvst    xr26, sp, 26*SZXREG
213         xvst    xr27, sp, 27*SZXREG
214         xvst    xr28, sp, 28*SZXREG
215         xvst    xr29, sp, 29*SZXREG
216         xvst    xr30, sp, 30*SZXREG
217         xvst    xr31, sp, 31*SZXREG
218         b           .Ltga
220 .Llsx:
221         /* Whether support LSX.  */
222         andi    t1, t0, HWCAP_LOONGARCH_LSX
223         beqz    t1, .Lfloat
225         /* Save 128-bit vector registers.  */
226         ADDI    sp, sp, -FRAME_SIZE_LSX
227         vst     vr0, sp, 0*SZVREG
228         vst     vr1, sp, 1*SZVREG
229         vst     vr2, sp, 2*SZVREG
230         vst     vr3, sp, 3*SZVREG
231         vst     vr4, sp, 4*SZVREG
232         vst     vr5, sp, 5*SZVREG
233         vst     vr6, sp, 6*SZVREG
234         vst     vr7, sp, 7*SZVREG
235         vst     vr8, sp, 8*SZVREG
236         vst     vr9, sp, 9*SZVREG
237         vst     vr10, sp, 10*SZVREG
238         vst     vr11, sp, 11*SZVREG
239         vst     vr12, sp, 12*SZVREG
240         vst     vr13, sp, 13*SZVREG
241         vst     vr14, sp, 14*SZVREG
242         vst     vr15, sp, 15*SZVREG
243         vst     vr16, sp, 16*SZVREG
244         vst     vr17, sp, 17*SZVREG
245         vst     vr18, sp, 18*SZVREG
246         vst     vr19, sp, 19*SZVREG
247         vst     vr20, sp, 20*SZVREG
248         vst     vr21, sp, 21*SZVREG
249         vst     vr22, sp, 22*SZVREG
250         vst     vr23, sp, 23*SZVREG
251         vst     vr24, sp, 24*SZVREG
252         vst     vr25, sp, 25*SZVREG
253         vst     vr26, sp, 26*SZVREG
254         vst     vr27, sp, 27*SZVREG
255         vst     vr28, sp, 28*SZVREG
256         vst     vr29, sp, 29*SZVREG
257         vst     vr30, sp, 30*SZVREG
258         vst     vr31, sp, 31*SZVREG
259         b           .Ltga
261 .Lfloat:
262         /* Save float registers.  */
263         ADDI    sp, sp, -FRAME_SIZE_FLOAT
264         FREG_S  fa0, sp, 0*SZFREG
265         FREG_S  fa1, sp, 1*SZFREG
266         FREG_S  fa2, sp, 2*SZFREG
267         FREG_S  fa3, sp, 3*SZFREG
268         FREG_S  fa4, sp, 4*SZFREG
269         FREG_S  fa5, sp, 5*SZFREG
270         FREG_S  fa6, sp, 6*SZFREG
271         FREG_S  fa7, sp, 7*SZFREG
272         FREG_S  ft0, sp, 8*SZFREG
273         FREG_S  ft1, sp, 9*SZFREG
274         FREG_S  ft2, sp, 10*SZFREG
275         FREG_S  ft3, sp, 11*SZFREG
276         FREG_S  ft4, sp, 12*SZFREG
277         FREG_S  ft5, sp, 13*SZFREG
278         FREG_S  ft6, sp, 14*SZFREG
279         FREG_S  ft7, sp, 15*SZFREG
280         FREG_S  ft8, sp, 16*SZFREG
281         FREG_S  ft9, sp, 17*SZFREG
282         FREG_S  ft10, sp, 18*SZFREG
283         FREG_S  ft11, sp, 19*SZFREG
284         FREG_S  ft12, sp, 20*SZFREG
285         FREG_S  ft13, sp, 21*SZFREG
286         FREG_S  ft14, sp, 22*SZFREG
287         FREG_S  ft15, sp, 23*SZFREG
289 #endif /* #ifndef __loongarch_soft_float */
291 .Ltga:
292         bl      HIDDEN_JUMPTARGET(__tls_get_addr)
293         ADDI    a0, a0, -TLS_DTV_OFFSET
295 #ifndef __loongarch_soft_float
297         la.global   t0, _rtld_global_ro
298         REG_L   t0, t0, GLRO_DL_HWCAP_OFFSET
299         andi    t1, t0, HWCAP_LOONGARCH_LASX
300         beqz    t1, .Llsx1
302         /* Restore 256-bit vector registers.  */
303         xvld    xr0, sp, 0*SZXREG
304         xvld    xr1, sp, 1*SZXREG
305         xvld    xr2, sp, 2*SZXREG
306         xvld    xr3, sp, 3*SZXREG
307         xvld    xr4, sp, 4*SZXREG
308         xvld    xr5, sp, 5*SZXREG
309         xvld    xr6, sp, 6*SZXREG
310         xvld    xr7, sp, 7*SZXREG
311         xvld    xr8, sp, 8*SZXREG
312         xvld    xr9, sp, 9*SZXREG
313         xvld    xr10, sp, 10*SZXREG
314         xvld    xr11, sp, 11*SZXREG
315         xvld    xr12, sp, 12*SZXREG
316         xvld    xr13, sp, 13*SZXREG
317         xvld    xr14, sp, 14*SZXREG
318         xvld    xr15, sp, 15*SZXREG
319         xvld    xr16, sp, 16*SZXREG
320         xvld    xr17, sp, 17*SZXREG
321         xvld    xr18, sp, 18*SZXREG
322         xvld    xr19, sp, 19*SZXREG
323         xvld    xr20, sp, 20*SZXREG
324         xvld    xr21, sp, 21*SZXREG
325         xvld    xr22, sp, 22*SZXREG
326         xvld    xr23, sp, 23*SZXREG
327         xvld    xr24, sp, 24*SZXREG
328         xvld    xr25, sp, 25*SZXREG
329         xvld    xr26, sp, 26*SZXREG
330         xvld    xr27, sp, 27*SZXREG
331         xvld    xr28, sp, 28*SZXREG
332         xvld    xr29, sp, 29*SZXREG
333         xvld    xr30, sp, 30*SZXREG
334         xvld    xr31, sp, 31*SZXREG
335         ADDI    sp, sp, FRAME_SIZE_LASX
336         b .Lfcsr
338 .Llsx1:
339         andi    t1, t0, HWCAP_LOONGARCH_LSX
340         beqz    t1, .Lfloat1
342         /* Restore 128-bit vector registers.  */
343         vld     vr0, sp, 0*SZVREG
344         vld     vr1, sp, 1*SZVREG
345         vld     vr2, sp, 2*SZVREG
346         vld     vr3, sp, 3*SZVREG
347         vld     vr4, sp, 4*SZVREG
348         vld     vr5, sp, 5*SZVREG
349         vld     vr6, sp, 6*SZVREG
350         vld     vr7, sp, 7*SZVREG
351         vld     vr8, sp, 8*SZVREG
352         vld     vr9, sp, 9*SZVREG
353         vld     vr10, sp, 10*SZVREG
354         vld     vr11, sp, 11*SZVREG
355         vld     vr12, sp, 12*SZVREG
356         vld     vr13, sp, 13*SZVREG
357         vld     vr14, sp, 14*SZVREG
358         vld     vr15, sp, 15*SZVREG
359         vld     vr16, sp, 16*SZVREG
360         vld     vr17, sp, 17*SZVREG
361         vld     vr18, sp, 18*SZVREG
362         vld     vr19, sp, 19*SZVREG
363         vld     vr20, sp, 20*SZVREG
364         vld     vr21, sp, 21*SZVREG
365         vld     vr22, sp, 22*SZVREG
366         vld     vr23, sp, 23*SZVREG
367         vld     vr24, sp, 24*SZVREG
368         vld     vr25, sp, 25*SZVREG
369         vld     vr26, sp, 26*SZVREG
370         vld     vr27, sp, 27*SZVREG
371         vld     vr28, sp, 28*SZVREG
372         vld     vr29, sp, 29*SZVREG
373         vld     vr30, sp, 30*SZVREG
374         vld     vr31, sp, 31*SZVREG
375         ADDI    sp, sp, FRAME_SIZE_LSX
376         b           .Lfcsr
378 .Lfloat1:
379         /* Restore float registers.  */
380         FREG_L  fa0, sp, 0*SZFREG
381         FREG_L  fa1, sp, 1*SZFREG
382         FREG_L  fa2, sp, 2*SZFREG
383         FREG_L  fa3, sp, 3*SZFREG
384         FREG_L  fa4, sp, 4*SZFREG
385         FREG_L  fa5, sp, 5*SZFREG
386         FREG_L  fa6, sp, 6*SZFREG
387         FREG_L  fa7, sp, 7*SZFREG
388         FREG_L  ft0, sp, 8*SZFREG
389         FREG_L  ft1, sp, 9*SZFREG
390         FREG_L  ft2, sp, 10*SZFREG
391         FREG_L  ft3, sp, 11*SZFREG
392         FREG_L  ft4, sp, 12*SZFREG
393         FREG_L  ft5, sp, 13*SZFREG
394         FREG_L  ft6, sp, 14*SZFREG
395         FREG_L  ft7, sp, 15*SZFREG
396         FREG_L  ft8, sp, 16*SZFREG
397         FREG_L  ft9, sp, 17*SZFREG
398         FREG_L  ft10, sp, 18*SZFREG
399         FREG_L  ft11, sp, 19*SZFREG
400         FREG_L  ft12, sp, 20*SZFREG
401         FREG_L  ft13, sp, 21*SZFREG
402         FREG_L  ft14, sp, 22*SZFREG
403         FREG_L  ft15, sp, 23*SZFREG
404         ADDI    sp, sp, FRAME_SIZE_FLOAT
406 .Lfcsr:
407         /* Restore fcsr0 register.  */
408         ld.w    t0, sp, FRAME_SIZE + 24
409         movgr2fcsr  fcsr0, t0
411 #endif /* #ifndef __loongarch_soft_float */
413         REG_L   ra, sp, 0 * SZREG
414         REG_L   a1, sp, 1 * SZREG
415         REG_L   a2, sp, 2 * SZREG
416         REG_L   a3, sp, 3 * SZREG
417         REG_L   a4, sp, 4 * SZREG
418         REG_L   a5, sp, 5 * SZREG
419         REG_L   a6, sp, 6 * SZREG
420         REG_L   a7, sp, 7 * SZREG
421         REG_L   t3, sp, 8 * SZREG
422         REG_L   t4, sp, 9 * SZREG
423         REG_L   t5, sp, 10 * SZREG
424         REG_L   t6, sp, 11 * SZREG
425         REG_L   t7, sp, 12 * SZREG
426         REG_L   t8, sp, 13 * SZREG
427         ADDI    sp, sp, FRAME_SIZE
429         b       .Lret
430         cfi_endproc
431         .size   _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
432         .hidden HIDDEN_JUMPTARGET(__tls_get_addr)
434 #endif /* #ifdef SHARED */