ARM_BX_ALIGN_LOG2
authorRoland McGrath <roland@hack.frob.com>
Wed, 13 Mar 2013 19:36:53 +0000 (12:36 -0700)
committerRoland McGrath <roland@hack.frob.com>
Wed, 13 Mar 2013 19:36:53 +0000 (12:36 -0700)
ports/ChangeLog.arm
ports/sysdeps/arm/arm-features.h
ports/sysdeps/arm/memcpy.S
ports/sysdeps/arm/memmove.S

index 71520a6..878eb60 100644 (file)
@@ -1,5 +1,9 @@
 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.
 
index 139a403..5104ba3 100644 (file)
    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 */
index 779f403..9265814 100644 (file)
@@ -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
index 4a2cb92..96b27cf 100644 (file)
@@ -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