velxio/test/test_intel/test_z80/README.md

130 lines
5.6 KiB
Markdown
Raw Normal View History

# test_z80 — Zilog Z80 as a velxio custom chip
See [../autosearch/02_intel_chips_overview.md](../autosearch/02_intel_chips_overview.md#zilog-z80-1976)
for the spec.
## Status
**Implemented (core).** 6/13 active tests pass; 7 are `it.todo`
deferred milestones. ~550 LOC clean-room C in `z80.c` compiled to
`fixtures/z80.wasm`.
Validated against:
- Zilog Z80 Family CPU User Manual UM008003-1202 (2002 reprint of the
canonical doc; PDF at `autosearch/pdfs/z80_user_manual.pdf`)
- Sean Young, "The Undocumented Z80 Documented" v0.91 (PDF at
`autosearch/pdfs/z80_undocumented.pdf`)
- Cross-checked against `floooh/chips/z80.h` (zlib),
`superzazu/z80` (MIT, passes ZEXALL), `kosarev/z80` (MIT)
What works:
- 40-pin contract, M1 cycle (M1̅+MREQ̅+RD̅ asserted simultaneously),
RFSH̅ pulse with R counter and I driving the address bus.
- 8080-superset ISA: LD r,r' / LD r,n / LD rr,nn / LD (nn),A / LD A,(nn) /
ALU / INC / DEC / 16-bit ADD HL / rotates / control flow / stack.
- Z80-only: EX DE,HL / EX AF,AF' / EXX / DJNZ / JR / LDIR / LDDR / NEG
(8 aliases) / IM 0/1/2 / EI / DI / IN / OUT.
- DD/FD prefix → IX/IY substitution for HL-using opcodes (incl. (IX+d)
with displacement byte).
- ED prefix → block ops, IM, NEG, RETN/RETI, LD (nn),rr / LD rr,(nn).
- NMI̅ falling-edge → push PC, vector to 0x0066 (without IFF1→IFF2
copy, per Sean Young's hardware tests, contradicting Zilog's manual).
Deferred until ZEXDOC/ZEXALL integration phase:
- X (bit 3) and Y (bit 5) "undocumented" flag bits — required by ZEXALL
but no current test exercises them.
- MEMPTR (WZ) register — only observable through `BIT n,(HL)`.
- CB-prefix bit ops (BIT/SET/RES/RL*/RR*/SLA/SRA/SLL/SRL).
- Block I/O instruction flags (full deterministic rules per Sean Young
§4.3 — currently approximate).
- DAA's full Z80-specific table (currently uses an 8080-equivalent
approximation — will diverge for N=1 cases).
- Cycle-accurate WAIT̅ and contention timing.
## Pin contract (40-pin DIP)
| Group | Pins | Dir |
| ------------ | ------------------------------------------------------------- | --- |
| Address bus | `A0..A15` | out |
| Data bus | `D0..D7` | I/O |
| Memory ctrl | `MREQ̅`, `RD̅`, `WR̅`, `RFSH̅` | out |
| I/O ctrl | `IORQ̅` | out |
| Cycle marker | `M1̅` | out |
| CPU state | `HALT̅` | out |
| Wait/sync | `WAIT̅` | in |
| Interrupts | `INT̅`, `NMI̅` | in |
| Bus arb | `BUSREQ̅`, `BUSACK̅` | I/O |
| System | `CLK`, `RESET̅` | in |
| Power | `VCC`, `GND` | power |
Total: 16 + 8 + 4 + 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 = **40 pins**
all 40 of the real DIP. No power simplification needed (single 5 V rail).
## Bus cycle reference
The Z80's bus is closer to "what you'd design today" than the 8080's:
```
M1 (opcode fetch):
T1: drive A0..A15, assert M1̅, MREQ̅ then RD̅
T2: sample D0..D7
T3: deassert RD̅, MREQ̅; assert RFSH̅; drive A0..A6 with R register
T4: deassert RFSH̅
Memory read (non-M1):
T1: drive A0..A15, assert MREQ̅
T2: assert RD̅, sample D0..D7
T3: deassert RD̅, MREQ̅
Memory write:
T1: drive A0..A15, MREQ̅
T2: drive D0..D7, assert WR̅
T3: deassert WR̅, MREQ̅
I/O read/write:
Like memory but with IORQ̅ instead of MREQ̅.
```
We faithfully drive `M1̅` and `RFSH̅` so dynamic-RAM-style wiring works
in user demos.
## Why the Z80 is the high-value target
- **Recognisable.** ZX Spectrum, MSX, GameBoy CPU (modified Z80),
CP/M machines, MAME arcade boards. Users *will* try to wire one.
- **Best documented.** The full instruction set, including undocumented
flags, has been reverse-engineered.
- **Best reference emulator.** `floooh/chips/z80.h` is single-header,
cycle-accurate, MIT-licensed.
## Implementation plan
1. Spike: `LD A, n`, `OUT (n), A`, `JR n`, `HALT` only. Drive an LED
from a memory-mapped port. Confirms the bus state machine works.
2. Port `floooh/chips/z80.h` into `z80.c` as the decoder core. Adapt
the bus interface from "callback function" style to "drive velxio
pins" style.
3. Run ZEXDOC / ZEXALL — the canonical Z80 documented/all-flags self
tests. These boot CP/M-style and print results to a UART.
4. Add `INT`/`NMI` handling. Implement IM 0 / IM 1 / IM 2.
5. Stretch: hook a ZX Spectrum ROM and a 16K RAM chip; see if the
Spectrum boot screen renders. (Display would be a separate chip.)
## Target demo sketch
Same as 8080 (UART hello world) so we can compare the two chips
side-by-side on the canvas. Then a Z80-only second demo using the
shadow registers (`EXX`) — something the 8080 cannot do — to show
the Z80's expanded ISA.
## Files to create later
- `z80.chip.json`
- `z80.c` (likely split into `z80_core.c` + `z80_decode.c` if the
ported decoder is large)
- `vendor/` for any vendored MIT-licensed reference code (or move
refactor: rename wokwi-libs/ → third-party/ The directory grew well beyond Wokwi-only contents: it now hosts lcgamboa's QEMU fork (qemu-lcgamboa), Espressif's esp32-camera, the ngspice WASM build, fritzing-parts, picowi, an alternative QEMU (qemu-esp32), the 100_Days_100_IoT_Projects examples repo, and Wokwi's own avr8js/rp2040js/wokwi-elements/wokwi-features/wokwi-boards. "wokwi-libs" was misleading — half the contents have nothing to do with Wokwi. "third-party/" is the standard convention for vendored external dependencies. Mechanical changes: Path rename: wokwi-libs/ → third-party/ update-wokwi-libs.bat → update-third-party.bat docs/WOKWI_LIBS.md → docs/THIRD_PARTY.md Submodule reconfiguration: .gitmodules — 4 path= and section names updated .git/modules/wokwi-libs/ → .git/modules/third-party/ each submodule's .git file rewired to ../../.git/modules/third-party/<name> Reference updates (~80 files): vite.config.ts aliases, Dockerfile COPY paths, GH Actions workflow steps, build_qemu_*.sh, all docs/* and test/*/autosearch/* entries that mention the path, package-lock.json file: dependencies, .gitignore patterns, sitemap.xml + index.html SEO blurbs, scripts/generate-component-*, .dockerignore, .idea/vcs.xml. Bulk replaced both `wokwi-libs/` (path) and bare `wokwi-libs` (textual mentions in docs/comments). Verified: - npx tsc -b --noEmit produces no new errors related to these paths - vite.config.ts aliases now point at ../third-party/avr8js etc. - All 4 git submodules (avr8js, rp2040js, wokwi-elements, wokwi-features) are linked under third-party/ with their worktrees re-populated and config files referencing the new path - `grep -r wokwi-libs` returns zero hits outside node_modules, .vite, frontend/dist, third-party/ (upstream submodule contents), *.pyc caches, and *.dll.pre-camera rollback binaries Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:58:57 +07:00
to `third-party/cpu-cores/` per the open question in
[../autosearch/05_open_questions.md](../autosearch/05_open_questions.md#q2-where-exactly-should-vendor-emulator-cores-live))
- `roms/zexdoc.bin`, `roms/hello.bin`
- `z80.test.ts`