arm: Introduce and use NEGOFF series of macros

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.
This commit is contained in:
Richard Henderson 2013-02-14 09:46:56 -08:00
parent cd24e113c3
commit 3ae44082ab
6 changed files with 43 additions and 14 deletions

View 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.

View File

@ -134,6 +134,22 @@
.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. */

View 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

View File

@ -28,14 +28,15 @@
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"

View 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); \

View File

@ -28,15 +28,17 @@
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"