summaryrefslogtreecommitdiff
path: root/coroutine/ppc64
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/ppc64
parent84257244cd67e40daed274c01ff0a6929e1a2b67 (diff)
downloadruby-539459abda3f4e086ca060620dee2586ebfed873.tar.gz
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
Diffstat (limited to 'coroutine/ppc64')
-rw-r--r--coroutine/ppc64/Context.S70
-rw-r--r--coroutine/ppc64/Context.h57
2 files changed, 127 insertions, 0 deletions
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 */