290 lines
8.2 KiB
ArmAsm
290 lines
8.2 KiB
ArmAsm
|
#include "tsan_ppc_regs.h"
|
||
|
|
||
|
.machine altivec
|
||
|
.section .text
|
||
|
.hidden __tsan_setjmp
|
||
|
.globl _setjmp
|
||
|
.type _setjmp, @function
|
||
|
.align 4
|
||
|
#if _CALL_ELF == 2
|
||
|
_setjmp:
|
||
|
#else
|
||
|
.section ".opd","aw"
|
||
|
.align 3
|
||
|
_setjmp:
|
||
|
.quad .L._setjmp,.TOC.@tocbase,0
|
||
|
.previous
|
||
|
#endif
|
||
|
.L._setjmp:
|
||
|
mflr r0
|
||
|
stdu r1,-48(r1)
|
||
|
std r2,24(r1)
|
||
|
std r3,32(r1)
|
||
|
std r0,40(r1)
|
||
|
// r3 is the original stack pointer.
|
||
|
addi r3,r1,48
|
||
|
// r4 is the mangled stack pointer (see glibc)
|
||
|
ld r4,-28696(r13)
|
||
|
xor r4,r3,r4
|
||
|
// Materialize a TOC in case we were called from libc.
|
||
|
// For big-endian, we load the TOC from the OPD. For little-
|
||
|
// endian, we use the .TOC. symbol to find it.
|
||
|
nop
|
||
|
bcl 20,31,0f
|
||
|
0:
|
||
|
mflr r2
|
||
|
#if _CALL_ELF == 2
|
||
|
addis r2,r2,.TOC.-0b@ha
|
||
|
addi r2,r2,.TOC.-0b@l
|
||
|
#else
|
||
|
addis r2,r2,_setjmp-0b@ha
|
||
|
addi r2,r2,_setjmp-0b@l
|
||
|
ld r2,8(r2)
|
||
|
#endif
|
||
|
// Call the interceptor.
|
||
|
bl __tsan_setjmp
|
||
|
nop
|
||
|
// Restore regs needed for setjmp.
|
||
|
ld r3,32(r1)
|
||
|
ld r0,40(r1)
|
||
|
// Emulate the real setjmp function. We do this because we can't
|
||
|
// perform a sibcall: The real setjmp function trashes the TOC
|
||
|
// pointer, and with a sibcall we have no way to restore it.
|
||
|
// This way we can make sure our caller's stack pointer and
|
||
|
// link register are saved correctly in the jmpbuf.
|
||
|
ld r6,-28696(r13)
|
||
|
addi r5,r1,48 // original stack ptr of caller
|
||
|
xor r5,r6,r5
|
||
|
std r5,0(r3) // mangled stack ptr of caller
|
||
|
ld r5,24(r1)
|
||
|
std r5,8(r3) // caller's saved TOC pointer
|
||
|
xor r0,r6,r0
|
||
|
std r0,16(r3) // caller's mangled return address
|
||
|
mfcr r0
|
||
|
// Nonvolatiles.
|
||
|
std r14,24(r3)
|
||
|
stfd f14,176(r3)
|
||
|
stw r0,172(r3) // CR
|
||
|
std r15,32(r3)
|
||
|
stfd f15,184(r3)
|
||
|
std r16,40(r3)
|
||
|
stfd f16,192(r3)
|
||
|
std r17,48(r3)
|
||
|
stfd f17,200(r3)
|
||
|
std r18,56(r3)
|
||
|
stfd f18,208(r3)
|
||
|
std r19,64(r3)
|
||
|
stfd f19,216(r3)
|
||
|
std r20,72(r3)
|
||
|
stfd f20,224(r3)
|
||
|
std r21,80(r3)
|
||
|
stfd f21,232(r3)
|
||
|
std r22,88(r3)
|
||
|
stfd f22,240(r3)
|
||
|
std r23,96(r3)
|
||
|
stfd f23,248(r3)
|
||
|
std r24,104(r3)
|
||
|
stfd f24,256(r3)
|
||
|
std r25,112(r3)
|
||
|
stfd f25,264(r3)
|
||
|
std r26,120(r3)
|
||
|
stfd f26,272(r3)
|
||
|
std r27,128(r3)
|
||
|
stfd f27,280(r3)
|
||
|
std r28,136(r3)
|
||
|
stfd f28,288(r3)
|
||
|
std r29,144(r3)
|
||
|
stfd f29,296(r3)
|
||
|
std r30,152(r3)
|
||
|
stfd f30,304(r3)
|
||
|
std r31,160(r3)
|
||
|
stfd f31,312(r3)
|
||
|
addi r5,r3,320
|
||
|
mfspr r0,256
|
||
|
stw r0,168(r3) // VRSAVE
|
||
|
addi r6,r5,16
|
||
|
stvx v20,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v21,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v22,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v23,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v24,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v25,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v26,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v27,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v28,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v29,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v30,0,r5
|
||
|
stvx v31,0,r6
|
||
|
// Clear the "mask-saved" slot.
|
||
|
li r4,0
|
||
|
stw r4,512(r3)
|
||
|
// Restore TOC, LR, and stack and return to caller.
|
||
|
ld r2,24(r1)
|
||
|
ld r0,40(r1)
|
||
|
addi r1,r1,48
|
||
|
li r3,0 // This is the setjmp return path
|
||
|
mtlr r0
|
||
|
blr
|
||
|
.size _setjmp, .-.L._setjmp
|
||
|
|
||
|
.globl setjmp
|
||
|
.type setjmp, @function
|
||
|
.align 4
|
||
|
setjmp:
|
||
|
b _setjmp
|
||
|
.size setjmp, .-setjmp
|
||
|
|
||
|
// sigsetjmp is like setjmp, except that the mask in r4 needs
|
||
|
// to be saved at offset 512 of the jump buffer.
|
||
|
.globl __sigsetjmp
|
||
|
.type __sigsetjmp, @function
|
||
|
.align 4
|
||
|
#if _CALL_ELF == 2
|
||
|
__sigsetjmp:
|
||
|
#else
|
||
|
.section ".opd","aw"
|
||
|
.align 3
|
||
|
__sigsetjmp:
|
||
|
.quad .L.__sigsetjmp,.TOC.@tocbase,0
|
||
|
.previous
|
||
|
#endif
|
||
|
.L.__sigsetjmp:
|
||
|
mflr r0
|
||
|
stdu r1,-64(r1)
|
||
|
std r2,24(r1)
|
||
|
std r3,32(r1)
|
||
|
std r4,40(r1)
|
||
|
std r0,48(r1)
|
||
|
// r3 is the original stack pointer.
|
||
|
addi r3,r1,64
|
||
|
// r4 is the mangled stack pointer (see glibc)
|
||
|
ld r4,-28696(r13)
|
||
|
xor r4,r3,r4
|
||
|
// Materialize a TOC in case we were called from libc.
|
||
|
// For big-endian, we load the TOC from the OPD. For little-
|
||
|
// endian, we use the .TOC. symbol to find it.
|
||
|
nop
|
||
|
bcl 20,31,1f
|
||
|
1:
|
||
|
mflr r2
|
||
|
#if _CALL_ELF == 2
|
||
|
addis r2,r2,.TOC.-1b@ha
|
||
|
addi r2,r2,.TOC.-1b@l
|
||
|
#else
|
||
|
addis r2,r2,_setjmp-1b@ha
|
||
|
addi r2,r2,_setjmp-1b@l
|
||
|
ld r2,8(r2)
|
||
|
#endif
|
||
|
// Call the interceptor.
|
||
|
bl __tsan_setjmp
|
||
|
nop
|
||
|
// Restore regs needed for __sigsetjmp.
|
||
|
ld r3,32(r1)
|
||
|
ld r4,40(r1)
|
||
|
ld r0,48(r1)
|
||
|
// Emulate the real sigsetjmp function. We do this because we can't
|
||
|
// perform a sibcall: The real sigsetjmp function trashes the TOC
|
||
|
// pointer, and with a sibcall we have no way to restore it.
|
||
|
// This way we can make sure our caller's stack pointer and
|
||
|
// link register are saved correctly in the jmpbuf.
|
||
|
ld r6,-28696(r13)
|
||
|
addi r5,r1,64 // original stack ptr of caller
|
||
|
xor r5,r6,r5
|
||
|
std r5,0(r3) // mangled stack ptr of caller
|
||
|
ld r5,24(r1)
|
||
|
std r5,8(r3) // caller's saved TOC pointer
|
||
|
xor r0,r6,r0
|
||
|
std r0,16(r3) // caller's mangled return address
|
||
|
mfcr r0
|
||
|
// Nonvolatiles.
|
||
|
std r14,24(r3)
|
||
|
stfd f14,176(r3)
|
||
|
stw r0,172(r3) // CR
|
||
|
std r15,32(r3)
|
||
|
stfd f15,184(r3)
|
||
|
std r16,40(r3)
|
||
|
stfd f16,192(r3)
|
||
|
std r17,48(r3)
|
||
|
stfd f17,200(r3)
|
||
|
std r18,56(r3)
|
||
|
stfd f18,208(r3)
|
||
|
std r19,64(r3)
|
||
|
stfd f19,216(r3)
|
||
|
std r20,72(r3)
|
||
|
stfd f20,224(r3)
|
||
|
std r21,80(r3)
|
||
|
stfd f21,232(r3)
|
||
|
std r22,88(r3)
|
||
|
stfd f22,240(r3)
|
||
|
std r23,96(r3)
|
||
|
stfd f23,248(r3)
|
||
|
std r24,104(r3)
|
||
|
stfd f24,256(r3)
|
||
|
std r25,112(r3)
|
||
|
stfd f25,264(r3)
|
||
|
std r26,120(r3)
|
||
|
stfd f26,272(r3)
|
||
|
std r27,128(r3)
|
||
|
stfd f27,280(r3)
|
||
|
std r28,136(r3)
|
||
|
stfd f28,288(r3)
|
||
|
std r29,144(r3)
|
||
|
stfd f29,296(r3)
|
||
|
std r30,152(r3)
|
||
|
stfd f30,304(r3)
|
||
|
std r31,160(r3)
|
||
|
stfd f31,312(r3)
|
||
|
addi r5,r3,320
|
||
|
mfspr r0,256
|
||
|
stw r0,168(r3) // VRSAVE
|
||
|
addi r6,r5,16
|
||
|
stvx v20,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v21,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v22,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v23,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v24,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v25,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v26,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v27,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v28,0,r5
|
||
|
addi r5,r5,32
|
||
|
stvx v29,0,r6
|
||
|
addi r6,r6,32
|
||
|
stvx v30,0,r5
|
||
|
stvx v31,0,r6
|
||
|
// Save into the "mask-saved" slot.
|
||
|
stw r4,512(r3)
|
||
|
// Restore TOC, LR, and stack and return to caller.
|
||
|
ld r2,24(r1)
|
||
|
ld r0,48(r1)
|
||
|
addi r1,r1,64
|
||
|
li r3,0 // This is the sigsetjmp return path
|
||
|
mtlr r0
|
||
|
blr
|
||
|
.size __sigsetjmp, .-.L.__sigsetjmp
|
||
|
|
||
|
.globl sigsetjmp
|
||
|
.type sigsetjmp, @function
|
||
|
.align 4
|
||
|
sigsetjmp:
|
||
|
b __sigsetjmp
|
||
|
.size sigsetjmp, .-sigsetjmp
|