OXYGENHUB
◆ rrdc-perf enhanced-x16-emulator / src / cpu history
..
.editorconfig …
6502.opcodes …
65c02.h …
65c02.opcodes …
65c816.opcodes …
buildtables.py …
extract.py …
fake6502.c …
fake6502.h …
instructions.h …
irq_ctx.c …
irq_ctx.h …
mnemonics.h …
modes.h …
README …
registers.h …
support.h …
tables.h …

The original fake6502.c has been split up into subcomponents, rather than being one long file - support functions, 6502 instructions, address modes, data tables and 65c02 extensions.

The file tables.h is now created from 6502.opcodes and 65c02.opcodes which are lists of instructions, cycle times, address modes and opcodes.

The python script buildtables.py creates this.

Minor changes have been made to modes.h and instructions.h to correct for 65C02 behaviour. These are documented in the files.

Breaking Changes

Note: these breaking changes are only in the emulator. The behaviour is correct for a 65C02, which is almost but not the same as a 6502.

(1) BRK clears D after pushing on the stack. Probably unimportant as most routines in 6502 code CLD to get round this issue anyway.

(2) ADC/SBC In Decimal Mode, these now set N and Z flags. They did not previously. It is possible that code may rely on this to preserve flag status through an ALU operation but unlikely.

(3) JMP The absolute indirect mode JMP (xxxx) had a bug where JMP ($12FF) got its target address from $12FF and $1200. This bug is corrected. This could break code with oddly positioned jump tables. Even align any vector tables or memory vectors.

(4) (Misc) Undocumented instructions now do not work. They don't work on a 65C02.

Also note that read-modify-write instructions all now do not do the double write. ASL xx would do read xx ; write xx ; write shifted xx on a 6502. On a 65C02 it does not. However, the emulator did not emulate this behaviour anyway, so it doesn't actually matter.

Paul Robson 4/Sep/19

Testing

Fixed stz bug .... writing a ... duh !

Conformance fixes

Found by tests/test_processor_tests.c, which runs SingleStepTests against the core. Each changes emulated behaviour, so code that depended on the old behaviour will see a difference.

(1) P bit 4 Was forced set on every instruction for the 65C02, which applies the 65C816's emulation-mode rule to the wrong CPU. Bit 4 has no register bit behind it on a 65C02 and is now preserved. PLP and RTI no longer load it from the stack.

(2) $5C $DC $FC Were one-byte implied NOPs, so their operand bytes were executed. Now three bytes, as on a real 65C02. $5C is 8 cycles per the WDC datasheet and the 6502.org opcode list; SingleStepTests says 4, and that divergence is recorded in the baseline rather than matched.

(3) SBC Decimal mode used the NMOS per-nibble correction. The 65C02 subtracts in binary and corrects afterwards. The two differ only when a digit is $A-$F. Overflow was also computed from the carry the instruction had just written rather than the one it started with.

(4) BRK Cost 14 cycles: interrupt6502() charges seven for the interrupt sequence, which BRK also pays through the opcode table. IRQ and NMI still need it, as neither goes through the table.

(5) Timing JMP (abs) is 6 cycles, not the NMOS 5. ASL, ROL, LSR and ROR abs,X are 6 plus one only when indexing crosses a page, where the NMOS always paid it. BIT abs,X gains the same conditional cycle. The variant opcode files may now override 6502.opcodes rather than only adding to it.

(6) 65C816 A 16-bit operand costs an extra cycle, which only LDA charged. PHX, PHY, PLX and PLY charged the accumulator width instead of the index width, and TSB charged nothing.

(7) 65C816 (dp), (dp,X), (dp),Y and (sr),Y ignored the data bank and used bank 0. Indexing now carries past $FFFF into the next bank.

The read-modify-write double write noted above is still not emulated, and shows up as a bus-trace divergence in the same tests.