]>
Commit | Line | Data |
---|---|---|
63d143a2 CM |
1 | /* Copyright (C) 2011 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. | |
3 | Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
ab84e3ff PE |
16 | License along with the GNU C Library. If not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
63d143a2 CM |
18 | |
19 | #include <sysdep.h> | |
20 | #include <tls.h> | |
21 | ||
22 | #ifdef _LP64 | |
23 | #define LOG_SIZEOF_DTV_T 4 | |
24 | #else | |
25 | #define LOG_SIZEOF_DTV_T 3 | |
26 | #endif | |
27 | ||
28 | /* On entry, r0 points to two words, the module and the offset. | |
29 | On return, r0 holds the pointer to the relevant TLS memory. | |
30 | Only registers r25..r29 are clobbered by the call. */ | |
31 | ||
32 | .text | |
33 | ENTRY (__tls_get_addr) | |
34 | { | |
35 | lnk r25 | |
36 | ADDI_PTR r27, tp, DTV_OFFSET | |
37 | } | |
38 | .Llnk: | |
39 | #ifdef __tilegx__ | |
40 | { | |
41 | LD_PTR r27, r27 /* r27 = THREAD_DTV() */ | |
42 | moveli r26, hw1_last(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) | |
43 | } | |
44 | shl16insli r26, r26, hw0(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) | |
45 | { | |
46 | ADD_PTR r25, r25, r26 | |
47 | LD_PTR r26, r0 /* r26 = ti_module */ | |
48 | } | |
49 | #else | |
50 | { | |
51 | LD_PTR r27, r27 /* r27 = THREAD_DTV() */ | |
52 | addli r25, r25, lo16(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) | |
53 | } | |
54 | { | |
55 | auli r25, r25, ha16(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) | |
56 | LD_PTR r26, r0 /* r26 = ti_module */ | |
57 | } | |
58 | #endif | |
59 | LD_PTR r25, r25 /* r25 = DL(dl_tls_generation) */ | |
60 | { | |
61 | LD_PTR r28, r27 /* r28 = THREAD_DTV()->counter */ | |
62 | ADDI_PTR r29, r0, __SIZEOF_POINTER__ | |
63 | } | |
64 | { | |
65 | LD_PTR r29, r29 /* r29 = ti_offset */ | |
66 | CMPEQ r25, r28, r25 /* r25 nonzero if generation OK */ | |
67 | shli r28, r26, LOG_SIZEOF_DTV_T /* byte index into dtv array */ | |
68 | } | |
69 | { | |
70 | BEQZ r25, .Lslowpath | |
71 | CMPEQI r25, r26, -1 /* r25 nonzero if ti_module invalid */ | |
72 | } | |
73 | { | |
74 | BNEZ r25, .Lslowpath | |
75 | ADD_PTR r28, r28, r27 /* pointer into module array */ | |
76 | } | |
77 | LD_PTR r26, r28 /* r26 = module TLS pointer */ | |
78 | { | |
79 | ADD_PTR r0, r26, r29 | |
80 | jrp lr | |
81 | } | |
82 | ||
83 | .Lslowpath: | |
84 | { | |
85 | ST sp, lr | |
86 | ADDLI_PTR r29, sp, - (25 * REGSIZE) | |
87 | } | |
88 | cfi_offset (lr, 0) | |
89 | { | |
90 | ST r29, sp | |
91 | ADDLI_PTR sp, sp, - (26 * REGSIZE) | |
92 | } | |
93 | cfi_def_cfa_offset (26 * REGSIZE) | |
94 | ADDI_PTR r29, sp, (2 * REGSIZE) | |
95 | { ST r29, r1; ADDI_PTR r29, r29, REGSIZE } | |
96 | { ST r29, r2; ADDI_PTR r29, r29, REGSIZE } | |
97 | { ST r29, r3; ADDI_PTR r29, r29, REGSIZE } | |
98 | { ST r29, r4; ADDI_PTR r29, r29, REGSIZE } | |
99 | { ST r29, r5; ADDI_PTR r29, r29, REGSIZE } | |
100 | { ST r29, r6; ADDI_PTR r29, r29, REGSIZE } | |
101 | { ST r29, r7; ADDI_PTR r29, r29, REGSIZE } | |
102 | { ST r29, r8; ADDI_PTR r29, r29, REGSIZE } | |
103 | { ST r29, r9; ADDI_PTR r29, r29, REGSIZE } | |
104 | { ST r29, r10; ADDI_PTR r29, r29, REGSIZE } | |
105 | { ST r29, r11; ADDI_PTR r29, r29, REGSIZE } | |
106 | { ST r29, r12; ADDI_PTR r29, r29, REGSIZE } | |
107 | { ST r29, r13; ADDI_PTR r29, r29, REGSIZE } | |
108 | { ST r29, r14; ADDI_PTR r29, r29, REGSIZE } | |
109 | { ST r29, r15; ADDI_PTR r29, r29, REGSIZE } | |
110 | { ST r29, r16; ADDI_PTR r29, r29, REGSIZE } | |
111 | { ST r29, r17; ADDI_PTR r29, r29, REGSIZE } | |
112 | { ST r29, r18; ADDI_PTR r29, r29, REGSIZE } | |
113 | { ST r29, r19; ADDI_PTR r29, r29, REGSIZE } | |
114 | { ST r29, r20; ADDI_PTR r29, r29, REGSIZE } | |
115 | { ST r29, r21; ADDI_PTR r29, r29, REGSIZE } | |
116 | { ST r29, r22; ADDI_PTR r29, r29, REGSIZE } | |
117 | { ST r29, r23; ADDI_PTR r29, r29, REGSIZE } | |
118 | { ST r29, r24; ADDI_PTR r29, r29, REGSIZE } | |
119 | .hidden __tls_get_addr_slow | |
120 | jal __tls_get_addr_slow | |
121 | ADDI_PTR r29, sp, (2 * REGSIZE) | |
122 | { LD r1, r29; ADDI_PTR r29, r29, REGSIZE } | |
123 | { LD r2, r29; ADDI_PTR r29, r29, REGSIZE } | |
124 | { LD r3, r29; ADDI_PTR r29, r29, REGSIZE } | |
125 | { LD r4, r29; ADDI_PTR r29, r29, REGSIZE } | |
126 | { LD r5, r29; ADDI_PTR r29, r29, REGSIZE } | |
127 | { LD r6, r29; ADDI_PTR r29, r29, REGSIZE } | |
128 | { LD r7, r29; ADDI_PTR r29, r29, REGSIZE } | |
129 | { LD r8, r29; ADDI_PTR r29, r29, REGSIZE } | |
130 | { LD r9, r29; ADDI_PTR r29, r29, REGSIZE } | |
131 | { LD r10, r29; ADDI_PTR r29, r29, REGSIZE } | |
132 | { LD r11, r29; ADDI_PTR r29, r29, REGSIZE } | |
133 | { LD r12, r29; ADDI_PTR r29, r29, REGSIZE } | |
134 | { LD r13, r29; ADDI_PTR r29, r29, REGSIZE } | |
135 | { LD r14, r29; ADDI_PTR r29, r29, REGSIZE } | |
136 | { LD r15, r29; ADDI_PTR r29, r29, REGSIZE } | |
137 | { LD r16, r29; ADDI_PTR r29, r29, REGSIZE } | |
138 | { LD r17, r29; ADDI_PTR r29, r29, REGSIZE } | |
139 | { LD r18, r29; ADDI_PTR r29, r29, REGSIZE } | |
140 | { LD r19, r29; ADDI_PTR r29, r29, REGSIZE } | |
141 | { LD r20, r29; ADDI_PTR r29, r29, REGSIZE } | |
142 | { LD r21, r29; ADDI_PTR r29, r29, REGSIZE } | |
143 | { LD r22, r29; ADDI_PTR r29, r29, REGSIZE } | |
144 | { LD r23, r29; ADDI_PTR r29, r29, REGSIZE } | |
145 | { LD r24, r29; ADDLI_PTR sp, sp, (26 * REGSIZE) } | |
146 | cfi_def_cfa_offset (0) | |
147 | LD lr, sp | |
148 | jrp lr | |
149 | END (__tls_get_addr) |