Finishing up my ZX81 on the CH32V006

I’ve finished my Z80 emulator for the CH32V006. It was interesting experimenting with different interpreter architectures as the CH32V006 is RISC-V and the performance was very sensitive to the compiler and architecture. In the end, a threaded interpreter using computed gotos was 2 x faster than the other architectures but only on GCC. All other combinations of (switch, threaded, tail call) x (clang, gcc) performed about the same.

According to zexdoc the system performs like a 4.2 MHz Z80. The ZX81 runs at 3.25 MHz and spends most of its time drawing the screen, giving an effective frequency of 0.8 MHz, so this emulator is ~5 x faster than the original.

Some highlights of the final version:

  • Includes a ZX81 and RC2014 emulator
  • Runs the ZX81 ROM and the zexdoc test suite
  • Core dispatch is generated from the https://github.com/deeptoaster/opcode-table machine-readable description
  • Generates threaded and tail call interpreters
  • Supports reducing the code size by re-using the dispatch code for infrequent instructions
  • IO backends for native Linux and Zephyr
  • Runs over the serial port, emits the UTF-8 versions of the ZX81 character set, and only updates the parts that changed between refreshes

There’s two interesting follow on projects. I’d like to change anything heavy, such as the IN, OUT, or LDIR to an emulator exits as I suspect that will let the compiler inline the core instructions without the extra register pressure of handling heavy instructions. I also have a custom CH32V006 board with 8 MiB of PSRAM and 16 MiB of flash which is more than enough to run the RC2014 version of CP/M.

Avatar
Michael Hope
Software Engineer