ARM: Support avoiding pc as destination register.
authorRoland McGrath <roland@hack.frob.com>
Wed, 13 Mar 2013 16:40:55 +0000 (09:40 -0700)
committerRoland McGrath <roland@hack.frob.com>
Wed, 13 Mar 2013 16:40:55 +0000 (09:40 -0700)
ports/ChangeLog.arm
ports/sysdeps/arm/arm-features.h
ports/sysdeps/arm/memcpy.S
ports/sysdeps/arm/memmove.S

index 2e250f7..72060ba 100644 (file)
@@ -1,3 +1,10 @@
+2013-03-13  Roland McGrath  <roland@hack.frob.com>
+
+       * sysdeps/arm/arm-features.h: Add comment about ARM_ALWAYS_BX.
+       * sysdeps/arm/memcpy.S: Include <arm-features.h>.
+       [ARM_ALWAYS_BX]: Avoid pc as destination.
+       * sysdeps/arm/memmove.S: Likewise.
+
 2013-03-12  Roland McGrath  <roland@hack.frob.com>
 
        * sysdeps/arm/armv6t2/memchr.S [NO_THUMB]:
index 31801cf..139a403 100644 (file)
@@ -36,4 +36,8 @@
    at runtime (or that we never care about its state) and so need not
    be checked for.  */
 
+/* A more-specific arm-features.h file may define ARM_ALWAYS_BX to indicate
+   that instructions using pc as a destination register must never be used,
+   so a "bx" (or "blx") instruction is always required.  */
+
 #endif  /* arm-features.h */
index eb9699d..779f403 100644 (file)
@@ -20,6 +20,7 @@
 /* Thumb requires excessive IT insns here.  */
 #define NO_THUMB
 #include <sysdep.h>
+#include <arm-features.h>
 
 /*
  * Data preload for architectures that support it (ARM V5TE and above)
@@ -89,7 +90,12 @@ ENTRY(memcpy)
        CALGN(  bcs     2f                      )
        CALGN(  adr     r4, 6f                  )
        CALGN(  subs    r2, r2, r3              )  @ C gets set
+#ifndef ARM_ALWAYS_BX
        CALGN(  add     pc, r4, ip              )
+#else
+       CALGN(  add     r4, r4, ip              )
+       CALGN(  bx      r4                      )
+#endif
 
        PLD(    pld     [r1, #0]                )
 2:     PLD(    subs    r2, r2, #96             )
@@ -108,8 +114,17 @@ ENTRY(memcpy)
 
 5:             ands    ip, r2, #28
                rsb     ip, ip, #32
+#ifndef ARM_ALWAYS_BX
                addne   pc, pc, ip              @ C is always clear here
                b       7f
+#else
+               beq     7f
+               push    {r10}
+               cfi_adjust_cfa_offset (4)
+               cfi_rel_offset (r10, 0)
+               add     r10, pc, ip
+               bx      r10
+#endif
 6:             nop
                ldr     r3, [r1], #4
                ldr     r4, [r1], #4
@@ -119,8 +134,13 @@ ENTRY(memcpy)
                ldr     r8, [r1], #4
                ldr     lr, [r1], #4
 
+#ifndef ARM_ALWAYS_BX
                add     pc, pc, ip
                nop
+#else
+               add     r10, pc, ip
+               bx      r10
+#endif
                nop
                str     r3, [r0], #4
                str     r4, [r0], #4
@@ -130,6 +150,12 @@ ENTRY(memcpy)
                str     r8, [r0], #4
                str     lr, [r0], #4
 
+#ifdef ARM_ALWAYS_BX
+               pop     {r10}
+               cfi_adjust_cfa_offset (-4)
+               cfi_restore (r10)
+#endif
+
        CALGN(  bcs     2b                      )
 
 7:             pop     {r5 - r8}
@@ -147,7 +173,8 @@ ENTRY(memcpy)
                strbcs  r4, [r0], #1
                strbcs  ip, [r0]
 
-#if defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
+#if ((defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)) \
+     || defined (ARM_ALWAYS_BX))
                pop     {r0, r4, lr}
                cfi_adjust_cfa_offset (-12)
                cfi_restore (r4)
index 9e8ad65..4a2cb92 100644 (file)
@@ -20,6 +20,7 @@
 /* Thumb requires excessive IT insns here.  */
 #define NO_THUMB
 #include <sysdep.h>
+#include <arm-features.h>
 
 /*
  * Data preload for architectures that support it (ARM V5TE and above)
@@ -105,7 +106,12 @@ ENTRY(memmove)
        CALGN(  bcs     2f                      )
        CALGN(  adr     r4, 6f                  )
        CALGN(  subs    r2, r2, ip              )  @ C is set here
+#ifndef ARM_ALWAYS_BX
        CALGN(  add     pc, r4, ip              )
+#else
+       CALGN(  add     r4, r4, ip              )
+       CALGN(  bx      r4                      )
+#endif
 
        PLD(    pld     [r1, #-4]               )
 2:     PLD(    subs    r2, r2, #96             )
@@ -124,8 +130,17 @@ ENTRY(memmove)
 
 5:             ands    ip, r2, #28
                rsb     ip, ip, #32
+#ifndef ARM_ALWAYS_BX
                addne   pc, pc, ip              @ C is always clear here
                b       7f
+#else
+               beq     7f
+               push    {r10}
+               cfi_adjust_cfa_offset (4)
+               cfi_rel_offset (r10, 0)
+               add     r10, pc, ip
+               bx      r10
+#endif
 6:             nop
                ldr     r3, [r1, #-4]!
                ldr     r4, [r1, #-4]!
@@ -135,8 +150,13 @@ ENTRY(memmove)
                ldr     r8, [r1, #-4]!
                ldr     lr, [r1, #-4]!
 
+#ifndef ARM_ALWAYS_BX
                add     pc, pc, ip
                nop
+#else
+               add     r10, pc, ip
+               bx      r10
+#endif
                nop
                str     r3, [r0, #-4]!
                str     r4, [r0, #-4]!
@@ -146,6 +166,12 @@ ENTRY(memmove)
                str     r8, [r0, #-4]!
                str     lr, [r0, #-4]!
 
+#ifdef ARM_ALWAYS_BX
+               pop     {r10}
+               cfi_adjust_cfa_offset (-4)
+               cfi_restore (r10)
+#endif
+
        CALGN(  bcs     2b                      )
 
 7:             pop     {r5 - r8}
@@ -163,7 +189,8 @@ ENTRY(memmove)
                strbcs  r4, [r0, #-1]!
                strbcs  ip, [r0, #-1]
 
-#if defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)
+#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
+     || defined (ARM_ALWAYS_BX))
                pop     {r0, r4, lr}
                cfi_adjust_cfa_offset (-12)
                cfi_restore (r4)