about summary refs log tree commit diff
path: root/src/setjmp
diff options
context:
space:
mode:
Diffstat (limited to 'src/setjmp')
-rw-r--r--src/setjmp/powerpc64/longjmp.s14
-rw-r--r--src/setjmp/powerpc64/setjmp.s21
2 files changed, 25 insertions, 10 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)