glibc/sysdeps/loongarch/dl-tlsdesc-dynamic.h
mengqinggang 6252c59f15 LoongArch: Fix macro redefined warning in tls-desc.S
Undef macro to avoid redefined warning.
2024-09-06 15:46:13 +08:00

223 lines
6.6 KiB
C

/* Thread-local storage handling in the ELF dynamic linker.
LoongArch version.
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define FRAME_SIZE (-((-14 * SZREG) & ALMASK))
/* Handler for dynamic TLS symbols.
Prototype:
_dl_tlsdesc_dynamic (tlsdesc *) ;
The second word of the descriptor points to a
tlsdesc_dynamic_arg structure.
Returns the offset between the thread pointer and the
object referenced by the argument.
ptrdiff_t
_dl_tlsdesc_dynamic (struct tlsdesc *tdp)
{
struct tlsdesc_dynamic_arg *td = tdp->arg;
dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer - SIZE_OF_TCB);
if (__glibc_likely (td->gen_count <= dtv[0].counter
&& (dtv[td->tlsinfo.ti_module].pointer.val
!= TLS_DTV_UNALLOCATED),
1))
return dtv[td->tlsinfo.ti_module].pointer.val
+ td->tlsinfo.ti_offset
- __thread_pointer;
return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
} */
.hidden _dl_tlsdesc_dynamic
.global _dl_tlsdesc_dynamic
.type _dl_tlsdesc_dynamic,%function
cfi_startproc
.align 2
_dl_tlsdesc_dynamic:
/* Save just enough registers to support fast path, if we fall
into slow path we will save additional registers. */
ADDI sp, sp, -32
cfi_adjust_cfa_offset (32)
REG_S t0, sp, 0
REG_S t1, sp, 8
REG_S t2, sp, 16
cfi_rel_offset (12, 0)
cfi_rel_offset (13, 8)
cfi_rel_offset (14, 16)
/* Runtime Storage Layout of Thread-Local Storage
TP point to the start of TLS block.
dtv
Low address TCB ----------------> dtv0(counter)
TP --> static_block0 <----- dtv1
static_block1 <----- dtv2
static_block2 <----- dtv3
dynamic_block0 <----- dtv4
Hign address dynamic_block1 <----- dtv5 */
REG_L t0, tp, -SIZE_OF_TCB /* t0 = dtv */
REG_L a0, a0, TLSDESC_ARG /* a0(td) = tdp->arg */
REG_L t1, a0, TLSDESC_GEN_COUNT /* t1 = td->gen_count */
REG_L t2, t0, DTV_COUNTER /* t2 = dtv[0].counter */
/* If dtv[0].counter < td->gen_count, goto slow path. */
bltu t2, t1, .Lslow
REG_L t1, a0, TLSDESC_MODID /* t1 = td->tlsinfo.ti_module */
/* t1 = t1 * sizeof(dtv_t) = t1 * (2 * sizeof(void*)) */
slli.d t1, t1, 4
add.d t1, t1, t0 /* t1 = dtv[td->tlsinfo.ti_module] */
REG_L t1, t1, 0 /* t1 = dtv[td->tlsinfo.ti_module].pointer.val */
li.d t2, TLS_DTV_UNALLOCATED
/* If dtv[td->tlsinfo.ti_module].pointer.val is TLS_DTV_UNALLOCATED,
goto slow path. */
beq t1, t2, .Lslow
cfi_remember_state
REG_L t2, a0, TLSDESC_MODOFF /* t2 = td->tlsinfo.ti_offset */
/* dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset */
add.d a0, t1, t2
.Lret:
sub.d a0, a0, tp
REG_L t0, sp, 0
REG_L t1, sp, 8
REG_L t2, sp, 16
ADDI sp, sp, 32
cfi_adjust_cfa_offset (-32)
RET
.Lslow:
/* This is the slow path. We need to call __tls_get_addr() which
means we need to save and restore all the register that the
callee will trash. */
/* Save the remaining registers that we must treat as caller save. */
cfi_restore_state
ADDI sp, sp, -FRAME_SIZE
cfi_adjust_cfa_offset (FRAME_SIZE)
REG_S ra, sp, 0 * SZREG
REG_S a1, sp, 1 * SZREG
REG_S a2, sp, 2 * SZREG
REG_S a3, sp, 3 * SZREG
REG_S a4, sp, 4 * SZREG
REG_S a5, sp, 5 * SZREG
REG_S a6, sp, 6 * SZREG
REG_S a7, sp, 7 * SZREG
REG_S t3, sp, 8 * SZREG
REG_S t4, sp, 9 * SZREG
REG_S t5, sp, 10 * SZREG
REG_S t6, sp, 11 * SZREG
REG_S t7, sp, 12 * SZREG
REG_S t8, sp, 13 * SZREG
cfi_rel_offset (1, 0 * SZREG)
cfi_rel_offset (5, 1 * SZREG)
cfi_rel_offset (6, 2 * SZREG)
cfi_rel_offset (7, 3 * SZREG)
cfi_rel_offset (8, 4 * SZREG)
cfi_rel_offset (9, 5 * SZREG)
cfi_rel_offset (10, 6 * SZREG)
cfi_rel_offset (11, 7 * SZREG)
cfi_rel_offset (15, 8 * SZREG)
cfi_rel_offset (16, 9 * SZREG)
cfi_rel_offset (17, 10 * SZREG)
cfi_rel_offset (18, 11 * SZREG)
cfi_rel_offset (19, 12 * SZREG)
cfi_rel_offset (20, 13 * SZREG)
#ifndef __loongarch_soft_float
/* Save fcsr0 register.
Only one physical fcsr0 register, fcsr1-fcsr3 are aliases
of some fields in fcsr0. */
movfcsr2gr t0, fcsr0
st.w t0, sp, FRAME_SIZE + 24 /* Use the spare slot above t2. */
#ifdef USE_LASX
#define V_REG_S xvst
#define V_REG_L xvld
#define V_SPACE (-((-32 * SZXREG) & ALMASK)) /* Space for LASX registers. */
#define V_REG(n) $xr##n
#define V_REGS 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
#define V_REGSZ SZXREG
#elif defined USE_LSX
#define V_REG_S vst
#define V_REG_L vld
#define V_SPACE (-((-32 * SZVREG) & ALMASK)) /* Space for LSX registers. */
#define V_REG(n) $vr##n
#define V_REGS 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
#define V_REGSZ SZVREG
#else
#define V_REG_S fst.d
#define V_REG_L fld.d
#define V_SPACE (-((-24 * SZFREG) & ALMASK)) /* Space for FLOAT registers. */
#define V_REG(n) $f##n
#define V_REGS 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23
#define V_REGSZ SZFREG
#endif
ADDI sp, sp, -V_SPACE
cfi_adjust_cfa_offset (V_SPACE)
.irp i,V_REGS
V_REG_S V_REG(\i), sp, \i * V_REGSZ
.endr
#endif /* #ifndef __loongarch_soft_float */
bl HIDDEN_JUMPTARGET(__tls_get_addr)
ADDI a0, a0, -TLS_DTV_OFFSET
#ifndef __loongarch_soft_float
.irp i,V_REGS
V_REG_L V_REG(\i), sp, \i * V_REGSZ
.endr
ADDI sp, sp, V_SPACE
cfi_adjust_cfa_offset (-V_SPACE)
/* Restore fcsr0 register. */
ld.w t0, sp, FRAME_SIZE + 24
movgr2fcsr fcsr0, t0
#endif /* #ifndef __loongarch_soft_float */
REG_L ra, sp, 0 * SZREG
REG_L a1, sp, 1 * SZREG
REG_L a2, sp, 2 * SZREG
REG_L a3, sp, 3 * SZREG
REG_L a4, sp, 4 * SZREG
REG_L a5, sp, 5 * SZREG
REG_L a6, sp, 6 * SZREG
REG_L a7, sp, 7 * SZREG
REG_L t3, sp, 8 * SZREG
REG_L t4, sp, 9 * SZREG
REG_L t5, sp, 10 * SZREG
REG_L t6, sp, 11 * SZREG
REG_L t7, sp, 12 * SZREG
REG_L t8, sp, 13 * SZREG
ADDI sp, sp, FRAME_SIZE
cfi_adjust_cfa_offset (-FRAME_SIZE)
b .Lret
cfi_endproc
.size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
.hidden HIDDEN_JUMPTARGET(__tls_get_addr)