So I completed the refactoring of the instruction decoding to allow two sources and two destinations. I’m pretty pleased with the results. It’s allowed me to completely eliminate several operations from the decoding code. All the jumps, calls and returns (except
RETI, which is not implemented yet and
RET cc which requires the stack to be popped only if the condition is true) have been eliminated and re-implemented as 16 bit loads or 16 bit conditional loads (i.e. a load that only happens if one of the flags is in a certain state). Also, the exchange instruction is now implemented as a 16 bit load that just reverses the operands.
The refactored Z80 seems to be running at about 240MHz for the whole of the ZEXALL test. However, I did notice some anomalies. At one point, it appeared to be running at around 360MHz but at the same time, the user interface got completely bogged down. My thought was that under normal circumstances, the UI updates were throttling the performance. I changed the code to do updates every 0.1 seconds instead of every 100,000 t-states (in retrospect, that was obviously too short) and, now, with all the changes, things have settled down to around 240MHz. Abstracting the operand fetches and result saves as function calls seems to have been a big drag, accounting, as far as I can tell, for most of the loss of performance from 360MHz.
As a further improvement, I am seriously considering making the a register and all of the general purpose registers full width unsigned integers. However, for now, I’m going to start building the Spectrum.