summaryrefslogtreecommitdiff
path: root/src/ldso/arm
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-10-01 19:36:14 -0400
committerRich Felker <dalias@aerifal.cx>2018-10-01 19:39:24 -0400
commit7bf773a8f9b97875ba67b646c1681ac5ca22016f (patch)
tree5647df1752aef1f7e862c54a4ff7e494defc32bd /src/ldso/arm
parent0beb9dfbecad38af9759b1e83eeb007e28b70abb (diff)
downloadmusl-7bf773a8f9b97875ba67b646c1681ac5ca22016f.tar.gz
inline cp15 thread pointer load in arm dynamic TLSDESC asm when possible
the indirect function call is a significant portion of the code path for the dynamic case, and most users are probably building for ISA levels where it can be omitted. we could drop at least one register save/restore (lr) with this change, and possibly another (ip) with some clever shuffling, but it's not clear whether there's a way to do it that's not more expensive, or whether avoiding the save/restore would have any practical effect, so in the interest of avoiding complexity it's omitted for now.
Diffstat (limited to 'src/ldso/arm')
-rw-r--r--src/ldso/arm/tlsdesc.S9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/ldso/arm/tlsdesc.S b/src/ldso/arm/tlsdesc.S
index f3d67fce..b81f3111 100644
--- a/src/ldso/arm/tlsdesc.S
+++ b/src/ldso/arm/tlsdesc.S
@@ -19,6 +19,10 @@ __tlsdesc_dynamic:
ldr r2,[r1,#4] // r2 = offset
ldr r1,[r1] // r1 = modid
+#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
+ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+ mrc p15,0,r0,c13,c0,3
+#else
ldr r0,1f
add r0,r0,pc
ldr r0,[r0]
@@ -29,6 +33,7 @@ __tlsdesc_dynamic:
mov lr,pc
bx r0
#endif
+#endif
ldr r3,[r0,#-4] // r3 = dtv
ldr ip,[r3] // ip = dtv slot count
cmp r1,ip
@@ -58,5 +63,9 @@ __tlsdesc_dynamic:
sub r0,r0,r1 // r0 = retval-tp
b 4b
+#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
+ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+#else
.align 2
1: .word __a_gettp_ptr - 2b
+#endif