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.S28
1 files changed, 22 insertions, 6 deletions
diff --git a/coroutine/ppc64le/Context.S b/coroutine/ppc64le/Context.S
index 61be9efcf0..819264c245 100644
--- a/coroutine/ppc64le/Context.S
+++ b/coroutine/ppc64le/Context.S
@@ -1,14 +1,20 @@
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
+.abiversion 2
.text
.align 2
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer), @function
-PREFIXED_SYMBOL(SYMBOL_PREFIX,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)
@@ -34,6 +40,10 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,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)
@@ -64,8 +74,14 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,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