summaryrefslogtreecommitdiff
path: root/coroutine
diff options
context:
space:
mode:
authorSergey Fedorov <vital.had@gmail.com>2022-05-22 11:02:03 +0800
committerGitHub <noreply@github.com>2022-05-22 15:02:03 +1200
commit539459abda3f4e086ca060620dee2586ebfed873 (patch)
treeb9a4f71f8a74bafb1b7afa81245688b553f255e4 /coroutine
parent84257244cd67e40daed274c01ff0a6929e1a2b67 (diff)
Ruby31: add support for Darwin ppc/ppc64 (#5927)
* add coroutines for ppc & ppc64 * fix universal coroutine to include ppc & ppc64 * add powerpc*-darwin to configure.ac * fix thread_pthread for older systems
Notes
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
Diffstat (limited to 'coroutine')
-rw-r--r--coroutine/ppc/Context.S73
-rw-r--r--coroutine/ppc/Context.h57
-rw-r--r--coroutine/ppc64/Context.S70
-rw-r--r--coroutine/ppc64/Context.h57
-rw-r--r--coroutine/universal/Context.S6
-rw-r--r--coroutine/universal/Context.h6
6 files changed, 267 insertions, 2 deletions
diff --git a/coroutine/ppc/Context.S b/coroutine/ppc/Context.S
new file mode 100644
index 0000000000..fe28390df0
--- /dev/null
+++ b/coroutine/ppc/Context.S
@@ -0,0 +1,73 @@
+#define TOKEN_PASTE(x,y) x##y
+#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
+
+.text
+.align 2
+
+.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
+PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+ # Make space on the stack for caller registers
+ addi r1,r1,-80
+
+ # Save caller registers
+ stw r13,0(r1)
+ stw r14,4(r1)
+ stw r15,8(r1)
+ stw r16,12(r1)
+ stw r17,16(r1)
+ stw r18,20(r1)
+ stw r19,24(r1)
+ stw r20,28(r1)
+ stw r21,32(r1)
+ stw r22,36(r1)
+ stw r23,40(r1)
+ stw r24,44(r1)
+ stw r25,48(r1)
+ stw r26,52(r1)
+ stw r27,56(r1)
+ stw r28,60(r1)
+ stw r29,64(r1)
+ stw r30,68(r1)
+ stw r31,72(r1)
+
+ # Save return address
+ mflr r0
+ stw r0,76(r1)
+
+ # Save stack pointer to first argument
+ stw r1,0(r3)
+
+ # Load stack pointer from second argument
+ lwz r1,0(r4)
+
+ # Restore caller registers
+ lwz r13,0(r1)
+ lwz r14,4(r1)
+ lwz r15,8(r1)
+ lwz r16,12(r1)
+ lwz r17,16(r1)
+ lwz r18,20(r1)
+ lwz r19,24(r1)
+ lwz r20,28(r1)
+ lwz r21,32(r1)
+ lwz r22,36(r1)
+ lwz r23,40(r1)
+ lwz r24,44(r1)
+ lwz r25,48(r1)
+ lwz r26,52(r1)
+ lwz r27,56(r1)
+ lwz r28,60(r1)
+ lwz r29,64(r1)
+ lwz r30,68(r1)
+ lwz r31,72(r1)
+
+ # Load return address
+ lwz r0,76(r1)
+ mtlr r0
+
+ # Pop stack frame
+ addi r1,r1,80
+
+ # Jump to return address
+ blr
+
diff --git a/coroutine/ppc/Context.h b/coroutine/ppc/Context.h
new file mode 100644
index 0000000000..9f69390388
--- /dev/null
+++ b/coroutine/ppc/Context.h
@@ -0,0 +1,57 @@
+#ifndef COROUTINE_PPC_CONTEXT_H
+#define COROUTINE_PPC_CONTEXT_H 1
+
+#pragma once
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#define COROUTINE __attribute__((noreturn)) void
+
+enum {
+ COROUTINE_REGISTERS =
+ 20 /* 19 general purpose registers (r13–r31) and 1 return address */
+ + 4 /* space for fiber_entry() to store the link register */
+};
+
+struct coroutine_context
+{
+ void **stack_pointer;
+ void *argument;
+};
+
+typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+
+static inline void coroutine_initialize_main(struct coroutine_context * context) {
+ context->stack_pointer = NULL;
+}
+
+static inline void coroutine_initialize(
+ struct coroutine_context *context,
+ coroutine_start start,
+ void *stack,
+ size_t size
+) {
+ assert(start && stack && size >= 1024);
+
+ // Stack grows down. Force 16-byte alignment.
+ char * top = (char*)stack + size;
+ context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
+
+ context->stack_pointer -= COROUTINE_REGISTERS;
+ memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
+
+ /* Skip a global prologue that sets the TOC register */
+ context->stack_pointer[19] = ((char*)start) + 8;
+}
+
+struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
+
+static inline void coroutine_destroy(struct coroutine_context * context)
+{
+ context->stack_pointer = NULL;
+}
+
+#endif /* COROUTINE_PPC_CONTEXT_H */
diff --git a/coroutine/ppc64/Context.S b/coroutine/ppc64/Context.S
new file mode 100644
index 0000000000..1bd9268f93
--- /dev/null
+++ b/coroutine/ppc64/Context.S
@@ -0,0 +1,70 @@
+#define TOKEN_PASTE(x,y) x##y
+#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
+
+.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
+
+ # 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)
+
+ # Save return address
+ mflr r0
+ std r0,144(r1)
+
+ # Save stack pointer to first argument
+ std r1,0(r3)
+
+ # 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,144(r1)
+ mtlr r0
+
+ # Pop stack frame
+ addi r1,r1,152
+
+ # Jump to return address
+ blr
diff --git a/coroutine/ppc64/Context.h b/coroutine/ppc64/Context.h
new file mode 100644
index 0000000000..5b47511b9c
--- /dev/null
+++ b/coroutine/ppc64/Context.h
@@ -0,0 +1,57 @@
+#ifndef COROUTINE_PPC64_CONTEXT_H
+#define COROUTINE_PPC64_CONTEXT_H 1
+
+#pragma once
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#define COROUTINE __attribute__((noreturn)) void
+
+enum {
+ COROUTINE_REGISTERS =
+ 19 /* 18 general purpose registers (r14–r31) and 1 return address */
+ + 4 /* space for fiber_entry() to store the link register */
+};
+
+struct coroutine_context
+{
+ void **stack_pointer;
+ void *argument;
+};
+
+typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+
+static inline void coroutine_initialize_main(struct coroutine_context * context) {
+ context->stack_pointer = NULL;
+}
+
+static inline void coroutine_initialize(
+ struct coroutine_context *context,
+ coroutine_start start,
+ void *stack,
+ size_t size
+) {
+ assert(start && stack && size >= 1024);
+
+ // Stack grows down. Force 16-byte alignment.
+ char * top = (char*)stack + size;
+ context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
+
+ context->stack_pointer -= COROUTINE_REGISTERS;
+ 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;
+}
+
+struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
+
+static inline void coroutine_destroy(struct coroutine_context * context)
+{
+ context->stack_pointer = NULL;
+}
+
+#endif /* COROUTINE_PPC64_CONTEXT_H */
diff --git a/coroutine/universal/Context.S b/coroutine/universal/Context.S
index 0fd8c01e7f..11c80a7927 100644
--- a/coroutine/universal/Context.S
+++ b/coroutine/universal/Context.S
@@ -3,7 +3,11 @@
# include "coroutine/amd64/Context.S"
#elif defined __i386__
# include "coroutine/x86/Context.S"
-#elif defined __ppc64__
+#elif defined __ppc__
+# include "coroutine/ppc/Context.S"
+#elif defined __ppc64__ && defined(WORDS_BIGENDIAN)
+# include "coroutine/ppc64/Context.S"
+#elif defined __ppc64__ && !defined(WORDS_BIGENDIAN)
# include "coroutine/ppc64le/Context.S"
#elif defined __arm64__
# include "coroutine/arm64/Context.S"
diff --git a/coroutine/universal/Context.h b/coroutine/universal/Context.h
index 9a2ef425db..ec4d2f484a 100644
--- a/coroutine/universal/Context.h
+++ b/coroutine/universal/Context.h
@@ -6,7 +6,11 @@
# include "coroutine/amd64/Context.h"
#elif defined __i386__
# include "coroutine/x86/Context.h"
-#elif defined __ppc64__
+#elif defined __ppc__
+# include "coroutine/ppc/Context.h"
+#elif defined __ppc64__ && defined(WORDS_BIGENDIAN)
+# include "coroutine/ppc64/Context.h"
+#elif defined __ppc64__ && !defined(WORDS_BIGENDIAN)
# include "coroutine/ppc64le/Context.h"
#elif defined __arm64__
# include "coroutine/arm64/Context.h"