aboutsummaryrefslogtreecommitdiffstats
path: root/src/proc.asm
blob: 762b30e3acdfd871136894210954f99025282bae (plain) (blame)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
; =============================================================================
; proc.asm - process table management, task creation, fork/exec (stubs)
; =============================================================================
INCLUDE "include/gbos.inc"

SECTION "proc", ROM0

; -----------------------------------------------------------------------------
; ProcInit - table already zeroed by ClearKernelRAM (PS_FREE=0). Seed pids.
; -----------------------------------------------------------------------------
ProcInit::
    ld a, 1
    ld [wNextPid], a
    ret

; -----------------------------------------------------------------------------
; PcbPtr - slot -> PCB pointer.  in: A=slot  out: DE=&PCB.  preserves BC.
; -----------------------------------------------------------------------------
PcbPtr::
    push bc
    ld hl, wProcTable
    ld bc, PROC_SIZE
    and a
    jr z, .done
.mul
    add hl, bc
    dec a
    jr nz, .mul
.done
    ld d, h
    ld e, l
    pop bc
    ret

; -----------------------------------------------------------------------------
; ProcCreate - allocate a PCB and build an initial (runnable) task.
;   in:  HL = task entry, B = cart-RAM bank, C = SVBK u-area bank
;   out: A  = pid, or 0 if the table is full
; -----------------------------------------------------------------------------
ProcCreate::
    ; stash params
    ld a, l
    ld [wTmpEntry], a
    ld a, h
    ld [wTmpEntry+1], a
    ld a, b
    ld [wTmpRamB], a
    ld a, c
    ld [wTmpWramB], a

    ; find a free slot
    ld c, 0
.find
    ld a, c
    call PcbPtr                 ; DE = &PCB[c]
    ld a, [de]
    cp PS_FREE
    jr z, .found
    inc c
    ld a, c
    cp MAX_PROCS
    jr c, .find
    xor a                       ; table full
    ret

.found
    ld a, c
    ld [wTmpSlot], a

    ; fill fields; HL walks the PCB
    ld h, d
    ld l, e
    ld a, PS_READY
    ld [hl+], a                 ; PROC_STATE
    ld a, [wNextPid]
    ld [hl+], a                 ; PROC_PID
    ld [wTmpPid], a
    inc a
    ld [wNextPid], a
    inc hl                      ; skip PROC_SP (filled below)
    inc hl
    ld a, 1
    ld [hl+], a                 ; PROC_ROMB lo (placeholder text bank)
    xor a
    ld [hl+], a                 ; PROC_ROMB hi
    ld a, [wTmpRamB]
    ld [hl+], a                 ; PROC_RAMB
    ld a, [wTmpWramB]
    ld [hl+], a                 ; PROC_WRAMB
    xor a
    ld [hl+], a                 ; PROC_PARENT
    ld [hl], a                  ; PROC_EXIT

    ; build the initial stack frame in the task's RAM bank
    ld a, [wTmpEntry]
    ld l, a
    ld a, [wTmpEntry+1]
    ld h, a                     ; HL = entry
    ld a, [wTmpRamB]
    ld b, a                     ; B = RAM bank
    call ProcSetupStack         ; out: HL = initial SP
    ld a, l
    ld [wTmpSP], a
    ld a, h
    ld [wTmpSP+1], a

    ; store SP into PCB.PROC_SP
    ld a, [wTmpSlot]
    call PcbPtr                 ; DE = &PCB
    ld a, e
    add PROC_SP
    ld l, a
    ld a, d
    adc 0
    ld h, a                     ; HL = &PROC_SP
    ld a, [wTmpSP]
    ld [hl+], a
    ld a, [wTmpSP+1]
    ld [hl], a

    ld a, [wTmpPid]
    ret

; -----------------------------------------------------------------------------
; ProcSetupStack - lay a fresh switch-in frame at the top of a task RAM bank.
;   in:  HL = entry, B = cart-RAM bank
;   out: HL = initial SP (points at the saved-HL slot)
; The frame matches hSwitchTo's restore sequence:
;   [SP+0..1]=hl [+2..3]=de [+4..5]=bc [+6]=f [+7]=a [+8..9]=entry (ret target)
; -----------------------------------------------------------------------------
ProcSetupStack::
    ld a, b
    ld [MBC5_RAMB], a           ; map task's RAM bank into $A000-$BFFF
    push hl                     ; save entry
    ld hl, TASK_STACK_TOP - 9   ; frame base = $BFF6
    xor a
    ld [hl+], a                 ; hl_lo
    ld [hl+], a                 ; hl_hi
    ld [hl+], a                 ; de_lo
    ld [hl+], a                 ; de_hi
    ld [hl+], a                 ; bc_lo
    ld [hl+], a                 ; bc_hi
    ld [hl+], a                 ; f
    ld [hl+], a                 ; a
    pop de                      ; DE = entry
    ld a, e
    ld [hl+], a                 ; entry lo (ret target)
    ld a, d
    ld [hl], a                  ; entry hi
    ld hl, TASK_STACK_TOP - 9   ; initial SP
    ret

; -----------------------------------------------------------------------------
; sys_fork / sys_exec - TODO. Plan:
;   fork: alloc slot, copy parent's 8 KiB RAM bank -> child bank, dup u-area,
;         patch child's saved-A to 0 (child return), parent gets child pid.
;   exec: point PROC_ROMB at a flashed program image, reset RAM-bank layout
;         (copy .data from ROM, zero .bss, fresh heap/stack), longjmp in.
; -----------------------------------------------------------------------------