aboutsummaryrefslogtreecommitdiff
path: root/sys/base/coro/unix_x64.s
blob: d7de2a24e4c1d57baa0e57bd2531a86e23cdd168 (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
111
112
113
; 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