summaryrefslogtreecommitdiff
path: root/coroutine/ppc64le
diff options
context:
space:
mode:
Diffstat (limited to 'coroutine/ppc64le')
-rw-r--r--coroutine/ppc64le/Context.S29
-rw-r--r--coroutine/ppc64le/Context.h8
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 */