From a28b5f22300827e0cbb32662eecf49b04bbc3c08 Mon Sep 17 00:00:00 2001 From: rajames Date: Thu, 15 Oct 2026 17:10:45 -0400 Subject: [PATCH] fix(v4): the final review's six minors in the ROM boot - Text after start is refused, as text.c refuses it: before it jumps, the ROM reads on to the end of the source; blanks, comments and the ends of blobs may follow, a token is ERR-AFTER (26), "text after start". - A token too long where a name, a target or a value is wanted is "name too long", as text.c says: (MISSING) reports "missing" only when no error came first. `", keeps "missing", which is text.c's word for both. - text.c's "address out of range" names the address, not the value. - The system's source files are one list, v4/sys_files.h: boot.c, the harness and the nucleus test are made from it. - The ROM's error codes and words are one list, v4/rom_errors.h: boot.c's messages, host_map.h's ROM_ERR_* and mkmap's ERR-* are made from it. - node.h says what v4_node_store does with a ROM address (nothing, as for any address outside RAM, D-14); test_host_rom_range pins it. ROM: 2095 words, rom_hash 0x06d0dcb7a0cb41a1. dict_hash unchanged, 0xe5a57f3eb72ff94a. make -C v4 test test-32 hosted-check pass. QEMU: amd64, aarch64, riscv64 to ok>, POST 538/538, POST: PASSED. Co-Authored-By: Claude Opus 5.5 --- capsules/v4/rom/dir.f18 | 17 +- capsules/v4/rom/in.f18 | 7 + capsules/v4/rom/word.f18 | 4 +- .../amd64/qemu-amd64-20261015-170147.log | 153 ++++++++++++++ .../aarch64/qemu-aarch64-20261015-170437.log | 126 +++++++++++ .../riscv64/qemu-riscv64-20261015-170846.log | 196 ++++++++++++++++++ v4/include/v4/node.h | 4 +- v4/include/v4/rom_errors.h | 43 ++++ v4/include/v4/sys_files.h | 17 ++ v4/src/text.c | 8 +- v4/system/boot.c | 30 ++- v4/tests/host_map.h | 30 +-- v4/tests/rom_harness.h | 13 +- v4/tests/test_host_rom_asm.c | 40 +++- v4/tests/test_host_rom_nucleus.c | 4 +- v4/tests/test_host_rom_range.c | 2 + v4/tests/test_text.c | 1 + v4/tools/mkmap.c | 40 ++-- 18 files changed, 646 insertions(+), 89 deletions(-) create mode 100644 logs/20261015-170147/amd64/qemu-amd64-20261015-170147.log create mode 100644 logs/20261015-170437/aarch64/qemu-aarch64-20261015-170437.log create mode 100644 logs/20261015-170846/riscv64/qemu-riscv64-20261015-170846.log create mode 100644 v4/include/v4/rom_errors.h create mode 100644 v4/include/v4/sys_files.h diff --git a/capsules/v4/rom/dir.f18 b/capsules/v4/rom/dir.f18 index c18a7f27..37776625 100644 --- a/capsules/v4/rom/dir.f18 +++ b/capsules/v4/rom/dir.f18 @@ -44,7 +44,7 @@ \ ( -- v 1 | 0 0 ) the next token as a VALUE : (NEXT-VALUE) (NEXT-TOKEN) if MISS drop jump (VALUE) - MISS: drop ERR-MISSING (FAIL) 0 0 ; + MISS: drop (MISSING) 0 0 ; : (H-CONSTANT) (IN-MACRO?) if OK drop ; @@ -56,7 +56,7 @@ -if NUM drop drop ERR-BIG jump (FAIL) NUM: drop (NAME-BACK) 2 jump (DEFINE) NAN: drop drop ERR-VALUE jump (FAIL) - MISS: drop ERR-MISSING jump (FAIL) + MISS: drop jump (MISSING) : (H-SET) (IN-MACRO?) if OK drop ; @@ -66,7 +66,7 @@ (NEXT-VALUE) if BADV drop (NAME-BACK) 4 jump (DEFINE) BADV: drop drop ; - MISS: drop ERR-MISSING jump (FAIL) + MISS: drop jump (MISSING) \ here alone is not something to assemble: only a VALUE : (H-HERE) ERR-TARGET jump (FAIL) @@ -88,6 +88,7 @@ (T2) a! @ (TOK) + a! @ (EMIT) (T2) a! @ 1 + ! jump L D: drop ; + \ text.c says "without a string, or one too long" for both: missing MISS: drop ERR-MISSING jump (FAIL) \ store ADDR VALUE: ADDR must be in RAM, as text.c requires @@ -113,7 +114,7 @@ 0 (RECN) a! ! 0 (POOLN) a! ! 0 (NREF) a! ! 0 (NLAB) a! ! 0 (WNP) a! ! 0 (NFOR) a! ! 0 (RDEPTH) a! ! ; -\ start NAME: the system's source has ended +\ start NAME: the system's source has ended; NAME, a word, is where it starts : (H-START) (IN-MACRO?) if OK drop ; OK: drop @@ -130,9 +131,15 @@ (FIND) if NOTW dup 2 + a! @ 1 xor if ISW drop drop jump NOTW0 ISW: drop 3 + a! @ (T1) a! ! + \ nothing may follow start but blanks, comments and the ends of blobs, + \ up to the end of all + A1: (TOKEN) if A2 + drop ERR-AFTER jump (FAIL) + A2: drop (FAILED) a! @ if A3 drop ; + A3: drop (EOF) a! @ if A1 drop (CLEAR) 0 DSTACK-REG a! ! 0 RSTACK-REG a! ! (T1) a! @ push ; NOTW: drop NOTW0: ERR-START jump (FAIL) - MISS: drop ERR-MISSING jump (FAIL) + MISS: drop jump (MISSING) diff --git a/capsules/v4/rom/in.f18 b/capsules/v4/rom/in.f18 index 7e7698fe..02cfb909 100644 --- a/capsules/v4/rom/in.f18 +++ b/capsules/v4/rom/in.f18 @@ -41,6 +41,13 @@ \ ( code -- ) stop with an error, noting the line : (FAIL) (FAILED) a! ! (LINE) a! @ (ERRLINE) a! ! ; +\ ( -- ) "missing": a name, a target or a value was wanted and there is +\ none -- unless an error came first, a token too long or a comment not +\ closed, which stands, as text.c's first error does +: (MISSING) + (FAILED) a! @ if M drop ; + M: drop ERR-MISSING jump (FAIL) + \ ( c -- ) one more character of the token: byte (TOKN)+1 of (TOK), into \ a cell whose byte there is still zero : (PUT) diff --git a/capsules/v4/rom/word.f18 b/capsules/v4/rom/word.f18 index 4d22cf73..c4f4e18f 100644 --- a/capsules/v4/rom/word.f18 +++ b/capsules/v4/rom/word.f18 @@ -346,7 +346,7 @@ OK: drop (NEXT-TOKEN) if NONAME drop (END-WORD) (LABEL) 1 jump (DEFINE) - NONAME: drop ERR-MISSING jump (FAIL) + NONAME: drop jump (MISSING) \ ( -- ) assemble the token : (ONE) @@ -379,7 +379,7 @@ 1 jump (BRANCH-NAME) PLAIN: drop jump (OP) FP: drop drop ERR-FETCH-P jump (FAIL) - NOTGT: drop drop ERR-MISSING jump (FAIL) + NOTGT: drop drop jump (MISSING) AMP: drop (TOKN) a! @ -1 + if ONECH drop (TOK-SAVE) 1 (MLEN) a! @ -1 + (TOK-SUB) (FIND) if BADA diff --git a/logs/20261015-170147/amd64/qemu-amd64-20261015-170147.log b/logs/20261015-170147/amd64/qemu-amd64-20261015-170147.log new file mode 100644 index 00000000..2e1d6986 --- /dev/null +++ b/logs/20261015-170147/amd64/qemu-amd64-20261015-170147.log @@ -0,0 +1,153 @@ +[=3hBdsDxe: loading Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0) +BdsDxe: starting Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0) +[=3hStarKernel UEFI Loader +Loading kernel from ESP... +[CKPT 001] Entered efi_main - ConOut live +RAW SERIAL UP +[CKPT 002] Serial (COM1) initialized +Monolithic build - kernel linked directly +Collecting boot information... +CmdLine: parsed OK +[CKPT 004] Command line parsed +[CKPT 005] Kernel stack allocation decided +[CKPT 006] Boot info collected (ACPI table located) +GOP: linear framebuffer found +[CKPT 007] GOP: linear framebuffer found +[CKPT 008] About to enter ExitBootServices retry loop +EBS... +EBS OK +Calling kernel_main (monolithic)... + + + _____ _ _ __ _ + / ____| | | |/ / | | + | (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| | + \___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ | + ____) | || (_| | | | . \ __/ | | | | | __/ | + |_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_| + +LithosAnanke v2.1.0 amd64 +Architecture: amd64 +Build: Oct 15 2026 17:01:20 + +UEFI BootServices: EXITED +Console: serial line is a 16550 at port 0x00000000000003f8 (COM1, probed) + +=== StarKernel Boot Information === +Memory map entries: 131 +Total memory: 1023 MB +Usable memory: 966 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 248682 + Free pages : 247159 + Used pages : 1523 + Total MB : 971 + Free MB : 965 + Used MB : 5 + +VMM initialized (mapped RAM, CR3 switched) +VMM initialized (mapped RAM, CR3 switched) +VMM self-test: mapped OK at 0xffff800000000000 +VMM self-test complete. + +IDT installed. + +APIC: init... +APIC: IA32_APIC_BASE MSR=0x00000000fee00900 +APIC: stale-ISR drain: 0 EOI(s) issued +APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear) +APIC: init done + +I/O APIC: init... +I/O APIC: base=0xfec00000, gsi_base=0, overrides=5 + override: source=00 gsi=2 flags=0x0000 + override: source=05 gsi=5 flags=0x000d + override: source=09 gsi=9 flags=0x000d + override: source=0a gsi=10 flags=0x000d + override: source=0b gsi=11 flags=0x000d +i8042: keyboard ACKed enable-scanning +i8042: IRQ1 enabled in controller config byte +I/O APIC: keyboard IRQ1 routed (masked) + +Timer: init... +Timer: init start +Timer: PM_TMR_BLK discovered from FADT at port 1544 +Timer: VM mode detected (hypervisor present). +Timer: HPET calibration disabled (VM-exit MMIO would poison timing). +Timer: WARNING: invariant TSC not present under hypervisor. +Timer: continuing in RELATIVE mode (no determinism guarantees). +Timer: RDTSCP not present; using RDTSC (less serialized). +Timer: CPUID frequency unavailable; trying PM Timer... +Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=2105825711 Hz +Timer: init done + +Kernel heap initialized. +Heap statistics: + Total bytes: 536870872 + Free bytes: 536870872 + Used bytes: 0 + Peak bytes: 0 + Heap base addr: 24641536 + Heap end addr: 561512448 + +Heartbeat: init... +APIC Timer: calibrating... +APIC Timer: apic_hz=1008922505, tick_hz=100, initial_count=10089225 +APIC Timer: configured (masked, ready to start) +Heartbeat: init done +Kernel initialization complete. +Boot successful! + +System: StarForth v4 (this build's default) +StarForth v4: one host node, the F18-derived engine +V4: capsule v4:sys:map-64.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0xaa70e1dee90f9000 +V4: capsule v4:sys:core.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:core.f18 capsule_hash=0x5282537f9cc6d053 +V4: capsule v4:sys:input.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:input.f18 capsule_hash=0x85d3ec486d929a79 +V4: capsule v4:sys:dict.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:dict.f18 capsule_hash=0x1379bd3b5de811dc +V4: capsule v4:sys:codegen.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:codegen.f18 capsule_hash=0x36d2ae84d2911b90 +V4: capsule v4:sys:compile.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:compile.f18 capsule_hash=0x11145c4c2ab819d8 +V4: capsule v4:sys:quit.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:quit.f18 capsule_hash=0x0278d4bcbd206dba +V4: capsule v4:sys:forth.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:forth.f18 capsule_hash=0x16cab4a1268b85da +V4: capsule v4:sys:numout.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:numout.f18 capsule_hash=0x01297cd8e8018acd +V4: capsule v4:sys:words.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:words.f18 capsule_hash=0xb1d381f927d9f14e +V4: capsule v4:sys:system.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:system.f18 capsule_hash=0xd92203664c2915bd +V4: capsule v4:sys:qmath.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:qmath.f18 capsule_hash=0x7117595eb17ace99 +V4: capsule v4:sys:blocks.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:blocks.f18 capsule_hash=0x76307ef48678dc2a +V4: capsule v4:sys:log.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:log.f18 capsule_hash=0xfc6540e6b824a52b +V4: capsule v4:sys:acl.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:acl.f18 capsule_hash=0x6845aa048db7eb22 +V4: capsule v4:sys:end.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:end.f18 capsule_hash=0x5ef01312c07b79cc +PARITY:V4_ROM words=2095 rom_hash=0x06d0dcb7a0cb41a1 instructions=62044480 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x6b56e15226ee3719 +PARITY:V4_POST tests=538 pass=538 fail=0 +PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a +PARITY:OK +POST: PASSED +[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks) +PCI: init... +PCI: ECAM mapped (amd64) +virtio-blk: found device +[HADES][INFO ] [KRELTSC: 79097487] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b +Artemis: virtio-blk attached +ok> 1 2 + . +3 ok +ok> \ No newline at end of file diff --git a/logs/20261015-170437/aarch64/qemu-aarch64-20261015-170437.log b/logs/20261015-170437/aarch64/qemu-aarch64-20261015-170437.log new file mode 100644 index 00000000..633e910f --- /dev/null +++ b/logs/20261015-170437/aarch64/qemu-aarch64-20261015-170437.log @@ -0,0 +1,126 @@ +UEFI firmware (version 2025.11-3ubuntu7.3 built at 15:40:26 on Sep 23 2026) +[=3hBdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x2,0x0): Not Found +BdsDxe: failed to load Boot0003 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:04.0-1" from PciRoot(0x0)/Pci(0x4,0x0)/USB(0x0,0x0): Not Found +BdsDxe: loading Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0) +BdsDxe: starting Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0) +[=3hStarKernel UEFI Loader +Loading kernel from ESP... +[CKPT 001] Entered efi_main - ConOut live +Collecting boot information... +[CKPT 004] Command line parsed +[CKPT 005] Kernel stack allocation decided +[CKPT 006] Boot info collected (ACPI table located) +[CKPT 007] GOP: linear framebuffer found +[CKPT 008] About to enter ExitBootServices retry loop + + + _____ _ _ __ _ + / ____| | | |/ / | | + | (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| | + \___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ | + ____) | || (_| | | | . \ __/ | | | | | __/ | + |_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_| + +LithosAnanke v2.1.0 aarch64 +Architecture: aarch64 +Build: Oct 15 2026 17:04:11 + +UEFI BootServices: EXITED +Console: serial line is a PL011 at 0x0000000009000000 (no devicetree: QEMU's) + +=== StarKernel Boot Information === +Memory map entries: 108 +Total memory: 4093 MB +Usable memory: 4054 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 1039291 + Free pages : 1037880 + Used pages : 1411 + Total MB : 4059 + Free MB : 4054 + Used MB : 5 + +VMM initialized (mapped RAM, CR3 switched) +VMM initialized (mapped RAM, CR3 switched) +VMM self-test: mapped OK at 0xffff800000000000 +VMM self-test complete. + +AArch64: running at EL1 +IDT installed. + +APIC: init... +PSCI: no DTB -- using HVC (QEMU virt-machine default) +GICv2: no DTB GIC node -- using QEMU virt-machine defaults +GICv2: distributor+CPU interface enabled, PPI 30 +APIC: init done + +Timer: init... +Timer: AArch64 generic timer initialised. +Timer: init done + +Kernel heap initialized. +Heap statistics: + Total bytes: 2147483608 + Free bytes: 2147483608 + Used bytes: 0 + Peak bytes: 0 + Heap base addr: 1207959552 + Heap end addr: 3355443200 + +Heartbeat: init... +Heartbeat: init done +Kernel initialization complete. +Boot successful! + +System: StarForth v4 (this build's default) +StarForth v4: one host node, the F18-derived engine +V4: capsule v4:sys:map-64.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0xaa70e1dee90f9000 +V4: capsule v4:sys:core.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:core.f18 capsule_hash=0x5282537f9cc6d053 +V4: capsule v4:sys:input.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:input.f18 capsule_hash=0x85d3ec486d929a79 +V4: capsule v4:sys:dict.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:dict.f18 capsule_hash=0x1379bd3b5de811dc +V4: capsule v4:sys:codegen.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:codegen.f18 capsule_hash=0x36d2ae84d2911b90 +V4: capsule v4:sys:compile.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:compile.f18 capsule_hash=0x11145c4c2ab819d8 +V4: capsule v4:sys:quit.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:quit.f18 capsule_hash=0x0278d4bcbd206dba +V4: capsule v4:sys:forth.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:forth.f18 capsule_hash=0x16cab4a1268b85da +V4: capsule v4:sys:numout.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:numout.f18 capsule_hash=0x01297cd8e8018acd +V4: capsule v4:sys:words.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:words.f18 capsule_hash=0xb1d381f927d9f14e +V4: capsule v4:sys:system.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:system.f18 capsule_hash=0xd92203664c2915bd +V4: capsule v4:sys:qmath.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:qmath.f18 capsule_hash=0x7117595eb17ace99 +V4: capsule v4:sys:blocks.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:blocks.f18 capsule_hash=0x76307ef48678dc2a +V4: capsule v4:sys:log.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:log.f18 capsule_hash=0xfc6540e6b824a52b +V4: capsule v4:sys:acl.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:acl.f18 capsule_hash=0x6845aa048db7eb22 +V4: capsule v4:sys:end.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:end.f18 capsule_hash=0x5ef01312c07b79cc +PARITY:V4_ROM words=2095 rom_hash=0x06d0dcb7a0cb41a1 instructions=62044480 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x6b56e15226ee3719 +PARITY:V4_POST tests=538 pass=538 fail=0 +PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a +PARITY:OK +POST: PASSED +[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks) +PCI: init... +virtio-blk: found device +[HADES][INFO ] [KRELTSC: 1331322] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b +Artemis: virtio-blk attached +ok> 1 2 + . +3 ok +ok> \ No newline at end of file diff --git a/logs/20261015-170846/riscv64/qemu-riscv64-20261015-170846.log b/logs/20261015-170846/riscv64/qemu-riscv64-20261015-170846.log new file mode 100644 index 00000000..0ea48484 --- /dev/null +++ b/logs/20261015-170846/riscv64/qemu-riscv64-20261015-170846.log @@ -0,0 +1,196 @@ + +OpenSBI v1.8 + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + +Platform Name : riscv-virtio,qemu +Platform Features : medeleg +Platform HART Count : 1 +Platform HART Protection : pmp +Platform IPI Device : aclint-mswi +Platform Timer Device : aclint-mtimer @ 10000000Hz +Platform Console Device : uart8250 +Platform HSM Device : --- +Platform PMU Device : --- +Platform Reboot Device : syscon-reboot +Platform Shutdown Device : syscon-poweroff +Platform Suspend Device : --- +Platform CPPC Device : --- +Firmware Base : 0x80000000 +Firmware Size : 321 KB +Firmware RW Offset : 0x40000 +Firmware RW Size : 65 KB +Firmware Heap Offset : 0x47000 +Firmware Heap Size : 37 KB (total), 0 KB (reserved), 12 KB (used), 23 KB (free) +Firmware Scratch Size : 4096 B (total), 1464 B (used), 2632 B (free) +Runtime SBI Version : 3.0 +Standard SBI Extensions : ipi,pmu,srst,sse,hsm,rfnc,fwft,time,base,legacy,dbcn,dbtr +Experimental SBI Extensions : none + +Domain0 Name : root +Domain0 Boot HART : 0 +Domain0 HARTs : 0* +Domain0 Region00 : 0x0000000080040000-0x000000008005ffff M: (F,R,W) S/U: () +Domain0 Region01 : 0x0000000080000000-0x000000008003ffff M: (F,R,X) S/U: () +Domain0 Region02 : 0x0000000000100000-0x0000000000100fff M: (I,R,W) S/U: (R,W) +Domain0 Region03 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W) +Domain0 Region04 : 0x0000000002000000-0x000000000200ffff M: (I,R,W) S/U: () +Domain0 Region05 : 0x000000000c400000-0x000000000c5fffff M: (I,R,W) S/U: (R,W) +Domain0 Region06 : 0x000000000c000000-0x000000000c3fffff M: (I,R,W) S/U: (R,W) +Domain0 Region07 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X) +Domain0 Next Address : 0x0000000020000000 +Domain0 Next Arg1 : 0x00000000bfe00000 +Domain0 Next Mode : S-mode +Domain0 SysReset : yes +Domain0 SysSuspend : yes + +Boot HART ID : 0 +Boot HART Domain : root +Boot HART Priv Version : v1.12 +Boot HART Base ISA : rv64imafdch +Boot HART ISA Extensions : sstc,zicntr,zihpm,zicboz,zicbom,sdtrig,svadu +Boot HART PMP Count : 16 +Boot HART PMP Granularity : 2 bits +Boot HART PMP Address Bits : 54 +Boot HART MHPM Info : 16 (0x0007fff8) +Boot HART Debug Triggers : 2 triggers +Boot HART MIDELEG : 0x0000000000001666 +Boot HART MEDELEG : 0x0000000000f4b509 +[=3hRISC-V EDK2 firmware version 2025.11-3ubuntu7.3 +Press ESCAPE within 5 seconds for boot options ERROR: C40000002:V03051002 I0 6D33944A-EC75-4855-A54D-809C75241F6C 83FFF850 +BdsDxe: failed to load Boot0001 "UEFI Misc Device" fr +om PciRoot(0x0)/Pci(0x1,0x0): Not Found +[=3hStarKernel UEFI Loader +Loading kernel from ESP... +[CKPT 001] Entered efi_main - ConOut live +Monolithic build - kernel linked directly +Collecting boot information... +CmdLine: parsed OK +[CKPT 004] Command line parsed +[CKPT 005] Kernel stack allocation decided +[CKPT 006] Boot info collected (ACPI table located) +GOP: linear framebuffer found +[CKPT 007] GOP: linear framebuffer found +[CKPT 008] About to enter ExitBootServices retry loop +Calling kernel_main (monolithic)... +riscv64 item 4.3.5a: satp state at kernel entry (before switch) + satp.MODE = 0x000000000000000a + satp.PPN = 0x00000000000bf868 + __kernel_start = 0x00000000bdc340aa +riscv64: satp cleared -- Bare mode, explicit (item 4.3.5a) + + + _____ _ _ __ _ + / ____| | | |/ / | | + | (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| | + \___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ | + ____) | || (_| | | | . \ __/ | | | | | __/ | + |_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_| + +LithosAnanke v2.1.0 riscv64 +Architecture: riscv64 +Build: Oct 15 2026 17:08:07 + +UEFI BootServices: EXITED +Console: serial line is a 16550 at 0x0000000010000000 (no devicetree: QEMU's) + +=== StarKernel Boot Information === +Memory map entries: 100 +Total memory: 1020 MB +Usable memory: 974 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 250212 + Free pages : 249560 + Used pages : 652 + Total MB : 977 + Free MB : 974 + Used MB : 2 + +VMM initialized (mapped RAM, CR3 switched) +VMM initialized (mapped RAM, CR3 switched) +VMM self-test: mapped OK at 0xffff800000000000 +VMM self-test complete. + +IDT installed. + +APIC: init... +PLIC: no DTB PLIC node -- using QEMU virt-machine default (base=0x0c000000) +PLIC: init (S-mode context 1, threshold=0) +APIC: init done + +Timer: init... +Timer: RISC-V time CSR @ 10000000 Hz (FALLBACK, no devicetree) +Timer: init done + +Kernel heap initialized. +Heap statistics: + Total bytes: 536870872 + Free bytes: 536870872 + Used bytes: 0 + Peak bytes: 0 + Heap base addr: 2214588416 + Heap end addr: 2751459328 + +Heartbeat: init... +Heartbeat: init done +Kernel initialization complete. +Boot successful! + +System: StarForth v4 (this build's default) +StarForth v4: one host node, the F18-derived engine +V4: capsule v4:sys:map-64.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0xaa70e1dee90f9000 +V4: capsule v4:sys:core.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:core.f18 capsule_hash=0x5282537f9cc6d053 +V4: capsule v4:sys:input.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:input.f18 capsule_hash=0x85d3ec486d929a79 +V4: capsule v4:sys:dict.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:dict.f18 capsule_hash=0x1379bd3b5de811dc +V4: capsule v4:sys:codegen.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:codegen.f18 capsule_hash=0x36d2ae84d2911b90 +V4: capsule v4:sys:compile.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:compile.f18 capsule_hash=0x11145c4c2ab819d8 +V4: capsule v4:sys:quit.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:quit.f18 capsule_hash=0x0278d4bcbd206dba +V4: capsule v4:sys:forth.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:forth.f18 capsule_hash=0x16cab4a1268b85da +V4: capsule v4:sys:numout.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:numout.f18 capsule_hash=0x01297cd8e8018acd +V4: capsule v4:sys:words.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:words.f18 capsule_hash=0xb1d381f927d9f14e +V4: capsule v4:sys:system.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:system.f18 capsule_hash=0xd92203664c2915bd +V4: capsule v4:sys:qmath.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:qmath.f18 capsule_hash=0x7117595eb17ace99 +V4: capsule v4:sys:blocks.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:blocks.f18 capsule_hash=0x76307ef48678dc2a +V4: capsule v4:sys:log.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:log.f18 capsule_hash=0xfc6540e6b824a52b +V4: capsule v4:sys:acl.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:acl.f18 capsule_hash=0x6845aa048db7eb22 +V4: capsule v4:sys:end.f18 signature: missing (unsigned) +PARITY:V4_F18 name=v4:sys:end.f18 capsule_hash=0x5ef01312c07b79cc +PARITY:V4_ROM words=2095 rom_hash=0x06d0dcb7a0cb41a1 instructions=62044480 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x6b56e15226ee3719 +PARITY:V4_POST tests=538 pass=538 fail=0 +PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a +PARITY:OK +POST: PASSED +[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks) +PCI: init... +virtio-blk: found device +[HADES][INFO ] [KRELTSC: 20917512] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b +Artemis: virtio-blk attached +ok> 1 2 + . +3 ok +ok> \ No newline at end of file diff --git a/v4/include/v4/node.h b/v4/include/v4/node.h index fef285f4..443dece4 100644 --- a/v4/include/v4/node.h +++ b/v4/include/v4/node.h @@ -60,7 +60,9 @@ /* THE ROM (docs/v4.0.0/MACHINE.md section 2, DATASHEET-F18.md section 5). * A read-only range of V4_ROM_WORDS words at V4_ROM_BASE, just above RAM. * An instruction fetch, an @p literal and a data fetch there read the ROM; a - * running programme's store there is an address fault. In the model it is + * running programme's store there is an address fault. C code's + * v4_node_store there does nothing and counts no fault, as for any address + * outside RAM (D-14, at v4_node_store below). In the model it is * attached, as every device is, and v4_node_reset detaches it: the owner * attaches it again after a reset. The range's size is a build parameter, * as RAM's is; 0 (the default) is a machine with no ROM. */ diff --git a/v4/include/v4/rom_errors.h b/v4/include/v4/rom_errors.h new file mode 100644 index 00000000..83135691 --- /dev/null +++ b/v4/include/v4/rom_errors.h @@ -0,0 +1,43 @@ +/* rom_errors.h -- the ROM's error codes and what they mean. + * + * The ROM (capsules/v4/rom) stops at (ROM-FAILED) with one of these codes in + * (FAILED); the loader, which owns the console, prints its words + * (v4/system/boot.c). This is the one list: the map's constants ERR-* the + * ROM is assembled with (v4/tools/mkmap.c, through v4/tests/host_map.h's + * ROM_ERR_*) and the boot's messages are both made from it. The codes run + * 1, 2, 3 ... in order; a new one goes at the end. + * + * X(NAME, CODE, WORDS) + */ +#ifndef V4_ROM_ERRORS_H +#define V4_ROM_ERRORS_H + +#define V4_ROM_ERRORS(X) \ + X(TOO_LONG, 1, "name too long") /* a token longer than 63 characters */ \ + X(COMMENT, 2, "comment not closed") /* a ( with no ) before the end of its blob */ \ + X(BAD_NAME, 3, "cannot be used as a name") /* an opcode, a reserved word, a label, a number or &... */ \ + X(DEFINED, 4, "already defined") \ + X(NAMES, 5, "too many names") /* the symbol table is full */ \ + X(FIT, 6, "does not fit: memory is full, or a branch cannot reach") \ + X(OPCODE, 7, "not an opcode the packer takes there") \ + X(IN_MACRO, 8, "not allowed in a macro") \ + X(MACRO, 9, "macro without endmacro, or endmacro without macro") \ + X(LABEL_DUP, 10, "label already defined in this word") \ + X(LABELS, 11, "too many labels in one word") \ + X(FOR, 12, "FOR nested too deep, NEXT or UNEXT without FOR, or FOR without NEXT") \ + X(UNEXT, 13, "FOR ... UNEXT must fit one instruction word and hold no literal") \ + X(TARGET, 14, "not something to branch to") \ + X(UNDEFINED, 15, "never defined") \ + X(BIG, 16, "number does not fit a cell") \ + X(AMP, 17, "& needs a word that is already defined") \ + X(FETCH_P, 18, "write the number, not @p") \ + X(MISSING, 19, "a name, a target, a value or a string is missing") \ + X(DEEP, 20, "macros nested too deep") \ + X(REFS, 21, "too many unresolved branches") \ + X(VALUE, 22, "not a value") \ + X(NO_START, 23, "the source ended with no start") \ + X(START, 24, "start of something not a word") \ + X(RANGE, 25, "address out of range") /* store outside RAM */ \ + X(AFTER, 26, "text after start") + +#endif diff --git a/v4/include/v4/sys_files.h b/v4/include/v4/sys_files.h new file mode 100644 index 00000000..710cb5c3 --- /dev/null +++ b/v4/include/v4/sys_files.h @@ -0,0 +1,17 @@ +/* sys_files.h -- the system's source, in the order the ROM reads it. + * + * capsules/v4/sys: the memory map (map-.f18) first, then these, + * then end.f18 -- the state the system is switched on in, and `start`. The + * one list: the boot feeds these blobs (v4/system/boot.c), and the tests + * that build the system read these files (v4/tests/rom_harness.h). + * + * X(FILE): capsules/v4/sys/FILE.f18 + */ +#ifndef V4_SYS_FILES_H +#define V4_SYS_FILES_H + +#define V4_SYS_FILES(X) \ + X(core) X(input) X(dict) X(codegen) X(compile) X(quit) X(forth) \ + X(numout) X(words) X(system) X(qmath) X(blocks) X(log) X(acl) + +#endif diff --git a/v4/src/text.c b/v4/src/text.c index 928c7900..865c454a 100644 --- a/v4/src/text.c +++ b/v4/src/text.c @@ -450,15 +450,15 @@ static void set_directive(v4_text *t, reader *r) /* `store ADDR VALUE`: a word of RAM is given VALUE. */ static void store_directive(v4_text *t, reader *r) { - char tok[V4_TEXT_MAX_TOKEN + 1u]; + char at[V4_TEXT_MAX_TOKEN + 1u], tok[V4_TEXT_MAX_TOKEN + 1u]; v4_cell addr, v; if (r->depth != 1) { fail(t, "not allowed in a macro", "store"); return; } - if (!next_token(t, r, tok)) { if (!t->failed) fail(t, "store without an address", NULL); return; } - if (!value_of(t, tok, &addr)) return; + if (!next_token(t, r, at)) { if (!t->failed) fail(t, "store without an address", NULL); return; } + if (!value_of(t, at, &addr)) return; if (!next_token(t, r, tok)) { if (!t->failed) fail(t, "store without a value", NULL); return; } if (!value_of(t, tok, &v)) return; - if (addr < 0 || (v4_ucell)addr >= V4_NODE_WORDS) { fail(t, "address out of range", tok); return; } + if (addr < 0 || (v4_ucell)addr >= V4_NODE_WORDS) { fail(t, "address out of range", at); return; } v4_node_store(t->as.n, addr, v); } diff --git a/v4/system/boot.c b/v4/system/boot.c index 6f73f249..1319bd86 100644 --- a/v4/system/boot.c +++ b/v4/system/boot.c @@ -8,6 +8,8 @@ #include "v4/post.h" #include "v4/blocks.h" #include "v4/boot.h" +#include "v4/rom_errors.h" +#include "v4/sys_files.h" #include "v4/message.h" #include "v4/wire.h" #include "starkernel/capsule.h" @@ -430,32 +432,24 @@ extern const unsigned v4_rom_32_words; #define EOT 4 /* the end of the source: the ROM's (KEY) sees no more */ /* The system's source, in the order the ROM reads it: the memory map, then - * the system, then its end -- the state it is switched on in, and `start`. - * capsules/v4/sys; each blob is a capsule like any other. */ + * the system (v4/sys_files.h), then its end -- the state it is switched on + * in, and `start`. capsules/v4/sys; each blob is a capsule like any other. */ #define MAP_NAME_(bits) "v4:sys:map-" #bits ".f18" #define MAP_NAME__(bits) MAP_NAME_(bits) static const char *const system_blobs[] = { +#define SYS_BLOB(file) "v4:sys:" #file ".f18", MAP_NAME__(V4_CELL_BITS), - "v4:sys:core.f18", "v4:sys:input.f18", "v4:sys:dict.f18", "v4:sys:codegen.f18", "v4:sys:compile.f18", - "v4:sys:quit.f18", "v4:sys:forth.f18", "v4:sys:numout.f18", "v4:sys:words.f18", "v4:sys:system.f18", - "v4:sys:qmath.f18", "v4:sys:blocks.f18", "v4:sys:log.f18", "v4:sys:acl.f18", + V4_SYS_FILES(SYS_BLOB) "v4:sys:end.f18", +#undef SYS_BLOB }; #define SYSTEM_BLOBS (sizeof system_blobs / sizeof system_blobs[0]) -/* What the ROM's error codes mean (v4/tests/host_map.h, ROM_ERR_*): the ROM - * stops with the code, and the loader, which owns the console, says it. */ -static const char *const rom_errors[] = { - "", "name too long", "comment not closed", "cannot be used as a name", "already defined", - "too many names", "does not fit: memory is full, or a branch cannot reach", "not an opcode the packer takes there", - "not allowed in a macro", "macro without endmacro, or endmacro without macro", - "label already defined in this word", "too many labels in one word", - "FOR nested too deep, NEXT or UNEXT without FOR, or FOR without NEXT", - "FOR ... UNEXT must fit one instruction word and hold no literal", "not something to branch to", - "never defined", "number does not fit a cell", "& needs a word that is already defined", - "write the number, not @p", "a name, a target, a value or a string is missing", "macros nested too deep", - "too many unresolved branches", "not a value", "the source ended with no start", "start of something not a word", "address out of range", -}; +/* What the ROM's error codes mean (v4/rom_errors.h): the ROM stops with the + * code, and the loader, which owns the console, says it. Code c is entry c. */ +#define ROM_ERROR_TEXT(name, code, text) text, +static const char *const rom_errors[] = { "", V4_ROM_ERRORS(ROM_ERROR_TEXT) }; +#undef ROM_ERROR_TEXT #define ROM_ERRORS (sizeof rom_errors / sizeof rom_errors[0]) /* FNV-1a over the ROM, a cell at a time, low byte first, as the dictionary diff --git a/v4/tests/host_map.h b/v4/tests/host_map.h index 381f4c31..58b00899 100644 --- a/v4/tests/host_map.h +++ b/v4/tests/host_map.h @@ -12,6 +12,7 @@ #ifndef V4_TESTS_HOST_MAP_H #define V4_TESTS_HOST_MAP_H +#include "v4/rom_errors.h" #include "v4/blocks.h" #include "v4/text.h" #include @@ -197,32 +198,9 @@ #define ROM_KIND_CONST 2 #define ROM_KIND_MACRO 3 #define ROM_KIND_SET 4 -/* the ROM's error codes */ -#define ROM_ERR_TOO_LONG 1 /* a token longer than 63 characters: "name too long" */ -#define ROM_ERR_COMMENT 2 /* a ( with no ) before the end: "comment not closed" */ -#define ROM_ERR_BAD_NAME 3 /* an opcode, a reserved word, a label, a number or &...: "cannot be used as a name" */ -#define ROM_ERR_DEFINED 4 /* "already defined" */ -#define ROM_ERR_NAMES 5 /* the symbol table is full: "too many names" */ -#define ROM_ERR_FIT 6 /* memory is full, or a branch cannot reach: "does not fit" */ -#define ROM_ERR_OPCODE 7 /* not an opcode the packer takes there */ -#define ROM_ERR_IN_MACRO 8 /* "not allowed in a macro" */ -#define ROM_ERR_MACRO 9 /* "macro without endmacro", "endmacro without macro" */ -#define ROM_ERR_LABEL_DUP 10 /* "label already defined in this word" */ -#define ROM_ERR_LABELS 11 /* "too many labels in one word" */ -#define ROM_ERR_FOR 12 /* FOR nested too deep, NEXT or UNEXT without FOR, FOR without NEXT */ -#define ROM_ERR_UNEXT 13 /* "FOR ... UNEXT must fit one instruction word and hold no literal" */ -#define ROM_ERR_TARGET 14 /* "not something to branch to" */ -#define ROM_ERR_UNDEFINED 15 /* "never defined" */ -#define ROM_ERR_BIG 16 /* "number does not fit a cell" */ -#define ROM_ERR_AMP 17 /* "& needs a word that is already defined" */ -#define ROM_ERR_FETCH_P 18 /* "write the number, not @p" */ -#define ROM_ERR_MISSING 19 /* a name, a target, a value or a string missing at the end */ -#define ROM_ERR_DEEP 20 /* "macros nested too deep" */ -#define ROM_ERR_REFS 21 /* "too many unresolved branches" */ -#define ROM_ERR_VALUE 22 /* "not a value", "not a number" */ -#define ROM_ERR_NO_START 23 /* the input ended with no start */ -#define ROM_ERR_START 24 /* start: not a word */ -#define ROM_ERR_RANGE 25 /* "address out of range": store outside RAM */ +/* the ROM's error codes: ROM_ERR_TOO_LONG, ROM_ERR_COMMENT ... (v4/rom_errors.h) */ +#define ROM_ERR_ENUM_(name, code, text) ROM_ERR_##name = code, +enum { V4_ROM_ERRORS(ROM_ERR_ENUM_) ROM_ERR_END_ }; #define ROM_ADDR_TOP ((v4_cell)(V4_NODE_WORDS + V4_ROM_WORDS - 1u)) /* the top of the address space */ #define WORD_DEFINED (BUF0_W - 11) /* the xt of the word that is told of each new entry, or 0 */ #define WORD_FORGOTTEN (BUF0_W - 12) /* the xt of the word that is told when entries go, or 0 */ diff --git a/v4/tests/rom_harness.h b/v4/tests/rom_harness.h index 97e33421..f775bbff 100644 --- a/v4/tests/rom_harness.h +++ b/v4/tests/rom_harness.h @@ -12,6 +12,7 @@ #include "v4/testcode.h" #include "host_map.h" +#include "v4/sys_files.h" #include #include #include @@ -105,13 +106,15 @@ static void rom_boot(v4_node *n) } /* THE SYSTEM, AS THE MACHINE BUILDS IT (MACHINE.md section 6, step 1). The - * system's source, capsules/v4/sys (V4_SYS_DIR): the map, the fourteen and + * system's source, capsules/v4/sys (V4_SYS_DIR): the map, v4/sys_files.h and * the end, each followed by a new line and V4_ROM_BLOB_END, then EOT -- what v4/system/boot.c * feeds the console. rom_system_text gives it whole, *len its length; * rom_build_system has `n`, booted with its ROM, assemble it, and runs it to * its start: 1 if it started, with *words the instruction words it took. */ -static const char *const rom_system_files[] = { "core", "input", "dict", "codegen", "compile", "quit", "forth", - "numout", "words", "system", "qmath", "blocks", "log", "acl" }; +#define ROM_SYS_FILE(file) #file, +static const char *const rom_system_files[] = { V4_SYS_FILES(ROM_SYS_FILE) }; +#undef ROM_SYS_FILE +#define ROM_SYS_FILES ((unsigned)(sizeof rom_system_files / sizeof rom_system_files[0])) static char *rom_system_text(size_t *len) { @@ -119,12 +122,12 @@ static char *rom_system_text(size_t *len) char *text = malloc(cap); unsigned i; if (!text) return NULL; - for (i = 0; i < 16; i++) { + for (i = 0; i < ROM_SYS_FILES + 2u; i++) { char path[512]; FILE *f; long n; if (i == 0) snprintf(path, sizeof path, "%s/map-%d.f18", V4_SYS_DIR, V4_CELL_BITS); - else if (i <= 14) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]); + else if (i <= ROM_SYS_FILES) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]); else snprintf(path, sizeof path, "%s/end.f18", V4_SYS_DIR); f = fopen(path, "rb"); if (!f) { printf(" cannot read %s\n", path); free(text); return NULL; } diff --git a/v4/tests/test_host_rom_asm.c b/v4/tests/test_host_rom_asm.c index ee1a7c1e..c9f61745 100644 --- a/v4/tests/test_host_rom_asm.c +++ b/v4/tests/test_host_rom_asm.c @@ -11,6 +11,7 @@ #include "rom_harness.h" #include "v4/text.h" #include "rom_asm_cases.h" +#include "v4/rom_errors.h" static int failures = 0, checks = 0; #define CHECK(c,...) do{checks++; if(!(c)){failures++; printf("FAIL %s:%d: ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\n");}}while(0) @@ -38,7 +39,7 @@ static v4_cell code_of(const char *m) { "write the number", ROM_ERR_FETCH_P }, { "too many unresolved", ROM_ERR_REFS }, { "not a value", ROM_ERR_VALUE }, { "not a number", ROM_ERR_VALUE }, { "too many names", ROM_ERR_NAMES }, { "out of name space", ROM_ERR_NAMES }, - { "address out of range", ROM_ERR_RANGE }, { "without", ROM_ERR_MISSING }, + { "address out of range", ROM_ERR_RANGE }, { "text after start", ROM_ERR_AFTER }, { "without", ROM_ERR_MISSING }, }; unsigned i; for (i = 0; i < sizeof map / sizeof map[0]; i++) if (strstr(m, map[i].s)) return map[i].c; @@ -246,6 +247,43 @@ int main(void) snprintf(t, sizeof t, "store %ld 5", (long)V4_NODE_WORDS - 1); same(t); } + /* a token too long where a name or a value is wanted: "name too long", as + * text.c says, not "missing" -- the first error stands */ + { + static const char *const forms[] = { "constant %s 5", "constant K %s", "set %s 5", "set S %s", ": %s", + "store %s 5", "store 300 %s", "#, %s", "jump %s", "if %s", "\", %s" }; + static char t[160], long_tok[65]; + memset(long_tok, 'X', 64); long_tok[64] = 0; + for (i = 0; i < sizeof forms / sizeof forms[0]; i++) { snprintf(t, sizeof t, forms[i], long_tok); same(t); } + } + + /* text after start: refused, as text.c refuses it; blanks, comments and + * the blob's end after it are not text */ + CHECK(rom_run(": Z ;\nstart Z\n1\n\x04") == 0 && b.mem[ROM_FAILED] == ROM_ERR_AFTER, "text after start: refused (code %ld)", + (long)b.mem[ROM_FAILED]); + CHECK(rom_run(": Z ;\nstart Z \\ a comment\n( and another )\n\x1c\x04") == 1, "comments and a blob's end after start: started (code %ld)", + (long)b.mem[ROM_FAILED]); + { + v4_node_reset(&a); + v4_text_begin(&tx, &a, ROM_ORIGIN); + CHECK(!v4_text_assemble(&tx, ": Z ;\nstart Z\n1\n") && code_of(v4_text_error(&tx)) == ROM_ERR_AFTER, + "text.c refuses text after start too: %s", v4_text_error(&tx)); + } + + /* the ROM's error messages, as the boot prints them: one list + * (v4/rom_errors.h), its codes 1, 2, 3 ... in order */ + { + static const struct { int code; const char *text; } list[] = { +#define E(name, code, text) { code, text }, + V4_ROM_ERRORS(E) +#undef E + }; + for (i = 0; i < sizeof list / sizeof list[0]; i++) if (list[i].code != (int)i + 1) break; + CHECK(i == sizeof list / sizeof list[0], "the ROM's error codes run 1, 2, 3 ... : entry %u is %d", i, list[i].code); + CHECK(ROM_ERR_RANGE == 25 && strcmp(list[ROM_ERR_RANGE - 1].text, "address out of range") == 0, "ROM_ERR_RANGE's message"); + CHECK(strcmp(list[ROM_ERR_AFTER - 1].text, "text after start") == 0, "ROM_ERR_AFTER's message"); + } + printf("test_host_rom_asm: %d checks, %d failures\n", checks, failures); return failures != 0; } diff --git a/v4/tests/test_host_rom_nucleus.c b/v4/tests/test_host_rom_nucleus.c index 4b583ff8..bcaa0e6d 100644 --- a/v4/tests/test_host_rom_nucleus.c +++ b/v4/tests/test_host_rom_nucleus.c @@ -28,9 +28,9 @@ static int build_a(void) unsigned i; v4_node_reset(&a); v4_text_begin(&tx, &a, ROM_ORIGIN); - for (i = 0; i < 16; i++) { + for (i = 0; i < ROM_SYS_FILES + 2u; i++) { if (i == 0) snprintf(path, sizeof path, "%s/map-%d.f18", V4_SYS_DIR, V4_CELL_BITS); - else if (i <= 14) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]); + else if (i <= ROM_SYS_FILES) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]); else snprintf(path, sizeof path, "%s/end.f18", V4_SYS_DIR); if (!v4_text_assemble_file(&tx, path)) return 0; } diff --git a/v4/tests/test_host_rom_range.c b/v4/tests/test_host_rom_range.c index 070e3bb2..83e10ec2 100644 --- a/v4/tests/test_host_rom_range.c +++ b/v4/tests/test_host_rom_range.c @@ -46,6 +46,8 @@ int main(void) v4_node_rom_attach(&n, rom, 16); CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0], "the ROM reads"); CHECK(v4_node_load(&n, V4_ROM_BASE + 16) == 0, "past the ROM's words: nothing"); + v4_node_store(&n, V4_ROM_BASE, 12345); + CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0] && n.faults == 0, "C code's store into the ROM does nothing and counts no fault (node.h)"); /* RAM 16: call the ROM's word, then return */ v4_asm_begin(&as, &n, 16); diff --git a/v4/tests/test_text.c b/v4/tests/test_text.c index d1b949e6..3cb8c26e 100644 --- a/v4/tests/test_text.c +++ b/v4/tests/test_text.c @@ -540,6 +540,7 @@ int main(void) CHECK(ok(": T ; constant A 300 store A 5 store A+1 &T") && nb.mem[300] == 5 && nb.mem[301] == ORIGIN, "store puts a VALUE anywhere in RAM"); CHECK(refused("store -1 5", "address out of range", 1), "store outside RAM is refused"); + CHECK(refused("store 99999 5", "address out of range: 99999", 1), "store outside RAM names the address, not the value"); CHECK(refused("store 5", "store without a value", 1), "store needs a value"); CHECK(ok(": A ; : B ; start B") && v4_text_start(&tx) == ORIGIN + 1, "start names the word the system starts at"); CHECK(ok(": A ;") && v4_text_start(&tx) == -1, "no start: -1"); diff --git a/v4/tools/mkmap.c b/v4/tools/mkmap.c index 6114f63e..315d97ad 100644 --- a/v4/tools/mkmap.c +++ b/v4/tools/mkmap.c @@ -83,9 +83,21 @@ int main(int argc, char **argv) constant("(SYMH)", (long)ROM_SYMH); constant("SYMREC", (long)ROM_SYMREC); constant("POOLTOP", (long)ROM_POOLTOP); - constant("ERR-BAD-NAME", (long)ROM_ERR_BAD_NAME); - constant("ERR-DEFINED", (long)ROM_ERR_DEFINED); - constant("ERR-NAMES", (long)ROM_ERR_NAMES); + { + /* the ROM's error codes, ERR-TOO-LONG ... (v4/rom_errors.h) */ + static const struct { const char *name; long code; } errs[] = { +#define ROM_ERR_CONST_(name, code, text) { #name, code }, + V4_ROM_ERRORS(ROM_ERR_CONST_) +#undef ROM_ERR_CONST_ + }; + unsigned e, c; + for (e = 0; e < sizeof errs / sizeof errs[0]; e++) { + char n[40] = "ERR-"; + for (c = 0; errs[e].name[c] && c < sizeof n - 5u; c++) n[4 + c] = errs[e].name[c] == '_' ? '-' : errs[e].name[c]; + n[4 + c] = 0; + constant(n, errs[e].code); + } + } constant("(HERE)", (long)ROM_HERE); constant("(CUR)", (long)ROM_CUR); constant("(SLOT)", (long)ROM_SLOT); @@ -96,8 +108,6 @@ int main(int argc, char **argv) constant("(RN)", (long)ROM_RN); constant("RAM-WORDS", (long)V4_NODE_WORDS); constant("ADDR-TOP", (long)ROM_ADDR_TOP); - constant("ERR-FIT", (long)ROM_ERR_FIT); - constant("ERR-OPCODE", (long)ROM_ERR_OPCODE); constant("(NREF)", (long)ROM_NREF); constant("(NLAB)", (long)ROM_NLAB); constant("(WNP)", (long)ROM_WNP); @@ -130,24 +140,6 @@ int main(int argc, char **argv) constant("DICT-END", (long)DICT_END_W); constant("BUF0", (long)BUF0_W); constant("TIB-W", (long)TIB_W); - constant("ERR-IN-MACRO", (long)ROM_ERR_IN_MACRO); - constant("ERR-MACRO", (long)ROM_ERR_MACRO); - constant("ERR-LABEL-DUP", (long)ROM_ERR_LABEL_DUP); - constant("ERR-LABELS", (long)ROM_ERR_LABELS); - constant("ERR-FOR", (long)ROM_ERR_FOR); - constant("ERR-UNEXT", (long)ROM_ERR_UNEXT); - constant("ERR-TARGET", (long)ROM_ERR_TARGET); - constant("ERR-UNDEFINED", (long)ROM_ERR_UNDEFINED); - constant("ERR-BIG", (long)ROM_ERR_BIG); - constant("ERR-AMP", (long)ROM_ERR_AMP); - constant("ERR-FETCH-P", (long)ROM_ERR_FETCH_P); - constant("ERR-MISSING", (long)ROM_ERR_MISSING); - constant("ERR-DEEP", (long)ROM_ERR_DEEP); - constant("ERR-REFS", (long)ROM_ERR_REFS); - constant("ERR-VALUE", (long)ROM_ERR_VALUE); - constant("ERR-NO-START", (long)ROM_ERR_NO_START); - constant("ERR-START", (long)ROM_ERR_START); - constant("ERR-RANGE", (long)ROM_ERR_RANGE); constant("DSTACK-REG", (long)DSTACK_REG); constant("RSTACK-REG", (long)RSTACK_REG); /* the cell width's constants (NUMBER) needs, written as signed cells */ @@ -155,7 +147,5 @@ int main(int argc, char **argv) constant("DEC-LIMIT", (long)(v4_cell)(~(v4_ucell)0 / 10u)); constant("DEC-NLAST", -(long)(~(v4_ucell)0 % 10u) - 1); constant("HEX-HIGH", (long)(v4_cell)~(~(v4_ucell)0 >> 4)); - constant("ERR-TOO-LONG", (long)ROM_ERR_TOO_LONG); - constant("ERR-COMMENT", (long)ROM_ERR_COMMENT); return 0; }