summaryrefslogtreecommitdiff
path: root/coroutine/+x86_64.s
blob: aaa69e0408033cdf3badcb8294d8eaab269824ac (plain)
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