aboutsummaryrefslogtreecommitdiff
path: root/src/coro_unix_x64.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/coro_unix_x64.s')
-rw-r--r--src/coro_unix_x64.s110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/coro_unix_x64.s b/src/coro_unix_x64.s
new file mode 100644
index 0000000..98710c2
--- /dev/null
+++ b/src/coro_unix_x64.s
@@ -0,0 +1,110 @@
+; Nicholas Noll 2019
+;
+; ===================================================================
+%use altreg
+
+ bits 64
+ default rel
+ global _newcoro
+ global _coroyield
+
+; ===================================================================
+ section .text
+; -------------------------------------------------------------------
+
+%assign L.coro -8
+%assign L.func -16
+
+coroinit:
+ mov R7, [RBP + L.coro]
+ mov R6, R0
+ call [RBP + L.func]
+
+rerun:
+ mov R7, [RBP + L.coro]
+ mov R6, R0
+ call _coroyield
+ jmp rerun
+
+; -------------------------------------------------------------------
+; # Register Mapping
+;
+; R0 R1 R2 R3 R4 R5 R6 R7 R8 ...
+; RAX RCX RDX RBX RSP RBP RSI RDI R8 ...
+;
+; # Sys V calling convention
+; func(R7, R6, R2, R1, R8, R9, Z0-7): R0
+;
+; # Stack layout of an in-flight coro
+; ^coro
+; ^func
+; ^bp (base pointer of stack)
+; ....... STACK .........
+; Saved Clobbers
+;
+; ###
+; Stack layout of an init coro
+; Stores the func pointer to init
+; Stores the clobber registers.
+;
+; L.coro [8]
+; L.func [7]
+; coroinit [6]
+; RBP [5]
+; R3 [4]
+; R12 [3]
+; R13 [2]
+; R14 [1]
+; R15 [0]
+
+%define WORDS 8
+%define SAVES 9
+
+; func sys.newCoro(co ^coro, fn func, bp ^stack)
+_newcoro:
+ lea R0, [coroinit]
+ lea R1, [R2 - SAVES*WORDS]
+
+ mov [R1 + 8*WORDS], R7
+ mov [R1 + 7*WORDS], R6
+ mov [R1 + 6*WORDS], R0
+ mov [R1 + 5*WORDS], R2
+
+ xor R0, R0
+
+ ; Blank out the clobbers
+ mov [R1 + 4*WORDS], R0 ; R3
+ mov [R1 + 3*WORDS], R0 ; R12
+ mov [R1 + 2*WORDS], R0 ; R13
+ mov [R1 + 1*WORDS], R0 ; R14
+ mov [R1 + 0*WORDS], R0 ; R15
+
+ mov [R7], R1
+ ret
+
+%macro pushclobs 0
+ push RBP
+ push R3
+ push R12
+ push R13
+ push R14
+ push R15
+%endmacro
+
+%macro popclobs 0
+ pop R15
+ pop R14
+ pop R13
+ pop R12
+ pop R3
+ pop RBP
+%endmacro
+
+; func coro.yield(co ^coro, ret uintptr)
+_coroyield:
+ pushclobs
+ mov R0, R6 ; Move return value into return register.
+ xchg RSP, [R7] ; Atomically swap the stack pointer with the yieldee.
+ popclobs
+
+ ret