Notes · Other Peoples' Talks · FOSDEM 2026 · The joys and horrors of NES dynamic recompilation
https://fosdem.org/2026/schedule/event/ETLVUA-the_joys_and_horrors_of_nes_dynamic_recompilation/
- Emulator vs recompiler
- Pros:
- Simple and flexible
- Can avoid pitfalls
- Very easy to debug
- Cons: Very slow to interpret
- Pros:
- JIT/Dynamic recompiler: the "easy" way
- When you want to run an instruction, you recompile a block of instructions
- Pros
- Usually faster than interpreters
- Can perform hot-path optimisations
- Can reuse code blocks
- Cons
- Hard to debug
- Overhead from new code
- AoT/Static Recompilation
- Recompile all of the code before running it
- Pros
- Fastest of all methods
- Can be recompiled just once, and then reused as required
- Can be easier to debug
- Cons
- Very, very difficul to implement correctly
- Cannot perform hot-path optimisations
- The project:
- NES dynamic recompiler
- C++20, LLVM ORC JIT, SDL
- Small hobby project, so:
- no self-modifying code
- doesn't handle all instructions
- can only rnu a subset of NES games
- uses an existing interpreter for PPU
- no audio
- It can run Pac-Man!
- How does it work?
- For every code block, recompile every instruction into a LLVM function
- Can restrict the amount to recompile
- Pass CPU state around as a struct to each code block function
- Regular instructions are transliterated into LLVM IR
- For conditional branching instructions, write an early return if possible to avoid recompiling the rest
- Jump/call writes address of recompiled target
- Horrors:
- Need to check for CPU interrupts in cycles, which can require cache invalidation