High Performance Z80 Emulation
floooh.github.io
floooh.github.io
If you've never tried to write an emulator I highly recommend it. In my opinion it's an exercise on par with writing a compiler, in terms of how much one can learn about these machines we work with and just developing a richer appreciation for the craft of software.
I don't know about the reasonable effort part, but I was able to get decent performance with this approach in BlastEm. It takes about 33.5s to run zexdoc on my laptop, which is faster than even the "instruction granularity" version in the article (~37.5s) despite running on a slower machine (2.2GHz base clock vs 2.8GHz base clock). It can pause both at the beginning of an instruction and at any non-instruction fetch memory access. Unfortunately, it can't currently accommodate wait-states on instruction fetch.
Fixing that is on my to-do list and I have a decent idea of how to do it without killing performance. I'm also flirting with a re-write of that will enable better performance generally. My current approach is pretty naive (doesn't even do redundant flag calculation elimination), but my handling of self-modifying code makes it hard to safely improve that without some fairly major changes.
I made my own emulator with no jump table or loop, and so no need to save and restore flags. It comprised just three instructions.
lodsb
mov ah,al
jmp ax
These instructions were appended to the emulation code for each of the 256 opcodes which were distributed sparsely through 64K of memory at 0x0000, 0x0101, 0x0202 etc. (no such thing as a free lunch - spending 64K of RAM to get some speed seemed like a daring decision at the time). So my emulator was inherently only 4 times slower than native, and faster PC hardware made up the difference much earlier for me than for people stuck with 10 times slower emulators.Of course these days it would probably mean the difference between running the 8 bit code 1000 times faster or 2000 times faster than native (something like that). Rather than going as fast as possible, the challenge now is accurately reproducing the original timing, as discussed in the article.
I'll quietly admit that the 8 bit software I was using extensively at the time ran happily on an 8080, and I never did all the extra work required to get Z80 emulation.
Like others, my dream is writing a Z80 emulator, even though others exist, just to do it. I'm going to write mine in Objective-C (my favorite language) to provide and interface to emulators (like a TI-8X one).
Reading this just gets me excited.
I've always got time to read more about low-level Z80 coding.
It's basically how my writing comes out on the first go, no distraction here :)
I hope my comment didn't come across as anything other than the constructive criticism it was intended as.