diff options
Diffstat (limited to 'coroutine/ppc64le')
| -rw-r--r-- | coroutine/ppc64le/Context.S | 29 | ||||
| -rw-r--r-- | coroutine/ppc64le/Context.h | 8 |
2 files changed, 31 insertions, 6 deletions
diff --git a/coroutine/ppc64le/Context.S b/coroutine/ppc64le/Context.S index 1b39086f8f..819264c245 100644 --- a/coroutine/ppc64le/Context.S +++ b/coroutine/ppc64le/Context.S @@ -1,11 +1,20 @@ +#define TOKEN_PASTE(x,y) x##y + +.abiversion 2 .text .align 2 -.globl coroutine_transfer -.type coroutine_transfer, @function -coroutine_transfer: +.globl PREFIXED_SYMBOL(coroutine_transfer) +.type PREFIXED_SYMBOL(coroutine_transfer), @function +PREFIXED_SYMBOL(coroutine_transfer): + # Global entry: set up TOC pointer (r2) from r12. + # Required by ELFv2 ABI when this function is reached via the PLT. + addis 2, 12, .TOC. - PREFIXED_SYMBOL(coroutine_transfer)@ha + addi 2, 2, .TOC. - PREFIXED_SYMBOL(coroutine_transfer)@l + .localentry PREFIXED_SYMBOL(coroutine_transfer), .-PREFIXED_SYMBOL(coroutine_transfer) + # Make space on the stack for caller registers - addi 1,1,-152 + addi 1,1,-160 # Save caller registers std 14,0(1) @@ -31,6 +40,10 @@ coroutine_transfer: mflr 0 std 0,144(1) + # Save caller special register + mfcr 0 + std 0, 152(1) + # Save stack pointer to first argument std 1,0(3) @@ -61,8 +74,14 @@ coroutine_transfer: ld 0,144(1) mtlr 0 + # Load special registers + ld 0,152(1) + # Restore cr register cr2, cr3 and cr4 (field index 3,4,5) + # (field index is 1-based, field 1 = cr0) using a mask (32|16|8 = 56) + mtcrf 56,0 + # Pop stack frame - addi 1,1,152 + addi 1,1,160 # Jump to return address blr diff --git a/coroutine/ppc64le/Context.h b/coroutine/ppc64le/Context.h index e36f9c3583..63ea9f19ff 100644 --- a/coroutine/ppc64le/Context.h +++ b/coroutine/ppc64le/Context.h @@ -1,3 +1,6 @@ +#ifndef COROUTINE_PPC64LE_CONTEXT_H +#define COROUTINE_PPC64LE_CONTEXT_H 1 + #pragma once #include <assert.h> @@ -9,13 +12,14 @@ enum { COROUTINE_REGISTERS = - 19 /* 18 general purpose registers (r14-r31) and 1 return address */ + 20 /* 18 general purpose registers (r14-r31), 1 special register (cr) 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); @@ -49,3 +53,5 @@ static inline void coroutine_destroy(struct coroutine_context * context) { context->stack_pointer = NULL; } + +#endif /* COROUTINE_PPC64LE_CONTEXT_H */ |
