ADR 0014 — v1.11.0: 65816 interrupts, remote bank reads, WASM 65816¶
- Status: Accepted
- Release: v1.11.0 (2026-07-08)
- Theme: The post-v1.10.0 tail — finishing the 65816's hardware-interrupt correctness, extending bank-awareness to the remote DAP path, and exposing the 65816 in the hosted WASM playground. Per-release decisions fold in here.
D1 — 65816 hardware interrupt handling (#511/#512)¶
-
Context: the 65816 core (#456) is Tom Harte-validated for all 256 opcodes (state + full pin bus trace), but the corpus is opcodes-only — it never tests hardware IRQ/NMI.
serviceVector(cpu/cpu.go) is 6502-only, so a hardware interrupt onVariantW65816used the 6502 vectors ($FFFE/$FFFA) even in native mode, pushed via the page-locked 8-bit stack, and never pushed PBR or cleared D. -
Decision:
serviceInterrupt816(vecEmu, vecNat)mirrors the existingbrk/cop(cpu/ctrl816.go) minus the signature-byte read, pushing P with the B bit clear (hardware, not a software BRK). Emulation pushes PC16+P at $FFFE/$FFFA (7 cycles); native pushes PBR+PC16+P at $FFEE/$FFEA (8 cycles). Both force PBR=0, set I, clear D, and read the vector through the 24-bit bus (pinVector).serviceNMI/serviceIRQbranch to it for the 65816. -
Consequences: 6502/CMOS/NES interrupt paths are byte-for-byte untouched. ABORT ($FFF8/$FFE8) is out of scope — no abort source exists (tracked in the epic #517 / #518). Interrupt-entry per-cycle bus-trace validation is deferred (#519) — the entry passes state + cycle-count checks, but Harte gives no hardware-interrupt reference.
D2 — Remote 65816 bank reads over DAP (#510/#516)¶
-
Context: the bank-aware bus (#505, ADR 0013) made the local source and the DAP server bank-aware, but
RemoteSource(internal/tui/source_remote.go) still served all memory from its 64 KiB bank-0 mirror, so a remote 65816's banks 1-255 were invisible over-dap-attach. -
Decision:
RemoteSource.ReadMemory/Disassemblebranch on the bank — bank 0 stays on the fast local mirror (reconciled byRefreshMemory+ #440 dirtyRanges, no per-frame round-trip); banks 1-255 fetch lazily over the wire vias.client(the remote server is bank-aware since #505/#507). -
Consequences: no mirror widening and no cross-bank
dirtyRangesneeded — the earlier ADR-0013 plan (a lazy per-bank page cache) proved unnecessary at this scale. Memory-panel windows never straddle a bank (memWindowForclamps within 64 KiB), so the per-window bank test is exact. Correctness-on-paper: no remote 65816 host exists in-tree (-dap-attachtargets stay 6502/NES), but the path is right and tested (TestRemoteSource_ReadMemory_BankOverWire).
D3 — 65816 in the WASM playground (#514/#515)¶
-
Context: the hosted playground (
cmd/chippy-wasm+web/) could select nmos/65c02/nes but not the fully-built 65816 —jsSetVariantlacked the case andrebuild()never calledSetBus24. -
Decision: add the
65816variant case +Banked24wiring inrebuild()(bank 0 through MMIO so the readMem/disasm panes stay accurate), theWDC 65C816dropdown option, and a native-mode demo. The demo (web/demos/hello816.bin, sourceexample/hello816.s) is hand-assembled and execution-verified against chippy's own 65816 core byexample/gen_hello816.go(go run, no cc65 on PATH).loadDemoapplies a demo'svariantbefore loading. -
Consequences: existing bank-0 demos run on the 65816 immediately (emulation mode is 6502-compatible). The browser panes stay bank-0 — a playground bank selector is deferred (#521). The
go rungenerator is the demo's provenance + regression check, kept in-tree under//go:build ignore.