Blame sysdeps/arm/sysdep.h

Packit Service 82fcde
/* Assembler macros for ARM.
Packit Service 82fcde
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
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 <sysdeps/generic/sysdep.h>
Packit Service 82fcde
#include <features.h>
Packit Service 82fcde
Packit Service 82fcde
#ifndef __ASSEMBLER__
Packit Service 82fcde
# include <stdint.h>
Packit Service 82fcde
#else
Packit Service 82fcde
# include <arm-features.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* The __ARM_ARCH define is provided by gcc 4.8.  Construct it otherwise.  */
Packit Service 82fcde
#ifndef __ARM_ARCH
Packit Service 82fcde
# ifdef __ARM_ARCH_2__
Packit Service 82fcde
#  define __ARM_ARCH 2
Packit Service 82fcde
# elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__)
Packit Service 82fcde
#  define __ARM_ARCH 3
Packit Service 82fcde
# elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__)
Packit Service 82fcde
#  define __ARM_ARCH 4
Packit Service 82fcde
# elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \
Packit Service 82fcde
       || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
Packit Service 82fcde
       || defined(__ARM_ARCH_5TEJ__)
Packit Service 82fcde
#  define __ARM_ARCH 5
Packit Service 82fcde
# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
Packit Service 82fcde
       || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
Packit Service 82fcde
       || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
Packit Service 82fcde
#  define __ARM_ARCH 6
Packit Service 82fcde
# elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
Packit Service 82fcde
       || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
Packit Service 82fcde
       || defined(__ARM_ARCH_7EM__)
Packit Service 82fcde
#  define __ARM_ARCH 7
Packit Service 82fcde
# else
Packit Service 82fcde
#  error unknown arm architecture
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
Packit Service 82fcde
# define ARCH_HAS_BX
Packit Service 82fcde
#endif
Packit Service 82fcde
#if __ARM_ARCH > 4
Packit Service 82fcde
# define ARCH_HAS_BLX
Packit Service 82fcde
#endif
Packit Service 82fcde
#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
Packit Service 82fcde
# define ARCH_HAS_HARD_TP
Packit Service 82fcde
#endif
Packit Service 82fcde
#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6T2__)
Packit Service 82fcde
# define ARCH_HAS_T2
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifdef	__ASSEMBLER__
Packit Service 82fcde
Packit Service 82fcde
/* Syntactic details of assembler.  */
Packit Service 82fcde
Packit Service 82fcde
#define ALIGNARG(log2) log2
Packit Service 82fcde
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
Packit Service 82fcde
Packit Service 82fcde
#define PLTJMP(_x)	_x##(PLT)
Packit Service 82fcde
Packit Service 82fcde
#ifdef ARCH_HAS_BX
Packit Service 82fcde
# define BX(R)		bx	R
Packit Service 82fcde
# define BXC(C, R)	bx##C	R
Packit Service 82fcde
# ifdef ARCH_HAS_BLX
Packit Service 82fcde
#  define BLX(R)	blx	R
Packit Service 82fcde
# else
Packit Service 82fcde
#  define BLX(R)	mov	lr, pc; bx R
Packit Service 82fcde
# endif
Packit Service 82fcde
#else
Packit Service 82fcde
# define BX(R)		mov	pc, R
Packit Service 82fcde
# define BXC(C, R)	mov##C	pc, R
Packit Service 82fcde
# define BLX(R)		mov	lr, pc; mov pc, R
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#define DO_RET(R)	BX(R)
Packit Service 82fcde
#define RETINSTR(C, R)	BXC(C, R)
Packit Service 82fcde
Packit Service 82fcde
/* Define an entry point visible from C.  */
Packit Service 82fcde
#define	ENTRY(name)					\
Packit Service 82fcde
	.globl	C_SYMBOL_NAME(name);			\
Packit Service 82fcde
	.type	C_SYMBOL_NAME(name),%function;		\
Packit Service 82fcde
	.align	ALIGNARG(4);				\
Packit Service 82fcde
  C_LABEL(name)						\
Packit Service 82fcde
	CFI_SECTIONS;					\
Packit Service 82fcde
	cfi_startproc;					\
Packit Service 82fcde
	CALL_MCOUNT
Packit Service 82fcde
Packit Service 82fcde
#define CFI_SECTIONS					\
Packit Service 82fcde
	.cfi_sections .debug_frame
Packit Service 82fcde
Packit Service 82fcde
#undef	END
Packit Service 82fcde
#define END(name)					\
Packit Service 82fcde
	cfi_endproc;					\
Packit Service 82fcde
	ASM_SIZE_DIRECTIVE(name)
Packit Service 82fcde
Packit Service 82fcde
/* If compiled for profiling, call `mcount' at the start of each function.  */
Packit Service 82fcde
#ifdef	PROF
Packit Service 82fcde
/* Call __gnu_mcount_nc (GCC >= 4.4).  */
Packit Service 82fcde
#define CALL_MCOUNT					\
Packit Service 82fcde
	push	{lr};					\
Packit Service 82fcde
	cfi_adjust_cfa_offset (4);			\
Packit Service 82fcde
	cfi_rel_offset (lr, 0);				\
Packit Service 82fcde
	bl	PLTJMP(mcount);				\
Packit Service 82fcde
	cfi_adjust_cfa_offset (-4);			\
Packit Service 82fcde
	cfi_restore (lr)
Packit Service 82fcde
#else
Packit Service 82fcde
#define CALL_MCOUNT		/* Do nothing.  */
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Since C identifiers are not normally prefixed with an underscore
Packit Service 82fcde
   on this system, the asm identifier `syscall_error' intrudes on the
Packit Service 82fcde
   C name space.  Make sure we use an innocuous name.  */
Packit Service 82fcde
#define	syscall_error	__syscall_error
Packit Service 82fcde
#define mcount		__gnu_mcount_nc
Packit Service 82fcde
Packit Service 82fcde
/* Tag_ABI_align8_preserved: This code preserves 8-byte
Packit Service 82fcde
   alignment in any callee.  */
Packit Service 82fcde
	.eabi_attribute 25, 1
Packit Service 82fcde
/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
Packit Service 82fcde
   the caller.  */
Packit Service 82fcde
	.eabi_attribute 24, 1
Packit Service 82fcde
Packit Service 82fcde
/* The thumb2 encoding is reasonably complete.  Unless suppressed, use it.  */
Packit Service 82fcde
	.syntax unified
Packit Service 82fcde
# if defined(__thumb2__) && !defined(NO_THUMB)
Packit Service 82fcde
	.thumb
Packit Service 82fcde
#else
Packit Service 82fcde
#  undef __thumb__
Packit Service 82fcde
#  undef __thumb2__
Packit Service 82fcde
	.arm
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* Load or store to/from address X + Y into/from R, (maybe) using T.
Packit Service 82fcde
   X or Y can use T freely; T can be R if OP is a load.  The first
Packit Service 82fcde
   version eschews the two-register addressing mode, while the
Packit Service 82fcde
   second version uses it.  */
Packit Service 82fcde
# define LDST_INDEXED_NOINDEX(OP, R, T, X, Y)		\
Packit Service 82fcde
	add	T, X, Y;				\
Packit Service 82fcde
	OP	R, [T]
Packit Service 82fcde
# define LDST_INDEXED_INDEX(OP, R, X, Y)		\
Packit Service 82fcde
	OP	R, [X, Y]
Packit Service 82fcde
Packit Service 82fcde
# ifdef ARM_NO_INDEX_REGISTER
Packit Service 82fcde
/* We're never using the two-register addressing mode, so this
Packit Service 82fcde
   always uses an intermediate add.  */
Packit Service 82fcde
#  define LDST_INDEXED(OP, R, T, X, Y)	LDST_INDEXED_NOINDEX (OP, R, T, X, Y)
Packit Service 82fcde
#  define LDST_PC_INDEXED(OP, R, T, X)	LDST_INDEXED_NOINDEX (OP, R, T, pc, X)
Packit Service 82fcde
# else
Packit Service 82fcde
/* The two-register addressing mode is OK, except on Thumb with pc.  */
Packit Service 82fcde
#  define LDST_INDEXED(OP, R, T, X, Y)	LDST_INDEXED_INDEX (OP, R, X, Y)
Packit Service 82fcde
#  ifdef __thumb2__
Packit Service 82fcde
#   define LDST_PC_INDEXED(OP, R, T, X)	LDST_INDEXED_NOINDEX (OP, R, T, pc, X)
Packit Service 82fcde
#  else
Packit Service 82fcde
#   define LDST_PC_INDEXED(OP, R, T, X)	LDST_INDEXED_INDEX (OP, R, pc, X)
Packit Service 82fcde
#  endif
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* Load or store to/from a pc-relative EXPR into/from R, using T.  */
Packit Service 82fcde
# ifdef __thumb2__
Packit Service 82fcde
#  define LDST_PCREL(OP, R, T, EXPR) \
Packit Service 82fcde
	ldr	T, 98f;					\
Packit Service 82fcde
	.subsection 2;					\
Packit Service 82fcde
98:	.word	EXPR - 99f - PC_OFS;			\
Packit Service 82fcde
	.previous;					\
Packit Service 82fcde
99:	add	T, T, pc;				\
Packit Service 82fcde
	OP	R, [T]
Packit Service 82fcde
# elif defined (ARCH_HAS_T2) && ARM_PCREL_MOVW_OK
Packit Service 82fcde
#  define LDST_PCREL(OP, R, T, EXPR)			\
Packit Service 82fcde
	movw	T, #:lower16:EXPR - 99f - PC_OFS;	\
Packit Service 82fcde
	movt	T, #:upper16:EXPR - 99f - PC_OFS;	\
Packit Service 82fcde
99:	LDST_PC_INDEXED (OP, R, T, T)
Packit Service 82fcde
# else
Packit Service 82fcde
#  define LDST_PCREL(OP, R, T, EXPR) \
Packit Service 82fcde
	ldr	T, 98f;					\
Packit Service 82fcde
	.subsection 2;					\
Packit Service 82fcde
98:	.word	EXPR - 99f - PC_OFS;			\
Packit Service 82fcde
	.previous;					\
Packit Service 82fcde
99:	OP	R, [pc, T]
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* Load from a global SYMBOL + CONSTANT into R, using T.  */
Packit Service 82fcde
# if defined (ARCH_HAS_T2) && !defined (PIC)
Packit Service 82fcde
#  define LDR_GLOBAL(R, T, SYMBOL, CONSTANT)				\
Packit Service 82fcde
	movw	T, #:lower16:SYMBOL;					\
Packit Service 82fcde
	movt	T, #:upper16:SYMBOL;					\
Packit Service 82fcde
	ldr	R, [T, $CONSTANT]
Packit Service 82fcde
# elif defined (ARCH_HAS_T2) && defined (PIC) && ARM_PCREL_MOVW_OK
Packit Service 82fcde
#  define LDR_GLOBAL(R, T, SYMBOL, CONSTANT)				\
Packit Service 82fcde
	movw	R, #:lower16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS;	\
Packit Service 82fcde
	movw	T, #:lower16:99f - 98f - PC_OFS;			\
Packit Service 82fcde
	movt	R, #:upper16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS;	\
Packit Service 82fcde
	movt	T, #:upper16:99f - 98f - PC_OFS;			\
Packit Service 82fcde
	.pushsection .rodata.cst4, "aM", %progbits, 4;			\
Packit Service 82fcde
	.balign 4;							\
Packit Service 82fcde
99:	.word	SYMBOL##(GOT);						\
Packit Service 82fcde
	.popsection;							\
Packit Service 82fcde
97:	add	R, R, pc;						\
Packit Service 82fcde
98:	LDST_PC_INDEXED (ldr, T, T, T);					\
Packit Service 82fcde
	LDST_INDEXED (ldr, R, T, R, T);					\
Packit Service 82fcde
	ldr	R, [R, $CONSTANT]
Packit Service 82fcde
# else
Packit Service 82fcde
#  define LDR_GLOBAL(R, T, SYMBOL, CONSTANT)		\
Packit Service 82fcde
	ldr	T, 99f;					\
Packit Service 82fcde
	ldr	R, 100f;				\
Packit Service 82fcde
98:	add	T, T, pc;				\
Packit Service 82fcde
	ldr	T, [T, R];				\
Packit Service 82fcde
	.subsection 2;					\
Packit Service 82fcde
99:	.word	_GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS;	\
Packit Service 82fcde
100:	.word	SYMBOL##(GOT);				\
Packit Service 82fcde
	.previous;					\
Packit Service 82fcde
	ldr	R, [T, $CONSTANT]
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* This is the same as LDR_GLOBAL, but for a SYMBOL that is known to
Packit Service 82fcde
   be in the same linked object (as for one with hidden visibility).
Packit Service 82fcde
   We can avoid the GOT indirection in the PIC case.  For the pure
Packit Service 82fcde
   static case, LDR_GLOBAL is already optimal.  */
Packit Service 82fcde
# ifdef PIC
Packit Service 82fcde
#  define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \
Packit Service 82fcde
  LDST_PCREL (ldr, R, T, SYMBOL + CONSTANT)
Packit Service 82fcde
# else
Packit Service 82fcde
#  define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \
Packit Service 82fcde
  LDR_GLOBAL (R, T, SYMBOL, CONSTANT)
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* Cope with negative memory offsets, which thumb can't encode.
Packit Service 82fcde
   Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
Packit Service 82fcde
   and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
Packit Service 82fcde
   or NEGOFF_OFF2 to use A-B for thumb and A for arm.  */
Packit Service 82fcde
# ifdef __thumb2__
Packit Service 82fcde
#  define NEGOFF_ADJ_BASE(R, OFF)	add R, R, $OFF
Packit Service 82fcde
#  define NEGOFF_ADJ_BASE2(D, S, OFF)	add D, S, $OFF
Packit Service 82fcde
#  define NEGOFF_OFF1(R, OFF)		[R]
Packit Service 82fcde
#  define NEGOFF_OFF2(R, OFFA, OFFB)	[R, $((OFFA) - (OFFB))]
Packit Service 82fcde
# else
Packit Service 82fcde
#  define NEGOFF_ADJ_BASE(R, OFF)
Packit Service 82fcde
#  define NEGOFF_ADJ_BASE2(D, S, OFF)	mov D, S
Packit Service 82fcde
#  define NEGOFF_OFF1(R, OFF)		[R, $OFF]
Packit Service 82fcde
#  define NEGOFF_OFF2(R, OFFA, OFFB)	[R, $OFFA]
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
/* Helper to get the TLS base pointer.  The interface is that TMP is a
Packit Service 82fcde
   register that may be used to hold the LR, if necessary.  TMP may be
Packit Service 82fcde
   LR itself to indicate that LR need not be saved.  The base pointer
Packit Service 82fcde
   is returned in R0.  Only R0 and TMP are modified.  */
Packit Service 82fcde
Packit Service 82fcde
# ifdef ARCH_HAS_HARD_TP
Packit Service 82fcde
/* If the cpu has cp15 available, use it.  */
Packit Service 82fcde
#  define GET_TLS(TMP)		mrc p15, 0, r0, c13, c0, 3
Packit Service 82fcde
# else
Packit Service 82fcde
/* At this generic level we have no tricks to pull.  Call the ABI routine.  */
Packit Service 82fcde
#  define GET_TLS(TMP)					\
Packit Service 82fcde
	push	{ r1, r2, r3, lr };			\
Packit Service 82fcde
	cfi_remember_state;				\
Packit Service 82fcde
	cfi_adjust_cfa_offset (16);			\
Packit Service 82fcde
	cfi_rel_offset (r1, 0);				\
Packit Service 82fcde
	cfi_rel_offset (r2, 4);				\
Packit Service 82fcde
	cfi_rel_offset (r3, 8);				\
Packit Service 82fcde
	cfi_rel_offset (lr, 12);			\
Packit Service 82fcde
	bl	__aeabi_read_tp;			\
Packit Service 82fcde
	pop	{ r1, r2, r3, lr };			\
Packit Service 82fcde
	cfi_restore_state
Packit Service 82fcde
# endif /* ARCH_HAS_HARD_TP */
Packit Service 82fcde
Packit Service 82fcde
/* These are the directives used for EABI unwind info.
Packit Service 82fcde
   Wrap them in macros so another configuration's sysdep.h
Packit Service 82fcde
   file can define them away if it doesn't use EABI unwind info.  */
Packit Service 82fcde
# define eabi_fnstart		.fnstart
Packit Service 82fcde
# define eabi_fnend		.fnend
Packit Service 82fcde
# define eabi_save(...)		.save __VA_ARGS__
Packit Service 82fcde
# define eabi_cantunwind	.cantunwind
Packit Service 82fcde
# define eabi_pad(n)		.pad n
Packit Service 82fcde
Packit Service 82fcde
#endif	/* __ASSEMBLER__ */
Packit Service 82fcde
Packit Service 82fcde
/* This number is the offset from the pc at the current location.  */
Packit Service 82fcde
#ifdef __thumb__
Packit Service 82fcde
# define PC_OFS  4
Packit Service 82fcde
#else
Packit Service 82fcde
# define PC_OFS  8
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Pointer mangling support.  */
Packit Service 82fcde
#if (IS_IN (rtld) || \
Packit Service 82fcde
     (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
Packit Service 82fcde
# ifdef __ASSEMBLER__
Packit Service 82fcde
#  define PTR_MANGLE_LOAD(guard, tmp)					\
Packit Service 82fcde
  LDR_HIDDEN (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local), 0)
Packit Service 82fcde
#  define PTR_MANGLE(dst, src, guard, tmp)				\
Packit Service 82fcde
  PTR_MANGLE_LOAD(guard, tmp);						\
Packit Service 82fcde
  PTR_MANGLE2(dst, src, guard)
Packit Service 82fcde
/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
Packit Service 82fcde
#  define PTR_MANGLE2(dst, src, guard)		\
Packit Service 82fcde
  eor dst, src, guard
Packit Service 82fcde
#  define PTR_DEMANGLE(dst, src, guard, tmp)	\
Packit Service 82fcde
  PTR_MANGLE (dst, src, guard, tmp)
Packit Service 82fcde
#  define PTR_DEMANGLE2(dst, src, guard)	\
Packit Service 82fcde
  PTR_MANGLE2 (dst, src, guard)
Packit Service 82fcde
# else
Packit Service 82fcde
extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
Packit Service 82fcde
#  define PTR_MANGLE(var) \
Packit Service 82fcde
  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
Packit Service 82fcde
#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
Packit Service 82fcde
# endif
Packit Service 82fcde
#else
Packit Service 82fcde
# ifdef __ASSEMBLER__
Packit Service 82fcde
#  define PTR_MANGLE_LOAD(guard, tmp)					\
Packit Service 82fcde
  LDR_GLOBAL (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard), 0);
Packit Service 82fcde
#  define PTR_MANGLE(dst, src, guard, tmp)				\
Packit Service 82fcde
  PTR_MANGLE_LOAD(guard, tmp);						\
Packit Service 82fcde
  PTR_MANGLE2(dst, src, guard)
Packit Service 82fcde
/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
Packit Service 82fcde
#  define PTR_MANGLE2(dst, src, guard)		\
Packit Service 82fcde
  eor dst, src, guard
Packit Service 82fcde
#  define PTR_DEMANGLE(dst, src, guard, tmp)	\
Packit Service 82fcde
  PTR_MANGLE (dst, src, guard, tmp)
Packit Service 82fcde
#  define PTR_DEMANGLE2(dst, src, guard)	\
Packit Service 82fcde
  PTR_MANGLE2 (dst, src, guard)
Packit Service 82fcde
# else
Packit Service 82fcde
extern uintptr_t __pointer_chk_guard attribute_relro;
Packit Service 82fcde
#  define PTR_MANGLE(var) \
Packit Service 82fcde
  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
Packit Service 82fcde
#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif