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.