; 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