Files
Z80/boot.asm
2026-08-30 19:27:08 +02:00

122 lines
2.2 KiB
NASM

STACK_TOP = 0xFFFF
; At 1 MHz the CPU has about 1000 T-states per millisecond.
; The inner delay loop below costs about 26 T-states per taken iteration:
; dec hl = 6T
; ld a,h = 4T
; or l = 4T
; jr nz = 12T
; 1000 / 26 = 38.5. Use 40 iterations to retain the previous calibration,
; which used 20 iterations at 500 kHz.
DELAY_LOOPS_PER_MS = 40
.globl _main
.globl _delay_ms
.globl _io_out
.globl _io_in
.globl s__DATA
.globl l__DATA
.globl s__INITIALIZER
.globl s__INITIALIZED
.globl l__INITIALIZER
.area _ITABLE (ABS)
.org 0x00
jp init
.org 0x08
reti
.org 0x10
reti
.org 0x18
reti
.org 0x20
reti
.org 0x28
reti
.org 0x30
reti
.org 0x38
reti
.area _HOME
init:
di
ld sp, #STACK_TOP
call gsinit
call _main
hang:
jr hang
.area _GSINIT
gsinit:
ld bc, #l__INITIALIZER
ld a, b
or c
jr z, zero_data
ld de, #s__INITIALIZED
ld hl, #s__INITIALIZER
ldir
zero_data:
ld bc, #l__DATA
ld a, b
or c
jr z, gsinit_done
ld hl, #s__DATA
xor a
clear_loop:
ld (hl), a
inc hl
dec bc
ld a, b
or c
jr nz, clear_loop
gsinit_done:
.area _GSFINAL
ret
.area _CODE
; Write a byte to an I/O port.
; Input: A = port address, L = data byte.
_io_out::
ld c, a
ld a, l
out (c), a
ret
; Read a byte from an I/O port.
; Input: A = port address.
; Return: A = data byte.
_io_in::
ld c, a
in a, (c)
ret
; Approximate millisecond delay.
; Input: HL = delay in milliseconds.
; For CLK_SPEED = 1000000 Hz this uses 40 inner iterations per ms.
_delay_ms::
ld a, h
or l
ret z
delay_ms_outer$:
push hl
ld hl, #DELAY_LOOPS_PER_MS
delay_ms_inner$:
dec hl
ld a, h
or l
jr nz, delay_ms_inner$
pop hl
dec hl
ld a, h
or l
jr nz, delay_ms_outer$
ret