diff options
author | Richard Henderson <rth@twiddle.net> | 2013-02-13 20:10:45 -0800 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2013-03-06 07:46:38 -0800 |
commit | 5232b909bf31420497ec864e34f806a545017185 (patch) | |
tree | 83dda99ea71e22aab52f25e4be58d7d20bc9d848 /ports/sysdeps/unix/sysv/linux/arm | |
parent | 3ae44082ab30918a6f5aa135620dda08e62593d5 (diff) | |
download | glibc-5232b909bf31420497ec864e34f806a545017185.tar glibc-5232b909bf31420497ec864e34f806a545017185.tar.gz glibc-5232b909bf31420497ec864e34f806a545017185.tar.bz2 glibc-5232b909bf31420497ec864e34f806a545017185.zip |
arm: Introduce and use GET_TLS
Factor out the sequence needed to call kuser_get_tls, as we can't
play subtract into pc games in thumb mode. Prepare for hard-tp,
pulling the save of LR into the macro.
Diffstat (limited to 'ports/sysdeps/unix/sysv/linux/arm')
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S | 6 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/clone.S | 4 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S | 10 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h | 2 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S | 10 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/sysdep.h | 30 |
6 files changed, 40 insertions, 22 deletions
diff --git a/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S b/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S index c4ddbc69ff..ecdc3228a3 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S +++ b/ports/sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S @@ -41,6 +41,12 @@ .hidden __aeabi_read_tp ENTRY (__aeabi_read_tp) +#ifdef __thumb2__ + movw r0, #0x0fe0 + movt r0, #0xffff + bx r0 +#else mov r0, #0xffff0fff sub pc, r0, #31 +#endif END (__aeabi_read_tp) diff --git a/ports/sysdeps/unix/sysv/linux/arm/clone.S b/ports/sysdeps/unix/sysv/linux/arm/clone.S index 653bd74102..9009393f33 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/clone.S +++ b/ports/sysdeps/unix/sysv/linux/arm/clone.S @@ -74,9 +74,7 @@ PSEUDO_END (__clone) #ifdef RESET_PID tst ip, #CLONE_THREAD bne 3f - mov r0, #0xffff0fff - mov lr, pc - sub pc, r0, #31 + GET_TLS (lr) mov r1, r0 tst ip, #CLONE_VM ldr r7, =SYS_ify(getpid) diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S b/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S index f79bb66f2b..ca50457070 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S +++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S @@ -19,15 +19,7 @@ /* Save the PID value. */ #define SAVE_PID \ - str lr, [sp, #-4]!; /* Save LR. */ \ - cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (lr, 0); \ - mov r0, #0xffff0fff; /* Point to the high page. */ \ - mov lr, pc; /* Save our return address. */ \ - sub pc, r0, #31; /* Jump to the TLS entry. */ \ - ldr lr, [sp], #4; /* Restore LR. */ \ - cfi_adjust_cfa_offset (-4); \ - cfi_restore (lr); \ + GET_TLS (r2); \ 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. */ \ diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h b/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h index 9157d03270..2fc053523f 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h +++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h @@ -216,7 +216,7 @@ extern int __local_multiple_threads attribute_hidden; stmfd sp!, {r0, lr}; \ cfi_adjust_cfa_offset (8); \ cfi_rel_offset (lr, 4); \ - bl __aeabi_read_tp; \ + GET_TLS (lr); \ NEGOFF_ADJ_BASE (r0, MULTIPLE_THREADS_OFFSET); \ ldr ip, NEGOFF_OFF1 (r0, MULTIPLE_THREADS_OFFSET); \ ldmfd sp!, {r0, lr}; \ diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S b/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S index 1c6f3bb2bf..216fb2d2eb 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S +++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/vfork.S @@ -19,15 +19,7 @@ /* Save the PID value. */ #define SAVE_PID \ - str lr, [sp, #-4]!; /* Save LR. */ \ - cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (lr, 0); \ - mov r0, #0xffff0fff; /* Point to the high page. */ \ - mov lr, pc; /* Save our return address. */ \ - sub pc, r0, #31; /* Jump to the TLS entry. */ \ - ldr lr, [sp], #4; /* Restore LR. */ \ - cfi_adjust_cfa_offset (-4); \ - cfi_restore (lr); \ + GET_TLS (r2); \ 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. */ \ diff --git a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h index 89208a9f19..dc2058b275 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -45,6 +45,36 @@ #ifdef __ASSEMBLER__ +/* Internal macro calling the linux kernel kuser_get_tls helper. + Note that in thumb mode, a constant pool break is often out of range, so + we always expand the constant inline. */ +#ifdef __thumb2__ +# define GET_TLS_BODY \ + movw r0, #0x0fe0; \ + movt r0, #0xffff; \ + blx r0 +#else +# define GET_TLS_BODY \ + mov r0, #0xffff0fff; /* Point to the high page. */ \ + mov lr, pc; /* Save our return address. */ \ + sub pc, r0, #31 /* Jump to the TLS entry. */ +#endif + +/* Helper to get the TLS base pointer. Save LR in TMP, return in R0, + and no other registers clobbered. TMP may be LR itself to indicate + that no save is necessary. */ +#undef GET_TLS +#define GET_TLS(TMP) \ + .ifnc TMP, lr; \ + mov TMP, lr; \ + cfi_register (lr, TMP); \ + GET_TLS_BODY; \ + mov lr, TMP; \ + cfi_restore (lr); \ + .else; \ + GET_TLS_BODY; \ + .endif + /* Linux uses a negative return value to indicate syscall errors, unlike most Unices, which use the condition codes' carry flag. |