EWM Update: Illegal Instructions

Today I found out that ProDOS 2.4.1 crashes in my Apple ][+ emulator. Very early on when booting a disk, even before it displays the welcome screen. This is odd because ProDOS 2.4.1 is supposed to be compatible with any Apple II model that has 64KB of RAM.

EWM Boot Loader

After some sleuthing I figured out what is happening here. The big hint is what the emulator prints:

CPU: Exited because of unimplemented instruction 0x1a at 0x2095

This is a good hint. The Apple ][+ uses a 6502, and for that CPU there is no instruction with opcode 0x1a. It does exist on the 65C02, which later models of the Apple II family use, where it is the INC, Increment Accumulator, instruction.

ProDOS 2.4.1 is supposed to run on all models, including the 6502, so why is this happening? Are we trying to execute some random invalid code in memory or is there something else happening?

Looking at the code around 0x2095 we can see this:

2093: A9 00    LDA #$00
2095: 1A       ???       ; Invalid on 6502, INC on 65C02
2096: D0 11    BNE $20A9

It is now pretty clear what this does. This is code to detect the CPU type.

On a 6502 the $1A instruction is invalid, but it does does not halt or interrupt the the CPU. On the 65C02 it increments the accumulator. The above CPU detection code takes advantage of that: on a 65C02, the accumulator wil increment to 1 and the branch to $20A9 will happen. On the 6502 the accumulator stays zero and the branch will not happen.

The problem is that my emulator does not handle illegal instructions correctly. It incorrectly triggers an interrupt, which puts the program counter at 0x03FE, which is what we see in the screenshot too.

(Ending up at 0x3FE is actually not correct since the interrupt handler is at 0x03FB. So maybe that is another bug.)

I fixed this with a patch that does two things:

  • I brought back the --strict option for the emulator. If --strict is enabled, then the emulator will immediate abort if it encounters an invalid instruction. This is not correct behaviour, because the 6502 does not actually do this in real hardware, but it can be used o verify that programs are correct.

  • I aliased all unimplemented 6502 instructions to nop. So they are simply ignored. This is also not entirely correct because some of those instructions have undocumented behaviour that some programs may take advantage of.

For now this is a decent fix. ProDOS 2.4.1 boots again. Maybe some day I will try to implement the undocumented behaviour of the 6502.

If you are interested in playing around with my emulator, you can find the project at github.com/st3fan/ewm.

This is a post in the Emulated Woz Machine series. Other posts in this series: