.global couroutine._start .type couroutine._start,@function .bss .align 8 coro_state: .quad 0 caller_state: .quad 0 .macro savestate to mov %rsp,(\to) mov %rbp,8(\to) mov %r12,16(\to) mov %r13,24(\to) mov %r14,32(\to) mov %r15,40(\to) mov %rbx,48(\to) .endm .macro loadstate from mov (\from),%rsp mov 8(\from),%rbp mov 16(\from),%r12 mov 24(\from),%r13 mov 32(\from),%r14 mov 40(\from),%r15 mov 48(\from),%rbx .endm .text .global coroutine.arch_init .type couroutine.arch_init,@function coroutine.arch_init: movabs $coro_state,%rax push (%rax) mov %rsi,(%rax) movabs $caller_state,%rax push (%rax) sub $56,%rsp mov %rsp,(%rax) savestate %rsp // Initialize stack pointer to supplied stack. add %rcx,%rdx mov %rdx,%rsp mov %rdx,%rbp // rdi contains function to be called by _start. call coroutine._start .global coroutine.arch_resume .type coroutine.arch_resume,@function coroutine.arch_resume: movabs $coro_state,%rax push (%rax) mov %rdi,(%rax) movabs $caller_state,%rax push (%rax) sub $56,%rsp mov %rsp,(%rax) savestate %rsp loadstate %rdi mov %rsi,%rax ret .global coroutine.arch_suspend .type coroutine.arch_suspend,@function coroutine.arch_suspend: movabs $coro_state,%rcx mov (%rcx),%rax savestate %rax movabs $caller_state,%rdx mov (%rdx),%rax loadstate %rax // The stack pointer (and other callee-saved registers) is now set back to // the original call to arch_resume. Restore the original coro_state and // caller_state values and return the value supplied as argument. add $56,%rsp pop (%rdx) pop (%rcx) mov %rdi,%rax ret