From 40bf9cd2d3d683893ea8950dfb639e2b241d9261 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 3 Mar 2024 11:28:14 +0000 Subject: [PATCH] 6502/65C02: Fix JSR for edge-case where JSR ABS16 is on stack and SP points to ABS16! (#1257) . Add CPU unit-tests --- source/CPU/cpu6502.h | 2 +- source/CPU/cpu65C02.h | 2 +- source/CPU/cpu_instructions.inl | 4 ++-- test/TestCPU6502/TestCPU6502.cpp | 38 ++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/source/CPU/cpu6502.h b/source/CPU/cpu6502.h index 63f3900d..a4bca6fb 100644 --- a/source/CPU/cpu6502.h +++ b/source/CPU/cpu6502.h @@ -94,7 +94,7 @@ static DWORD Cpu6502(DWORD uTotalCycles, const bool bVideoUpdate) case 0x1D: ABSX_OPT ORA CYC(4) break; case 0x1E: ABSX_CONST ASLn CYC(7) break; case 0x1F: ABSX_CONST ASO CYC(7) break; // invalid - case 0x20: ABS JSR CYC(6) break; + case 0x20: JSR CYC(6) break; // GH#1257: not ABS case 0x21: idx AND CYC(6) break; case 0x22: HLT CYC(2) break; // invalid case 0x23: idx RLA CYC(8) break; // invalid diff --git a/source/CPU/cpu65C02.h b/source/CPU/cpu65C02.h index b8b2e648..09acbfd1 100644 --- a/source/CPU/cpu65C02.h +++ b/source/CPU/cpu65C02.h @@ -94,7 +94,7 @@ static DWORD Cpu65C02(DWORD uTotalCycles, const bool bVideoUpdate) case 0x1D: ABSX_OPT ORA CYC(4) break; case 0x1E: ABSX_OPT ASLc CYC(6) break; case 0x1F: NOP CYC(1) break; // invalid - case 0x20: ABS JSR CYC(6) break; + case 0x20: JSR CYC(6) break; // GH#1257: not ABS case 0x21: idx AND CYC(6) break; case 0x22: IMM NOP CYC(2) break; // invalid case 0x23: NOP CYC(1) break; // invalid diff --git a/source/CPU/cpu_instructions.inl b/source/CPU/cpu_instructions.inl index c67addce..0ca09163 100644 --- a/source/CPU/cpu_instructions.inl +++ b/source/CPU/cpu_instructions.inl @@ -400,10 +400,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define INY ++regs.y; \ SETNZ(regs.y) #define JMP regs.pc = addr; -#define JSR --regs.pc; \ +#define JSR addr = *(LPBYTE)(mem+regs.pc); regs.pc++; \ PUSH(regs.pc >> 8) \ PUSH(regs.pc & 0xFF) \ - regs.pc = addr; + regs.pc = addr | (*(LPBYTE)(mem+regs.pc)) << 8; /* GH#1257 */ #define LAS /*bSlowerOnPagecross = 1*/; \ val = (BYTE)(READ & regs.sp); \ regs.a = regs.x = (BYTE) val; \ diff --git a/test/TestCPU6502/TestCPU6502.cpp b/test/TestCPU6502/TestCPU6502.cpp index 8afe92c7..bf7bb860 100644 --- a/test/TestCPU6502/TestCPU6502.cpp +++ b/test/TestCPU6502/TestCPU6502.cpp @@ -1266,6 +1266,41 @@ int GH321_test() //------------------------------------- +int GH1257_test() +{ + const UINT kNumTests = 3; + const BYTE code[kNumTests][6] = { { 0xA2, 0x7C, 0x9A, 0x20, 0x55, 0x13 }, // LDA #$7C; TXS; JSR $1355 + { 0xA2, 0x7D, 0x9A, 0x20, 0x55, 0x13 }, // LDA #$7D; TXS; JSR $1355 - actually JSRs to $0155 + { 0xA2, 0x7E, 0x9A, 0x20, 0x55, 0x13 } }; // LDA #$7E; TXS; JSR $1355 - actually JSRs to $7D55 + const WORD resPC[kNumTests] = { 0x1355, 0x0155, 0x7D55 }; + + const UINT org = 0x0178; + g_bStopOnBRK = true; + + for (UINT i = 0; i < kNumTests; i++) + { + memcpy(mem + org, code[i], sizeof(code[i])); + mem[resPC[i]] = 0x00; // BRK + reset(); + regs.pc = org; + TestCpu6502(2 + 2 + 6); + if (regs.pc != resPC[i]) return 1; + + // + + memcpy(mem + org, code[i], sizeof(code[i])); + mem[resPC[i]] = 0x00; // BRK + reset(); + regs.pc = org; + TestCpu65C02(2 + 2 + 6); + if (regs.pc != resPC[i]) return 1; + } + + return 0; +} + +//------------------------------------- + int testCB(int id, int cycles, ULONG uExecutedCycles) { return 0; @@ -1346,6 +1381,9 @@ int _tmain(int argc, _TCHAR* argv[]) res = GH292_test(); if (res) return res; + res = GH1257_test(); + if (res) return res; + res = SyncEvents_test(); if (res) return res;