aboutsummaryrefslogtreecommitdiff
path: root/sys/base/coro/unix_x64.s
diff options
context:
space:
mode:
Diffstat (limited to 'sys/base/coro/unix_x64.s')
-rw-r--r--sys/base/coro/unix_x64.s113
1 files changed, 113 insertions, 0 deletions
diff --git a/sys/base/coro/unix_x64.s b/sys/base/coro/unix_x64.s
new file mode 100644
index 0000000..d7de2a2
--- /dev/null
+++ b/sys/base/coro/unix_x64.s
@@ -0,0 +1,113 @@
+; 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 WORDSZ 8
+%define NSAVES 9
+
+; coro *coro·new(co *coro, fn func, bp *stack)
+_newcoro:
+ lea R0, [coroinit] ; Store address of init function
+ lea R1, [R2 - NSAVES*WORDSZ] ; Store offset address of stack
+
+ mov [R1 + 8*WORDSZ], R7 ; Store context pointer
+ mov [R1 + 7*WORDSZ], R6 ; Store function pointer
+ mov [R1 + 6*WORDSZ], R0 ; Store initializer pointer
+ mov [R1 + 5*WORDSZ], R2 ; Store stack base pointer
+
+ xor R0, R0
+
+ ; Start of mutable stack
+ ; Blank out the clobbers
+ mov [R1 + 4*WORDSZ], R0 ; R3
+ mov [R1 + 3*WORDSZ], R0 ; R12
+ mov [R1 + 2*WORDSZ], R0 ; R13
+ mov [R1 + 1*WORDSZ], R0 ; R14
+ mov [R1 + 0*WORDSZ], R0 ; R15
+
+ mov [R7], R1
+ ret
+
+; Saves register state
+%macro pushclobs 0
+ push RBP
+ push R3
+ push R12
+ push R13
+ push R14
+ push R15
+%endmacro
+
+; Restores register state
+%macro popclobs 0
+ pop R15
+ pop R14
+ pop R13
+ pop R12
+ pop R3
+ pop RBP
+%endmacro
+
+; uintptr coro.yield(co *coro, data 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