rzumer / dez80

A Z80 instruction decoding and (dis)assembly library.
MIT License
4 stars 1 forks source link

Provide a way to get an opcode or InstructionType from a partial decode #18

Closed rzumer closed 8 months ago

rzumer commented 9 months ago

It can be a pain to identify where we are in the decoding process when implementing an emulator, and this would avoid having to store fetched bytes elsewhere temporarily. For example DJNZ has an extended M1 cycle followed by an operand read, so at the stage where the extension has to be inserted, the decoder result is still an error, and we can't blindly fetch the operand; cycle timing is critical, because some input lines are sampled regularly at a certain clock (edge) of every machine cycle.

When fetching the opcode byte, it's not possible to identify DJNZ definitely unless we know both the opcode and the decoder state from a try_decode() call either before or after it. It can be too restrictive depending on how low-level the emulator gets.

Another example is LD (IX/IY+d), n. This is the only indexed instruction that is not in the bitwise instruction table and does not end with the displacement fetch. When this occurs, the displacement computation overlaps with the final fetch cycle. But since the decoder state (when invoking try_decode() with each pushed byte) goes RootOpcode, IndexedOpcode, IndexedOperand, IndexedOperand, we can't distinguish between other indexed 4-byte instructions unless we know the full context of the decoding process. So we either need to save some more intermediary information or add IndexedDisplacement to replace IndexedOperand when the next value that the decoder needs is the displacement.

rzumer commented 8 months ago

Displacement DecoderState variants added in #21.

For DJNZ it's a little more complicated, so I don't know if I'll implement some other way to identify it more easily. There are multiple relative jump root instructions, so it's not possible to rely solely on the RootDisplacement state, but matching the opcode byte or the decoded instruction type after obtaining that state variant and pushing the operand byte is doable even if it's not the most elegant solution. I'm not keen on decomposing incomplete decodes further into partial instructions because of the performance implications.