arm: Introduce and use NEGOFF series of macros
authorRichard Henderson <rth@twiddle.net>
Thu, 14 Feb 2013 17:46:56 +0000 (09:46 -0800)
committerRichard Henderson <rth@twiddle.net>
Wed, 6 Mar 2013 15:44:25 +0000 (07:44 -0800)
There are several places in which we access negative offsets from
the thread-pointer, but thumb2 only supports positive offsets in
memory references.

Avoid duplicating the rather large macros in which these references
are embedded by abstracting out the operation.

ports/ChangeLog.arm
ports/sysdeps/arm/sysdep.h
ports/sysdeps/unix/sysv/linux/arm/clone.S
ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S
ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h
ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S

index d3da2fbb1042bbbe312d4036fa1604c79a57dee9..b5c9ef3347a67b9bc4890a2288fab82153bb944c 100644 (file)
@@ -1,5 +1,13 @@
 2013-03-06  Richard Henderson <rth@redhat.com>
 
+       * sysdeps/arm/sysdep.h (NEGOFF_ADJ_BASE): New macro.
+       (NEGOFF_ADJ_BASE2, NEGOFF_OFF1, NEGOFF_OFF2): New macros.
+       * sysdeps/unix/sysv/linux/arm/clone.S (__clone): Use them.
+       * sysdeps/unix/sysv/linux/arm/nptl/vfork.S: Likewise.
+       * sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S: Likewise.
+       * sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h (SINGLE_THREAD_P):
+       Likewise.
+
        * sysdeps/arm/sysdep.h (LDST_PCREL): New macro.
        * sysdeps/unix/arm/sysdep.S (__syscall_error): Use LDST_PCREL.
        Fix up gottpoff load of errno for thumb2.
index 29a78f043dbc6c015fbc8c7752f3f65a5edfca86..9230131c78b4499c7c2df8109fd55c59a46ef817 100644 (file)
        .previous;                                      \
 99:    OP      R, [pc, T]
 # endif
+
+/* Cope with negative memory offsets, which thumb can't encode.
+   Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
+   and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
+   or NEGOFF_OFF2 to use A-B for thumb and A for arm.  */
+# ifdef __thumb2__
+#  define NEGOFF_ADJ_BASE(R, OFF)      add R, R, $OFF
+#  define NEGOFF_ADJ_BASE2(D, S, OFF)  add D, S, $OFF
+#  define NEGOFF_OFF1(R, OFF)          [R]
+#  define NEGOFF_OFF2(R, OFFA, OFFB)   [R, $((OFFA) - (OFFB))]
+# else
+#  define NEGOFF_ADJ_BASE(R, OFF)
+#  define NEGOFF_ADJ_BASE2(D, S, OFF)  mov D, S
+#  define NEGOFF_OFF1(R, OFF)          [R, $OFF]
+#  define NEGOFF_OFF2(R, OFFA, OFFB)   [R, $OFFA]
+# endif
 #endif /* __ASSEMBLER__ */
 
 /* This number is the offset from the pc at the current location.  */
index 732a3ffd0176230803d4c2b238481f5774e07168..653bd74102d52d004c1eb3d94bf88052e6ddbb6a 100644 (file)
@@ -83,8 +83,9 @@ PSEUDO_END (__clone)
        ite     ne
        movne   r0, #-1
        swieq   0x0
-       str     r0, [r1, #PID_OFFSET]
-       str     r0, [r1, #TID_OFFSET]
+       NEGOFF_ADJ_BASE (r1, TID_OFFSET)
+       str     r0, NEGOFF_OFF1 (r1, TID_OFFSET)
+       str     r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET)
 3:
 #endif
        @ pick the function arg and call address off the stack and execute
index a38d56419c9db5abbda02dcd5d6f654df2bc12ff..f79bb66f2bf6d199950526b2e0421bf87f2891ea 100644 (file)
        ldr     lr, [sp], #4;           /* Restore LR.  */              \
        cfi_adjust_cfa_offset (-4);                                     \
        cfi_restore (lr);                                               \
-       mov     r2, r0;                 /* Save the TLS addr in r2.  */ \
-       ldr     r3, [r2, #PID_OFFSET];  /* Load the saved PID.  */      \
-       rsb     r0, r3, #0;             /* Negate it.  */               \
-       str     r0, [r2, #PID_OFFSET]   /* Store the temporary PID.  */
+       NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET); /* Save the TLS addr in r2. */ \
+       ldr     r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* Load the saved PID.  */  \
+       rsb     r0, r3, #0;             /* Negate it.  */                    \
+       str     r0, NEGOFF_OFF1 (r2, PID_OFFSET); /* Store the temp PID.  */
 
 /* Restore the old PID value in the parent.  */
 #define RESTORE_PID \
        cmp     r0, #0;                 /* If we are the parent... */   \
-       strne   r3, [r2, #PID_OFFSET]   /* ... restore the saved PID.  */
+       it      ne;                                                     \
+       strne   r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* restore the saved PID.  */
 
 #include "../vfork.S"
index 8889369ae3eae57a4a7d47b8f592460ea2b506f1..9157d03270c16886cb797c27722d488105415ca8 100644 (file)
@@ -217,7 +217,8 @@ extern int __local_multiple_threads attribute_hidden;
        cfi_adjust_cfa_offset (8);                                      \
        cfi_rel_offset (lr, 4);                                         \
        bl      __aeabi_read_tp;                                        \
-       ldr     ip, [r0, #MULTIPLE_THREADS_OFFSET];                     \
+       NEGOFF_ADJ_BASE (r0, MULTIPLE_THREADS_OFFSET);                  \
+       ldr     ip, NEGOFF_OFF1 (r0, MULTIPLE_THREADS_OFFSET);          \
        ldmfd   sp!, {r0, lr};                                          \
        cfi_adjust_cfa_offset (-8);                                     \
        cfi_restore (lr);                                               \
index 3fce2d1afaea10f527966a6e2dcabdc47e173287..1c6f3bb2bf4573e041fc87e5021742fc9fdc2642 100644 (file)
        ldr     lr, [sp], #4;           /* Restore LR.  */              \
        cfi_adjust_cfa_offset (-4);                                     \
        cfi_restore (lr);                                               \
-       mov     r2, r0;                 /* Save the TLS addr in r2.  */ \
-       ldr     r3, [r2, #PID_OFFSET];  /* Load the saved PID.  */      \
-       rsbs    r0, r3, #0;             /* Negate it.  */               \
-       moveq   r0, #0x80000000;        /* Use 0x80000000 if it was 0.  */ \
-       str     r0, [r2, #PID_OFFSET]   /* Store the temporary PID.  */
+       NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET); /* Save the TLS addr in r2.  */ \
+       ldr     r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* Load the saved PID.  */   \
+       rsbs    r0, r3, #0;             /* Negate it.  */                     \
+       it      eq;                                                           \
+       moveq   r0, #0x80000000;        /* Use 0x80000000 if it was 0.  */    \
+       str     r0, NEGOFF_OFF1 (r2, PID_OFFSET); /* Store the temp PID.  */
 
 /* Restore the old PID value in the parent.  */
 #define RESTORE_PID \
        cmp     r0, #0;         /* If we are the parent... */           \
-       strne   r3, [r2, #PID_OFFSET]   /* ... restore the saved PID.  */
+       it      ne;                                                     \
+       strne   r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* restore the saved PID.  */
 
 #include "../vfork.S"