65C816 native to emulation mode switch

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
Kaisha
Posts: 14
Joined: Mon Apr 26, 2021 9:06 am

65C816 native to emulation mode switch

Post by Kaisha » Mon Apr 26, 2021 9:58 am

Hi, I'm new around here :) And having some time during lockdowns thought I'd throw my hat in the ring and do what many have done before me, write an SNES emulator. I have a few small questions in regards to mode switching in the 65C816.

When switching from native to emulation mode (XCE with carry set to 1) from my understanding:
- A is left unchanged (though only the low byte is used)
- M and X flags get set to 1
- high byte of X and Y registers gets set to 0
- high byte of stack is set to 1

What isn't mentioned, and I'm unclear about, is what happens to the other registers D, DB, PB (otherwise named K in some places). These registers didn't exist on the 6502. D (direct page register) for example replaces zero-page addressing with direct-mode addressing, so the 6502 instructions that rely on zero-page addressing wouldn't function the same if the D register was left after a mode change. So do I:

A) Leave D untouched. It's up to the programmer to realize that D has possibly changed.
B) Zero D when a mode switch happens. It's up to the programmer to save/restore D when switching back to native mode.
C) Leave D untouched, but all direct-page addressing is treated as if D is zero when in emulation mode.

Likewise for data and program banks (DB/PB).

Also a question for stack relative addressing modes (STACK, S and (STACK, S), Y in the docs). While these modes are not available on the 6502, all 256 ops codes are available in emulation mode on the 65C816. If a program were to use a stack relative addressing mode while in emulation mode, what should I do:

A) This is an error and should/will never happen?
B) Fix the stack to page 1 so any offset roll overs stay on page 1?
C) Pretend the stack pointer is 16-bits for this one instruction?
D) Something else?

Any thoughts or ideas is appreciated :)

Revenant
Posts: 455
Joined: Sat Apr 25, 2015 1:47 pm
Location: FL

Re: 65C816 native to emulation mode switch

Post by Revenant » Mon Apr 26, 2021 1:03 pm

D remains untouched in emulation mode, but behaves a little differently in emulation mode: indexed addresses will wrap-around within a single page if D is page-aligned (i.e. the lower byte of the register is zero), otherwise it behaves the same as in native mode. Here is the implementation in bsnes, as an example:

Code: Select all

auto WDC65816::readDirect(uint address) -> uint8 {
  if(EF && !D.l) return read(D.w | address & 0xff);
  return read(D.w + address & 0xffff);
}
(where "address" is the offset into the direct page, EF is the emulation mode flag, D.l is the low byte of D, and D.w is the full value of D)

DB and PB stay the same in emulation mode. The only important difference is that interrupts do not save PB on the stack in emulation mode, so if an interrupt occurs when execution is outside of bank 0, you're screwed.

Stack-relative addressing still treats SP as 16-bit, but anything that modifies SP (i.e. pushes/pops) will never change the high byte of SP.

Also, the REP instruction cannot be used to clear M or X when in emulation mode.

Kaisha
Posts: 14
Joined: Mon Apr 26, 2021 9:06 am

Re: 65C816 native to emulation mode switch

Post by Kaisha » Mon Apr 26, 2021 2:11 pm

Perfect, thank-you :)

Post Reply