From: Roland McGrath Date: Wed, 13 Mar 2013 19:36:53 +0000 (-0700) Subject: ARM_BX_ALIGN_LOG2 X-Git-Tag: glibc-2.18~541 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb48a26acf98a377a0ec235d127311ae4fbfb623;p=thirdparty%2Fglibc.git ARM_BX_ALIGN_LOG2 --- diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm index 71520a63445..878eb608286 100644 --- a/ports/ChangeLog.arm +++ b/ports/ChangeLog.arm @@ -1,5 +1,9 @@ 2013-03-13 Roland McGrath + * sysdeps/arm/arm-features.h (ARM_BX_ALIGN_LOG2): New macro. + * sysdeps/arm/memcpy.S: Respect ARM_BX_ALIGN_LOG2. + * sysdeps/arm/memmove.S: Likewise. + * sysdeps/arm/add_n.S: Include . [ARM_ALWAYS_BX]: Don't pop into pc. diff --git a/ports/sysdeps/arm/arm-features.h b/ports/sysdeps/arm/arm-features.h index 139a40368bc..5104ba33294 100644 --- a/ports/sysdeps/arm/arm-features.h +++ b/ports/sysdeps/arm/arm-features.h @@ -40,4 +40,17 @@ that instructions using pc as a destination register must never be used, so a "bx" (or "blx") instruction is always required. */ +/* The log2 of the minimum alignment required for an address that + is the target of a computed branch (i.e. a "bx" instruction). + A more-specific arm-features.h file may define this to set a more + stringent requirement. + + Using this only makes sense for code in ARM mode (where instructions + always have a fixed size of four bytes), or for Thumb-mode code that is + specifically aligning all the related branch targets to match (since + Thumb instructions might be either two or four bytes). */ +#ifndef ARM_BX_ALIGN_LOG2 +# define ARM_BX_ALIGN_LOG2 2 +#endif + #endif /* arm-features.h */ diff --git a/ports/sysdeps/arm/memcpy.S b/ports/sysdeps/arm/memcpy.S index 779f4035768..926581434e3 100644 --- a/ports/sysdeps/arm/memcpy.S +++ b/ports/sysdeps/arm/memcpy.S @@ -91,9 +91,9 @@ ENTRY(memcpy) CALGN( adr r4, 6f ) CALGN( subs r2, r2, r3 ) @ C gets set #ifndef ARM_ALWAYS_BX - CALGN( add pc, r4, ip ) + CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)) #else - CALGN( add r4, r4, ip ) + CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)) CALGN( bx r4 ) #endif @@ -115,39 +115,56 @@ ENTRY(memcpy) 5: ands ip, r2, #28 rsb ip, ip, #32 #ifndef ARM_ALWAYS_BX - addne pc, pc, ip @ C is always clear here + /* C is always clear here. */ + addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) b 7f #else beq 7f push {r10} cfi_adjust_cfa_offset (4) cfi_rel_offset (r10, 0) - add r10, pc, ip + add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) bx r10 #endif + .p2align ARM_BX_ALIGN_LOG2 6: nop + .p2align ARM_BX_ALIGN_LOG2 ldr r3, [r1], #4 + .p2align ARM_BX_ALIGN_LOG2 ldr r4, [r1], #4 + .p2align ARM_BX_ALIGN_LOG2 ldr r5, [r1], #4 + .p2align ARM_BX_ALIGN_LOG2 ldr r6, [r1], #4 + .p2align ARM_BX_ALIGN_LOG2 ldr r7, [r1], #4 + .p2align ARM_BX_ALIGN_LOG2 ldr r8, [r1], #4 + .p2align ARM_BX_ALIGN_LOG2 ldr lr, [r1], #4 #ifndef ARM_ALWAYS_BX - add pc, pc, ip + add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) nop #else - add r10, pc, ip + add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) bx r10 #endif + .p2align ARM_BX_ALIGN_LOG2 nop + .p2align ARM_BX_ALIGN_LOG2 str r3, [r0], #4 + .p2align ARM_BX_ALIGN_LOG2 str r4, [r0], #4 + .p2align ARM_BX_ALIGN_LOG2 str r5, [r0], #4 + .p2align ARM_BX_ALIGN_LOG2 str r6, [r0], #4 + .p2align ARM_BX_ALIGN_LOG2 str r7, [r0], #4 + .p2align ARM_BX_ALIGN_LOG2 str r8, [r0], #4 + .p2align ARM_BX_ALIGN_LOG2 str lr, [r0], #4 #ifdef ARM_ALWAYS_BX diff --git a/ports/sysdeps/arm/memmove.S b/ports/sysdeps/arm/memmove.S index 4a2cb92ea45..96b27cfefc6 100644 --- a/ports/sysdeps/arm/memmove.S +++ b/ports/sysdeps/arm/memmove.S @@ -107,9 +107,9 @@ ENTRY(memmove) CALGN( adr r4, 6f ) CALGN( subs r2, r2, ip ) @ C is set here #ifndef ARM_ALWAYS_BX - CALGN( add pc, r4, ip ) + CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)) #else - CALGN( add r4, r4, ip ) + CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)) CALGN( bx r4 ) #endif @@ -131,39 +131,56 @@ ENTRY(memmove) 5: ands ip, r2, #28 rsb ip, ip, #32 #ifndef ARM_ALWAYS_BX - addne pc, pc, ip @ C is always clear here + /* C is always clear here. */ + addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) b 7f #else beq 7f push {r10} cfi_adjust_cfa_offset (4) cfi_rel_offset (r10, 0) - add r10, pc, ip + add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) bx r10 #endif + .p2align ARM_BX_ALIGN_LOG2 6: nop + .p2align ARM_BX_ALIGN_LOG2 ldr r3, [r1, #-4]! + .p2align ARM_BX_ALIGN_LOG2 ldr r4, [r1, #-4]! + .p2align ARM_BX_ALIGN_LOG2 ldr r5, [r1, #-4]! + .p2align ARM_BX_ALIGN_LOG2 ldr r6, [r1, #-4]! + .p2align ARM_BX_ALIGN_LOG2 ldr r7, [r1, #-4]! + .p2align ARM_BX_ALIGN_LOG2 ldr r8, [r1, #-4]! + .p2align ARM_BX_ALIGN_LOG2 ldr lr, [r1, #-4]! #ifndef ARM_ALWAYS_BX - add pc, pc, ip + add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) nop #else - add r10, pc, ip + add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2) bx r10 #endif + .p2align ARM_BX_ALIGN_LOG2 nop + .p2align ARM_BX_ALIGN_LOG2 str r3, [r0, #-4]! + .p2align ARM_BX_ALIGN_LOG2 str r4, [r0, #-4]! + .p2align ARM_BX_ALIGN_LOG2 str r5, [r0, #-4]! + .p2align ARM_BX_ALIGN_LOG2 str r6, [r0, #-4]! + .p2align ARM_BX_ALIGN_LOG2 str r7, [r0, #-4]! + .p2align ARM_BX_ALIGN_LOG2 str r8, [r0, #-4]! + .p2align ARM_BX_ALIGN_LOG2 str lr, [r0, #-4]! #ifdef ARM_ALWAYS_BX