about summary refs log tree commit diff
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