diff options
author | Sergey Fedorov <vital.had@gmail.com> | 2022-05-22 11:02:03 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-22 15:02:03 +1200 |
commit | 539459abda3f4e086ca060620dee2586ebfed873 (patch) | |
tree | b9a4f71f8a74bafb1b7afa81245688b553f255e4 /coroutine | |
parent | 84257244cd67e40daed274c01ff0a6929e1a2b67 (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.S | 73 | ||||
-rw-r--r-- | coroutine/ppc/Context.h | 57 | ||||
-rw-r--r-- | coroutine/ppc64/Context.S | 70 | ||||
-rw-r--r-- | coroutine/ppc64/Context.h | 57 | ||||
-rw-r--r-- | coroutine/universal/Context.S | 6 | ||||
-rw-r--r-- | coroutine/universal/Context.h | 6 |
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" |