570 lines
10 KiB
Z80 Assembly
570 lines
10 KiB
Z80 Assembly
.global tasking_init
|
|
tasking_init:
|
|
ld bc, (next_pid)
|
|
push bc
|
|
pop de
|
|
inc de
|
|
ld (next_pid), de
|
|
push bc
|
|
call allocate_process
|
|
push bc
|
|
pop ix
|
|
pop bc
|
|
push bc
|
|
ld (ix+2), 0x3
|
|
ld (ix+3), 0xF
|
|
ld (ix+4), 0x0
|
|
ld (ix+9), c
|
|
ld (ix+10), b
|
|
push ix
|
|
pop iy
|
|
ld bc, 11
|
|
add iy, bc
|
|
ld c, 0
|
|
task_init_pmap_set_loop:
|
|
call get_frame
|
|
ld (iy+0), b
|
|
ld (iy+1), d
|
|
ld (iy+2), e
|
|
inc iy
|
|
inc iy
|
|
inc iy
|
|
inc c
|
|
cp 12
|
|
jp nz, task_init_pmap_set_loop
|
|
pop bc
|
|
jp schedule_process
|
|
|
|
.global new_process
|
|
; Creates a new process
|
|
; Entry point in HL, page mapping pointer in IY
|
|
new_process:
|
|
ld bc, (next_pid)
|
|
push bc
|
|
pop de
|
|
inc de
|
|
ld (next_pid), de
|
|
push bc
|
|
push hl
|
|
call allocate_process
|
|
pop hl
|
|
push bc
|
|
pop ix
|
|
pop bc
|
|
push bc
|
|
ld (ix+9), c
|
|
ld (ix+10), b
|
|
ld bc, 0
|
|
ld (ix+5), c
|
|
ld (ix+6), b
|
|
/* ld (ix+7), e */
|
|
/* ld (ix+8), d */
|
|
pop bc
|
|
push hl
|
|
push bc
|
|
push iy
|
|
pop hl
|
|
push ix
|
|
pop iy
|
|
ld de, 11
|
|
add iy, de
|
|
ld b, 12
|
|
new_p_pmap_set_loop:
|
|
ld a, (hl)
|
|
ld (iy+0), a
|
|
inc hl
|
|
ld a, (hl)
|
|
ld (iy+1), a
|
|
inc hl
|
|
ld a, (hl)
|
|
ld (iy+2), a
|
|
inc hl
|
|
inc iy
|
|
inc iy
|
|
inc iy
|
|
djnz new_p_pmap_set_loop
|
|
new_p_sp_set:
|
|
push ix
|
|
call get_free_frame
|
|
new_p_after_gff:
|
|
pop ix
|
|
pop de
|
|
push bc
|
|
push de
|
|
pop bc
|
|
push hl
|
|
push de
|
|
call get_process_ptr
|
|
new_p_after_gpp:
|
|
pop de
|
|
push bc
|
|
pop ix
|
|
pop hl
|
|
pop bc
|
|
ld (ix+2), c
|
|
ld (ix+3), l
|
|
ld (ix+4), h
|
|
ld (ix+0), 0xEA
|
|
ld (ix+1), 0xFF
|
|
ld b, c
|
|
ld c, 0xE
|
|
push de
|
|
push hl
|
|
pop de
|
|
push ix
|
|
call set_frame
|
|
pop ix
|
|
new_p_ep_set:
|
|
pop bc
|
|
pop hl
|
|
ld (0xEFFE), hl
|
|
; Schedules the process with the pid in BC
|
|
schedule_process:
|
|
ld hl, (ready_to_run_head)
|
|
ld a, h
|
|
cp 0
|
|
jp nz, block1
|
|
ld a, l
|
|
cp 0
|
|
jp nz, block1
|
|
jp end1
|
|
block1:
|
|
push hl
|
|
push bc
|
|
call get_process_ptr
|
|
push bc
|
|
pop ix
|
|
pop bc
|
|
pop hl
|
|
ld (ix+5), l
|
|
ld (ix+6), h
|
|
ld (ready_to_run_head), bc
|
|
ret
|
|
end1:
|
|
ld hl, (current_process)
|
|
ld a, h
|
|
cp 0
|
|
jp nz, block2
|
|
ld a, l
|
|
cp 0
|
|
jp nz, block2
|
|
jp block3
|
|
block2:
|
|
ld (ready_to_run_head), bc
|
|
ld (ready_to_run_tail), bc
|
|
ret
|
|
block3:
|
|
ld (current_process), bc
|
|
ret
|
|
|
|
.global yield
|
|
yield:
|
|
push ix
|
|
ld ix, (ready_to_run_head)
|
|
ld a, ixh
|
|
cp 0
|
|
jp nz, end3
|
|
ld a, ixl
|
|
cp 0
|
|
jp nz, end3
|
|
pop ix
|
|
ret
|
|
end3:
|
|
pop ix
|
|
; Save old process context
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
exx
|
|
ex af, af'
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
exx
|
|
ex af, af'
|
|
push ix
|
|
push iy
|
|
ld bc, (current_process)
|
|
call get_process_ptr
|
|
yield_store_pm_gpp_done:
|
|
push bc
|
|
pop ix
|
|
ld de, 11
|
|
add ix, de
|
|
call pmap_set
|
|
ld bc, (current_process)
|
|
call get_process_ptr
|
|
push bc
|
|
pop iy
|
|
ld hl, 0
|
|
add hl, sp
|
|
ld (iy+0), l
|
|
ld (iy+1), h
|
|
yield_list_manip:
|
|
; Get next process into ix, unlink it from the
|
|
; ready to run list, and link the current process in
|
|
; Logic:
|
|
; next_process = ready_to_run_head
|
|
; if (current_process == 1) {
|
|
; ready_to_run_head = 0
|
|
; ready_to_run_tail = 0
|
|
; } else {
|
|
; ready_to_run_head = ready_to_run_head->next
|
|
; current_process->next = 0
|
|
; if (ready_to_run_head==0) {
|
|
; ready_to_run_head=current_process;
|
|
; ready_to_run_tail=current_process;
|
|
; } else {
|
|
; ready_to_run_tail->next = current_process
|
|
; ready_to_run_tail = current_process;
|
|
; }
|
|
; }
|
|
; current_process = next_process
|
|
call pop_rtr_head
|
|
ld bc, (current_process)
|
|
ld a, c
|
|
cp 1
|
|
jp z, ylm_skip_link
|
|
push de
|
|
call push_rtr_tail
|
|
pop de
|
|
ylm_skip_link:
|
|
ld (current_process), de
|
|
yield_sp_page_set:
|
|
push de
|
|
pop bc
|
|
call get_process_ptr
|
|
y_sp_ps_gpp_done:
|
|
push bc
|
|
pop ix
|
|
push ix
|
|
ld de, 11
|
|
add ix, de
|
|
call pmap_load
|
|
ysps_pl_done:
|
|
pop ix
|
|
; Load next process context
|
|
ld b, (ix+2)
|
|
ld c, 0xF
|
|
ld e, (ix+3)
|
|
ld d, (ix+4)
|
|
ld iy, vmem_mapping_card
|
|
ld (iy+0xF), b
|
|
ld iy, vmem_mapping_bank_low
|
|
ld (iy+0xF), e
|
|
ld iy, vmem_mapping_bank_high
|
|
ld (iy+0xF), d
|
|
ld a, e
|
|
out (c), a
|
|
ld a, c
|
|
or 0x20
|
|
ld c, a
|
|
ld a, d
|
|
or 0x80
|
|
out (c), a
|
|
ld bc, (current_process)
|
|
call get_process_ptr
|
|
push bc
|
|
pop ix
|
|
yield_sp_load:
|
|
ld l, (ix+0)
|
|
ld h, (ix+1)
|
|
ld sp, hl
|
|
pop iy
|
|
pop ix
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
exx
|
|
ex af, af'
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
ret
|
|
|
|
;Gets the ID of the head of the ready to run list in DE and removes the element from the list
|
|
;Logic:
|
|
; bc = *ready_to_run_head;
|
|
; ix = get_process_ptr(bc);
|
|
; ready_to_run_head = ix->next;
|
|
; if (ready_to_run_head==0) {
|
|
; ready_to_run_tail=0;
|
|
; }
|
|
; return bc;
|
|
pop_rtr_head:
|
|
ld bc, (ready_to_run_head)
|
|
push bc
|
|
call get_process_ptr
|
|
pop_rh_gpp_done:
|
|
push bc
|
|
pop ix
|
|
pop de
|
|
ld l, (ix+5)
|
|
ld h, (ix+6)
|
|
ld (ready_to_run_head), hl
|
|
ld a, l
|
|
cp 0
|
|
jp nz, pop_rh_ok
|
|
ld a, h
|
|
cp 0
|
|
jp nz, pop_rh_ok
|
|
ld (ready_to_run_tail), hl
|
|
pop_rh_ok:
|
|
ret
|
|
|
|
;Pushes the process with the ID in BC onto the ready to run list
|
|
; Clobbers A, DE, HL, and IX
|
|
; Logic:
|
|
; if (*ready_to_run_tail == 0) {
|
|
; *ready_to_run_tail = bc
|
|
; *ready_to_run_head = bc
|
|
; } else {
|
|
; ix = get_process_ptr(bc);
|
|
; ix->next = 0;
|
|
; ix = get_process_ptr(*ready_to_run_tail);
|
|
; ix->next = bc;
|
|
; *ready_to_run_tail=bc;
|
|
; }
|
|
push_rtr_tail:
|
|
ld hl, (ready_to_run_tail)
|
|
ld a, l
|
|
cp 0
|
|
jp nz, push_rtr_tail_nz
|
|
ld a, h
|
|
cp 0
|
|
jp nz, push_rtr_tail_nz
|
|
ld (ready_to_run_head), bc
|
|
ld (ready_to_run_tail), bc
|
|
ret
|
|
push_rtr_tail_nz:
|
|
push bc
|
|
call get_process_ptr
|
|
push_rtr_gpp_done:
|
|
push bc
|
|
pop ix
|
|
ld (ix+5), 0
|
|
ld (ix+6), 0
|
|
ld bc, (ready_to_run_tail)
|
|
call get_process_ptr
|
|
push_rtr_gpp2_done:
|
|
push bc
|
|
pop ix
|
|
pop bc
|
|
ld (ix+5), c
|
|
ld (ix+6), b
|
|
ld (ready_to_run_tail), bc
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
ready_to_run_head: .ds.b 2
|
|
ready_to_run_tail: .ds.b 2
|
|
current_process: .ds.b 2
|
|
next_pid: .dc.w 1
|
|
process_allocation_bitmap: .ds.b 128
|
|
process_heap_pages: .ds.b 48
|
|
|
|
; Given a pid BC, return the pointer to the process or 0 if it's nonexistent, mapping the right page in if necessary
|
|
; Clobbers A, BC, DE, HL, and IX
|
|
get_process_ptr:
|
|
push bc
|
|
ld a, c
|
|
and 0x7
|
|
sla a
|
|
sla a
|
|
sla a
|
|
or 0xC7
|
|
ld (set_ins+1), a
|
|
; Shift bc right 3 times to get the byte number in c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
ld hl, process_allocation_bitmap
|
|
add hl, bc
|
|
ld a, (hl)
|
|
set_ins: set 0, a
|
|
ld (hl), a
|
|
pop bc
|
|
push bc
|
|
; Shift bc right 6 times to get the page number in c
|
|
push bc
|
|
pop hl
|
|
xor a
|
|
add hl, hl
|
|
rla
|
|
add hl, hl
|
|
rla
|
|
ld l, h
|
|
ld h, a
|
|
push hl
|
|
pop bc
|
|
; Multiply the page number by 3 to get the start offset in the table
|
|
add hl, bc
|
|
add hl, bc
|
|
push hl
|
|
pop bc
|
|
ld hl, process_heap_pages
|
|
add hl, bc
|
|
ld a, (hl)
|
|
cp 0
|
|
jp z, not_allocated
|
|
ld c, 0xE
|
|
ld b, (hl)
|
|
inc hl
|
|
ld e, (hl)
|
|
inc hl
|
|
ld d, (hl)
|
|
call set_frame
|
|
pop bc
|
|
ld a, c
|
|
and 0x3F
|
|
ld c, a
|
|
ld b, 0
|
|
; Shift BC right 6 bits (BC=BC*64)
|
|
push bc
|
|
pop hl
|
|
xor a
|
|
srl h
|
|
rr l
|
|
rra
|
|
srl h
|
|
rr l
|
|
rra
|
|
ld h, l
|
|
ld l, a
|
|
push hl
|
|
pop bc
|
|
ld a, b
|
|
add a, 0xE0
|
|
ld b, a
|
|
ret
|
|
not_allocated:
|
|
pop bc
|
|
ld bc, 0
|
|
ret
|
|
|
|
|
|
; Given a pid BC, allocate the space for that process and return a pointer to it in BC
|
|
; Clobbers A, DE, HL, and IX
|
|
allocate_process:
|
|
push bc
|
|
ld a, c
|
|
and 0x7
|
|
sla a
|
|
sla a
|
|
sla a
|
|
or 0xC7
|
|
ld (set_ins_2+1), a
|
|
; Shift bc right 3 times to get the byte number in c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
ld hl, process_allocation_bitmap
|
|
add hl, bc
|
|
ld a, (hl)
|
|
set_ins_2: set 0, a
|
|
ld (hl), a
|
|
pop bc
|
|
push bc
|
|
; Shift bc right 6 times to get the page number in c
|
|
push bc
|
|
pop hl
|
|
xor a
|
|
add hl, hl
|
|
rla
|
|
add hl, hl
|
|
rla
|
|
ld l, h
|
|
ld h, a
|
|
push hl
|
|
pop bc
|
|
; Multiply the page number by 3 to get the start offset in the table
|
|
add hl, bc
|
|
add hl, bc
|
|
push hl
|
|
pop bc
|
|
ld hl, process_heap_pages
|
|
add hl, bc
|
|
ld a, (hl)
|
|
cp 0
|
|
jp nz, return_ptr
|
|
push hl
|
|
call get_free_frame
|
|
pop de
|
|
ld a, c
|
|
ld (de), a
|
|
inc de
|
|
ld a, l
|
|
ld (de), a
|
|
inc de
|
|
ld a, h
|
|
ld (de), a
|
|
dec de
|
|
dec de
|
|
push de
|
|
pop hl
|
|
return_ptr:
|
|
ld c, 0xE
|
|
ld b, (hl)
|
|
inc hl
|
|
ld e, (hl)
|
|
inc hl
|
|
ld d, (hl)
|
|
call set_frame
|
|
pop bc
|
|
ld a, c
|
|
and 0x3F
|
|
ld c, a
|
|
ld b, 0
|
|
; Shift BC left 6 bits (BC=BC*64)
|
|
xor a
|
|
srl b
|
|
rr c
|
|
rra
|
|
srl b
|
|
rr c
|
|
rra
|
|
ld b, c
|
|
ld c, a
|
|
ld a, b
|
|
add a, 0xE0
|
|
ld b, a
|
|
ret
|
|
|
|
; Given a pid in BC, free the processes memory
|
|
; Clobber A, BC, and HL
|
|
free_process:
|
|
ld a, c
|
|
and 0x7
|
|
sla a
|
|
sla a
|
|
sla a
|
|
or 0x87
|
|
ld (res_ins+1), a
|
|
; Shift bc right 3 times to get the byte number in c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
ld hl, process_allocation_bitmap
|
|
add hl, bc
|
|
ld a, (hl)
|
|
res_ins: res 0, a
|
|
ld (hl), a
|
|
ret
|
|
|