Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPC700 tests never start with H-flag set #18

Open
angelo-wf opened this issue Oct 2, 2022 · 5 comments
Open

SPC700 tests never start with H-flag set #18

angelo-wf opened this issue Oct 2, 2022 · 5 comments

Comments

@angelo-wf
Copy link

The generated SPC700 tests never start with the H-flag set, meaning opcodes that depend on its state are not tested fully for correctness. This affects DAA (0xdf), DAS (0xbe) and CLRV (0xe0). Additionally, other opcodes could clear it accidentally and not be caught by the tests as they are now.

It looks like this is caused by the generator wanting to never start tests with the B-flag set, but masking off the wrong bit in the PSW by mistake. It's probably better to not mask off any bits, as never starting with the B-flag set would mean it doesn't check for opcodes accidentally clearing it.

@raddad772
Copy link
Owner

Excellent, thanks for finding this! I fixed & pushed. Out of curiosity, do you have an SPC700 core that passes or is in conflict with the tests? SPC700 isn't super widely used unlike some, so having people test these is a great blessing.

@angelo-wf
Copy link
Author

angelo-wf commented Oct 5, 2022

I do now have a SPC700-core that passes all of the (old) tests (haven't tested with the new set yet) as part of (eventually) getting back to working on my SNES emulator LakeSnes.

While getting the tests to run I did run into some possible problems:

  • wai and stp seem to generally be listed as taking 3 cycles, but the tests have 7, with 2 sets of a read from PC + idle cycle being extra.
  • Reads from PC that are really just idle cycles (second cycle of instructions that would have an idle cycle) are listed as having null as the read value. With the way I was running the tests this was interpreted as the value being 0. For all but one test this didn't matter as I cleared RAM to all zeroes before running and it always read a 0, but for dbnz y, rel (0xfe) it reads the relative offset in that cycle, which was of course rarely 0. It might be better to explicitly define these values in RAM instead of having null as the value.
  • One issue, which might actually end up being an inaccuracy in higan/ares as well, is that indirect indexed reading opcodes (and/or/eor/adc/sbc/cmp/mov a, (dp)+y) have the idle cycle at a different spot than the writing opcode mov (dp)+y, a. The write has the idle cycle after fetching the pointer (5th cycle), which matches the 6502's garbage fetch for (zp), y, but reads have it instead after reading the direct page address, like where (dp+x) has it (3th cycle). The cycle timing document by Overload claims that reads and writes have this cycle in the same place, after the pointer fetch. It doesn't really make sense for it to differ for this one addressing mode and for it to not match the 6502 like for the other addressing modes. That document also matches higan/ares and these tests perfectly for all other opcodes expect those 7.

@raddad772
Copy link
Owner

raddad772 commented Oct 5, 2022 via email

@raddad772
Copy link
Owner

So investigating 0xFE, we have a test where..

cycle 1: read instruction
cycle 2: read, but we don't care about the value, since it isn't actually used as the operand
cycle 3: idle
cycle 4: here is where the operand we use is actually fetched

IIRC I remember reading a thread about this. This behavior was determined by reading from the built-in timers in the SNES and using that as a branch offset, to measure which cycle the read actually latched on. I can't come up with source but I'm fairly confident in it. This gels with the Higan/Ares source. Mesen-S also agrees with this behavior, and SNES9x disagrees.

In regards to EOR A, [dp]+Y aka opcode 0x57, the tests agree with Higan and SNES9x but disagree with Mesen-S. Higan and SNES9x include separate code for this difference specifically, whereas Mesen-S re-uses the same addressing code between opcodes.
Again, I'm (reasonably) certain that Higan's behavior was verified using carefully timed code running on real SNESes. But...I again can't find a source.

Probably this specific thing could be a generation-time option if you'd like, unless I track down the thread on the topic. Or look at git blame for those lines...It would certainly be easy enough to make it so. If it's good enough for SNES9x, it should be good enough for almost everyone else.

@raddad772
Copy link
Owner

I'm going to mark this as closed due to lack of movement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants