diff options
Diffstat (limited to 'libc/ports/sysdeps/unix/sysv/linux/arm')
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/arm-features.h | 30 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/bits/atomic.h (renamed from libc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h) | 93 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/configure | 1 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/configure.in | 1 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/dl-machine.h | 30 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/getcontext.S | 78 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/getrlimit.c | 1 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/kernel-features.h | 10 | ||||
-rw-r--r-- | libc/ports/sysdeps/unix/sysv/linux/arm/setcontext.S | 89 |
9 files changed, 180 insertions, 153 deletions
diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/arm-features.h b/libc/ports/sysdeps/unix/sysv/linux/arm/arm-features.h new file mode 100644 index 000000000..f20a70556 --- /dev/null +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/arm-features.h @@ -0,0 +1,30 @@ +/* Macros to test for CPU features on ARM. Linux version. + Copyright (C) 2012 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _LINUX_ARM_FEATURES_H +#define _LINUX_ARM_FEATURES_H 1 + +#ifndef __ASSEMBLER__ +# include <ldsodefs.h> + +# define ARM_HAVE_VFP (GLRO (dl_hwcap) & HWCAP_ARM_VFP) +#endif + +#include_next <arm-features.h> + +#endif /* arm-features.h */ diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h b/libc/ports/sysdeps/unix/sysv/linux/arm/bits/atomic.h index 4e810a28d..337415386 100644 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/bits/atomic.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Atomic operations. ARM/Linux version. + Copyright (C) 2002-2012 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 @@ -15,41 +16,17 @@ License along with the GNU C Library. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdint.h> -#include <sysdep.h> - - -typedef int8_t atomic8_t; -typedef uint8_t uatomic8_t; -typedef int_fast8_t atomic_fast8_t; -typedef uint_fast8_t uatomic_fast8_t; - -typedef int32_t atomic32_t; -typedef uint32_t uatomic32_t; -typedef int_fast32_t atomic_fast32_t; -typedef uint_fast32_t uatomic_fast32_t; - -typedef intptr_t atomicptr_t; -typedef uintptr_t uatomicptr_t; -typedef intmax_t atomic_max_t; -typedef uintmax_t uatomic_max_t; - -void __arm_link_error (void); - -/* Use the atomic builtins provided by GCC in case the backend provides - a pattern to do this efficiently. */ - -#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 -#define atomic_full_barrier() __sync_synchronize () -#elif defined __thumb2__ -#define atomic_full_barrier() \ +/* If the compiler doesn't provide a primitive, we'll use this macro + to get assistance from the kernel. */ +#ifdef __thumb2__ +# define __arm_assisted_full_barrier() \ __asm__ __volatile__ \ ("movw\tip, #0x0fa0\n\t" \ "movt\tip, #0xffff\n\t" \ "blx\tip" \ : : : "ip", "lr", "cc", "memory"); #else -#define atomic_full_barrier() \ +# define __arm_assisted_full_barrier() \ __asm__ __volatile__ \ ("mov\tip, #0xffff0fff\n\t" \ "mov\tlr, pc\n\t" \ @@ -60,31 +37,28 @@ void __arm_link_error (void); /* Atomic compare and exchange. This sequence relies on the kernel to provide a compare and exchange operation which is atomic on the current architecture, either via cleverness on pre-ARMv6 or via - ldrex / strex on ARMv6. */ - -#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ - ({ __arm_link_error (); oldval; }) - -#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ - ({ __arm_link_error (); oldval; }) + ldrex / strex on ARMv6. -#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 -#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ - __sync_val_compare_and_swap ((mem), (oldval), (newval)) - -/* It doesn't matter what register is used for a_oldval2, but we must + It doesn't matter what register is used for a_oldval2, but we must specify one to work around GCC PR rtl-optimization/21223. Otherwise - it may cause a_oldval or a_tmp to be moved to a different register. */ - -#elif defined __thumb2__ + it may cause a_oldval or a_tmp to be moved to a different register. + + We use the union trick rather than simply using __typeof (...) in the + declarations of A_OLDVAL et al because when NEWVAL or OLDVAL is of the + form *PTR and PTR has a 'volatile ... *' type, then __typeof (*PTR) has + a 'volatile ...' type and this triggers -Wvolatile-register-var to + complain about 'register volatile ... asm ("reg")'. */ +#ifdef __thumb2__ /* Thumb-2 has ldrex/strex. However it does not have barrier instructions, so we still need to use the kernel helper. */ -#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ - ({ register __typeof (oldval) a_oldval asm ("r0"); \ - register __typeof (oldval) a_newval asm ("r1") = (newval); \ +# define __arm_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) };\ + union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) };\ + register uint32_t a_oldval asm ("r0"); \ + register uint32_t a_newval asm ("r1") = newval_arg.v; \ register __typeof (mem) a_ptr asm ("r2") = (mem); \ - register __typeof (oldval) a_tmp asm ("r3"); \ - register __typeof (oldval) a_oldval2 asm ("r4") = (oldval); \ + register uint32_t a_tmp asm ("r3"); \ + register uint32_t a_oldval2 asm ("r4") = oldval_arg.v; \ __asm__ __volatile__ \ ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ "cmp\t%[tmp], %[old2]\n\t" \ @@ -100,14 +74,16 @@ void __arm_link_error (void); : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ [old2] "r" (a_oldval2) \ : "ip", "lr", "cc", "memory"); \ - a_tmp; }) + (__typeof (oldval)) a_tmp; }) #else -#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ - ({ register __typeof (oldval) a_oldval asm ("r0"); \ - register __typeof (oldval) a_newval asm ("r1") = (newval); \ +# define __arm_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) };\ + union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) };\ + register uint32_t a_oldval asm ("r0"); \ + register uint32_t a_newval asm ("r1") = newval_arg.v; \ register __typeof (mem) a_ptr asm ("r2") = (mem); \ - register __typeof (oldval) a_tmp asm ("r3"); \ - register __typeof (oldval) a_oldval2 asm ("r4") = (oldval); \ + register uint32_t a_tmp asm ("r3"); \ + register uint32_t a_oldval2 asm ("r4") = oldval_arg.v; \ __asm__ __volatile__ \ ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ "cmp\t%[tmp], %[old2]\n\t" \ @@ -123,8 +99,7 @@ void __arm_link_error (void); : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ [old2] "r" (a_oldval2) \ : "ip", "lr", "cc", "memory"); \ - a_tmp; }) + (__typeof (oldval)) a_tmp; }) #endif -#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ - ({ __arm_link_error (); oldval; }) +#include <sysdeps/arm/bits/atomic.h> diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/configure b/libc/ports/sysdeps/unix/sysv/linux/arm/configure index 5b5f4c993..cb94cc5eb 100644 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/configure +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/configure @@ -1,6 +1,5 @@ # This file is generated from configure.in by Autoconf. DO NOT EDIT! # Local configure fragment for sysdeps/unix/sysv/linux/arm. -arch_minimum_kernel=2.6.16 libc_cv_gcc_unwind_find_fde=no CFLAGS=${CFLAGS% -fno-unwind-tables} diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/configure.in b/libc/ports/sysdeps/unix/sysv/linux/arm/configure.in index b57c4e37b..3e67dee42 100644 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/configure.in +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/configure.in @@ -1,6 +1,5 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. # Local configure fragment for sysdeps/unix/sysv/linux/arm. -arch_minimum_kernel=2.6.16 libc_cv_gcc_unwind_find_fde=no CFLAGS=${CFLAGS% -fno-unwind-tables} diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/dl-machine.h b/libc/ports/sysdeps/unix/sysv/linux/arm/dl-machine.h new file mode 100644 index 000000000..68e8be9e6 --- /dev/null +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/dl-machine.h @@ -0,0 +1,30 @@ +/* Machine-dependent ELF dynamic relocation inline functions. ARM/Linux version + Copyright (C) 1995-2012 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef dl_machine_h + +/* This definition is Linux-specific. */ +#define CLEAR_CACHE(BEG,END) \ + INTERNAL_SYSCALL_ARM (cacheflush, , 3, (BEG), (END), 0) + +#endif + +/* The rest is just machine-specific. + This #include is outside the #ifndef because the parts of + dl-machine.h used only by dynamic-link.h are outside the guard. */ +#include <sysdeps/arm/dl-machine.h> diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/getcontext.S b/libc/ports/sysdeps/unix/sysv/linux/arm/getcontext.S index 116d6e8f3..2281c9eff 100644 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/getcontext.S +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/getcontext.S @@ -41,54 +41,56 @@ ENTRY(__getcontext) /* Save ucontext_t * across the next call. */ mov r4, r0 - + /* __sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */ mov r0, #SIG_BLOCK mov r1, #0 add r2, r4, #UCONTEXT_SIGMASK bl PLTJMP(__sigprocmask) - + /* Store FP regs. Much of the FP code is copied from arm/setjmp.S. */ #ifdef PIC - ldr r2, 1f - ldr r1, Lrtld_global_ro + ldr r2, 1f + ldr r1, .Lrtld_global_ro 0: add r2, pc, r2 - ldr r2, [r2, r1] - ldr r2, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] + ldr r2, [r2, r1] + ldr r2, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] #else - ldr r2, Lhwcap - ldr r2, [r2, #0] + ldr r2, .Lhwcap + ldr r2, [r2, #0] #endif add r0, r4, #UCONTEXT_REGSPACE - tst r2, #HWCAP_ARM_VFP - beq Lno_vfp - - /* Store the VFP registers. - Don't use VFP instructions directly because this code - is used in non-VFP multilibs. */ - /* Following instruction is vstmia r0!, {d8-d15}. */ - stc p11, cr8, [r0], #64 - /* Store the floating-point status register. */ - /* Following instruction is vmrs r1, fpscr. */ - mrc p10, 7, r1, cr1, cr0, 0 - str r1, [r0], #4 -Lno_vfp: - - tst r2, #HWCAP_ARM_IWMMXT - beq Lno_iwmmxt - - /* Save the call-preserved iWMMXt registers. */ - /* Following instructions are wstrd wr10, [r0], #8 (etc.) */ - stcl p1, cr10, [r0], #8 - stcl p1, cr11, [r0], #8 - stcl p1, cr12, [r0], #8 - stcl p1, cr13, [r0], #8 - stcl p1, cr14, [r0], #8 - stcl p1, cr15, [r0], #8 -Lno_iwmmxt: +#ifdef __SOFTFP__ + tst r2, #HWCAP_ARM_VFP + beq .Lno_vfp +#endif + + /* Store the VFP registers. + Don't use VFP instructions directly because this code + is used in non-VFP multilibs. */ + /* Following instruction is vstmia r0!, {d8-d15}. */ + stc p11, cr8, [r0], #64 + /* Store the floating-point status register. */ + /* Following instruction is vmrs r1, fpscr. */ + mrc p10, 7, r1, cr1, cr0, 0 + str r1, [r0], #4 +.Lno_vfp: + + tst r2, #HWCAP_ARM_IWMMXT + beq .Lno_iwmmxt + + /* Save the call-preserved iWMMXt registers. */ + /* Following instructions are wstrd wr10, [r0], #8 (etc.) */ + stcl p1, cr10, [r0], #8 + stcl p1, cr11, [r0], #8 + stcl p1, cr12, [r0], #8 + stcl p1, cr13, [r0], #8 + stcl p1, cr14, [r0], #8 + stcl p1, cr15, [r0], #8 +.Lno_iwmmxt: /* Restore the clobbered R4 and LR. */ ldr r14, [r4, #MCONTEXT_ARM_LR] @@ -102,11 +104,11 @@ END(__getcontext) #ifdef PIC 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 -Lrtld_global_ro: - .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) +.Lrtld_global_ro: + .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) #else -Lhwcap: - .long C_SYMBOL_NAME(_dl_hwcap) +.Lhwcap: + .long C_SYMBOL_NAME(_dl_hwcap) #endif diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/getrlimit.c b/libc/ports/sysdeps/unix/sysv/linux/arm/getrlimit.c deleted file mode 100644 index fc06dbd64..000000000 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/getrlimit.c +++ /dev/null @@ -1 +0,0 @@ -#include <sysdeps/unix/sysv/linux/i386/getrlimit.c> diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/kernel-features.h b/libc/ports/sysdeps/unix/sysv/linux/arm/kernel-features.h index 9092df719..b003b17b0 100644 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/kernel-features.h +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/kernel-features.h @@ -18,21 +18,13 @@ <http://www.gnu.org/licenses/>. */ /* The utimes syscall was added before 2.6.1. */ -#if __LINUX_KERNEL_VERSION >= 132609 -# define __ASSUME_UTIMES 1 -#endif +#define __ASSUME_UTIMES 1 /* On ARM the mmap2/stat64/lstat64/fstat64 syscalls were introduced in 2.3.35. */ #define __ASSUME_MMAP2_SYSCALL 1 #define __ASSUME_STAT64_SYSCALL 1 -/* Arm got fcntl64 in 2.4.4. */ -#define __ASSUME_FCNTL64 1 - -/* The vfork syscall on arm was definitely available in 2.4. */ -#define __ASSUME_VFORK_SYSCALL 1 - /* The signal frame layout changed in 2.6.18. */ #if __LINUX_KERNEL_VERSION >= 132626 # define __ASSUME_SIGFRAME_V2 1 diff --git a/libc/ports/sysdeps/unix/sysv/linux/arm/setcontext.S b/libc/ports/sysdeps/unix/sysv/linux/arm/setcontext.S index d163fc4a4..64367704b 100644 --- a/libc/ports/sysdeps/unix/sysv/linux/arm/setcontext.S +++ b/libc/ports/sysdeps/unix/sysv/linux/arm/setcontext.S @@ -29,40 +29,42 @@ ENTRY(__setcontext) mov r4, r0 add r0, r0, #UCONTEXT_REGSPACE - /* Restore the VFP registers. Copied from arm/__longjmp.S. */ + /* Restore the VFP registers. Copied from arm/__longjmp.S. */ #ifdef PIC - ldr r2, 1f - ldr r1, Lrtld_global_ro + ldr r2, 1f + ldr r1, .Lrtld_global_ro 0: add r2, pc, r2 - ldr r2, [r2, r1] - ldr r2, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] + ldr r2, [r2, r1] + ldr r2, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] #else - ldr r2, Lhwcap - ldr r2, [r2, #0] + ldr r2, .Lhwcap + ldr r2, [r2, #0] #endif - tst r2, #HWCAP_ARM_VFP - beq Lno_vfp_sc - - /* Following instruction is vldmia r0!, {d8-d15}. */ - ldc p11, cr8, [r0], #64 - /* Restore the floating-point status register. */ - ldr r1, [r0], #4 - /* Following instruction is fmxr fpscr, r1. */ - mcr p10, 7, r1, cr1, cr0, 0 -Lno_vfp_sc: - tst r2, #HWCAP_ARM_IWMMXT - beq Lno_iwmmxt_sc - - /* Restore the call-preserved iWMMXt registers. */ - /* Following instructions are wldrd wr10, [r0], #8 (etc.) */ - ldcl p1, cr10, [r0], #8 - ldcl p1, cr11, [r0], #8 - ldcl p1, cr12, [r0], #8 - ldcl p1, cr13, [r0], #8 - ldcl p1, cr14, [r0], #8 - ldcl p1, cr15, [r0], #8 -Lno_iwmmxt_sc: +#ifdef __SOFTFP__ + tst r2, #HWCAP_ARM_VFP + beq .Lno_vfp_sc +#endif + + /* Following instruction is vldmia r0!, {d8-d15}. */ + ldc p11, cr8, [r0], #64 + /* Restore the floating-point status register. */ + ldr r1, [r0], #4 + /* Following instruction is fmxr fpscr, r1. */ + mcr p10, 7, r1, cr1, cr0, 0 +.Lno_vfp_sc: + tst r2, #HWCAP_ARM_IWMMXT + beq .Lno_iwmmxt_sc + + /* Restore the call-preserved iWMMXt registers. */ + /* Following instructions are wldrd wr10, [r0], #8 (etc.) */ + ldcl p1, cr10, [r0], #8 + ldcl p1, cr11, [r0], #8 + ldcl p1, cr12, [r0], #8 + ldcl p1, cr13, [r0], #8 + ldcl p1, cr14, [r0], #8 + ldcl p1, cr15, [r0], #8 +.Lno_iwmmxt_sc: /* Now bring back the signal status. */ mov r0, #SIG_SETMASK @@ -70,12 +72,12 @@ Lno_iwmmxt_sc: mov r2, #0 bl PLTJMP(__sigprocmask) - /* Loading r0-r3 makes makecontext easier. */ - add r14, r4, #MCONTEXT_ARM_R0 - ldmia r14, {r0-r12} - ldr r13, [r14, #(MCONTEXT_ARM_SP - MCONTEXT_ARM_R0)] - add r14, r14, #(MCONTEXT_ARM_LR - MCONTEXT_ARM_R0) - ldmia r14, {r14, pc} + /* Loading r0-r3 makes makecontext easier. */ + add r14, r4, #MCONTEXT_ARM_R0 + ldmia r14, {r0-r12} + ldr r13, [r14, #(MCONTEXT_ARM_SP - MCONTEXT_ARM_R0)] + add r14, r14, #(MCONTEXT_ARM_LR - MCONTEXT_ARM_R0) + ldmia r14, {r14, pc} END(setcontext) weak_alias(__setcontext, setcontext) @@ -83,19 +85,18 @@ weak_alias(__setcontext, setcontext) /* Called when a makecontext() context returns. Start the context in R4 or fall through to exit(). */ ENTRY(__startcontext) - movs r0, r4 - bne PLTJMP(__setcontext) + movs r0, r4 + bne PLTJMP(__setcontext) - @ New context was 0 - exit - b PLTJMP(HIDDEN_JUMPTARGET(_exit)) + @ New context was 0 - exit + b PLTJMP(HIDDEN_JUMPTARGET(_exit)) END(__startcontext) #ifdef PIC 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 -Lrtld_global_ro: - .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) +.Lrtld_global_ro: + .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) #else -Lhwcap: - .long C_SYMBOL_NAME(_dl_hwcap) +.Lhwcap: + .long C_SYMBOL_NAME(_dl_hwcap) #endif - |