1 | #include "tsan_ppc_regs.h" |
2 | |
3 | .section .text |
4 | .hidden __tsan_setjmp |
5 | .globl _setjmp |
6 | .type _setjmp, @function |
7 | .align 4 |
8 | #if _CALL_ELF == 2 |
9 | _setjmp: |
10 | #else |
11 | .section ".opd" ,"aw" |
12 | .align 3 |
13 | _setjmp: |
14 | .quad .L._setjmp,.TOC.@tocbase,0 |
15 | .previous |
16 | #endif |
17 | .L._setjmp: |
18 | mflr r0 |
19 | stdu r1,-48(r1) |
20 | std r2,24(r1) |
21 | std r3,32(r1) |
22 | std r0,40(r1) |
23 | // r3 is the original stack pointer. |
24 | addi r3,r1,48 |
25 | // r4 is the mangled stack pointer (see glibc) |
26 | ld r4,-28696(r13) |
27 | xor r4,r3,r4 |
28 | // Materialize a TOC in case we were called from libc. |
29 | // For big-endian, we load the TOC from the OPD. For little- |
30 | // endian, we use the .TOC. symbol to find it. |
31 | nop |
32 | bcl 20,31,0f |
33 | 0: |
34 | mflr r2 |
35 | #if _CALL_ELF == 2 |
36 | addis r2,r2,.TOC.-0b@ha |
37 | addi r2,r2,.TOC.-0b@l |
38 | #else |
39 | addis r2,r2,_setjmp-0b@ha |
40 | addi r2,r2,_setjmp-0b@l |
41 | ld r2,8(r2) |
42 | #endif |
43 | // Call the interceptor. |
44 | bl __tsan_setjmp |
45 | nop |
46 | // Restore regs needed for setjmp. |
47 | ld r3,32(r1) |
48 | ld r0,40(r1) |
49 | // Emulate the real setjmp function. We do this because we can't |
50 | // perform a sibcall: The real setjmp function trashes the TOC |
51 | // pointer, and with a sibcall we have no way to restore it. |
52 | // This way we can make sure our caller's stack pointer and |
53 | // link register are saved correctly in the jmpbuf. |
54 | ld r6,-28696(r13) |
55 | addi r5,r1,48 // original stack ptr of caller |
56 | xor r5,r6,r5 |
57 | std r5,0(r3) // mangled stack ptr of caller |
58 | ld r5,24(r1) |
59 | std r5,8(r3) // caller's saved TOC pointer |
60 | xor r0,r6,r0 |
61 | std r0,16(r3) // caller's mangled return address |
62 | mfcr r0 |
63 | // Nonvolatiles. |
64 | std r14,24(r3) |
65 | stfd f14,176(r3) |
66 | stw r0,172(r3) // CR |
67 | std r15,32(r3) |
68 | stfd f15,184(r3) |
69 | std r16,40(r3) |
70 | stfd f16,192(r3) |
71 | std r17,48(r3) |
72 | stfd f17,200(r3) |
73 | std r18,56(r3) |
74 | stfd f18,208(r3) |
75 | std r19,64(r3) |
76 | stfd f19,216(r3) |
77 | std r20,72(r3) |
78 | stfd f20,224(r3) |
79 | std r21,80(r3) |
80 | stfd f21,232(r3) |
81 | std r22,88(r3) |
82 | stfd f22,240(r3) |
83 | std r23,96(r3) |
84 | stfd f23,248(r3) |
85 | std r24,104(r3) |
86 | stfd f24,256(r3) |
87 | std r25,112(r3) |
88 | stfd f25,264(r3) |
89 | std r26,120(r3) |
90 | stfd f26,272(r3) |
91 | std r27,128(r3) |
92 | stfd f27,280(r3) |
93 | std r28,136(r3) |
94 | stfd f28,288(r3) |
95 | std r29,144(r3) |
96 | stfd f29,296(r3) |
97 | std r30,152(r3) |
98 | stfd f30,304(r3) |
99 | std r31,160(r3) |
100 | stfd f31,312(r3) |
101 | addi r5,r3,320 |
102 | mfspr r0,256 |
103 | stw r0,168(r3) // VRSAVE |
104 | addi r6,r5,16 |
105 | stvx v20,0,r5 |
106 | addi r5,r5,32 |
107 | stvx v21,0,r6 |
108 | addi r6,r6,32 |
109 | stvx v22,0,r5 |
110 | addi r5,r5,32 |
111 | stvx v23,0,r6 |
112 | addi r6,r6,32 |
113 | stvx v24,0,r5 |
114 | addi r5,r5,32 |
115 | stvx v25,0,r6 |
116 | addi r6,r6,32 |
117 | stvx v26,0,r5 |
118 | addi r5,r5,32 |
119 | stvx v27,0,r6 |
120 | addi r6,r6,32 |
121 | stvx v28,0,r5 |
122 | addi r5,r5,32 |
123 | stvx v29,0,r6 |
124 | addi r6,r6,32 |
125 | stvx v30,0,r5 |
126 | stvx v31,0,r6 |
127 | // Clear the "mask-saved" slot. |
128 | li r4,0 |
129 | stw r4,512(r3) |
130 | // Restore TOC, LR, and stack and return to caller. |
131 | ld r2,24(r1) |
132 | ld r0,40(r1) |
133 | addi r1,r1,48 |
134 | li r3,0 // This is the setjmp return path |
135 | mtlr r0 |
136 | blr |
137 | .size _setjmp, .-.L._setjmp |
138 | |
139 | .globl setjmp |
140 | .type setjmp, @function |
141 | .align 4 |
142 | setjmp: |
143 | b _setjmp |
144 | .size setjmp, .-setjmp |
145 | |
146 | // sigsetjmp is like setjmp, except that the mask in r4 needs |
147 | // to be saved at offset 512 of the jump buffer. |
148 | .globl __sigsetjmp |
149 | .type __sigsetjmp, @function |
150 | .align 4 |
151 | #if _CALL_ELF == 2 |
152 | __sigsetjmp: |
153 | #else |
154 | .section ".opd" ,"aw" |
155 | .align 3 |
156 | __sigsetjmp: |
157 | .quad .L.__sigsetjmp,.TOC.@tocbase,0 |
158 | .previous |
159 | #endif |
160 | .L.__sigsetjmp: |
161 | mflr r0 |
162 | stdu r1,-64(r1) |
163 | std r2,24(r1) |
164 | std r3,32(r1) |
165 | std r4,40(r1) |
166 | std r0,48(r1) |
167 | // r3 is the original stack pointer. |
168 | addi r3,r1,64 |
169 | // r4 is the mangled stack pointer (see glibc) |
170 | ld r4,-28696(r13) |
171 | xor r4,r3,r4 |
172 | // Materialize a TOC in case we were called from libc. |
173 | // For big-endian, we load the TOC from the OPD. For little- |
174 | // endian, we use the .TOC. symbol to find it. |
175 | nop |
176 | bcl 20,31,1f |
177 | 1: |
178 | mflr r2 |
179 | #if _CALL_ELF == 2 |
180 | addis r2,r2,.TOC.-1b@ha |
181 | addi r2,r2,.TOC.-1b@l |
182 | #else |
183 | addis r2,r2,_setjmp-1b@ha |
184 | addi r2,r2,_setjmp-1b@l |
185 | ld r2,8(r2) |
186 | #endif |
187 | // Call the interceptor. |
188 | bl __tsan_setjmp |
189 | nop |
190 | // Restore regs needed for __sigsetjmp. |
191 | ld r3,32(r1) |
192 | ld r4,40(r1) |
193 | ld r0,48(r1) |
194 | // Emulate the real sigsetjmp function. We do this because we can't |
195 | // perform a sibcall: The real sigsetjmp function trashes the TOC |
196 | // pointer, and with a sibcall we have no way to restore it. |
197 | // This way we can make sure our caller's stack pointer and |
198 | // link register are saved correctly in the jmpbuf. |
199 | ld r6,-28696(r13) |
200 | addi r5,r1,64 // original stack ptr of caller |
201 | xor r5,r6,r5 |
202 | std r5,0(r3) // mangled stack ptr of caller |
203 | ld r5,24(r1) |
204 | std r5,8(r3) // caller's saved TOC pointer |
205 | xor r0,r6,r0 |
206 | std r0,16(r3) // caller's mangled return address |
207 | mfcr r0 |
208 | // Nonvolatiles. |
209 | std r14,24(r3) |
210 | stfd f14,176(r3) |
211 | stw r0,172(r3) // CR |
212 | std r15,32(r3) |
213 | stfd f15,184(r3) |
214 | std r16,40(r3) |
215 | stfd f16,192(r3) |
216 | std r17,48(r3) |
217 | stfd f17,200(r3) |
218 | std r18,56(r3) |
219 | stfd f18,208(r3) |
220 | std r19,64(r3) |
221 | stfd f19,216(r3) |
222 | std r20,72(r3) |
223 | stfd f20,224(r3) |
224 | std r21,80(r3) |
225 | stfd f21,232(r3) |
226 | std r22,88(r3) |
227 | stfd f22,240(r3) |
228 | std r23,96(r3) |
229 | stfd f23,248(r3) |
230 | std r24,104(r3) |
231 | stfd f24,256(r3) |
232 | std r25,112(r3) |
233 | stfd f25,264(r3) |
234 | std r26,120(r3) |
235 | stfd f26,272(r3) |
236 | std r27,128(r3) |
237 | stfd f27,280(r3) |
238 | std r28,136(r3) |
239 | stfd f28,288(r3) |
240 | std r29,144(r3) |
241 | stfd f29,296(r3) |
242 | std r30,152(r3) |
243 | stfd f30,304(r3) |
244 | std r31,160(r3) |
245 | stfd f31,312(r3) |
246 | addi r5,r3,320 |
247 | mfspr r0,256 |
248 | stw r0,168(r3) // VRSAVE |
249 | addi r6,r5,16 |
250 | stvx v20,0,r5 |
251 | addi r5,r5,32 |
252 | stvx v21,0,r6 |
253 | addi r6,r6,32 |
254 | stvx v22,0,r5 |
255 | addi r5,r5,32 |
256 | stvx v23,0,r6 |
257 | addi r6,r6,32 |
258 | stvx v24,0,r5 |
259 | addi r5,r5,32 |
260 | stvx v25,0,r6 |
261 | addi r6,r6,32 |
262 | stvx v26,0,r5 |
263 | addi r5,r5,32 |
264 | stvx v27,0,r6 |
265 | addi r6,r6,32 |
266 | stvx v28,0,r5 |
267 | addi r5,r5,32 |
268 | stvx v29,0,r6 |
269 | addi r6,r6,32 |
270 | stvx v30,0,r5 |
271 | stvx v31,0,r6 |
272 | // Save into the "mask-saved" slot. |
273 | stw r4,512(r3) |
274 | // Restore TOC, LR, and stack and return to caller. |
275 | ld r2,24(r1) |
276 | ld r0,48(r1) |
277 | addi r1,r1,64 |
278 | li r3,0 // This is the sigsetjmp return path |
279 | mtlr r0 |
280 | blr |
281 | .size __sigsetjmp, .-.L.__sigsetjmp |
282 | |
283 | .globl sigsetjmp |
284 | .type sigsetjmp, @function |
285 | .align 4 |
286 | sigsetjmp: |
287 | b __sigsetjmp |
288 | .size sigsetjmp, .-sigsetjmp |
289 | |