gianlucag / mos6502

A fast & simple MOS 6502 CPU emulator written in C++
MIT License
286 stars 56 forks source link

The dummy read before stack pulls doesn't seem to happen #16

Open omarandlorraine opened 1 year ago

omarandlorraine commented 1 year ago

The stack pointer hardware in the 6502 can only update the stack pointer after the stack access has happened. So, it decrements the stack pointer after pushing a value onto the stack, so that the stack pointer is ready for another push.

But when pulling, this means it has to pull some dummy data (just to update the stack pointer) before pulling the real data.

It looks as though gianlucag/mos6502 does not do this dummy read. While executing a plp instruction, which is a four-cycle instruction, gianlucag/mos6502 performs only two memory reads:

  1. the opcode byte
  2. the PSW from the stack

but the real chip will perform the following four memory reads:

  1. the opcode byte
  2. the next byte in the instruction stream (all instructions do this in cycle two, while the instruction is being decoded, just in case)
  3. the byte immediately below where the PSW is about to be read from
  4. the PSW from the stack

Exactly the same problem affects other instructions that read from the stack: rts, pla, and probably also rti.

gianlucag commented 1 year ago

Feel free to open a PR for this issue

essial commented 1 month ago

For anyone who winds up here because they are testing this against cycle-accurate unit tests, note that although this project listed "100% cycle accuracy" as "still to implement". This emulator is fundamentally unable to execute at a cycle-accurate level as the entire thing is built around instruction-accurate code. Cycle accurate code requires a very different (and more CPU intensive) microcode-centric approach.

gianlucag commented 2 weeks ago

For anyone who winds up here because they are testing this against cycle-accurate unit tests, note that although this project listed "100% cycle accuracy" as "still to implement". This emulator is fundamentally unable to execute at a cycle-accurate level as the entire thing is built around instruction-accurate code. Cycle accurate code requires a very different (and more CPU intensive) microcode-centric approach.

Please have a look at https://emulation.gametechwiki.com/index.php/Emulation_accuracy

Strictly speaking, this emulator is cycle-based accurate but not full-cycle accurate, meaning that it reproduces the system's functional behavior within a specified number of cycles (specified in the Run() method). The provided cycle amount is executed as fast as possible.