higan CPU emulation mode bug? (attn: byuu or any 65816 guru)

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

higan CPU emulation mode bug? (attn: byuu or any 65816 guru)

Post by AWJ »

From the WDC W65C816S datasheet, page 42 (emphasis added):
8.2.1 The Direct Addressing modes are often used to access memory registers and pointers.
The effective address generated by Direct; Direct,X and Direct,Y addressing modes will always be in the Native mode range 000000 to 00FFFF. When in the Emulation mode, the direct addressing range is 000000 to 0000FF, except for [Direct] and [Direct],Y addressing modes and the PEI instruction which will increment from 0000FE or 0000FF into the Stack area.
8.2.2 When in the Emulation mode and DH is not equal to zero, the direct addressing range is 00DH00 to 00DHFF, except for [Direct] and [Direct],Y addressing modes and the PEI instruction which will increment from 00DHFE or 00DHFF into the next higher page.
Here's what the 65816 core in higan v098 does for direct page address calculation (from higan/processor/r65816/memory.hpp):

Code: Select all

alwaysinline auto readdp(uint32 addr) -> uint8 {
  if(regs.e && regs.d.l == 0x00) {
    return read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
  } else {
    return read((regs.d + (addr & 0xffff)) & 0xffff);
  }
}

// snip

alwaysinline auto writedp(uint32 addr, uint8 data) -> void {
  if(regs.e && regs.d.l == 0x00) {
    write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
  } else {
    write((regs.d + (addr & 0xffff)) & 0xffff, data);
  }
}
Assuming the datasheet is correct, the emulation flag and DP low byte test should not be done for pei and indirect long addressing modes. There should either be an "alwaysnative" argument to the functions, or a second pair of "readdpn" and "writedpn" functions that always do the native mode behaviour. The second is the prevailing style in the r65816 core, but the first is more DRY, and weren't you planning to update the code style in the older parts of higan anyway?

Of course there's a possibility that the datasheet is wrong (I noticed that it incorrectly claims that indexed indirect jmp fetches the vector from bank 0--it's actually from the PB) But the datasheet seems highly plausible to me--there's a definite pattern in the 65816 where emulation mode preserves 6502 behaviour only for instructions and addressing modes that actually exist on a 6502, while new 65816 instructions and modes always have "native mode" behaviour.

Also, the masking in those direct page functions is extremely redundant. The following much simpler and more readable formulas are exactly equivalent to what you have:

Code: Select all

if(regs.e && regs.d.l == 0x00) {
  return read(regs.d + (addr & 0xff)); // we've just tested that (regs.d & 0xff00) == regs.d
} else {
  return read((regs.d + addr) & 0xffff); // we only need to mask with 0xffff once
}
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by tepples »

Can you whip up a Super NES ROM that exhibits the difference, so I can run it on my PowerPak?
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by koitsu »

I'd second your theory on this (that the indirect long and indirect long indexed modes probably page wrap regardless of e=1). It'd be easy enough to test for -- I do have my Apple IIGS laying around. Easy enough to test using lda [$xx] or the like (I don't see the need to test [$xx],y or pei directly because the design aspect pertains to long indirect addressing as a whole).

Also, if you're ever curious about actual 65816 CPU behaviour, feel free to contact WDC directly. Bill Mensch (CPU inventor) actually answers support requests (I know, because he actually got back to me!), and I'm sure something he doesn't know off the top of his head he could review the schematics for. His direct Email address is bill.mensch at westerndesigncenter.com.

Footnote: I don't see how testing this on a SNES is practical (or rather, "quickly achievable" given that there's no easy to way to get details (registers, etc.) without writing a whole bunch of code and PPU stuffs. The Apple IIGS monitor + mini assembler make this pretty easy. Testing it on actual hardware is important here (emulators, ex. KEGS or ActiveGS, may get it wrong).
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by AWJ »

koitsu wrote:I'd second your theory on this (that the indirect long and indirect long indexed modes probably page wrap regardless of e=1). It'd be easy enough to test for -- I do have my Apple IIGS laying around. Easy enough to test using lda [$xx] or the like (I don't see the need to test [$xx],y or pei directly because the design aspect pertains to long indirect addressing as a whole).

Also, if you're ever curious about actual 65816 CPU behaviour, feel free to contact WDC directly. Bill Mensch (CPU inventor) actually answers support requests (I know, because he actually got back to me!), and I'm sure something he doesn't know off the top of his head he could review the schematics for. His direct Email address is bill.mensch at westerndesigncenter.com.

Footnote: I don't see how testing this on a SNES is practical (or rather, "quickly achievable" given that there's no easy to way to get details (registers, etc.) without writing a whole bunch of code and PPU stuffs. The Apple IIGS monitor + mini assembler make this pretty easy. Testing it on actual hardware is important here (emulators, ex. KEGS or ActiveGS, may get it wrong).
I'd much appreciate it if you did test on your IIGS--fully agree that using a built-in monitor is much less work than assembling a SNES ROM!
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by tepples »

I think other CPU test ROMs work by ripping the "code and PPU stuffs" from another test ROM. This is certainly true of Blargg's NES tests, which appear to all use the same output framework.
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by koitsu »

Prefer a second or tertiary set of eyes before pulling out hardware and having to set all that up. Working on the test case for 8.2.1 (8.2.2 may be more complicated given that $00/02xx on the Apple II is ROM, so I can't control what's in $00/02xx):

Code: Select all

; Bank $00/0000-00ff = zero page (RAM)
; Bank $00/0100-01ff = stack (RAM)
; Bank $01/0000-ffff = 64KB RAM

; $00/0000 = bank byte (if $00ff->$0100 wrap doesn't happen) of pointer to $00/6502
; $00/00fe = low byte of long pointer to $01/6502
; $00/00ff = high byte of long pointer to $01/6502
; $00/0100 = bank byte of long pointer to $01/6502

; $00/6502 = $aa
; $01/6502 = $bb

; $00/fdda = Apple II ROM: prints 8-bit accumulator in hex

.org $8000
sei
clc
xce
rep #$30
lda #$0000
tcd
sep #$30

lda #$00
pha
plb

clc
xce
lda [$fe]   ; Expect $bb
jsr $fdda

sec
xce
lda [$fe]   ; Expect: $aa
jsr $fdda

brk $00
And in the monitor, preassign some values:

Code: Select all

00/0000:00
00/00fe:02
00/00ff:65
00/0100:01
00/6502:aa
01/6502:bb
If this look correct: the results on ActiveGS (not hardware!) are BBBB. I'd expect BBAA, since in the 2nd situation, e=1, which should read from $00/6502 not $01/6502.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by tepples »

koitsu wrote:Working on the test case for 8.2.1 (8.2.2 may be more complicated given that $00/02xx on the Apple II is ROM, so I can't control what's in $00/02xx):
Since when? I thought ROM on a GS was $F00000 and above (with the language card area $FFD000-$FFFFFF optionally mirrored down to $00D000-$00FFFF), and $000200-$0002FF was Applesoft BASIC's input buffer (source).
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by koitsu »

tepples wrote:
koitsu wrote:Working on the test case for 8.2.1 (8.2.2 may be more complicated given that $00/02xx on the Apple II is ROM, so I can't control what's in $00/02xx):
Since when? I thought ROM on a GS was $F00000 and above (optionally mirrored down to $00D000-$00FFFF), and $000200-$0002FF was Applesoft BASIC's input buffer (source).
It acts as ROM in the sense that any changes you make to it in the monitor (ex. 00/0200: 01 02 03 04 05 06 07 08) are completely ignored (previous values remain in effect). Coding something that writes to $00/0200 also does nothing (silently ignored). I believe the sources (and trust me, I've already looked), but I can't fight what's there. Either way, we can determine what $00/0200 is (it'd be the bank byte for the indirect long), just that we can't change it.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by AWJ »

koitsu wrote:Prefer a second or tertiary set of eyes before pulling out hardware and having to set all that up. Working on the test case for 8.2.1 (8.2.2 may be more complicated given that $00/02xx on the Apple II is ROM, so I can't control what's in $00/02xx):

Code: Select all

; Bank $00/0000-00ff = zero page (RAM)
; Bank $00/0100-01ff = stack (RAM)
; Bank $01/0000-ffff = 64KB RAM

; $00/0000 = bank byte (if $00ff->$0100 wrap doesn't happen) of pointer to $00/6502
; $00/00fe = low byte of long pointer to $01/6502
; $00/00ff = high byte of long pointer to $01/6502
; $00/0100 = bank byte of long pointer to $01/6502

; $00/6502 = $aa
; $01/6502 = $bb

; $00/fdda = Apple II ROM: prints 8-bit accumulator in hex

.org $8000
sei
clc
xce
rep #$30
lda #$0000
tcd
sep #$30

lda #$00
pha
plb

clc
xce
lda [$fe]   ; Expect $bb
jsr $fdda

sec
xce
lda [$fe]   ; Expect: $aa
jsr $fdda

brk $00
And in the monitor, preassign some values:

Code: Select all

00/0000:00
00/00fe:02
00/00ff:65
00/0100:01
00/6502:aa
01/6502:bb
If this look correct: the results on ActiveGS (not hardware!) are BBBB. I'd expect BBAA, since in the 2nd situation, e=1, which should read from $00/6502 not $01/6502.
If the datasheet is correct (and higan is wrong) then hardware should print BBBB. The datasheet claims that lda [$fe] always has "native mode" wrapping behaviour regardless of the e flag.
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by koitsu »

Thanks AWJ. I have to keep going back and trying to re-comprehend the datasheet phrasing. So yeah, great, BBBB is correct (while BBAA would be wrong). I'll go pull out the IIGS, hook it up, and see what the results there are. But at least ActiveGS gets it correct.
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by koitsu »

Testing this on actual hardware is going to a bit of a pain, simply because the native ROM routines apparently behave very badly (in 8.2.2's case, stp ends up getting executed -- awesome!) if you change D on them. So I'll need to re-work some of this code to be significantly more safe with ROM routines.

In the meantime, I've removed the jsr accumulator-print call (replaced with brk so I could drop to the debugger easier, but then realise this was pointless since I was already in it), and stepped through the actual code in GSBug to see what the indirect long lda ended up getting for 8.2.2. It got $BB in both cases (e=0 and e=1) (I only show the e=0 case but trust me, e=1 has the same thing; I even set A=$0000 before the lda [$fe]).
Attachments
Capture.PNG
Capture2.PNG
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by AWJ »

koitsu wrote:Testing this on actual hardware is going to a bit of a pain, simply because the native ROM routines apparently behave very badly (in 8.2.2's case, stp ends up getting executed -- awesome!) if you change D on them. So I'll need to re-work some of this code to be significantly more safe with ROM routines.
Can you stash the test results in RAM somewhere they aren't going to get clobbered, put the CPU back into a state that the ROM is happy with, and then call the print routine?
Revenant
Posts: 455
Joined: Sat Apr 25, 2015 1:47 pm
Location: FL

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by Revenant »

https://dl.dropboxusercontent.com/u/431 ... getest.sfc

For anyone who cares, here's a quick and dirty SNES version of koitsu's test. As expected(?), it shows BBBB on hardware, but BBAA in bsnes-plus (not sure about current higan).
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by koitsu »

Revenant wrote:https://dl.dropboxusercontent.com/u/431 ... getest.sfc

For anyone who cares, here's a quick and dirty SNES version of koitsu's test. As expected(?), it shows BBBB on hardware, but BBAA in bsnes-plus (not sure about current higan).
Thank you for this!
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: higan CPU emulation mode bug? (attn: byuu or any 65816 g

Post by Near »

Okay, I'll fix it in the next WIP. Much appreciated for the bug report and for the help confirming it!

> Also, the masking in those direct page functions is extremely redundant.

Yeah, that code's been around since 2005 or so. I'm not a great programmer now, but I was a total hack back then. I finally just outright killed the balanced PPU core, which was some of the ugliest code I've ever written bar xkas. I've been doing some gradual code cleanups in the v098 WIPs, and as expected, it's caused some regressions that I've had to fix, so it's not very enjoyable doing many cleanups per release.

I have a huge list of important fixes (mostly UI related, but my GB/C core is falling apart at the moment), yet I haven't done anything at all in over two weeks now. I don't really have an excuse, I don't know what my deal is right now. But this one will be near the top of the list for its importance.

For what it's worth, there's likely a lot more emulation mode bugs. I don't know of a single official game in the entire SNES library that runs in emulation mode, so there's bound to be more issues lurking in there than just this. Doesn't mean the issues aren't critical. Single opcode tests to detect bsnes are a huge problem.

> I think other CPU test ROMs work by ripping the "code and PPU stuffs" from another test ROM.

On my eternal todo list is building a testing framework out of the 21fx module. Why bother with writing results on the screen when we can send them back to the PC and automate pass/fail regression tests? We won't be able to test mid-scanline PPU timing with such tests, but CPU/SMP/DSP behaviors (up to the echo buffer) should all be quite doable.
Post Reply