perf(cpu): code-generate the opcode dispatch table - #67
Open
eduardovra wants to merge 1 commit into
Open
Conversation
Replace the decorator + string-arg instruction table with per-opcode handlers generated from a compact spec. Memory/modify families (187 opcodes) are emitted as inlined literal handlers — index register, width flag, and operation/source baked in, so PyPy folds them per-opcode trace (~2x faster dispatch on hot read/write instructions; the shared decorator+string dispatch could not). The irregular ops (69: branches, jumps, calls/returns, flags, transfers, push/pull, block move, interrupt, exchanges) are emitted as thin handlers that delegate to the existing addressing functions. opcodes_spec.py compact spec (source of truth) scripts/gen_opcodes.py generator (edit spec -> regenerate -> commit) opcodes_generated.py committed generated handlers + HANDLERS instructions.py 3-line adapter over HANDLERS Removes the now-inlined read.py/write.py/modify.py addressing-mode functions. cpu.py is untouched, so existing save states are unaffected. Verified: 6144 Tom Harte SingleStepTest cases (all opcodes x both M/X widths) and the full unit suite pass; regenerator output is reproducible. Dispatch ~2x faster in a micro-benchmark; in-game effect is within noise (dispatch is a small slice of frame time) — the win here is architectural uniformity.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the WDC 65816 decorator + string-arg instruction table with per-opcode handlers generated from a compact spec. All 256 opcodes now dispatch through generated
op_NN(cpu)handlers; the old table is retired.decorator + string-argdispatch couldn't (the index/flag arrived as runtime args shared across opcodes). ~2× faster dispatch on hot read/write instructions.BlockMove/Interrupt/control-flow.Layout
opcodes_spec.pySPEC+MISC_SPEC)scripts/gen_opcodes.pyuv run scripts/gen_opcodes.py→ commitopcodes_generated.pyHANDLERSinstructions.pyINSTRUCTIONSfromHANDLERSscripts/bench_cpu.pyRemoves the now-inlined
read.py/write.py/modify.pyaddressing-mode functions.cpu.pyis untouched → existing save states are unaffected.Verification
bench_cpu.py(≈125 ns → ≈45 ns/instruction on hot indexed ops).Honest scope note
The dispatch speedup is real on the micro-benchmark, but the in-game effect is within measurement noise — dispatch is a small slice of total frame time (the rest is the operations, register access, APU, PPU). The primary value here is architectural uniformity (one spec-driven dispatch system, retiring the decorator+string table and ~570 lines of hand-written addressing-mode functions), not felt FPS.
🤖 Generated with Claude Code