aboutsummaryrefslogtreecommitdiff
path: root/src/coro_unix_x64.s
blob: 98710c214d5f934a0c7020eb9a2e2d67edf6304e (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
; 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 WORDS 8
%define SAVES 9 

; func sys.newCoro(co ^coro, fn func, bp ^stack)
_newcoro:
    lea     R0, [coroinit]
    lea     R1, [R2 - SAVES*WORDS]
    
    mov     [R1 + 8*WORDS], R7
    mov     [R1 + 7*WORDS], R6
    mov     [R1 + 6*WORDS], R0
    mov     [R1 + 5*WORDS], R2

    xor     R0, R0

    ; Blank out the clobbers
    mov     [R1 + 4*WORDS], R0 ; R3
    mov     [R1 + 3*WORDS], R0 ; R12
    mov     [R1 + 2*WORDS], R0 ; R13
    mov     [R1 + 1*WORDS], R0 ; R14
    mov     [R1 + 0*WORDS], R0 ; R15

    mov     [R7], R1
    ret

%macro pushclobs 0
    push     RBP
    push     R3
    push     R12
    push     R13
    push     R14
    push     R15
%endmacro

%macro popclobs 0
    pop      R15
    pop      R14
    pop      R13
    pop      R12
    pop      R3
    pop      RBP
%endmacro

; func coro.yield(co ^coro, ret 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