aboutsummaryrefslogtreecommitdiffstats
path: root/coroutine/ppc64
diff options
context:
space:
mode:
authorSergey Fedorov <vital.had@gmail.com>2022-10-19 18:49:45 +0800
committerGitHub <noreply@github.com>2022-10-19 23:49:45 +1300
commit567725ed303b6738493c80efaf93dc4c1e65a9c9 (patch)
tree75f141047050eee63c05d613491595a7a9380afa /coroutine/ppc64
parentfc3137ef54562c3c3290245c0f62e0bb193c3145 (diff)
downloadruby-567725ed303b6738493c80efaf93dc4c1e65a9c9.tar.gz
Fix and improve coroutines for Darwin (macOS) ppc/ppc64. (#5975)
Diffstat (limited to 'coroutine/ppc64')
-rw-r--r--coroutine/ppc64/Context.S121
-rw-r--r--coroutine/ppc64/Context.h4
2 files changed, 72 insertions, 53 deletions
diff --git a/coroutine/ppc64/Context.S b/coroutine/ppc64/Context.S
index 1bd9268f93..f8561e0e7d 100644
--- a/coroutine/ppc64/Context.S
+++ b/coroutine/ppc64/Context.S
@@ -1,70 +1,89 @@
+; Based on the code by Samuel Williams. Created by Sergey Fedorov on 04/06/2022.
+; Credits to Samuel Williams, Rei Odaira and Iain Sandoe. Errors, if any, are mine.
+; Some relevant examples: https://github.com/gcc-mirror/gcc/blob/master/libphobos/libdruntime/config/powerpc/switchcontext.S
+; https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/rs6000/darwin-gpsave.S
+; https://www.ibm.com/docs/en/aix/7.2?topic=epilogs-saving-gprs-only
+
+; Notice that this code is only for Darwin (macOS). Darwin ABI differs from AIX and ELF.
+; To add support for AIX, *BSD or *Linux, please make separate implementations.
+
#define TOKEN_PASTE(x,y) x##y
#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
+.machine ppc64 ; = G5
.text
-.align 3
.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
- # Make space on the stack for caller registers
- addi r1,r1,-152
+.align 2
- # Save caller registers
- std r14,0(r1)
- std r15,8(r1)
- std r16,16(r1)
- std r17,24(r1)
- std r18,32(r1)
- std r19,40(r1)
- std r20,48(r1)
- std r21,56(r1)
- std r22,64(r1)
- std r23,72(r1)
- std r24,80(r1)
- std r25,88(r1)
- std r26,96(r1)
- std r27,104(r1)
- std r28,112(r1)
- std r29,120(r1)
- std r30,128(r1)
- std r31,136(r1)
+PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+ ; Make space on the stack for caller registers
+ ; (Should we rather use red zone? See libphobos example.)
+ subi r1,r1,160
- # Save return address
+ ; Get LR
mflr r0
- std r0,144(r1)
- # Save stack pointer to first argument
+ ; Save caller registers
+ std r31,0(r1)
+ std r30,8(r1)
+ std r29,16(r1)
+ std r28,24(r1)
+ std r27,32(r1)
+ std r26,40(r1)
+ std r25,48(r1)
+ std r24,56(r1)
+ std r23,64(r1)
+ std r22,72(r1)
+ std r21,80(r1)
+ std r20,88(r1)
+ std r19,96(r1)
+ std r18,104(r1)
+ std r17,112(r1)
+ std r16,120(r1)
+ std r15,128(r1)
+ std r14,136(r1)
+ 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 stack pointer to first argument
std r1,0(r3)
- # Load stack pointer from second argument
+ ; Load stack pointer from second argument
ld r1,0(r4)
- # Restore caller registers
- ld r14,0(r1)
- ld r15,8(r1)
- ld r16,16(r1)
- ld r17,24(r1)
- ld r18,32(r1)
- ld r19,40(r1)
- ld r20,48(r1)
- ld r21,56(r1)
- ld r22,64(r1)
- ld r23,72(r1)
- ld r24,80(r1)
- ld r25,88(r1)
- ld r26,96(r1)
- ld r27,104(r1)
- ld r28,112(r1)
- ld r29,120(r1)
- ld r30,128(r1)
- ld r31,136(r1)
+ ; Load return address
+ ld r0,152(r1)
+
+ ; Restore caller registers
+ ld r13,144(r1)
+ ld r14,136(r1)
+ ld r15,128(r1)
+ ld r16,120(r1)
+ ld r17,112(r1)
+ ld r18,104(r1)
+ ld r19,96(r1)
+ ld r20,88(r1)
+ ld r21,80(r1)
+ ld r22,72(r1)
+ ld r23,64(r1)
+ ld r24,56(r1)
+ ld r25,48(r1)
+ ld r26,40(r1)
+ ld r27,32(r1)
+ ld r28,24(r1)
+ ld r29,16(r1)
+ ld r30,8(r1)
+ ld r31,0(r1)
- # Load return address
- ld r0,144(r1)
+ ; Set LR
mtlr r0
- # Pop stack frame
- addi r1,r1,152
+ ; Pop stack frame
+ addi r1,r1,160
- # Jump to return address
+ ; Jump to return address
blr
diff --git a/coroutine/ppc64/Context.h b/coroutine/ppc64/Context.h
index 5b47511b9c..3e6f77f55a 100644
--- a/coroutine/ppc64/Context.h
+++ b/coroutine/ppc64/Context.h
@@ -12,7 +12,7 @@
enum {
COROUTINE_REGISTERS =
- 19 /* 18 general purpose registers (r14–r31) and 1 return address */
+ 20 /* 19 general purpose registers (r13–r31) and 1 return address */
+ 4 /* space for fiber_entry() to store the link register */
};
@@ -44,7 +44,7 @@ static inline void coroutine_initialize(
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
/* Skip a global prologue that sets the TOC register */
- context->stack_pointer[18] = ((char*)start) + 8;
+ context->stack_pointer[19] = ((char*)start) + 8;
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);