summaryrefslogtreecommitdiff
path: root/src/ldso/arm/tlsdesc.S
blob: 4e67c3e25cfef21c1198db99e0a918361c63d989 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
.syntax unified

.text
.global __tlsdesc_static
.hidden __tlsdesc_static
.type __tlsdesc_static,%function
__tlsdesc_static:
	ldr r0,[r0]
	bx lr

.hidden __tls_get_new

.global __tlsdesc_dynamic
.hidden __tlsdesc_dynamic
.type __tlsdesc_dynamic,%function
__tlsdesc_dynamic:
	push {r2,r3,ip,lr}
	ldr r1,[r0]
	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]
2:
#if __ARM_ARCH >= 5
	blx r0          // r0 = tp
#else
	mov lr,pc
	bx r0
#endif
#endif
	ldr r3,[r0,#-4] // r3 = dtv
	ldr ip,[r3]     // ip = dtv slot count
	cmp r1,ip
	bhi 3f
	ldr ip,[r3,r1,LSL #2]
	sub r0,ip,r0
	add r0,r0,r2    // r0 = r3[r1]-r0+r2
4:
#if __ARM_ARCH >= 5
	pop {r2,r3,ip,pc}
#else
	pop {r2,r3,ip,lr}
	bx lr
#endif

3:
#if __ARM_PCS_VFP || !__SOFTFP__
	.fpu vfp
	vpush {d0-d7}
#endif
	push {r0-r3}
	add r0,sp,#4
	bl __tls_get_new
	pop {r1-r3,ip}
#if __ARM_PCS_VFP || !__SOFTFP__
	vpop {d0-d7}
#endif
	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