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
65C816 native to emulation mode switch
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Re: 65C816 native to emulation mode switch
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:
(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.
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);
}
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.
Re: 65C816 native to emulation mode switch
Perfect, thank-you