1292925Sdim#include "tsan_ppc_regs.h"
2292925Sdim
3292925Sdim        .section .text
4292925Sdim        .hidden __tsan_setjmp
5292925Sdim        .globl _setjmp
6292925Sdim        .type _setjmp, @function
7292925Sdim        .align 4
8292925Sdim#if _CALL_ELF == 2
9292925Sdim_setjmp:
10292925Sdim#else
11292925Sdim	.section ".opd","aw"
12292925Sdim	.align 3
13292925Sdim_setjmp:
14292925Sdim	.quad   .L._setjmp,.TOC.@tocbase,0
15292925Sdim	.previous
16292925Sdim#endif
17292925Sdim.L._setjmp:
18292925Sdim        mflr    r0
19292925Sdim        stdu    r1,-48(r1)
20292925Sdim        std     r2,24(r1)
21292925Sdim        std     r3,32(r1)
22292925Sdim        std     r0,40(r1)
23292925Sdim        // r3 is the original stack pointer.
24292925Sdim        addi    r3,r1,48
25292925Sdim        // r4 is the mangled stack pointer (see glibc)
26292925Sdim        ld      r4,-28696(r13)
27292925Sdim        xor     r4,r3,r4
28292925Sdim        // Materialize a TOC in case we were called from libc.
29292925Sdim        // For big-endian, we load the TOC from the OPD.  For little-
30292925Sdim        // endian, we use the .TOC. symbol to find it.
31292925Sdim        nop
32292925Sdim        bcl     20,31,0f
33292925Sdim0:
34292925Sdim        mflr    r2
35292925Sdim#if _CALL_ELF == 2
36292925Sdim        addis   r2,r2,.TOC.-0b@ha
37292925Sdim        addi    r2,r2,.TOC.-0b@l
38292925Sdim#else
39292925Sdim        addis   r2,r2,_setjmp-0b@ha
40292925Sdim        addi    r2,r2,_setjmp-0b@l
41292925Sdim        ld      r2,8(r2)
42292925Sdim#endif
43292925Sdim        // Call the interceptor.
44292925Sdim        bl      __tsan_setjmp
45292925Sdim        nop
46292925Sdim        // Restore regs needed for setjmp.
47292925Sdim        ld      r3,32(r1)
48292925Sdim        ld      r0,40(r1)
49292925Sdim        // Emulate the real setjmp function.  We do this because we can't
50292925Sdim        // perform a sibcall:  The real setjmp function trashes the TOC
51292925Sdim        // pointer, and with a sibcall we have no way to restore it.
52292925Sdim        // This way we can make sure our caller's stack pointer and
53292925Sdim        // link register are saved correctly in the jmpbuf.
54292925Sdim        ld      r6,-28696(r13)
55292925Sdim        addi    r5,r1,48  // original stack ptr of caller
56292925Sdim        xor     r5,r6,r5
57292925Sdim        std     r5,0(r3)  // mangled stack ptr of caller
58292925Sdim        ld      r5,24(r1)
59292925Sdim        std     r5,8(r3)  // caller's saved TOC pointer
60292925Sdim        xor     r0,r6,r0
61292925Sdim        std     r0,16(r3) // caller's mangled return address
62292925Sdim        mfcr    r0
63292925Sdim        // Nonvolatiles.
64292925Sdim        std     r14,24(r3)
65292925Sdim        stfd    f14,176(r3)
66292925Sdim        stw     r0,172(r3) // CR
67292925Sdim        std     r15,32(r3)
68292925Sdim        stfd    f15,184(r3)
69292925Sdim        std     r16,40(r3)
70292925Sdim        stfd    f16,192(r3)
71292925Sdim        std     r17,48(r3)
72292925Sdim        stfd    f17,200(r3)
73292925Sdim        std     r18,56(r3)
74292925Sdim        stfd    f18,208(r3)
75292925Sdim        std     r19,64(r3)
76292925Sdim        stfd    f19,216(r3)
77292925Sdim        std     r20,72(r3)
78292925Sdim        stfd    f20,224(r3)
79292925Sdim        std     r21,80(r3)
80292925Sdim        stfd    f21,232(r3)
81292925Sdim        std     r22,88(r3)
82292925Sdim        stfd    f22,240(r3)
83292925Sdim        std     r23,96(r3)
84292925Sdim        stfd    f23,248(r3)
85292925Sdim        std     r24,104(r3)
86292925Sdim        stfd    f24,256(r3)
87292925Sdim        std     r25,112(r3)
88292925Sdim        stfd    f25,264(r3)
89292925Sdim        std     r26,120(r3)
90292925Sdim        stfd    f26,272(r3)
91292925Sdim        std     r27,128(r3)
92292925Sdim        stfd    f27,280(r3)
93292925Sdim        std     r28,136(r3)
94292925Sdim        stfd    f28,288(r3)
95292925Sdim        std     r29,144(r3)
96292925Sdim        stfd    f29,296(r3)
97292925Sdim        std     r30,152(r3)
98292925Sdim        stfd    f30,304(r3)
99292925Sdim        std     r31,160(r3)
100292925Sdim        stfd    f31,312(r3)
101292925Sdim        addi    r5,r3,320
102292925Sdim        mfspr   r0,256
103292925Sdim        stw     r0,168(r3)  // VRSAVE
104292925Sdim        addi    r6,r5,16
105292925Sdim        stvx    v20,0,r5
106292925Sdim        addi    r5,r5,32
107292925Sdim        stvx    v21,0,r6
108292925Sdim        addi    r6,r6,32
109292925Sdim        stvx    v22,0,r5
110292925Sdim        addi    r5,r5,32
111292925Sdim        stvx    v23,0,r6
112292925Sdim        addi    r6,r6,32
113292925Sdim        stvx    v24,0,r5
114292925Sdim        addi    r5,r5,32
115292925Sdim        stvx    v25,0,r6
116292925Sdim        addi    r6,r6,32
117292925Sdim        stvx    v26,0,r5
118292925Sdim        addi    r5,r5,32
119292925Sdim        stvx    v27,0,r6
120292925Sdim        addi    r6,r6,32
121292925Sdim        stvx    v28,0,r5
122292925Sdim        addi    r5,r5,32
123292925Sdim        stvx    v29,0,r6
124292925Sdim        addi    r6,r6,32
125292925Sdim        stvx    v30,0,r5
126292925Sdim        stvx    v31,0,r6
127292925Sdim        // Clear the "mask-saved" slot.
128292925Sdim        li      r4,0
129292925Sdim        stw     r4,512(r3)
130292925Sdim        // Restore TOC, LR, and stack and return to caller.
131292925Sdim        ld      r2,24(r1)
132292925Sdim        ld      r0,40(r1)
133292925Sdim        addi    r1,r1,48
134292925Sdim        li      r3,0  // This is the setjmp return path
135292925Sdim        mtlr    r0
136292925Sdim        blr
137292925Sdim        .size _setjmp, .-.L._setjmp
138292925Sdim
139292925Sdim        .globl setjmp
140292925Sdim        .type setjmp, @function
141292925Sdim        .align 4
142292925Sdimsetjmp:
143292925Sdim        b       _setjmp
144292925Sdim        .size setjmp, .-setjmp
145292925Sdim
146292925Sdim        // sigsetjmp is like setjmp, except that the mask in r4 needs
147292925Sdim        // to be saved at offset 512 of the jump buffer.
148292925Sdim        .globl __sigsetjmp
149292925Sdim        .type __sigsetjmp, @function
150292925Sdim        .align 4
151292925Sdim#if _CALL_ELF == 2
152292925Sdim__sigsetjmp:
153292925Sdim#else
154292925Sdim	.section ".opd","aw"
155292925Sdim	.align 3
156292925Sdim__sigsetjmp:
157292925Sdim	.quad   .L.__sigsetjmp,.TOC.@tocbase,0
158292925Sdim	.previous
159292925Sdim#endif
160292925Sdim.L.__sigsetjmp:
161292925Sdim        mflr    r0
162292925Sdim        stdu    r1,-64(r1)
163292925Sdim        std     r2,24(r1)
164292925Sdim        std     r3,32(r1)
165292925Sdim        std     r4,40(r1)
166292925Sdim        std     r0,48(r1)
167292925Sdim        // r3 is the original stack pointer.
168292925Sdim        addi    r3,r1,64
169292925Sdim        // r4 is the mangled stack pointer (see glibc)
170292925Sdim        ld      r4,-28696(r13)
171292925Sdim        xor     r4,r3,r4
172292925Sdim        // Materialize a TOC in case we were called from libc.
173292925Sdim        // For big-endian, we load the TOC from the OPD.  For little-
174292925Sdim        // endian, we use the .TOC. symbol to find it.
175292925Sdim        nop
176292925Sdim        bcl     20,31,1f
177292925Sdim1:
178292925Sdim        mflr    r2
179292925Sdim#if _CALL_ELF == 2
180292925Sdim        addis   r2,r2,.TOC.-1b@ha
181292925Sdim        addi    r2,r2,.TOC.-1b@l
182292925Sdim#else
183292925Sdim        addis   r2,r2,_setjmp-1b@ha
184292925Sdim        addi    r2,r2,_setjmp-1b@l
185292925Sdim        ld      r2,8(r2)
186292925Sdim#endif
187292925Sdim        // Call the interceptor.
188292925Sdim        bl      __tsan_setjmp
189292925Sdim        nop
190292925Sdim        // Restore regs needed for __sigsetjmp.
191292925Sdim        ld      r3,32(r1)
192292925Sdim        ld      r4,40(r1)
193292925Sdim        ld      r0,48(r1)
194292925Sdim        // Emulate the real sigsetjmp function.  We do this because we can't
195292925Sdim        // perform a sibcall:  The real sigsetjmp function trashes the TOC
196292925Sdim        // pointer, and with a sibcall we have no way to restore it.
197292925Sdim        // This way we can make sure our caller's stack pointer and
198292925Sdim        // link register are saved correctly in the jmpbuf.
199292925Sdim        ld      r6,-28696(r13)
200292925Sdim        addi    r5,r1,64  // original stack ptr of caller
201292925Sdim        xor     r5,r6,r5
202292925Sdim        std     r5,0(r3)  // mangled stack ptr of caller
203292925Sdim        ld      r5,24(r1)
204292925Sdim        std     r5,8(r3)  // caller's saved TOC pointer
205292925Sdim        xor     r0,r6,r0
206292925Sdim        std     r0,16(r3) // caller's mangled return address
207292925Sdim        mfcr    r0
208292925Sdim        // Nonvolatiles.
209292925Sdim        std     r14,24(r3)
210292925Sdim        stfd    f14,176(r3)
211292925Sdim        stw     r0,172(r3) // CR
212292925Sdim        std     r15,32(r3)
213292925Sdim        stfd    f15,184(r3)
214292925Sdim        std     r16,40(r3)
215292925Sdim        stfd    f16,192(r3)
216292925Sdim        std     r17,48(r3)
217292925Sdim        stfd    f17,200(r3)
218292925Sdim        std     r18,56(r3)
219292925Sdim        stfd    f18,208(r3)
220292925Sdim        std     r19,64(r3)
221292925Sdim        stfd    f19,216(r3)
222292925Sdim        std     r20,72(r3)
223292925Sdim        stfd    f20,224(r3)
224292925Sdim        std     r21,80(r3)
225292925Sdim        stfd    f21,232(r3)
226292925Sdim        std     r22,88(r3)
227292925Sdim        stfd    f22,240(r3)
228292925Sdim        std     r23,96(r3)
229292925Sdim        stfd    f23,248(r3)
230292925Sdim        std     r24,104(r3)
231292925Sdim        stfd    f24,256(r3)
232292925Sdim        std     r25,112(r3)
233292925Sdim        stfd    f25,264(r3)
234292925Sdim        std     r26,120(r3)
235292925Sdim        stfd    f26,272(r3)
236292925Sdim        std     r27,128(r3)
237292925Sdim        stfd    f27,280(r3)
238292925Sdim        std     r28,136(r3)
239292925Sdim        stfd    f28,288(r3)
240292925Sdim        std     r29,144(r3)
241292925Sdim        stfd    f29,296(r3)
242292925Sdim        std     r30,152(r3)
243292925Sdim        stfd    f30,304(r3)
244292925Sdim        std     r31,160(r3)
245292925Sdim        stfd    f31,312(r3)
246292925Sdim        addi    r5,r3,320
247292925Sdim        mfspr   r0,256
248292925Sdim        stw     r0,168(r3) // VRSAVE
249292925Sdim        addi    r6,r5,16
250292925Sdim        stvx    v20,0,r5
251292925Sdim        addi    r5,r5,32
252292925Sdim        stvx    v21,0,r6
253292925Sdim        addi    r6,r6,32
254292925Sdim        stvx    v22,0,r5
255292925Sdim        addi    r5,r5,32
256292925Sdim        stvx    v23,0,r6
257292925Sdim        addi    r6,r6,32
258292925Sdim        stvx    v24,0,r5
259292925Sdim        addi    r5,r5,32
260292925Sdim        stvx    v25,0,r6
261292925Sdim        addi    r6,r6,32
262292925Sdim        stvx    v26,0,r5
263292925Sdim        addi    r5,r5,32
264292925Sdim        stvx    v27,0,r6
265292925Sdim        addi    r6,r6,32
266292925Sdim        stvx    v28,0,r5
267292925Sdim        addi    r5,r5,32
268292925Sdim        stvx    v29,0,r6
269292925Sdim        addi    r6,r6,32
270292925Sdim        stvx    v30,0,r5
271292925Sdim        stvx    v31,0,r6
272292925Sdim        // Save into the "mask-saved" slot.
273292925Sdim        stw     r4,512(r3)
274292925Sdim        // Restore TOC, LR, and stack and return to caller.
275292925Sdim        ld      r2,24(r1)
276292925Sdim        ld      r0,48(r1)
277292925Sdim        addi    r1,r1,64
278292925Sdim        li      r3,0  // This is the sigsetjmp return path
279292925Sdim        mtlr    r0
280292925Sdim        blr
281292925Sdim        .size __sigsetjmp, .-.L.__sigsetjmp
282292925Sdim
283292925Sdim        .globl sigsetjmp
284292925Sdim        .type sigsetjmp, @function
285292925Sdim        .align 4
286292925Sdimsigsetjmp:
287292925Sdim        b       __sigsetjmp
288292925Sdim        .size sigsetjmp, .-sigsetjmp
289