wdc65816: emulate (direct,X) wraparound bug in emulation mode

Manually cherry-picked ares commit be8fa76e7d

Co-Authored-By: Adrian Siekierka <kontakt@asie.pl>
This commit is contained in:
Morilli 2024-03-01 13:03:04 +01:00 committed by Screwtapello
parent 4faca659c1
commit ccbe394e7d
4 changed files with 16 additions and 8 deletions

View File

@ -113,8 +113,8 @@ auto WDC65816::instructionIndexedIndirectRead8(alu8 op) -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
L W.l = readBank(V.w + 0); L W.l = readBank(V.w + 0);
alu(W.l); alu(W.l);
} }
@ -123,8 +123,8 @@ auto WDC65816::instructionIndexedIndirectRead16(alu16 op) -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
W.l = readBank(V.w + 0); W.l = readBank(V.w + 0);
L W.h = readBank(V.w + 1); L W.h = readBank(V.w + 1);
alu(W.w); alu(W.w);

View File

@ -90,8 +90,8 @@ auto WDC65816::instructionIndexedIndirectWrite8() -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
L writeBank(V.w + 0, A.l); L writeBank(V.w + 0, A.l);
} }
@ -99,8 +99,8 @@ auto WDC65816::instructionIndexedIndirectWrite16() -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
writeBank(V.w + 0, A.l); writeBank(V.w + 0, A.l);
L writeBank(V.w + 1, A.h); L writeBank(V.w + 1, A.h);
} }

View File

@ -59,6 +59,13 @@ auto WDC65816::writeDirect(uint address, uint8 data) -> void {
write(D.w + address & 0xffff, data); write(D.w + address & 0xffff, data);
} }
auto WDC65816::readDirectX(uint address, uint offset) -> uint8 {
// The (direct,X) addressing mode has a bug in which the high byte is
// wrapped within the page if E = 1 and D&0xFF != 0.
if(EF && D.l) return read(((D.w + address) & 0xffff00) | ((D.w + address + offset) & 0xff));
else return readDirect(address + offset);
}
auto WDC65816::readDirectN(uint address) -> uint8 { auto WDC65816::readDirectN(uint address) -> uint8 {
return read(D.w + address & 0xffff); return read(D.w + address & 0xffff);
} }

View File

@ -58,6 +58,7 @@ struct WDC65816 {
alwaysinline auto pushN(uint8 data) -> void; alwaysinline auto pushN(uint8 data) -> void;
alwaysinline auto readDirect(uint address) -> uint8; alwaysinline auto readDirect(uint address) -> uint8;
alwaysinline auto writeDirect(uint address, uint8 data) -> void; alwaysinline auto writeDirect(uint address, uint8 data) -> void;
alwaysinline auto readDirectX(uint address, uint offset) -> uint8;
alwaysinline auto readDirectN(uint address) -> uint8; alwaysinline auto readDirectN(uint address) -> uint8;
alwaysinline auto readBank(uint address) -> uint8; alwaysinline auto readBank(uint address) -> uint8;
alwaysinline auto writeBank(uint address, uint8 data) -> void; alwaysinline auto writeBank(uint address, uint8 data) -> void;