From 6dcf80c78273c5e0bdcacaf64a9b34fd930b405f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 9 Aug 2012 11:51:05 -0700 Subject: [PATCH] Avoid VFP HWCAP check in setjmp/longjmp and getcontext/setcontext when compiled without __SOFTFP__ defined. --- ports/ChangeLog.arm | 6 ++ ports/sysdeps/arm/__longjmp.S | 29 +++++---- ports/sysdeps/arm/setjmp.S | 24 +++---- ports/sysdeps/unix/sysv/linux/arm/getcontext.S | 78 +++++++++++----------- ports/sysdeps/unix/sysv/linux/arm/setcontext.S | 89 +++++++++++++------------- 5 files changed, 119 insertions(+), 107 deletions(-) diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm index 08020e9..1375922 100644 --- a/ports/ChangeLog.arm +++ b/ports/ChangeLog.arm @@ -1,5 +1,11 @@ 2012-08-09 Roland McGrath + * sysdeps/arm/__longjmp.S: Use .Lxxx rather than Lxxx for local labels. + [__SOFTFP__]: Conditionalize HWCAP_ARM_VFP check on this. + * sysdeps/arm/setjmp.S: Likewise. + * sysdeps/unix/sysv/linux/arm/getcontext.S: Likewise. + * sysdeps/unix/sysv/linux/arm/setcontext.S: Likewise. + * sysdeps/arm/arm-features.h: New file. * sysdeps/unix/sysv/linux/arm/arm-features.h: New file. * sysdeps/arm/fclrexcpt.c: Use ARM_HAVE_VFP instead of hwcap bits. diff --git a/ports/sysdeps/arm/__longjmp.S b/ports/sysdeps/arm/__longjmp.S index cc802c1..aa5cf74 100644 --- a/ports/sysdeps/arm/__longjmp.S +++ b/ports/sysdeps/arm/__longjmp.S @@ -1,6 +1,5 @@ /* longjmp for ARM. - Copyright (C) 1997, 1998, 2005, 2006, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1997-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 @@ -48,26 +47,28 @@ ENTRY (__longjmp) cfi_restore (lr) #ifdef IS_IN_rtld - ldr a2, 1f - ldr a3, Lrtld_local_ro + ldr a2, 1f + ldr a3, .Lrtld_local_ro 0: add a2, pc, a2 add a2, a2, a3 ldr a2, [a2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] #else #ifdef PIC - ldr a2, 1f - ldr a3, Lrtld_global_ro + ldr a2, 1f + ldr a3, .Lrtld_global_ro 0: add a2, pc, a2 ldr a2, [a2, a3] ldr a2, [a2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] #else - ldr a2, Lhwcap + ldr a2, .Lhwcap ldr a2, [a2, #0] #endif #endif +#ifdef __SOFTFP__ tst a2, #HWCAP_ARM_VFP - beq Lno_vfp + beq .Lno_vfp +#endif /* Restore the VFP registers. */ /* Following instruction is vldmia ip!, {d8-d15}. */ @@ -76,10 +77,10 @@ ENTRY (__longjmp) ldr a3, [ip], #4 /* Following instruction is fmxr fpscr, a3. */ mcr p10, 7, a3, cr1, cr0, 0 -Lno_vfp: +.Lno_vfp: tst a2, #HWCAP_ARM_IWMMXT - beq Lno_iwmmxt + beq .Lno_iwmmxt /* Restore the call-preserved iWMMXt registers. */ /* Following instructions are wldrd wr10, [ip], #8 (etc.) */ @@ -89,21 +90,21 @@ Lno_vfp: ldcl p1, cr13, [r12], #8 ldcl p1, cr14, [r12], #8 ldcl p1, cr15, [r12], #8 -Lno_iwmmxt: +.Lno_iwmmxt: DO_RET(lr) #ifdef IS_IN_rtld 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 -Lrtld_local_ro: +.Lrtld_local_ro: .long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF) #else #ifdef PIC 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 -Lrtld_global_ro: +.Lrtld_global_ro: .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) #else -Lhwcap: +.Lhwcap: .long C_SYMBOL_NAME(_dl_hwcap) #endif #endif diff --git a/ports/sysdeps/arm/setjmp.S b/ports/sysdeps/arm/setjmp.S index 5e3f39c..9bfacc1 100644 --- a/ports/sysdeps/arm/setjmp.S +++ b/ports/sysdeps/arm/setjmp.S @@ -1,5 +1,5 @@ /* setjmp for ARM. - Copyright (C) 1997, 1998, 2005, 2006, 2008 Free Software Foundation, Inc. + Copyright (C) 1997-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 @@ -31,25 +31,27 @@ ENTRY (__sigsetjmp) /* Check if we have a VFP unit. */ #ifdef IS_IN_rtld ldr a3, 1f - ldr a4, Lrtld_local_ro + ldr a4, .Lrtld_local_ro 0: add a3, pc, a3 add a3, a3, a4 ldr a3, [a3, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] #else #ifdef PIC ldr a3, 1f - ldr a4, Lrtld_global_ro + ldr a4, .Lrtld_global_ro 0: add a3, pc, a3 ldr a3, [a3, a4] ldr a3, [a3, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] #else - ldr a3, Lhwcap + ldr a3, .Lhwcap ldr a3, [a3, #0] #endif #endif +#ifdef __SOFTFP__ tst a3, #HWCAP_ARM_VFP - beq Lno_vfp + beq .Lno_vfp +#endif /* Store the VFP registers. Don't use VFP instructions directly because this code @@ -60,10 +62,10 @@ ENTRY (__sigsetjmp) /* Following instruction is vmrs a4, fpscr. */ mrc p10, 7, a4, cr1, cr0, 0 str a4, [ip], #4 -Lno_vfp: +.Lno_vfp: tst a3, #HWCAP_ARM_IWMMXT - beq Lno_iwmmxt + beq .Lno_iwmmxt /* Save the call-preserved iWMMXt registers. */ /* Following instructions are wstrd wr10, [ip], #8 (etc.) */ @@ -73,22 +75,22 @@ Lno_vfp: stcl p1, cr13, [r12], #8 stcl p1, cr14, [r12], #8 stcl p1, cr15, [r12], #8 -Lno_iwmmxt: +.Lno_iwmmxt: /* Make a tail call to __sigjmp_save; it takes the same args. */ B PLTJMP(C_SYMBOL_NAME(__sigjmp_save)) #ifdef IS_IN_rtld 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 -Lrtld_local_ro: +.Lrtld_local_ro: .long C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF) #else #ifdef PIC 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 -Lrtld_global_ro: +.Lrtld_global_ro: .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) #else -Lhwcap: +.Lhwcap: .long C_SYMBOL_NAME(_dl_hwcap) #endif #endif diff --git a/ports/sysdeps/unix/sysv/linux/arm/getcontext.S b/ports/sysdeps/unix/sysv/linux/arm/getcontext.S index 116d6e8..2281c9e 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/getcontext.S +++ b/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/ports/sysdeps/unix/sysv/linux/arm/setcontext.S b/ports/sysdeps/unix/sysv/linux/arm/setcontext.S index d163fc4..6436770 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/setcontext.S +++ b/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 - -- 2.7.4