Convert 7 outstanding it.todo markers into actual passing tests now
that the chips and bus infrastructure can support them:
- 4004 LDM: ACC observed via SRC + WMP X2 bus drive
- 4004 FIM: register pair observed via SRC X2/X3 nibble drives
- 8080 hand-built loop: LXI/MVI/INR/DCR/JNZ decrements counter
- Z80 IM 2: vector table at I:00 → ISR via INT̅ low
- 8086 1 MB wrap: DS=0xFFFF + offset 0x11 lands at physical 0x00001
- 8086 ALE pulse: counts ALE rising edges per bus cycle
- 8086 AD release: external drive sticks during T2 (chip released)
- 8086 hello-world: 5 MOV BYTE [imm], imm writes to memory-mapped
"UART" at DS:0x9000; bus capture + RAM peek verify "Hello"
Plus: remove redundant 8080 CPUDIAG and Z80 ZEXDOC todos — the
actual end-to-end runs already pass in dedicated cpudiag.test.js
and zexdoc.test.js files.
Suite is now 125/126 passing, 1 todo (Busicom 141-PF demo, awaiting
firmware ROM), 0 failed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First test wiring the 8086 CPU to a real 8259 PIC chip on the same
board and proving hardware-interrupt routing works end-to-end:
IRQ0 input → PIC asserts INT → CPU's INTR pin → CPU runs INTA
cycle → PIC drives vector 0x40 on AD bus → CPU does do_int(0x40)
→ fetches CS:IP from IVT entry at 0x100 → ISR runs → IRET → main
resumes from HLT.
Two related chip fixes required to make this work:
1. 8086 INTA cycle no longer drives AD itself.
Real 8086 INTA bus cycle has the PIC drive the data lines, not
the CPU. My earlier code did `bus_read_byte(0, false)` which
first drove AD with addr=0, overwriting whatever the PIC had
driven. Fix: release_ad → INTA̅ low → sample AD (PIC's INTA
watcher fires synchronously and drives) → INTA̅ high.
2. 8086 HLT now interruptible.
on_clock previously early-returned on G.halted, so step()
never ran and the INTR check never executed. Real 8086 HLT
wakes on INTR/NMI. Fix: remove the early return; step()'s
own halted check (later in the function) only no-ops if no
pending interrupt.
Tests: total test_intel 110 → 111 passing (+1, the integration
test). 0 failed. 11 todo. test_8086 now 11→12 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root cause of the deferred CALL/RET test: my chip was missing the
0xC6 / 0xC7 (Group 11 — MOV r/m, imm) opcodes. Bytes like the
test's "MOV byte [0x8002], 0x55" (0xC6 0x06 0x02 0x80 0x55) fell
through to the default NOP, then the chip decoded the residual
0x06 0x02 0x80 0x55 as PUSH ES + ADD r/m + ... taking SP into
unpredictable territory.
Implementation:
- 0xC6 (8-bit) and 0xC7 (16-bit) variants added.
- The encoding is opcode + modrm + disp + imm. Critically the disp
bytes (consumed by calc_ea) come BEFORE the immediate, so we
compute EA first, then fetch imm. Earlier draft had imm fetched
before disp — that had imm winning the disp slot and disp becoming
the next instruction's bytes. Caught only after wiring CALL+RET.
Tests: 8086 10→11 passing. Total test_intel: 93→94 passing,
0 failed, 11 todo. CALL/RET integration test now active and green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All 5 retro CPUs (Intel 4004/4040/8080/8086 + Zilog Z80) plus all 3
bus devices (rom-32k, ram-64k, latch-8282) are now implemented.
Update top-level matrix and per-chip READMEs to reflect 63/80 tests
passing, 0 failed, 17 deferred.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>