summaryrefslogtreecommitdiff
path: root/coroutine/ppc64le/Context.S
diff options
context:
space:
mode:
Diffstat (limited to 'coroutine/ppc64le/Context.S')
-rw-r--r--coroutine/ppc64le/Context.S29
1 files changed, 24 insertions, 5 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