Here's what the 65816 core in higan v098 does for direct page address calculation (from higan/processor/r65816/memory.hpp):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.
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);
}
}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
}