Blame sysdeps/aarch64/dl-tlsdesc.S

Packit Service 82fcde
/* Thread-local storage handling in the ELF dynamic linker.
Packit Service 82fcde
   AArch64 version.
Packit Service 82fcde
   Copyright (C) 2011-2018 Free Software Foundation, Inc.
Packit Service 82fcde
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#include <tls.h>
Packit Service 82fcde
#include "tlsdesc.h"
Packit Service 82fcde
Packit Service 82fcde
#define NSAVEDQREGPAIRS	16
Packit Service 82fcde
#define SAVE_Q_REGISTERS				\
Packit Service 82fcde
	stp	q0, q1,	[sp, #-32*NSAVEDQREGPAIRS]!;	\
Packit Service 82fcde
	cfi_adjust_cfa_offset (32*NSAVEDQREGPAIRS);	\
Packit Service 82fcde
	stp	 q2,  q3, [sp, #32*1];			\
Packit Service 82fcde
	stp	 q4,  q5, [sp, #32*2];			\
Packit Service 82fcde
	stp	 q6,  q7, [sp, #32*3];			\
Packit Service 82fcde
	stp	 q8,  q9, [sp, #32*4];			\
Packit Service 82fcde
	stp	q10, q11, [sp, #32*5];			\
Packit Service 82fcde
	stp	q12, q13, [sp, #32*6];			\
Packit Service 82fcde
	stp	q14, q15, [sp, #32*7];			\
Packit Service 82fcde
	stp	q16, q17, [sp, #32*8];			\
Packit Service 82fcde
	stp	q18, q19, [sp, #32*9];			\
Packit Service 82fcde
	stp	q20, q21, [sp, #32*10];			\
Packit Service 82fcde
	stp	q22, q23, [sp, #32*11];			\
Packit Service 82fcde
	stp	q24, q25, [sp, #32*12];			\
Packit Service 82fcde
	stp	q26, q27, [sp, #32*13];			\
Packit Service 82fcde
	stp	q28, q29, [sp, #32*14];			\
Packit Service 82fcde
	stp	q30, q31, [sp, #32*15];
Packit Service 82fcde
Packit Service 82fcde
#define RESTORE_Q_REGISTERS				\
Packit Service 82fcde
	ldp	 q2,  q3, [sp, #32*1];			\
Packit Service 82fcde
	ldp	 q4,  q5, [sp, #32*2];			\
Packit Service 82fcde
	ldp	 q6,  q7, [sp, #32*3];			\
Packit Service 82fcde
	ldp	 q8,  q9, [sp, #32*4];			\
Packit Service 82fcde
	ldp	q10, q11, [sp, #32*5];			\
Packit Service 82fcde
	ldp	q12, q13, [sp, #32*6];			\
Packit Service 82fcde
	ldp	q14, q15, [sp, #32*7];			\
Packit Service 82fcde
	ldp	q16, q17, [sp, #32*8];			\
Packit Service 82fcde
	ldp	q18, q19, [sp, #32*9];			\
Packit Service 82fcde
	ldp	q20, q21, [sp, #32*10];			\
Packit Service 82fcde
	ldp	q22, q23, [sp, #32*11];			\
Packit Service 82fcde
	ldp	q24, q25, [sp, #32*12];			\
Packit Service 82fcde
	ldp	q26, q27, [sp, #32*13];			\
Packit Service 82fcde
	ldp	q28, q29, [sp, #32*14];			\
Packit Service 82fcde
	ldp	q30, q31, [sp, #32*15];			\
Packit Service 82fcde
	ldp	 q0,  q1, [sp], #32*NSAVEDQREGPAIRS;	\
Packit Service 82fcde
	cfi_adjust_cfa_offset (-32*NSAVEDQREGPAIRS);
Packit Service 82fcde
Packit Service 82fcde
	.text
Packit Service 82fcde
Packit Service 82fcde
	/* Compute the thread pointer offset for symbols in the static
Packit Service 82fcde
	   TLS block. The offset is the same for all threads.
Packit Service 82fcde
	   Prototype:
Packit Service 82fcde
	   _dl_tlsdesc_return (tlsdesc *) ;
Packit Service 82fcde
	 */
Packit Service 82fcde
	.hidden _dl_tlsdesc_return
Packit Service 82fcde
	.global	_dl_tlsdesc_return
Packit Service 82fcde
	.type	_dl_tlsdesc_return,%function
Packit Service 82fcde
	cfi_startproc
Packit Service 82fcde
	.align 2
Packit Service 82fcde
_dl_tlsdesc_return:
Packit Service 82fcde
	DELOUSE (0)
Packit Service 82fcde
	ldr	PTR_REG (0), [x0, #PTR_SIZE]
Packit Service 82fcde
	RET
Packit Service 82fcde
	cfi_endproc
Packit Service 82fcde
	.size	_dl_tlsdesc_return, .-_dl_tlsdesc_return
Packit Service 82fcde
Packit Service 82fcde
	/* Handler for undefined weak TLS symbols.
Packit Service 82fcde
	   Prototype:
Packit Service 82fcde
	   _dl_tlsdesc_undefweak (tlsdesc *);
Packit Service 82fcde
Packit Service 82fcde
	   The second word of the descriptor contains the addend.
Packit Service 82fcde
	   Return the addend minus the thread pointer. This ensures
Packit Service 82fcde
	   that when the caller adds on the thread pointer it gets back
Packit Service 82fcde
	   the addend.  */
Packit Service 82fcde
Packit Service 82fcde
	.hidden _dl_tlsdesc_undefweak
Packit Service 82fcde
	.global	_dl_tlsdesc_undefweak
Packit Service 82fcde
	.type	_dl_tlsdesc_undefweak,%function
Packit Service 82fcde
	cfi_startproc
Packit Service 82fcde
	.align  2
Packit Service 82fcde
_dl_tlsdesc_undefweak:
Packit Service 82fcde
	str	x1, [sp, #-16]!
Packit Service 82fcde
	cfi_adjust_cfa_offset (16)
Packit Service 82fcde
	DELOUSE (0)
Packit Service 82fcde
	ldr	PTR_REG (0), [x0, #PTR_SIZE]
Packit Service 82fcde
	mrs	x1, tpidr_el0
Packit Service 82fcde
	sub	PTR_REG (0), PTR_REG (0), PTR_REG (1)
Packit Service 82fcde
	ldr	x1, [sp], #16
Packit Service 82fcde
	cfi_adjust_cfa_offset (-16)
Packit Service 82fcde
	RET
Packit Service 82fcde
	cfi_endproc
Packit Service 82fcde
	.size	_dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
Packit Service 82fcde
Packit Service 82fcde
#ifdef SHARED
Packit Service 82fcde
	/* Handler for dynamic TLS symbols.
Packit Service 82fcde
	   Prototype:
Packit Service 82fcde
	   _dl_tlsdesc_dynamic (tlsdesc *) ;
Packit Service 82fcde
Packit Service 82fcde
	   The second word of the descriptor points to a
Packit Service 82fcde
	   tlsdesc_dynamic_arg structure.
Packit Service 82fcde
Packit Service 82fcde
	   Returns the offset between the thread pointer and the
Packit Service 82fcde
	   object referenced by the argument.
Packit Service 82fcde
Packit Service 82fcde
	   ptrdiff_t
Packit Service 82fcde
	   __attribute__ ((__regparm__ (1)))
Packit Service 82fcde
	   _dl_tlsdesc_dynamic (struct tlsdesc *tdp)
Packit Service 82fcde
	   {
Packit Service 82fcde
	     struct tlsdesc_dynamic_arg *td = tdp->arg;
Packit Service 82fcde
	     dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + TCBHEAD_DTV);
Packit Service 82fcde
	     if (__builtin_expect (td->gen_count <= dtv[0].counter
Packit Service 82fcde
		&& (dtv[td->tlsinfo.ti_module].pointer.val
Packit Service 82fcde
		    != TLS_DTV_UNALLOCATED),
Packit Service 82fcde
		1))
Packit Service 82fcde
	       return dtv[td->tlsinfo.ti_module].pointer.val
Packit Service 82fcde
		+ td->tlsinfo.ti_offset
Packit Service 82fcde
		- __thread_pointer;
Packit Service 82fcde
Packit Service 82fcde
	     return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
Packit Service 82fcde
	   }
Packit Service 82fcde
	 */
Packit Service 82fcde
Packit Service 82fcde
	.hidden _dl_tlsdesc_dynamic
Packit Service 82fcde
	.global	_dl_tlsdesc_dynamic
Packit Service 82fcde
	.type	_dl_tlsdesc_dynamic,%function
Packit Service 82fcde
	cfi_startproc
Packit Service 82fcde
	.align 2
Packit Service 82fcde
_dl_tlsdesc_dynamic:
Packit Service 82fcde
	DELOUSE (0)
Packit Service 82fcde
Packit Service 82fcde
	/* Save just enough registers to support fast path, if we fall
Packit Service 82fcde
	   into slow path we will save additional registers.  */
Packit Service 82fcde
	stp	x1,  x2, [sp, #-32]!
Packit Service 82fcde
	stp	x3,  x4, [sp, #16]
Packit Service 82fcde
	cfi_adjust_cfa_offset (32)
Packit Service 82fcde
	cfi_rel_offset (x1, 0)
Packit Service 82fcde
	cfi_rel_offset (x2, 8)
Packit Service 82fcde
	cfi_rel_offset (x3, 16)
Packit Service 82fcde
	cfi_rel_offset (x4, 24)
Packit Service 82fcde
Packit Service 82fcde
	mrs	x4, tpidr_el0
Packit Service 82fcde
	ldr	PTR_REG (1), [x0,#TLSDESC_ARG]
Packit Service 82fcde
	ldr	PTR_REG (0), [x4,#TCBHEAD_DTV]
Packit Service 82fcde
	ldr	PTR_REG (3), [x1,#TLSDESC_GEN_COUNT]
Packit Service 82fcde
	ldr	PTR_REG (2), [x0,#DTV_COUNTER]
Packit Service 82fcde
	cmp	PTR_REG (3), PTR_REG (2)
Packit Service 82fcde
	b.hi	2f
Packit Service 82fcde
	/* Load r2 = td->tlsinfo.ti_module and r3 = td->tlsinfo.ti_offset.  */
Packit Service 82fcde
	ldp	PTR_REG (2), PTR_REG (3), [x1,#TLSDESC_MODID]
Packit Service 82fcde
	add	PTR_REG (0), PTR_REG (0), PTR_REG (2), lsl #(PTR_LOG_SIZE + 1)
Packit Service 82fcde
	ldr	PTR_REG (0), [x0] /* Load val member of DTV entry.  */
Packit Service 82fcde
	cmp	PTR_REG (0), #TLS_DTV_UNALLOCATED
Packit Service 82fcde
	b.eq	2f
Packit Service 82fcde
	sub	PTR_REG (3), PTR_REG (3), PTR_REG (4)
Packit Service 82fcde
	add	PTR_REG (0), PTR_REG (0), PTR_REG (3)
Packit Service 82fcde
1:
Packit Service 82fcde
	ldp	 x3,  x4, [sp, #16]
Packit Service 82fcde
	ldp	 x1,  x2, [sp], #32
Packit Service 82fcde
	cfi_adjust_cfa_offset (-32)
Packit Service 82fcde
	RET
Packit Service 82fcde
2:
Packit Service 82fcde
	/* This is the slow path. We need to call __tls_get_addr() which
Packit Service 82fcde
	   means we need to save and restore all the register that the
Packit Service 82fcde
	   callee will trash.  */
Packit Service 82fcde
Packit Service 82fcde
	/* Save the remaining registers that we must treat as caller save.  */
Packit Service 82fcde
# define NSAVEXREGPAIRS 8
Packit Service 82fcde
	stp	x29, x30, [sp,#-16*NSAVEXREGPAIRS]!
Packit Service 82fcde
	cfi_adjust_cfa_offset (16*NSAVEXREGPAIRS)
Packit Service 82fcde
	cfi_rel_offset (x29, 0)
Packit Service 82fcde
	cfi_rel_offset (x30, 8)
Packit Service 82fcde
	mov	x29, sp
Packit Service 82fcde
	stp	 x5,  x6, [sp, #16*1]
Packit Service 82fcde
	stp	 x7,  x8, [sp, #16*2]
Packit Service 82fcde
	stp	 x9, x10, [sp, #16*3]
Packit Service 82fcde
	stp	x11, x12, [sp, #16*4]
Packit Service 82fcde
	stp	x13, x14, [sp, #16*5]
Packit Service 82fcde
	stp	x15, x16, [sp, #16*6]
Packit Service 82fcde
	stp	x17, x18, [sp, #16*7]
Packit Service 82fcde
	cfi_rel_offset (x5, 16*1)
Packit Service 82fcde
	cfi_rel_offset (x6, 16*1+8)
Packit Service 82fcde
	cfi_rel_offset (x7, 16*2)
Packit Service 82fcde
	cfi_rel_offset (x8, 16*2+8)
Packit Service 82fcde
	cfi_rel_offset (x9, 16*3)
Packit Service 82fcde
	cfi_rel_offset (x10, 16*3+8)
Packit Service 82fcde
	cfi_rel_offset (x11, 16*4)
Packit Service 82fcde
	cfi_rel_offset (x12, 16*4+8)
Packit Service 82fcde
	cfi_rel_offset (x13, 16*5)
Packit Service 82fcde
	cfi_rel_offset (x14, 16*5+8)
Packit Service 82fcde
	cfi_rel_offset (x15, 16*6)
Packit Service 82fcde
	cfi_rel_offset (x16, 16*6+8)
Packit Service 82fcde
	cfi_rel_offset (x17, 16*7)
Packit Service 82fcde
	cfi_rel_offset (x18, 16*7+8)
Packit Service 82fcde
Packit Service 82fcde
	SAVE_Q_REGISTERS
Packit Service 82fcde
Packit Service 82fcde
	mov	x0, x1
Packit Service 82fcde
	bl	__tls_get_addr
Packit Service 82fcde
Packit Service 82fcde
	mrs	x1, tpidr_el0
Packit Service 82fcde
	sub	PTR_REG (0), PTR_REG (0), PTR_REG (1)
Packit Service 82fcde
Packit Service 82fcde
	RESTORE_Q_REGISTERS
Packit Service 82fcde
Packit Service 82fcde
	ldp	 x5,  x6, [sp, #16*1]
Packit Service 82fcde
	ldp	 x7,  x8, [sp, #16*2]
Packit Service 82fcde
	ldp	 x9, x10, [sp, #16*3]
Packit Service 82fcde
	ldp	x11, x12, [sp, #16*4]
Packit Service 82fcde
	ldp	x13, x14, [sp, #16*5]
Packit Service 82fcde
	ldp	x15, x16, [sp, #16*6]
Packit Service 82fcde
	ldp	x17, x18, [sp, #16*7]
Packit Service 82fcde
Packit Service 82fcde
	ldp	x29, x30, [sp], #16*NSAVEXREGPAIRS
Packit Service 82fcde
	cfi_adjust_cfa_offset (-16*NSAVEXREGPAIRS)
Packit Service 82fcde
	cfi_restore (x29)
Packit Service 82fcde
	cfi_restore (x30)
Packit Service 82fcde
	b	1b
Packit Service 82fcde
	cfi_endproc
Packit Service 82fcde
	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
Packit Service 82fcde
# undef NSAVEXREGPAIRS
Packit Service 82fcde
#endif