Compare commits

..

No commits in common. "95344d73cbf621430f925c99cb76cf7879d0fa4a" and "a4761efed289c4b33829cdf4ec15689395cee8fa" have entirely different histories.

6 changed files with 1491 additions and 1669 deletions

2
.gitignore vendored
View file

@ -11,6 +11,6 @@
*.srec *.srec
*.s19 *.s19
*.elf *.elf
*.map
AGENTS.md AGENTS.md
.pre-commit-config.yaml .pre-commit-config.yaml

View file

@ -2,16 +2,12 @@
# SPDX-FileCopyrightText: (c) 2025 A.M. Rowsell # SPDX-FileCopyrightText: (c) 2025 A.M. Rowsell
ASM=vasm_z80_std ASM=vasm_z80_std
LINK=vlink LINK=vlink
MAP=zone.map
ASMFLAGS=-Fvobj ASMFLAGS=-Fvobj
LINKFLAGS=-b ihex -T linker.cmd -M LINKFLAGS=-b ihex -T linker.cmd
BINLINKFLAGS=-b rawbin -T linker.cmd -M
all: zone.hex all: zone.hex
binary: zone.bin
float.o: float.asm float.o: float.asm
$(ASM) $(ASMFLAGS) -o $@ $< $(ASM) $(ASMFLAGS) -o $@ $<
@ -25,12 +21,9 @@ boot.o: boot.asm
$(ASM) $(ASMFLAGS) -o $@ $< $(ASM) $(ASMFLAGS) -o $@ $<
zone.hex: float.o vectorTable.o zone.o boot.o linker.cmd zone.hex: float.o vectorTable.o zone.o boot.o linker.cmd
$(LINK) $(LINKFLAGS) -o $@ float.o vectorTable.o zone.o boot.o > $(MAP) $(LINK) $(LINKFLAGS) -o $@ float.o vectorTable.o zone.o boot.o
zone.bin: float.o vectorTable.o zone.o boot.o linker.cmd
$(LINK) $(BINLINKFLAGS) -o $@ float.o vectorTable.o zone.o boot.o > $(MAP)
clean: clean:
rm -f float.o vectorTable.o zone.o boot.o zone.hex zone.bin $(MAP) rm -f float.o vectorTable.o zone.o boot.o zone.hex
.PHONY: all clean .PHONY: all clean

View file

@ -5,14 +5,7 @@
.global os_warm_boot .global os_warm_boot
.extern os_main_loop .extern os_main_loop
; ==================================
; This is the cold boot entry point!
; It is linked to land at 0xC3C3
; ==================================
_start:
zone_setup: zone_setup:
ld a, ixl
ld sp, 0x6FFF ld sp, 0x6FFF
jp os_main_loop jp os_main_loop

175
float.asm
View file

@ -8,11 +8,11 @@
; byte1: S|F22..F16 (bit7 = sign, bits6..0 = top 7 fraction bits) ; byte1: S|F22..F16 (bit7 = sign, bits6..0 = top 7 fraction bits)
; byte2: F15..F8 ; byte2: F15..F8
; byte3: F7..F0 ; byte3: F7..F0
;
; For EXP != 0: ; For EXP != 0:
; value = (-1)^S * (1.F) * 2^(EXP - FP_BIAS) ; value = (-1)^S * (1.F) * 2^(EXP - FP_BIAS)
; FP_BIAS = 127 ; FP_BIAS = 127
;
; Calling convention (in-place ops): ; Calling convention (in-place ops):
; HL -> A (4 bytes) ; HL -> A (4 bytes)
; DE -> B (4 bytes) ; DE -> B (4 bytes)
@ -20,11 +20,11 @@
; fp_sub: A = A - B ; fp_sub: A = A - B
; fp_mul: A = A * B ; fp_mul: A = A * B
; fp_div: A = A / B ; fp_div: A = A / B
;
; Extra: ; Extra:
; fp_print: print float at (HL) using external os_print_vec (A=ASCII) ; fp_print: print float at (HL) using external os_print_vec (A=ASCII)
; fp_parse: parse null-terminated string at (DE) into float at (HL) ; fp_parse: parse null-terminated string at (DE) into float at (HL)
;
; Limitations: ; Limitations:
; - No NaN/Inf/denormals ; - No NaN/Inf/denormals
; - Truncation (no rounding) ; - Truncation (no rounding)
@ -40,7 +40,7 @@
; ============================================================ ; ============================================================
; CODE ; CODE
; ============================================================ ; ============================================================
.section "zone", "acrx" .section "float","acrx"
; ------------------------------------------------------------ ; ------------------------------------------------------------
; External routine you provide: ; External routine you provide:
; os_print_vec: prints ASCII character in A ; os_print_vec: prints ASCII character in A
@ -54,7 +54,6 @@
; ------------------------------------------------------------ ; ------------------------------------------------------------
; fp_add: A = A + B ; fp_add: A = A + B
; ------------------------------------------------------------ ; ------------------------------------------------------------
fp_add: fp_add:
push hl push hl
push de push de
@ -70,7 +69,6 @@ fp_add:
; A==0 => result=B ; A==0 => result=B
call fp_pack_from_B_into_A call fp_pack_from_B_into_A
ret ret
fp_add_checkB: fp_add_checkB:
ld a,(B_exp) ld a,(B_exp)
or a or a
@ -86,10 +84,10 @@ fp_add_checkB:
; signs differ -> magnitude subtract ; signs differ -> magnitude subtract
jp fp_add_diff_sign jp fp_add_diff_sign
; ------------------------------------------------------------ ; ------------------------------------------------------------
; fp_sub: A = A - B (flip B sign in memory, add, flip back) ; fp_sub: A = A - B (flip B sign in memory, add, flip back)
; ------------------------------------------------------------ ; ------------------------------------------------------------
fp_sub: fp_sub:
; Flip sign bit of B byte1 (DE+1) ; Flip sign bit of B byte1 (DE+1)
push hl push hl
@ -114,10 +112,10 @@ fp_sub:
pop hl pop hl
ret ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; fp_mul: A = A * B ; fp_mul: A = A * B
; ------------------------------------------------------------ ; ------------------------------------------------------------
fp_mul: fp_mul:
push hl push hl
push de push de
@ -159,10 +157,10 @@ fp_mul:
call fp_packA call fp_packA
ret ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; fp_div: A = A / B ; fp_div: A = A / B
; ------------------------------------------------------------ ; ------------------------------------------------------------
fp_div: fp_div:
push hl push hl
push de push de
@ -205,6 +203,7 @@ fp_div:
call fp_packA call fp_packA
ret ret
; ============================================================ ; ============================================================
; Add/Sub core (unpacked) ; Add/Sub core (unpacked)
; ============================================================ ; ============================================================
@ -219,19 +218,18 @@ fp_add_same_sign:
ld a,(A_exp) ld a,(A_exp)
inc a inc a
ld (A_exp),a ld (A_exp),a
fp_add_same_sign_noCarry: fp_add_same_sign_noCarry:
call normalize_A_mant call normalize_A_mant
call fp_packA call fp_packA
ret ret
fp_add_diff_sign: fp_add_diff_sign:
; compare |A| vs |B|, do larger - smaller, sign = sign(larger) ; compare |A| vs |B|, do larger - smaller, sign = sign(larger)
call compare_mag_A_B call compare_mag_A_B
jr c,fp_add_diff_sign_A_ge_B jr c,fp_add_diff_sign_A_ge_B
; |B| > |A| => swap ; |B| > |A| => swap
call swap_A_B_unpacked call swap_A_B_unpacked
fp_add_diff_sign_A_ge_B: fp_add_diff_sign_A_ge_B:
call align_exponents_A_B call align_exponents_A_B
call sub24_A_minus_B call sub24_A_minus_B
@ -241,12 +239,12 @@ fp_add_diff_sign_A_ge_B:
call fp_packA call fp_packA
ret ret
; ============================================================ ; ============================================================
; Unpack / Pack helpers ; Unpack / Pack helpers
; ============================================================ ; ============================================================
; Unpack A from (HL) ; Unpack A from (HL)
fp_unpackA: fp_unpackA:
ld a,(hl) ld a,(hl)
ld (A_exp),a ld (A_exp),a
@ -260,10 +258,8 @@ fp_unpackA:
jp z,fp_unpackA_sa0 jp z,fp_unpackA_sa0
ld a,1 ld a,1
jr fp_unpackA_sa1 jr fp_unpackA_sa1
fp_unpackA_sa0: fp_unpackA_sa0:
xor a xor a
fp_unpackA_sa1: fp_unpackA_sa1:
ld (A_sign),a ld (A_sign),a
@ -279,7 +275,6 @@ fp_unpackA_sa1:
ld a,(hl) ld a,(hl)
ld (A_m0),a ld (A_m0),a
ret ret
fp_unpackA_zeroA: fp_unpackA_zeroA:
xor a xor a
ld (A_sign),a ld (A_sign),a
@ -288,8 +283,8 @@ fp_unpackA_zeroA:
ld (A_m0),a ld (A_m0),a
ret ret
; Unpack B from (DE)
; Unpack B from (DE)
fp_unpackB: fp_unpackB:
ld a,(de) ld a,(de)
ld (B_exp),a ld (B_exp),a
@ -302,10 +297,8 @@ fp_unpackB:
jp z,fp_unpackB_sb0 jp z,fp_unpackB_sb0
ld a,1 ld a,1
jr fp_unpackB_sb1 jr fp_unpackB_sb1
fp_unpackB_sb0: fp_unpackB_sb0:
xor a xor a
fp_unpackB_sb1: fp_unpackB_sb1:
ld (B_sign),a ld (B_sign),a
@ -320,7 +313,6 @@ fp_unpackB_sb1:
ld a,(de) ld a,(de)
ld (B_m0),a ld (B_m0),a
ret ret
fp_unpackB_zeroB: fp_unpackB_zeroB:
xor a xor a
ld (B_sign),a ld (B_sign),a
@ -329,8 +321,8 @@ fp_unpackB_zeroB:
ld (B_m0),a ld (B_m0),a
ret ret
; Pack unpacked A back into memory at (HL)
; Pack unpacked A back into memory at (HL)
fp_packA: fp_packA:
ld a,(A_exp) ld a,(A_exp)
or a or a
@ -362,10 +354,8 @@ fp_packA_packNZ:
ld a,b ld a,b
or 0x80 or 0x80
jr fp_packA_storeB1 jr fp_packA_storeB1
fp_packA_sign0: fp_packA_sign0:
ld a,b ld a,b
fp_packA_storeB1: fp_packA_storeB1:
ld (hl),a ld (hl),a
inc hl inc hl
@ -376,8 +366,8 @@ fp_packA_storeB1:
ld (hl),a ld (hl),a
ret ret
; Pack from unpacked B into memory A (HL points to A destination)
; Pack from unpacked B into memory A (HL points to A destination)
fp_pack_from_B_into_A: fp_pack_from_B_into_A:
ld a,(B_exp) ld a,(B_exp)
ld (hl),a ld (hl),a
@ -391,10 +381,8 @@ fp_pack_from_B_into_A:
ld a,b ld a,b
or 0x80 or 0x80
jr fp_pack_from_B_bs1 jr fp_pack_from_B_bs1
fp_pack_from_B_bs0: fp_pack_from_B_bs0:
ld a,b ld a,b
fp_pack_from_B_bs1: fp_pack_from_B_bs1:
ld (hl),a ld (hl),a
inc hl inc hl
@ -405,6 +393,7 @@ fp_pack_from_B_bs1:
ld (hl),a ld (hl),a
ret ret
fp_store_zero_A: fp_store_zero_A:
xor a xor a
ld (A_exp),a ld (A_exp),a
@ -414,12 +403,12 @@ fp_store_zero_A:
ld (A_m0),a ld (A_m0),a
jp fp_packA jp fp_packA
; ============================================================ ; ============================================================
; Exponent alignment / compare / swap ; Exponent alignment / compare / swap
; ============================================================ ; ============================================================
; Ensure A_exp >= B_exp; shift smaller mantissa right by diff ; Ensure A_exp >= B_exp; shift smaller mantissa right by diff
align_exponents_A_B: align_exponents_A_B:
ld a,(A_exp) ld a,(A_exp)
ld b,a ld b,a
@ -428,7 +417,6 @@ align_exponents_A_B:
jr z,align_exponents_A_B_done jr z,align_exponents_A_B_done
jr c,align_exponents_A_B_bigger_exp ; B_exp < A_exp jr c,align_exponents_A_B_bigger_exp ; B_exp < A_exp
call swap_A_B_unpacked ; make A the larger exponent call swap_A_B_unpacked ; make A the larger exponent
align_exponents_A_B_bigger_exp: align_exponents_A_B_bigger_exp:
ld a,(A_exp) ld a,(A_exp)
ld b,a ld b,a
@ -439,12 +427,11 @@ align_exponents_A_B_bigger_exp:
call shr24_B_by_A call shr24_B_by_A
ld a,(A_exp) ld a,(A_exp)
ld (B_exp),a ld (B_exp),a
align_exponents_A_B_done: align_exponents_A_B_done:
ret ret
; Carry set if |A| >= |B|, else carry clear
; Carry set if |A| >= |B|, else carry clear
compare_mag_A_B: compare_mag_A_B:
ld a,(A_exp) ld a,(A_exp)
ld b,a ld b,a
@ -454,11 +441,9 @@ compare_mag_A_B:
jr c,compare_mag_A_B_ge jr c,compare_mag_A_B_ge
or a or a
ret ret
compare_mag_A_B_ge: compare_mag_A_B_ge:
scf scf
ret ret
compare_mag_A_B_cmpMant: compare_mag_A_B_cmpMant:
ld a,(A_m2) ld a,(A_m2)
ld b,a ld b,a
@ -468,11 +453,9 @@ compare_mag_A_B_cmpMant:
jr c,compare_mag_A_B_ge2 jr c,compare_mag_A_B_ge2
or a or a
ret ret
compare_mag_A_B_ge2: compare_mag_A_B_ge2:
scf scf
ret ret
compare_mag_A_B_m1: compare_mag_A_B_m1:
ld a,(A_m1) ld a,(A_m1)
ld b,a ld b,a
@ -482,11 +465,9 @@ compare_mag_A_B_m1:
jr c,compare_mag_A_B_ge3 jr c,compare_mag_A_B_ge3
or a or a
ret ret
compare_mag_A_B_ge3: compare_mag_A_B_ge3:
scf scf
ret ret
compare_mag_A_B_m0: compare_mag_A_B_m0:
ld a,(A_m0) ld a,(A_m0)
ld b,a ld b,a
@ -495,11 +476,11 @@ compare_mag_A_B_m0:
jr c,compare_mag_A_B_ge4 jr c,compare_mag_A_B_ge4
scf scf
ret ret
compare_mag_A_B_ge4: compare_mag_A_B_ge4:
scf scf
ret ret
swap_A_B_unpacked: swap_A_B_unpacked:
ld a,(A_exp) ld a,(A_exp)
ld b,a ld b,a
@ -533,6 +514,7 @@ swap_A_B_unpacked:
ld (B_m0),a ld (B_m0),a
ret ret
; ============================================================ ; ============================================================
; 24-bit mantissa ops ; 24-bit mantissa ops
; ============================================================ ; ============================================================
@ -555,6 +537,7 @@ add24_A_plus_B:
ld (A_m2),a ld (A_m2),a
ret ; carry meaningful ret ; carry meaningful
sub24_A_minus_B: sub24_A_minus_B:
ld a,(B_m0) ld a,(B_m0)
ld b,a ld b,a
@ -573,6 +556,7 @@ sub24_A_minus_B:
ld (A_m2),a ld (A_m2),a
ret ret
is_A_mant_zero: is_A_mant_zero:
ld a,(A_m2) ld a,(A_m2)
ld b,a ld b,a
@ -583,6 +567,7 @@ is_A_mant_zero:
or b or b
ret ret
shr24_A_1: shr24_A_1:
ld a,(A_m2) ld a,(A_m2)
srl a srl a
@ -595,6 +580,7 @@ shr24_A_1:
ld (A_m0),a ld (A_m0),a
ret ret
shl24_A_1: shl24_A_1:
ld a,(A_m0) ld a,(A_m0)
add a,a add a,a
@ -607,8 +593,8 @@ shl24_A_1:
ld (A_m2),a ld (A_m2),a
ret ret
; Shift B mantissa right by A bits (A=0..255)
; Shift B mantissa right by A bits (A=0..255)
shr24_B_by_A: shr24_B_by_A:
ld (SHCNT),a ld (SHCNT),a
ld a,(SHCNT) ld a,(SHCNT)
@ -619,12 +605,10 @@ shr24_B_by_A:
ld (B_m1),a ld (B_m1),a
ld (B_m0),a ld (B_m0),a
ret ret
shr24_B_by_A_ok: shr24_B_by_A_ok:
ld a,(SHCNT) ld a,(SHCNT)
or a or a
ret z ret z
shr24_B_by_A_loop: shr24_B_by_A_loop:
ld a,(B_m2) ld a,(B_m2)
srl a srl a
@ -641,18 +625,17 @@ shr24_B_by_A_loop:
jr nz,shr24_B_by_A_loop jr nz,shr24_B_by_A_loop
ret ret
normalize_A_mant: normalize_A_mant:
call is_A_mant_zero call is_A_mant_zero
jr nz,normalize_A_mant_nz jr nz,normalize_A_mant_nz
xor a xor a
ld (A_exp),a ld (A_exp),a
ret ret
normalize_A_mant_nz: normalize_A_mant_nz:
ld a,(A_m2) ld a,(A_m2)
bit 7,a bit 7,a
ret nz ret nz
normalize_A_mant_left_loop: normalize_A_mant_left_loop:
ld a,(A_m0) ld a,(A_m0)
add a,a add a,a
@ -671,33 +654,31 @@ normalize_A_mant_left_loop:
jr z,normalize_A_mant_left_loop jr z,normalize_A_mant_left_loop
ret ret
; ============================================================ ; ============================================================
; 8x8 -> 16 multiply (unsigned), shift-add ; 8x8 -> 16 multiply (unsigned), shift-add
; in: A = multiplicand, C = multiplier ; in: A = multiplicand, C = multiplier
; out: HL = 16-bit product ; out: HL = 16-bit product
; ============================================================ ; ============================================================
mul8u: mul8u:
ld h,0 ld h,0
ld l,0 ld l,0
ld b,8 ld b,8
mul8u_m8: mul8u_m8:
srl c srl c
jr nc,mul8u_noadd jr nc,mul8u_noadd
ld e,a ld e,a
ld d,0 ld d,0
add hl,de add hl,de
mul8u_noadd: mul8u_noadd:
add a,a add a,a
djnz mul8u_m8 djnz mul8u_m8
ret ret
; ============================================================ ; ============================================================
; 24x24 schoolbook multiply into P0..P5 (P0 LSB) ; 24x24 schoolbook multiply into P0..P5 (P0 LSB)
; ============================================================ ; ============================================================
mul24x24_schoolbook: mul24x24_schoolbook:
xor a xor a
ld (P0),a ld (P0),a
@ -772,6 +753,7 @@ mul24x24_schoolbook:
ret ret
add16_to_P_at0: add16_to_P_at0:
ld a,(P0) ld a,(P0)
add a,l add a,l
@ -780,7 +762,6 @@ add16_to_P_at0:
adc a,h adc a,h
ld (P1),a ld (P1),a
ret ret
add16_to_P_at1: add16_to_P_at1:
ld a,(P1) ld a,(P1)
add a,l add a,l
@ -789,7 +770,6 @@ add16_to_P_at1:
adc a,h adc a,h
ld (P2),a ld (P2),a
ret ret
add16_to_P_at2: add16_to_P_at2:
ld a,(P2) ld a,(P2)
add a,l add a,l
@ -798,7 +778,6 @@ add16_to_P_at2:
adc a,h adc a,h
ld (P3),a ld (P3),a
ret ret
add16_to_P_at3: add16_to_P_at3:
ld a,(P3) ld a,(P3)
add a,l add a,l
@ -807,7 +786,6 @@ add16_to_P_at3:
adc a,h adc a,h
ld (P4),a ld (P4),a
ret ret
add16_to_P_at4: add16_to_P_at4:
ld a,(P4) ld a,(P4)
add a,l add a,l
@ -817,11 +795,11 @@ add16_to_P_at4:
ld (P5),a ld (P5),a
ret ret
; ============================================================ ; ============================================================
; Normalize product P into A mantissa ; Normalize product P into A mantissa
; P is 48-bit, P0 LSB .. P5 MSB ; P is 48-bit, P0 LSB .. P5 MSB
; ============================================================ ; ============================================================
norm_product_to_A: norm_product_to_A:
ld a,(P5) ld a,(P5)
bit 7,a bit 7,a
@ -832,11 +810,9 @@ norm_product_to_A:
inc a inc a
ld (A_exp),a ld (A_exp),a
jr norm_product_take jr norm_product_take
norm_product_shift23: norm_product_shift23:
ld a,23 ld a,23
call shr48_P_by_A call shr48_P_by_A
norm_product_take: norm_product_take:
ld a,(P2) ld a,(P2)
ld (A_m2),a ld (A_m2),a
@ -846,12 +822,12 @@ norm_product_take:
ld (A_m0),a ld (A_m0),a
ret ret
shr48_P_by_A: shr48_P_by_A:
ld (SHCNT),a ld (SHCNT),a
ld a,(SHCNT) ld a,(SHCNT)
or a or a
ret z ret z
shr48_P_by_A_loop: shr48_P_by_A_loop:
ld a,(P5) ld a,(P5)
srl a srl a
@ -877,11 +853,11 @@ shr48_P_by_A_loop:
jr nz,shr48_P_by_A_loop jr nz,shr48_P_by_A_loop
ret ret
; ============================================================ ; ============================================================
; Mantissa division (restoring-style) ; Mantissa division (restoring-style)
; A_m = (A_m << 23) / B_m ; A_m = (A_m << 23) / B_m
; ============================================================ ; ============================================================
div_mantissas_to_A: div_mantissas_to_A:
; P = A_m as 48-bit, then shift left 23 ; P = A_m as 48-bit, then shift left 23
xor a xor a
@ -905,7 +881,6 @@ div_mantissas_to_A:
ld (A_m0),a ld (A_m0),a
ld b,24 ld b,24
div_mantissas_loop: div_mantissas_loop:
call shl24_A_1 call shl24_A_1
call shl48_P_1 call shl48_P_1
@ -918,20 +893,18 @@ div_mantissas_loop:
or 0x1 or 0x1
ld (A_m0),a ld (A_m0),a
jr div_mantissas_next jr div_mantissas_next
div_mantissas_restore: div_mantissas_restore:
call add24_Phigh_plus_B call add24_Phigh_plus_B
div_mantissas_next: div_mantissas_next:
djnz div_mantissas_loop djnz div_mantissas_loop
ret ret
shl48_P_by_A: shl48_P_by_A:
ld (SHCNT),a ld (SHCNT),a
ld a,(SHCNT) ld a,(SHCNT)
or a or a
ret z ret z
shl48_P_by_A_loop: shl48_P_by_A_loop:
call shl48_P_1 call shl48_P_1
ld a,(SHCNT) ld a,(SHCNT)
@ -940,6 +913,7 @@ shl48_P_by_A_loop:
jr nz,shl48_P_by_A_loop jr nz,shl48_P_by_A_loop
ret ret
shl48_P_1: shl48_P_1:
ld a,(P0) ld a,(P0)
add a,a add a,a
@ -961,6 +935,7 @@ shl48_P_1:
ld (P5),a ld (P5),a
ret ret
sub24_Phigh_minus_B: sub24_Phigh_minus_B:
ld a,(B_m0) ld a,(B_m0)
ld b,a ld b,a
@ -979,6 +954,7 @@ sub24_Phigh_minus_B:
ld (P5),a ld (P5),a
ret ; carry set indicates borrow ret ; carry set indicates borrow
add24_Phigh_plus_B: add24_Phigh_plus_B:
ld a,(B_m0) ld a,(B_m0)
ld b,a ld b,a
@ -997,12 +973,12 @@ add24_Phigh_plus_B:
ld (P5),a ld (P5),a
ret ret
; ============================================================ ; ============================================================
; fp_print: fixed format printing ; fp_print: fixed format printing
; Prints: [-]I.FFFFFF (FRAC_DIGITS digits) ; Prints: [-]I.FFFFFF (FRAC_DIGITS digits)
; Uses os_print_vec (A=char) ; Uses os_print_vec (A=char)
; ============================================================ ; ============================================================
fp_print: fp_print:
; zero? ; zero?
ld a,(hl) ld a,(hl)
@ -1013,7 +989,6 @@ fp_print:
ld a,'.' ld a,'.'
call os_print_vec call os_print_vec
ld b,FRAC_DIGITS ld b,FRAC_DIGITS
fp_print_zf: fp_print_zf:
ld a,'0' ld a,'0'
call os_print_vec call os_print_vec
@ -1034,10 +1009,8 @@ fp_print_nz:
jp z,fp_print_ps0 jp z,fp_print_ps0
ld a,1 ld a,1
jr fp_print_ps1 jr fp_print_ps1
fp_print_ps0: fp_print_ps0:
xor a xor a
fp_print_ps1: fp_print_ps1:
ld (PR_SIGN),a ld (PR_SIGN),a
@ -1059,7 +1032,6 @@ fp_print_ps1:
jp z,fp_print_mag jp z,fp_print_mag
ld a,'-' ld a,'-'
call os_print_vec call os_print_vec
fp_print_mag: fp_print_mag:
; S = (E - 23) ; S = (E - 23)
ld a,(PR_E) ld a,(PR_E)
@ -1097,7 +1069,6 @@ fp_print_S_nonneg:
cp 32 cp 32
jr c,fp_print_doShl jr c,fp_print_doShl
ld a,31 ld a,31
fp_print_doShl: fp_print_doShl:
ld b,a ld b,a
ld a,(PR_M0) ld a,(PR_M0)
@ -1115,7 +1086,6 @@ fp_print_print_int_and_frac:
ld a,'.' ld a,'.'
call os_print_vec call os_print_vec
ld b,FRAC_DIGITS ld b,FRAC_DIGITS
fp_print_fr: fp_print_fr:
call mul_remainder_by_10 call mul_remainder_by_10
ld a,(PR_R3) ld a,(PR_R3)
@ -1126,15 +1096,14 @@ fp_print_fr:
djnz fp_print_fr djnz fp_print_fr
ret ret
; Shift-right PR_INT by B, collect shifted-out bits into PR_R3 (simplified)
; Shift-right PR_INT by B, collect shifted-out bits into PR_R3 (simplified)
shr32_INT_to_INT_with_remainder: shr32_INT_to_INT_with_remainder:
xor a xor a
ld (PR_R3),a ld (PR_R3),a
ld a,b ld a,b
or a or a
ret z ret z
shr32_INT_to_INT_with_remainder_loop: shr32_INT_to_INT_with_remainder_loop:
ld a,(PR_INT3) ld a,(PR_INT3)
srl a srl a
@ -1156,11 +1125,11 @@ shr32_INT_to_INT_with_remainder_loop:
djnz shr32_INT_to_INT_with_remainder_loop djnz shr32_INT_to_INT_with_remainder_loop
ret ret
shl32_INT_by_B: shl32_INT_by_B:
ld a,b ld a,b
or a or a
ret z ret z
shl32_INT_by_B_loop: shl32_INT_by_B_loop:
ld a,(PR_INT0) ld a,(PR_INT0)
add a,a add a,a
@ -1177,6 +1146,7 @@ shl32_INT_by_B_loop:
djnz shl32_INT_by_B_loop djnz shl32_INT_by_B_loop
ret ret
mul_remainder_by_10: mul_remainder_by_10:
ld a,(PR_R3) ld a,(PR_R3)
ld b,a ld b,a
@ -1188,8 +1158,8 @@ mul_remainder_by_10:
ld (PR_R3),a ld (PR_R3),a
ret ret
; Print PR_INT (u32) as decimal
; Print PR_INT (u32) as decimal
print_u32_dec: print_u32_dec:
ld a,(PR_INT0) ld a,(PR_INT0)
ld b,a ld b,a
@ -1205,11 +1175,9 @@ print_u32_dec:
ld a,'0' ld a,'0'
call os_print_vec call os_print_vec
ret ret
print_u32_dec_nz: print_u32_dec_nz:
xor a xor a
ld (DIGLEN),a ld (DIGLEN),a
print_u32_dec_dloop: print_u32_dec_dloop:
call u32_div10_inplace ; remainder in A, quotient back in PR_INT call u32_div10_inplace ; remainder in A, quotient back in PR_INT
ld hl,DIGBUF ld hl,DIGBUF
@ -1237,7 +1205,6 @@ print_u32_dec_dloop:
; print in reverse ; print in reverse
ld a,(DIGLEN) ld a,(DIGLEN)
ld b,a ld b,a
print_u32_dec_pr: print_u32_dec_pr:
dec b dec b
ld hl,DIGBUF ld hl,DIGBUF
@ -1251,8 +1218,8 @@ print_u32_dec_pr:
jr nz,print_u32_dec_pr jr nz,print_u32_dec_pr
ret ret
; Divide PR_INT (u32) by 10, return remainder in A (0..9)
; Divide PR_INT (u32) by 10, return remainder in A (0..9)
u32_div10_inplace: u32_div10_inplace:
ld b,0 ; remainder ld b,0 ; remainder
ld hl,PR_INT3 ld hl,PR_INT3
@ -1265,14 +1232,12 @@ u32_div10_inplace:
call u32_div10_step call u32_div10_step
ld a,b ld a,b
ret ret
u32_div10_step: u32_div10_step:
; DE = remainder*256 + byte ; DE = remainder*256 + byte
ld a,b ld a,b
ld d,a ld d,a
ld e,(hl) ld e,(hl)
ld c,0 ; quotient byte ld c,0 ; quotient byte
u32_div10_div: u32_div10_div:
ld a,d ld a,d
or a or a
@ -1280,7 +1245,6 @@ u32_div10_div:
ld a,e ld a,e
cp 10 cp 10
jr c,u32_div10_done jr c,u32_div10_done
u32_div10_sub: u32_div10_sub:
ld a,e ld a,e
sub 10 sub 10
@ -1290,18 +1254,17 @@ u32_div10_sub:
ld d,a ld d,a
inc c inc c
jr u32_div10_div jr u32_div10_div
u32_div10_done: u32_div10_done:
ld (hl),c ld (hl),c
ld b,e ld b,e
ret ret
; ============================================================ ; ============================================================
; fp_parse: parse decimal string -> float ; fp_parse: parse decimal string -> float
; DE -> "[-]ddd[.ddd]\0" ; DE -> "[-]ddd[.ddd]\0"
; HL -> output float ; HL -> output float
; ============================================================ ; ============================================================
fp_parse: fp_parse:
xor a xor a
ld (P_SIGN),a ld (P_SIGN),a
@ -1319,7 +1282,6 @@ fp_parse:
ld (P_SIGN),a ld (P_SIGN),a
inc de inc de
jr fp_parse_intpart jr fp_parse_intpart
fp_parse_chkplus: fp_parse_chkplus:
ld a,(de) ld a,(de)
cp '+' cp '+'
@ -1330,7 +1292,6 @@ fp_parse_intpart:
ld a,(de) ld a,(de)
call is_digit call is_digit
jr nc,fp_parse_maybe_dot jr nc,fp_parse_maybe_dot
fp_parse_il: fp_parse_il:
ld a,(de) ld a,(de)
sub '0' sub '0'
@ -1349,7 +1310,6 @@ fp_parse_maybe_dot:
inc de inc de
ld b,MAX_FRAC ld b,MAX_FRAC
fp_parse_fl: fp_parse_fl:
ld a,(de) ld a,(de)
call is_digit call is_digit
@ -1397,6 +1357,7 @@ fp_parse_apply_sign:
ld (hl),a ld (hl),a
ret ret
is_digit: is_digit:
cp '0' cp '0'
jr c,is_digit_no jr c,is_digit_no
@ -1404,13 +1365,12 @@ is_digit:
jr nc,is_digit_no jr nc,is_digit_no
scf scf
ret ret
is_digit_no: is_digit_no:
or a or a
ret ret
; P_S = P_S*10 (uses PR_INT and PR_R0..3 as scratch)
; P_S = P_S*10 (uses PR_INT and PR_R0..3 as scratch)
u32_mul10_scaled: u32_mul10_scaled:
; PR_INT = P ; PR_INT = P
ld a,(P_S0) ld a,(P_S0)
@ -1461,11 +1421,11 @@ u32_mul10_scaled:
ld (P_S3),a ld (P_S3),a
ret ret
shl32_R_by_B: shl32_R_by_B:
ld a,b ld a,b
or a or a
ret z ret z
shl32_R_by_B_loop: shl32_R_by_B_loop:
ld a,(PR_R0) ld a,(PR_R0)
add a,a add a,a
@ -1482,8 +1442,8 @@ shl32_R_by_B_loop:
djnz shl32_R_by_B_loop djnz shl32_R_by_B_loop
ret ret
; P_S += C (0..9)
; P_S += C (0..9)
u32_add8_scaled: u32_add8_scaled:
ld a,(P_S0) ld a,(P_S0)
add a,c add a,c
@ -1499,8 +1459,8 @@ u32_add8_scaled:
ld (P_S3),a ld (P_S3),a
ret ret
; Convert P_S (u32) to float at (HL). Positive only; sign handled by caller.
; Convert P_S (u32) to float at (HL). Positive only; sign handled by caller.
fp_from_u32_scaled_to_A: fp_from_u32_scaled_to_A:
ld a,(P_S0) ld a,(P_S0)
ld b,a ld b,a
@ -1542,7 +1502,6 @@ fp_from_u32_scaled_to_A_nz:
ld b,7 ld b,7
ld a,(P_S0) ld a,(P_S0)
ld c,a ld c,a
fp_from_u32_scaled_to_A_scan: fp_from_u32_scaled_to_A_scan:
fp_from_u32_scaled_to_A_find: fp_from_u32_scaled_to_A_find:
bit 7,c bit 7,c
@ -1552,7 +1511,6 @@ fp_from_u32_scaled_to_A_find:
ld c,a ld c,a
dec b dec b
jr fp_from_u32_scaled_to_A_find jr fp_from_u32_scaled_to_A_find
fp_from_u32_scaled_to_A_found: fp_from_u32_scaled_to_A_found:
; EXP = FP_BIAS + B ; EXP = FP_BIAS + B
ld a,b ld a,b
@ -1588,6 +1546,7 @@ fp_from_u32_scaled_to_A_found:
ld (hl),a ld (hl),a
ret ret
; ============================================================ ; ============================================================
; BSS / WORKSPACE ; BSS / WORKSPACE
; ============================================================ ; ============================================================
@ -1609,27 +1568,14 @@ fp_from_u32_scaled_to_A_found:
B_m0: .space 1 B_m0: .space 1
; 48-bit workspace (P0 LSB .. P5 MSB) ; 48-bit workspace (P0 LSB .. P5 MSB)
P0: .space 1
P1: .space 1
P2: .space 1
P3: .space 1
P4: .space 1
P5: .space 1
P0: SHCNT: .space 1
.space 1
P1:
.space 1
P2:
.space 1
P3:
.space 1
P4:
.space 1
P5:
.space 1
SHCNT:
.space 1
; Print temps ; Print temps
PR_SIGN: .space 1 PR_SIGN: .space 1
@ -1655,12 +1601,8 @@ SHCNT:
P_S3: .space 1 P_S3: .space 1
; Digit buffer ; Digit buffer
DIGBUF: .space 1
DIGBUF: DIGLEN: .space 1
.space 1
DIGLEN:
.space 1
; ============================================================ ; ============================================================
; pow10_table: 10^k constants (k=0..6) in THIS float encoding ; pow10_table: 10^k constants (k=0..6) in THIS float encoding
@ -1673,8 +1615,7 @@ DIGLEN:
; 100000.0 = 143 43 50 00 ; 100000.0 = 143 43 50 00
; 1000000.0= 146 74 24 00 ; 1000000.0= 146 74 24 00
; ============================================================ ; ============================================================
.section "zone", "acrx" .section "float","acrx"
pow10_table: pow10_table:
.byte 127, 0x00, 0x00, 0x00 ; 10^0 = 1 .byte 127, 0x00, 0x00, 0x00 ; 10^0 = 1
.byte 130, 0x20, 0x00, 0x00 ; 10^1 = 10 .byte 130, 0x20, 0x00, 0x00 ; 10^1 = 10

View file

@ -2,10 +2,10 @@
/* SPDX-FileCopyrightText: (c) 2025 A.M. Rowsell */ /* SPDX-FileCopyrightText: (c) 2025 A.M. Rowsell */
SECTIONS SECTIONS
{ {
.zone 0xA000 : { zone.o(zone) float.o(zone) *(.zone) *(zone) } .zone 0xA000 : { *(.zone) *(zone) }
.boot 0xC3C3 : { *(.boot) *(boot) } .boot 0xC3C3 : { *(.boot) *(boot) }
.text 0xE000 : { *(.text) *(.float) *(float) }
.vectors 0xF000 : { *(.vectors) } .vectors 0xF000 : { *(.vectors) }
.data 0x7000 : { *(.data) } .data 0x7000 : { *(.data) }
__data_end = .; .bss : { *(.bss) }
.bss __data_end : { *(.bss) }
} }

113
zone.asm
View file

@ -4,132 +4,27 @@
; ZONE OS main section ; ZONE OS main section
; ============================================================ ; ============================================================
.section "zone","acrx" .section "zone","acrx"
.global zone_start
.global os_print_vec .global os_print_vec
.global os_getch_vec .global os_getch_vec
.global os_outbyte_vec .global os_outbyte_vec
.global os_inbyte_vec .global os_inbyte_vec
.global os_main_loop .global os_main_loop
.local os_print_signon
.set UARTSTATUS, 6 zone_start:
.set UARTDATA, 7 ret
os_print_vec: os_print_vec:
; this takes a character in a and sends it to the UART
push af
push bc
push de
ld d, a
ld c, UARTSTATUS
$1:
in a, (c); get status byte
bit 0, a; test bit 0
jr z, $1; jump back if UART not ready
ld a, d
ld c, UARTDATA
out (c), a; send byte to uart
pop de
pop bc
pop af
ret ret
os_getch_vec: os_getch_vec:
; this gets a character from the UART and puts in in a
push bc
ld c, UARTSTATUS
a2:
in a, (c); get status byte
bit 1, a
jr z, a2
ld c, UARTDATA
in a, (c)
pop bc
ret ret
os_outbyte_vec: os_outbyte_vec:
; this takes a byte in a and sends it to port in hl
push af
push bc
push hl
ld c, l
out (c), a
pop hl
pop bc
pop af
ret ret
os_inbyte_vec: os_inbyte_vec:
; this gets a byte from port in hl and returns it in a
push bc
push hl
ld c, l
in a, (c)
pop hl
pop bc
ret ret
os_main_loop: os_main_loop:
call os_print_signon jp os_main_loop
os_busy_loop:
jp os_busy_loop
; ======================
; non-vectored functions
; ======================
os_print_signon:
ld hl, zoneSignon
ld a, (hl)
$2:
call os_print_vec
inc hl
ld a, (hl)
jr nz, $2
$3:
ld hl, zoneCopyright
ld a, (hl)
$4:
call os_print_vec
inc hl
ld a, (hl)
jr nz, $4
ret
zoneSignon:
.byte "ZONE OS ver. 0.01"
.byte 10, 13, 0
zoneCopyright:
.byte "(c) A.M. Rowsell, license MPLv2"
.byte 10, 13, 0
zonePrompt:
.string "z] "
; error messages
errorSyntax:
.string "Syntax error!"
errorTimeout:
.string "Command timed out."
errorNotFound:
.string "Command/file not found."
errorHardware:
.string "Hardware error!"
errorRAMFailed:
.string "RAM test failed!"
stringTable:
.word zoneSignon, zoneCopyright, zonePrompt
.word errorSyntax, errorTimeout, errorNotFound
.word errorHardware, errorRAMFailed