mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
ARM: Use movw/movt more when available
This commit is contained in:
parent
b5af9297d5
commit
8c2b1ed8bb
27
ChangeLog
27
ChangeLog
@ -1,3 +1,30 @@
|
||||
2014-10-22 Roland McGrath <roland@hack.frob.com>
|
||||
|
||||
* sysdeps/arm/__longjmp.S [NEED_HWCAP] [IS_IN_rtld]: Use LDST_PCREL
|
||||
macro to get at the _rt_local_ro field.
|
||||
[NEED_HWCAP] [!IS_IN_rtld]: Use LDR_GLOBAL to get at _rtld_global_ro
|
||||
([PIC] case) or _dl_hwcap ([!PIC] case).
|
||||
* sysdeps/arm/setjmp.S: Likewise.
|
||||
|
||||
* config.h.in (ARM_PCREL_MOVW_OK): New macro.
|
||||
* sysdeps/arm/configure.ac: New check to define it.
|
||||
* sysdeps/arm/configure: Regenerated.
|
||||
* sysdeps/arm/sysdep.h [__ASSEMBLER__]: Include <arm-features.h>.
|
||||
(LDST_INDEXED_NOINDEX, LDST_INDEXED_INDEX): New macros.
|
||||
(LDST_INDEXED, LDST_PC_INDEXED): New macros, differing definitions
|
||||
depending on [ARM_NO_INDEX_REGISTER] and [__thumb2__].
|
||||
(LDST_PCREL) [!__thumb2__ && ARCH_HAS_T2 && ARM_PCREL_MOVW_OK]:
|
||||
Use move/movt pair instead of a load.
|
||||
(LDST_GLOBAL): Macro removed.
|
||||
(LDR_GLOBAL): New macro replaces it.
|
||||
(LDR_HIDDEN): New macro.
|
||||
(PTR_MANGLE_LOAD): Use LDR_GLOBAL rather than LDST_GLOBAL.
|
||||
Use LDR_HIDDEN instead for __pointer_chk_guard_local.
|
||||
|
||||
* setjmp/tst-setjmp-static.c: New file.
|
||||
* setjmp/Makefile (tests): Add it.
|
||||
(tests-static): New variable.
|
||||
|
||||
2014-10-22 Maciej W. Rozycki <macro@codesourcery.com>
|
||||
|
||||
[BZ #17485]
|
||||
|
@ -243,6 +243,9 @@
|
||||
/* The ARM hard-float ABI is being used. */
|
||||
#undef HAVE_ARM_PCS_VFP
|
||||
|
||||
/* The ARM movw/movt instructions using PC-relative relocs work right. */
|
||||
#define ARM_PCREL_MOVW_OK 0
|
||||
|
||||
/* The pt_chown binary is being built and used by grantpt. */
|
||||
#define HAVE_PT_CHOWN 0
|
||||
|
||||
|
@ -28,7 +28,8 @@ routines := setjmp sigjmp bsd-setjmp bsd-_setjmp \
|
||||
longjmp __longjmp jmp-unwind
|
||||
|
||||
tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
|
||||
tst-sigsetjmp
|
||||
tst-sigsetjmp tst-setjmp-static
|
||||
tests-static := tst-setjmp-static
|
||||
|
||||
|
||||
include ../Rules
|
||||
|
1
setjmp/tst-setjmp-static.c
Normal file
1
setjmp/tst-setjmp-static.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-setjmp.c"
|
@ -77,21 +77,15 @@ ENTRY (__longjmp)
|
||||
|
||||
#ifdef NEED_HWCAP
|
||||
# ifdef IS_IN_rtld
|
||||
ldr a4, 1f
|
||||
ldr a3, .Lrtld_local_ro
|
||||
0: add a4, pc, a4
|
||||
add a4, a4, a3
|
||||
ldr a4, [a4, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
|
||||
LDST_PCREL (ldr, a4, a3, \
|
||||
C_SYMBOL_NAME(_rtld_local_ro) \
|
||||
+ RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
# ifdef PIC
|
||||
ldr a4, 1f
|
||||
ldr a3, .Lrtld_global_ro
|
||||
0: add a4, pc, a4
|
||||
ldr a4, [a4, a3]
|
||||
ldr a4, [a4, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
|
||||
LDR_GLOBAL (a4, a3, C_SYMBOL_NAME(_rtld_global_ro), \
|
||||
RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
ldr a4, .Lhwcap
|
||||
ldr a4, [a4, #0]
|
||||
LDR_GLOBAL (a4, a3, C_SYMBOL_NAME(_dl_hwcap), 0)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@ -138,21 +132,4 @@ ENTRY (__longjmp)
|
||||
|
||||
DO_RET(lr)
|
||||
|
||||
#ifdef NEED_HWCAP
|
||||
# ifdef IS_IN_rtld
|
||||
1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
|
||||
.Lrtld_local_ro:
|
||||
.long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF)
|
||||
# else
|
||||
# ifdef PIC
|
||||
1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
|
||||
.Lrtld_global_ro:
|
||||
.long C_SYMBOL_NAME(_rtld_global_ro)(GOT)
|
||||
# else
|
||||
.Lhwcap:
|
||||
.long C_SYMBOL_NAME(_dl_hwcap)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
END (__longjmp)
|
||||
|
48
sysdeps/arm/configure
vendored
48
sysdeps/arm/configure
vendored
@ -211,6 +211,54 @@ else
|
||||
have-arm-tls-desc = no"
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether PC-relative relocs in movw/movt work properly" >&5
|
||||
$as_echo_n "checking whether PC-relative relocs in movw/movt work properly... " >&6; }
|
||||
if ${libc_cv_arm_pcrel_movw+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
||||
cat > conftest.s <<\EOF
|
||||
.syntax unified
|
||||
.arm
|
||||
.arch armv7-a
|
||||
|
||||
.text
|
||||
.globl foo
|
||||
.type foo,%function
|
||||
foo: movw r0, #:lower16:symbol - 1f - 8
|
||||
movt r0, #:upper16:symbol - 1f - 8
|
||||
1: add r0, pc
|
||||
@ And now a case with a local symbol.
|
||||
movw r0, #:lower16:3f - 2f - 8
|
||||
movt r0, #:upper16:3f - 2f - 8
|
||||
2: add r0, pc
|
||||
bx lr
|
||||
|
||||
.data
|
||||
.globl symbol
|
||||
.hidden symbol
|
||||
symbol: .long 23
|
||||
3: .long 17
|
||||
EOF
|
||||
libc_cv_arm_pcrel_movw=no
|
||||
${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
|
||||
-nostartfiles -nostdlib -shared \
|
||||
-o conftest.so conftest.s 1>&5 2>&5 &&
|
||||
LC_ALL=C $READELF -dr conftest.so > conftest.dr 2>&5 &&
|
||||
{
|
||||
cat conftest.dr 1>&5
|
||||
fgrep 'TEXTREL
|
||||
R_ARM_NONE' conftest.dr > /dev/null || libc_cv_arm_pcrel_movw=yes
|
||||
}
|
||||
rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arm_pcrel_movw" >&5
|
||||
$as_echo "$libc_cv_arm_pcrel_movw" >&6; }
|
||||
if test $libc_cv_arm_pcrel_movw = yes; then
|
||||
$as_echo "#define ARM_PCREL_MOVW_OK 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
libc_cv_gcc_unwind_find_fde=no
|
||||
|
||||
# Remove -fno-unwind-tables that was added in sysdeps/arm/preconfigure.ac.
|
||||
|
@ -40,6 +40,46 @@ else
|
||||
LIBC_CONFIG_VAR([have-arm-tls-desc], [no])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether PC-relative relocs in movw/movt work properly],
|
||||
libc_cv_arm_pcrel_movw, [
|
||||
cat > conftest.s <<\EOF
|
||||
.syntax unified
|
||||
.arm
|
||||
.arch armv7-a
|
||||
|
||||
.text
|
||||
.globl foo
|
||||
.type foo,%function
|
||||
foo: movw r0, #:lower16:symbol - 1f - 8
|
||||
movt r0, #:upper16:symbol - 1f - 8
|
||||
1: add r0, pc
|
||||
@ And now a case with a local symbol.
|
||||
movw r0, #:lower16:3f - 2f - 8
|
||||
movt r0, #:upper16:3f - 2f - 8
|
||||
2: add r0, pc
|
||||
bx lr
|
||||
|
||||
.data
|
||||
.globl symbol
|
||||
.hidden symbol
|
||||
symbol: .long 23
|
||||
3: .long 17
|
||||
EOF
|
||||
libc_cv_arm_pcrel_movw=no
|
||||
${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
|
||||
-nostartfiles -nostdlib -shared \
|
||||
-o conftest.so conftest.s 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD &&
|
||||
LC_ALL=C $READELF -dr conftest.so > conftest.dr 2>&AS_MESSAGE_LOG_FD &&
|
||||
{
|
||||
cat conftest.dr 1>&AS_MESSAGE_LOG_FD
|
||||
fgrep 'TEXTREL
|
||||
R_ARM_NONE' conftest.dr > /dev/null || libc_cv_arm_pcrel_movw=yes
|
||||
}
|
||||
rm -f conftest*])
|
||||
if test $libc_cv_arm_pcrel_movw = yes; then
|
||||
AC_DEFINE([ARM_PCREL_MOVW_OK])
|
||||
fi
|
||||
|
||||
libc_cv_gcc_unwind_find_fde=no
|
||||
|
||||
# Remove -fno-unwind-tables that was added in sysdeps/arm/preconfigure.ac.
|
||||
|
@ -58,21 +58,15 @@ ENTRY (__sigsetjmp)
|
||||
#ifdef NEED_HWCAP
|
||||
/* Check if we have a VFP unit. */
|
||||
# ifdef IS_IN_rtld
|
||||
ldr a3, 1f
|
||||
ldr a4, .Lrtld_local_ro
|
||||
0: add a3, pc, a3
|
||||
add a3, a3, a4
|
||||
ldr a3, [a3, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
|
||||
LDST_PCREL (ldr, a3, a4, \
|
||||
C_SYMBOL_NAME(_rtld_local_ro) \
|
||||
+ RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
# ifdef PIC
|
||||
ldr a3, 1f
|
||||
ldr a4, .Lrtld_global_ro
|
||||
0: add a3, pc, a3
|
||||
ldr a3, [a3, a4]
|
||||
ldr a3, [a3, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
|
||||
LDR_GLOBAL (a3, a4, C_SYMBOL_NAME(_rtld_global_ro), \
|
||||
RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
ldr a3, .Lhwcap
|
||||
ldr a3, [a3, #0]
|
||||
LDR_GLOBAL (a3, a4, C_SYMBOL_NAME(_dl_hwcap), 0)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@ -114,23 +108,6 @@ ENTRY (__sigsetjmp)
|
||||
/* Make a tail call to __sigjmp_save; it takes the same args. */
|
||||
B PLTJMP(C_SYMBOL_NAME(__sigjmp_save))
|
||||
|
||||
#ifdef NEED_HWCAP
|
||||
# ifdef IS_IN_rtld
|
||||
1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
|
||||
.Lrtld_local_ro:
|
||||
.long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF)
|
||||
# else
|
||||
# ifdef PIC
|
||||
1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS
|
||||
.Lrtld_global_ro:
|
||||
.long C_SYMBOL_NAME(_rtld_global_ro)(GOT)
|
||||
# else
|
||||
.Lhwcap:
|
||||
.long C_SYMBOL_NAME(_dl_hwcap)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
END (__sigsetjmp)
|
||||
|
||||
hidden_def (__sigsetjmp)
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <stdint.h>
|
||||
#else
|
||||
# include <arm-features.h>
|
||||
#endif
|
||||
|
||||
/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
|
||||
@ -157,6 +159,32 @@
|
||||
.arm
|
||||
# endif
|
||||
|
||||
/* Load or store to/from address X + Y into/from R, (maybe) using T.
|
||||
X or Y can use T freely; T can be R if OP is a load. The first
|
||||
version eschews the two-register addressing mode, while the
|
||||
second version uses it. */
|
||||
# define LDST_INDEXED_NOINDEX(OP, R, T, X, Y) \
|
||||
add T, X, Y; \
|
||||
sfi_breg T, \
|
||||
OP R, [T]
|
||||
# define LDST_INDEXED_INDEX(OP, R, X, Y) \
|
||||
OP R, [X, Y]
|
||||
|
||||
# ifdef ARM_NO_INDEX_REGISTER
|
||||
/* We're never using the two-register addressing mode, so this
|
||||
always uses an intermediate add. */
|
||||
# define LDST_INDEXED(OP, R, T, X, Y) LDST_INDEXED_NOINDEX (OP, R, T, X, Y)
|
||||
# define LDST_PC_INDEXED(OP, R, T, X) LDST_INDEXED_NOINDEX (OP, R, T, pc, X)
|
||||
# else
|
||||
/* The two-register addressing mode is OK, except on Thumb with pc. */
|
||||
# define LDST_INDEXED(OP, R, T, X, Y) LDST_INDEXED_INDEX (OP, R, X, Y)
|
||||
# ifdef __thumb2__
|
||||
# define LDST_PC_INDEXED(OP, R, T, X) LDST_INDEXED_NOINDEX (OP, R, T, pc, X)
|
||||
# else
|
||||
# define LDST_PC_INDEXED(OP, R, T, X) LDST_INDEXED_INDEX (OP, R, pc, X)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Load or store to/from a pc-relative EXPR into/from R, using T. */
|
||||
# ifdef __thumb2__
|
||||
# define LDST_PCREL(OP, R, T, EXPR) \
|
||||
@ -166,6 +194,11 @@
|
||||
.previous; \
|
||||
99: add T, T, pc; \
|
||||
OP R, [T]
|
||||
# elif defined (ARCH_HAS_T2) && ARM_PCREL_MOVW_OK
|
||||
# define LDST_PCREL(OP, R, T, EXPR) \
|
||||
movw T, #:lower16:EXPR - 99f - PC_OFS; \
|
||||
movt T, #:upper16:EXPR - 99f - PC_OFS; \
|
||||
99: LDST_PC_INDEXED (OP, R, T, T)
|
||||
# else
|
||||
# define LDST_PCREL(OP, R, T, EXPR) \
|
||||
ldr T, 98f; \
|
||||
@ -175,17 +208,50 @@
|
||||
99: OP R, [pc, T]
|
||||
# endif
|
||||
|
||||
/* Load or store to/from a global EXPR into/from R, using T. */
|
||||
# define LDST_GLOBAL(OP, R, T, EXPR) \
|
||||
/* Load from a global SYMBOL + CONSTANT into R, using T. */
|
||||
# if defined (ARCH_HAS_T2) && !defined (PIC)
|
||||
# define LDR_GLOBAL(R, T, SYMBOL, CONSTANT) \
|
||||
movw T, #:lower16:SYMBOL; \
|
||||
movt T, #:upper16:SYMBOL; \
|
||||
ldr R, [T, $CONSTANT]
|
||||
# elif defined (ARCH_HAS_T2) && defined (PIC) && ARM_PCREL_MOVW_OK
|
||||
# define LDR_GLOBAL(R, T, SYMBOL, CONSTANT) \
|
||||
movw R, #:lower16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS; \
|
||||
movw T, #:lower16:99f - 98f - PC_OFS; \
|
||||
movt R, #:upper16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS; \
|
||||
movt T, #:upper16:99f - 98f - PC_OFS; \
|
||||
.pushsection .rodata.cst4, "aM", %progbits, 4; \
|
||||
.balign 4; \
|
||||
99: .word SYMBOL##(GOT); \
|
||||
.popsection; \
|
||||
97: add R, R, pc; \
|
||||
98: LDST_PC_INDEXED (ldr, T, T, T); \
|
||||
LDST_INDEXED (ldr, R, T, R, T); \
|
||||
ldr R, [R, $CONSTANT]
|
||||
# else
|
||||
# define LDR_GLOBAL(R, T, SYMBOL, CONSTANT) \
|
||||
ldr T, 99f; \
|
||||
ldr R, 100f; \
|
||||
98: add T, T, pc; \
|
||||
ldr T, [T, R]; \
|
||||
.subsection 2; \
|
||||
99: .word _GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS; \
|
||||
100: .word EXPR##(GOT); \
|
||||
100: .word SYMBOL##(GOT); \
|
||||
.previous; \
|
||||
OP R, [T]
|
||||
ldr R, [T, $CONSTANT]
|
||||
# endif
|
||||
|
||||
/* This is the same as LDR_GLOBAL, but for a SYMBOL that is known to
|
||||
be in the same linked object (as for one with hidden visibility).
|
||||
We can avoid the GOT indirection in the PIC case. For the pure
|
||||
static case, LDR_GLOBAL is already optimal. */
|
||||
# ifdef PIC
|
||||
# define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \
|
||||
LDST_PCREL (ldr, R, T, SYMBOL + CONSTANT)
|
||||
# else
|
||||
# define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \
|
||||
LDR_GLOBAL (R, T, SYMBOL, CONSTANT)
|
||||
# endif
|
||||
|
||||
/* Cope with negative memory offsets, which thumb can't encode.
|
||||
Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
|
||||
@ -296,7 +362,7 @@
|
||||
(!defined SHARED && (!defined NOT_IN_libc || defined IS_IN_libpthread)))
|
||||
# ifdef __ASSEMBLER__
|
||||
# define PTR_MANGLE_LOAD(guard, tmp) \
|
||||
LDST_PCREL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local));
|
||||
LDR_HIDDEN (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local), 0)
|
||||
# define PTR_MANGLE(dst, src, guard, tmp) \
|
||||
PTR_MANGLE_LOAD(guard, tmp); \
|
||||
PTR_MANGLE2(dst, src, guard)
|
||||
@ -316,7 +382,7 @@ extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
|
||||
#else
|
||||
# ifdef __ASSEMBLER__
|
||||
# define PTR_MANGLE_LOAD(guard, tmp) \
|
||||
LDST_GLOBAL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard));
|
||||
LDR_GLOBAL (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard), 0);
|
||||
# define PTR_MANGLE(dst, src, guard, tmp) \
|
||||
PTR_MANGLE_LOAD(guard, tmp); \
|
||||
PTR_MANGLE2(dst, src, guard)
|
||||
|
Loading…
Reference in New Issue
Block a user