summaryrefslogtreecommitdiff
path: root/coroutine/ppc
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/ppc
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/ppc')
-rw-r--r--coroutine/ppc/Context.S73
-rw-r--r--coroutine/ppc/Context.h57
2 files changed, 130 insertions, 0 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 */