From 54e8f884788d2cd89d2f6ed966dc52b6887a0d38 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Fri, 28 Mar 2025 20:43:09 +0800
Subject: [PATCH] ppc/ppc64 coroutines: save/restore CR as well

Corresponding change for ppc64le: https://github.com/ruby/ruby/commit/d8a21592b462aba0a66324f7444a2f6e61116d3a
---
 coroutine/ppc/Context.S   | 15 ++++++++++++---
 coroutine/ppc64/Context.S | 15 ++++++++++++---
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git coroutine/ppc/Context.S coroutine/ppc/Context.S
index f44b2419b4..a77ecdcbaf 100644
--- coroutine/ppc/Context.S
+++ coroutine/ppc/Context.S
@@ -19,7 +19,7 @@
 PREFIXED_SYMBOL(coroutine_transfer):
 	; Make space on the stack for caller registers
 	; (Should we rather use red zone? See libphobos example.)
-	subi r1,r1,80
+	subi r1,r1,84
 
 	; Get LR
 	mflr r0
@@ -46,9 +46,12 @@ PREFIXED_SYMBOL(coroutine_transfer):
 	stw r13,72(r1)
 
 	; Save return address
-	; Possibly should rather be saved into linkage area, see libphobos and IBM docs
 	stw r0,76(r1)
 
+	; Save caller CR register
+	mfcr r0
+	stw r0,80(r1)
+
 	; Save stack pointer to first argument
 	stw r1,0(r3)
 
@@ -82,8 +85,14 @@ PREFIXED_SYMBOL(coroutine_transfer):
 	; Set LR
 	mtlr r0
 
+	; Load CR register
+	lwz r0,80(r1)
+	; While it is feasible to deal with select fields of CR,
+	; it is easier and potentially faster to use the whole of it.
+	mtcr r0
+
 	; Pop stack frame
-	addi r1,r1,80
+	addi r1,r1,84
 
 	; Jump to return address
 	blr
diff --git coroutine/ppc64/Context.S coroutine/ppc64/Context.S
index 20a47c61c6..0082428629 100644
--- coroutine/ppc64/Context.S
+++ coroutine/ppc64/Context.S
@@ -18,7 +18,7 @@
 PREFIXED_SYMBOL(coroutine_transfer):
 	; Make space on the stack for caller registers
 	; (Should we rather use red zone? See libphobos example.)
-	subi r1,r1,160
+	subi r1,r1,168
 
 	; Get LR
 	mflr r0
@@ -45,9 +45,12 @@ PREFIXED_SYMBOL(coroutine_transfer):
 	std r13,144(r1)
 
 	; Save return address
-	; Possibly should rather be saved into linkage area, see libphobos and IBM docs
 	std r0,152(r1)
 
+	; Save caller CR register
+	mfcr r0
+	std r0,160(r1)
+
 	; Save stack pointer to first argument
 	std r1,0(r3)
 
@@ -81,8 +84,14 @@ PREFIXED_SYMBOL(coroutine_transfer):
 	; Set LR
 	mtlr r0
 
+	; Load CR register
+	ld r0,160(r1)
+	; While it is feasible to deal with select fields of CR,
+	; it is easier and potentially faster to use the whole of it.
+	mtcr r0
+
 	; Pop stack frame
-	addi r1,r1,160
+	addi r1,r1,168
 
 	; Jump to return address
 	blr

--- coroutine/ppc/Context.h	2026-07-14 08:22:10.000000000 +0800
+++ coroutine/ppc/Context.h	2026-07-18 00:29:45.000000000 +0800
@@ -13,7 +13,7 @@
 
 enum {
   COROUTINE_REGISTERS =
-  20  /* 19 general purpose registers (r13-r31) and 1 return address */
+  21  /* 19 general purpose registers (r13-r31), 1 special register (cr) and 1 return address */
   + 4  /* space for fiber_entry() to store the link register */
 };
 
--- coroutine/ppc64/Context.h	2026-07-14 08:22:10.000000000 +0800
+++ coroutine/ppc64/Context.h	2026-07-18 00:29:19.000000000 +0800
@@ -12,7 +12,7 @@
 
 enum {
   COROUTINE_REGISTERS =
-  20  /* 19 general purpose registers (r13-r31) and 1 return address */
+  21  /* 19 general purpose registers (r13-r31), 1 special register (cr) and 1 return address */
   + 4  /* space for fiber_entry() to store the link register */
 };
 
