1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
.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
|