summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/setjmp/powerpc64/longjmp.s14
-rw-r--r--src/setjmp/powerpc64/setjmp.s21
-rw-r--r--src/signal/powerpc64/sigsetjmp.s21
3 files changed, 39 insertions, 17 deletions
diff --git a/src/setjmp/powerpc64/longjmp.s b/src/setjmp/powerpc64/longjmp.s
index 7f241c2d..81d45ff6 100644
--- a/src/setjmp/powerpc64/longjmp.s
+++ b/src/setjmp/powerpc64/longjmp.s
@@ -10,10 +10,14 @@ longjmp:
# 1) restore cr
ld 0, 1*8(3)
mtcr 0
- # 2) restore r1-r2 (SP and TOC)
+ # 2) restore SP
ld 1, 2*8(3)
+ # 3) restore TOC into both r2 and the caller's stack.
+ # Which location is required depends on whether setjmp was called
+ # locally or non-locally, but it's always safe to restore to both.
ld 2, 3*8(3)
- # 3) restore r14-r31
+ std 2, 24(1)
+ # 4) restore r14-r31
ld 14, 4*8(3)
ld 15, 5*8(3)
ld 16, 6*8(3)
@@ -32,7 +36,7 @@ longjmp:
ld 29, 19*8(3)
ld 30, 20*8(3)
ld 31, 21*8(3)
- # 4) restore floating point registers f14-f31
+ # 5) restore floating point registers f14-f31
lfd 14, 22*8(3)
lfd 15, 23*8(3)
lfd 16, 24*8(3)
@@ -52,7 +56,7 @@ longjmp:
lfd 30, 38*8(3)
lfd 31, 39*8(3)
- # 5) restore vector registers v20-v31
+ # 6) restore vector registers v20-v31
addi 3, 3, 40*8
lvx 20, 0, 3 ; addi 3, 3, 16
lvx 21, 0, 3 ; addi 3, 3, 16
@@ -67,7 +71,7 @@ longjmp:
lvx 30, 0, 3 ; addi 3, 3, 16
lvx 31, 0, 3
- # 6) return r4 ? r4 : 1
+ # 7) return r4 ? r4 : 1
mr 3, 4
cmpwi cr7, 4, 0
bne cr7, 1f
diff --git a/src/setjmp/powerpc64/setjmp.s b/src/setjmp/powerpc64/setjmp.s
index d16d4bae..37683fda 100644
--- a/src/setjmp/powerpc64/setjmp.s
+++ b/src/setjmp/powerpc64/setjmp.s
@@ -1,24 +1,35 @@
- .global ___setjmp
- .hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
-___setjmp:
__setjmp:
_setjmp:
setjmp:
+ ld 5, 24(1) # load from the TOC slot in the caller's stack frame
+ b __setjmp_toc
+
+ .localentry __setjmp,.-__setjmp
+ .localentry _setjmp,.-_setjmp
+ .localentry setjmp,.-setjmp
+ mr 5, 2
+
+ .global __setjmp_toc
+ .hidden __setjmp_toc
+ # same as normal setjmp, except TOC pointer to save is provided in r5.
+ # r4 would normally be the 2nd parameter, but we're using r5 to simplify calling from sigsetjmp.
+ # solves the problem of knowing whether to save the TOC pointer from r2 or the caller's stack frame.
+__setjmp_toc:
# 0) store IP into 0, then into the jmpbuf pointed to by r3 (first arg)
mflr 0
std 0, 0*8(3)
# 1) store cr
mfcr 0
std 0, 1*8(3)
- # 2) store r1-r2 (SP and TOC)
+ # 2) store SP and TOC
std 1, 2*8(3)
- std 2, 3*8(3)
+ std 5, 3*8(3)
# 3) store r14-31
std 14, 4*8(3)
std 15, 5*8(3)
diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
index 52ac1d03..410c2831 100644
--- a/src/signal/powerpc64/sigsetjmp.s
+++ b/src/signal/powerpc64/sigsetjmp.s
@@ -2,29 +2,36 @@
.global __sigsetjmp
.type sigsetjmp,%function
.type __sigsetjmp,%function
- .hidden ___setjmp
+ .hidden __setjmp_toc
sigsetjmp:
__sigsetjmp:
addis 2, 12, .TOC.-__sigsetjmp@ha
addi 2, 2, .TOC.-__sigsetjmp@l
+ ld 5, 24(1) # load from the TOC slot in the caller's stack frame
+ b 1f
+
.localentry sigsetjmp,.-sigsetjmp
.localentry __sigsetjmp,.-__sigsetjmp
+ mr 5, 2
+1:
cmpwi cr7, 4, 0
- beq- cr7, ___setjmp
+ beq- cr7, __setjmp_toc
- mflr 5
- std 5, 512(3)
- std 16, 512+8+8(3)
+ mflr 6
+ std 6, 512(3)
+ std 2, 512+16(3)
+ std 16, 512+24(3)
mr 16, 3
- bl ___setjmp
+ bl __setjmp_toc
mr 4, 3
mr 3, 16
ld 5, 512(3)
mtlr 5
- ld 16, 512+8+8(3)
+ ld 2, 512+16(3)
+ ld 16, 512+24(3)
.hidden __sigsetjmp_tail
b __sigsetjmp_tail