SPC700 instruction cycle breakdown

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: SPC700 instruction cycle breakdown

Post by Near »

> Are you absolutely sure about that?

I am absolutely sure, yes. You read the post before I had a chance to update it with the actual bug.

There was an "addw $00" instruction, and I was performing a read instead of an idle for cycle 4. $1A meant the idle would've been slower than the read, hence the test was completing too quickly.

The test completes properly now, as do all other tests thus far. You're right that I'm being a bit too clever with maybe<uint16>, but well ... you know me >_>

I didn't want to have to type out "wait(0, true)" for idle(), and "wait(addr, false)" for read(), write().

Anyway ... I think we finally did it! A million thanks to you, Revenant, Cydrak, and Overload! We finally have the TEST register fully emulated in bsnes/higan, after thirteen long years of mystery! :D

Tangent: I thought about passing the address bus value along with idle() just so whatever inherits from Processor::SPC700 could spy on the value if there were some need for it ... but honestly it's just gonna be a source of confusion. Nothing else that we emulate is ever gonna use an SPC700, so it's just busy work for a side effect that is irrelevant to emulation. Much like emulating a CIC, for example. Overload's PDF has that information, so that's good enough for technical documentation on it.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: SPC700 instruction cycle breakdown

Post by AWJ »

See, even I'm not right all the time :mrgreen:

!0 being false is PHP-tier insanity and makes all my programming senses scream in anguish. If it makes sense to you then go ahead and keep on doing it that way, but don't be surprised when everyone except your most devoted followers prefers to fork older versions of your code that don't contain quite as much black magic.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: SPC700 instruction cycle breakdown

Post by Near »

> !0 being false is PHP-tier insanity and makes all my programming senses scream in anguish.

C++14 added optional<T> as well. nall/maybe is equivalent in functionality to that, only it has a few other small features in addition.

> don't be surprised when everyone except your most devoted followers prefers to fork older versions of your code that don't contain quite as much black magic.

If they want to use your fork from 2010 that's full of all of my various coding styles from 2004 to 2010 (hooray, ppu-balanced!), plus your own coding style changes, they're more than welcome to.

You may even end up with more users than people running higan official. That's fine, it's not a popularity contest to me. Hopefully not to you, either. One of these days, someone is going to come along and write a fast+accurate SNES emulator like gambatte, mGBA, BlastEm, etc. And overnight, bsnes/higan and all 18+ forks of it are going to be mostly abandoned by users, frontend emulators (RA, Openemu, Bizhawk), etc.

Basically, you get to choose between clean code and running fast. Clean code is also way easier to work with and improve, which is good for idiots like me (and I do mean that, I'm not very smart, never claimed to be.) The tricky part of clean code is that reasonable people disagree on what is cleaner. You have people on one extreme like endrift writing all code in C. You have people on the other extreme like Nemesis creating separate C++ classes for every individual CPU instruction. Then you have crazy people like me bringing back cooperative threading like it's 1989.

Anyway, as long as you're not outright disparaging, I'm willing to continue talking with you to better both of our emulator versions.

You may've been wrong on maybe this time, but you also may've been right. I appreciate you were trying to help fix a bug in my codebase either way.

In general, I'd just really like more civility in emudev. I know I was awful at it in the past, but I really am trying to be nice going forward. The MAME dev comments finally slowed down, and now the Bizhawk team has just been savagely condescending lately with my stuff, and it's really wearing me down.
Last edited by Near on Mon Jul 03, 2017 12:29 pm, edited 2 times in total.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: SPC700 instruction cycle breakdown

Post by AWJ »

byuu wrote:C++14 added optional<T> as well. nall/maybe is equivalent in functionality to that, only it has a few other small features in addition.
optional<T> is only standard in C++17; it's experimental in C++14. And even if it's standard, using it with integer types, or with any type which has an implicit bool conversion of its own (e.g. a container which is false when empty) strikes me as a dangerous thing to do.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: SPC700 instruction cycle breakdown

Post by tepples »

AWJ wrote:!0 being false is PHP-tier insanity
In my experience, PHP is no more or less insane than JavaScript. Several stylistic recommendations by Douglas Crockford in JavaScript: The Good Parts apply equally to PHP.

But what are the semantics of java.lang.Integer in boolean context?
byuu wrote:Then you have crazy people like me bringing back cooperative threading like it's 1989.
Or like the JavaScript programmers who have rediscovered asynchronous concurrency.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: SPC700 instruction cycle breakdown

Post by Near »

Okay, I fixed both ADDW,SUBW,MOVW(read) idle cycle 4, plus BBC,BBS,CBNE idle cycle 4.

All of blargg's and Revenant's tests are passing nicely now. Thanks again, everyone!

...

By the way, I should note that AWJ referred to the SPC700 assembler syntax as "opcode target,source" ... however, Overload's PDF uses "opcode source,target"

For instance, see 14b. Indirect (x+):
Cycle 3 is marked as condition (5) => internal operation for MOV A,(X+)
Cycle 4 is marked as condition (6) => internal operation for MOV (X+),A

The read version that loads (X+) and puts the value into A has cycle 4 as the idle cycle.
The write version that writes A into (X+) has cycle 3 as the idle cycle.

Also see 6d. Direct dp:
Cycle 4 is marked as condition (8) => internal operation for ADDW, SUBW, and MOVW YA,dp
Which would mean that this condition doesn't apply for MOVW dp,YA

But it's clear that the three condition (8) instructions are the ones that read from direct page, not write to it.

Not too important, it's just ... one more reason why I hate the official SPC700 assembler syntax.

I have a lot of ideas about how to make that PDF more readable, but I don't have the time or interest in trying to improve it myself.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: SPC700 instruction cycle breakdown

Post by AWJ »

byuu wrote:By the way, I should note that AWJ referred to the SPC700 assembler syntax as "opcode target,source" ... however, Overload's PDF uses "opcode source,target"

For instance, see 14b. Indirect (x+):
Cycle 3 is marked as condition (5) => internal operation for MOV A,(X+)
Cycle 4 is marked as condition (6) => internal operation for MOV (X+),A

The read version that loads (X+) and puts the value into A has cycle 4 as the idle cycle.
The write version that writes A into (X+) has cycle 3 as the idle cycle.
You're right, Overload has these two backwards.
Also see 6d. Direct dp:
Cycle 4 is marked as condition (8) => internal operation for ADDW, SUBW, and MOVW YA,dp
Which would mean that this condition doesn't apply for MOVW dp,YA

But it's clear that the three condition (8) instructions are the ones that read from direct page, not write to it.
This one is consistent with the official syntax. ADDW YA,dp, SUBW YA,dp, and MOVW YA,dp are all read instructions and all have an internal operation on cycle 4.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: SPC700 instruction cycle breakdown

Post by Near »

I was bored, so make of this what you will ...

Image

Image

Basically ... the cycle wait states of {2, 4, 10, 20} become {2, 4, ???, 248}, but only for internal wait states. External wait states are still {2, 4, 10, 20}, and timer wait states are still {2, 4, 8, 16}.

That's a hell of a jump from 20 to 248 ... I can't make any sense of how this would change between models so drastically. The missing internal[2] value could be 10, or it could be 124, or something else entirely. Obviously we can't test it if every real system locks up when we try.

I have no idea if I should even bother emulating this behavior with a switch in the code for documentation purposes.

Super unoptimized code, modified to match Revenant's values:

Code: Select all

auto SMP::wait(maybe<uint16> addr) -> void {
  static const uint cycleWaitStatesInternal[4] = {2, 4, 10, 248};  //10 is unverified
  static const uint cycleWaitStatesExternal[4] = {2, 4, 10,  20};
  static const uint timerWaitStates        [4] = {2, 4,  8,  16};

  bool internal = false;
  if(!addr) internal = true;  //idle cycles
  else if((*addr & 0xfff0) == 0x00f0) internal = true;  //IO registers
  else if(*addr >= 0xffc0 && io.iplromEnable) internal = true;  //IPLROM

  step(internal ? cycleWaitStatesInternal[io.internalWaitStates] : cycleWaitStatesExternal[io.externalWaitStates]);
  stepTimers(internal ? timerWaitStates[io.internalWaitStates] : timerWaitStates[io.externalWaitStates]);
}
Revenant
Posts: 462
Joined: Sat Apr 25, 2015 1:47 pm
Location: FL

Re: SPC700 instruction cycle breakdown

Post by Revenant »

How do smptesttest and test_timer_speed* behave when using 248 wait states?

I double-checked test_timer_speed on my SNES and it hangs as early as 2A, rather than CA, for whatever reason. Not sure if the same issue is at play here.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: SPC700 instruction cycle breakdown

Post by Near »

I can already guarantee blargg's test_speed ROMs will fail. He wasn't aware of these alternate timing numbers.

I'll try smptesttest tomorrow.
Revenant
Posts: 462
Joined: Sat Apr 25, 2015 1:47 pm
Location: FL

Re: SPC700 instruction cycle breakdown

Post by Revenant »

I know blargg's test would fail, but I'm curious if using all those extra wait states would manage to somehow reproduce the issue on some consoles where using certain values with those tests makes the SMP appear to become totally unresponsive.
Post Reply