Run-time detection of i8085, z80 & LR35902
Silly project as a consequence of the previous post, let’s make a piece of code that will run on all three CPUs and generate three execution paths, one for the z80, one for the i8085 and one from the GameBoy’s LR35902.
Detecting the i8085
For detecting the i8085 we will exploit the difference on byte 0x20
which
on the i8085 translates to RIM
(Read Interrupt Mask) opcode and on the z80
and LR35902 is a two-byte relative jump JR NZ n
. The code is the following:
Offs. | Bytes | i8085 | z80 and LR35902 (GB) |
--------------------------------------------------------------------------
??00h | 00 | NOP | NOP |
??01h | AF | XRA A | XOR A |
??02h | 3C | INR A | INC A |
??03h | 20 20 | RIM | JR NZ ??25h |
| | RIM | |
??04h | ?? | [i8085-only path] | |
[...] | | | |
??25h | ?? | | [z80 and GameBoy execution path] |
To trigger two different execution paths first we set the A
register to zero
then incrementing it, clearing the Zero flag, so when execution hits ??03h
on the i8085 RIM
is executed twice while on the z80 a relative jump is
taken, thus telling the i8085 aside from the other two CPUs.
Detecting the z80
For setting aside the z80 and the LR35902 we will exploit another one byte
opcode, this time 0xD9
which on the z80 corresponds to EXX
and on the
GameBoy is RETI
. Presuming the SP
is correctly set, performing a CALL
to the following code will generate two different execution paths on the z80
and on the GameBoy:
Offs. | Bytes | z80 | LR35902 (GB) |
------------------------------------------------------------------------
??01h | D9 | EXX | RETI [return to GB path] |
??02h | D9 | EXX | |
??03h | 33 | INC SP | |
??04h | 33 | INC SP [Fix SP] | |
??05h | ?? | [z80-only code path] | |
Calling the ??01h
address on a GameBoy will immediately return to the caller,
while on a z80, it will execute EXX
twice (no effect) and then fix the SP
register (discard the CALL
return address) and continue on the z80-only code
path.