2013-03-13 Roland McGrath <roland@hack.frob.com>
+ * 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-features.h>.
[ARM_ALWAYS_BX]: Don't pop into pc.
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 */
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
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
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
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