Debugger: Fixed regression at prior commit dd274bc000 for bpm addr16 not triggering.

. Extended debugger regression tests to catch this (and test many other variants).
This commit is contained in:
tomcw 2019-12-09 16:27:13 +00:00
parent ba7a4005b0
commit b1316dc3da
5 changed files with 461 additions and 46 deletions

View File

@ -1127,11 +1127,11 @@ int CheckBreakpointsIO ()
int iTarget;
int nAddress;
// bIgnoreNextOpcodeAddress = true:
// bIncludeNextOpcodeAddress == false:
// . JSR addr16: ignore addr16 as a target
// . RTS/RTI : ignore return as a target
_6502_GetTargets( regs.pc, &aTarget[0], &aTarget[1], &aTarget[2], &nBytes, true, true, true );
// . BRK/RTS/RTI: ignore return (or vector) addr16 as a target
_6502_GetTargets( regs.pc, &aTarget[0], &aTarget[1], &aTarget[2], &nBytes, true, true, false );
if (nBytes)
{
for (iTarget = 0; iTarget < NUM_TARGETS; iTarget++ )

View File

@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Addressing _____________________________________________________________________________________
AddressingMode_t g_aOpmodes[ NUM_ADDRESSING_MODES ] =
{ // Outut, but eventually used for Input when Assembler is working.
{ // Output, but eventually used for Input when Assembler is working.
{TEXT("") , 1 , "(implied)" }, // (implied)
{TEXT("") , 1 , "n/a 1" }, // INVALID1
{TEXT("") , 2 , "n/a 2" }, // INVALID2
@ -584,7 +584,7 @@ bool _6502_GetStackReturnAddress ( WORD & nAddress_ )
//===========================================================================
bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial2_, int *pTargetPointer_, int * pTargetBytes_,
bool bIgnoreJSRJMP /*= true*/, bool bIgnoreBranch /*= true*/, bool bIgnoreNextOpcodeAddress /*= false*/ )
bool bIgnoreJSRJMP /*= true*/, bool bIgnoreBranch /*= true*/, bool bIncludeNextOpcodeAddress /*= true*/ )
{
bool bStatus = false;
@ -657,29 +657,35 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
nTarget16 = _6502_STACK_BEGIN + ((regs.sp+1) & 0xFF);
}
*pTargetPointer_ = nTarget16;
if (bIncludeNextOpcodeAddress || (nOpcode != OPCODE_RTI && nOpcode != OPCODE_RTS && nOpcode != OPCODE_BRK))
*pTargetPointer_ = nTarget16;
if (pTargetBytes_)
*pTargetBytes_ = 1;
}
break;
case AM_A: // $Absolute
case AM_A: // Absolute
if (nOpcode == OPCODE_JSR) // JSR?
{
*pTargetPartial_ = _6502_STACK_BEGIN + ((regs.sp+0) & 0xFF);
*pTargetPartial2_ = _6502_STACK_BEGIN + ((regs.sp-1) & 0xFF);
}
*pTargetPointer_ = nTarget16;
if (bIncludeNextOpcodeAddress || (nOpcode != OPCODE_JSR))
*pTargetPointer_ = nTarget16;
if (pTargetBytes_)
*pTargetBytes_ = 2;
break;
case AM_IAX: // Indexed (Absolute) Indirect
case AM_IAX: // Indexed (Absolute) Indirect - ie. JMP (abs,x)
_ASSERT(nOpcode == OPCODE_JMP_IAX);
nTarget16 += regs.x;
*pTargetPartial_ = nTarget16;
*pTargetPointer_ = *(LPWORD)(mem + nTarget16);
*pTargetPartial2_ = nTarget16+1;
if (bIncludeNextOpcodeAddress)
*pTargetPointer_ = *(LPWORD)(mem + nTarget16);
if (pTargetBytes_)
*pTargetBytes_ = 2;
break;
@ -698,9 +704,12 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
*pTargetBytes_ = 2;
break;
case AM_NA: // Indirect (Absolute) i.e. JMP
case AM_NA: // Indirect (Absolute) - ie. JMP (abs)
_ASSERT(nOpcode == OPCODE_JMP_NA);
*pTargetPartial_ = nTarget16;
*pTargetPointer_ = *(LPWORD)(mem + nTarget16);
*pTargetPartial2_ = nTarget16+1;
if (bIncludeNextOpcodeAddress)
*pTargetPointer_ = *(LPWORD)(mem + nTarget16);
if (pTargetBytes_)
*pTargetBytes_ = 2;
break;
@ -728,7 +737,7 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
break;
case AM_R:
if (! bIgnoreBranch)
if (!bIgnoreBranch)
{
*pTargetPartial_ = nTarget8;
*pTargetPointer_ = nAddress + 2;
@ -784,13 +793,6 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
}
}
if (bIgnoreNextOpcodeAddress)
{
*pTargetPointer_ = NO_6502_TARGET;
if (pTargetBytes_)
*pTargetBytes_ = 0;
}
return bStatus;
}

View File

@ -194,7 +194,7 @@ extern int g_aAssemblerFirstDirective[ NUM_ASSEMBLERS ];
void _6502_GetOpcodeOpmodeOpbyte( int & iOpcode_, int & iOpmode_, int & nOpbytes_ );
bool _6502_GetStackReturnAddress( WORD & nAddress_ );
bool _6502_GetTargets( WORD nAddress, int *pTargetPartial_, int *pTargetPartial2_, int *pTargetPointer_, int * pBytes_
, const bool bIgnoreJSRJMP = true, bool bIgnoreBranch = true, bool bIgnoreNextOpcodeAddress = false );
, const bool bIgnoreJSRJMP = true, bool bIgnoreBranch = true, bool bIncludeNextOpcodeAddress = true );
bool _6502_GetTargetAddress( const WORD & nAddress, WORD & nTarget_ );
bool _6502_IsOpcodeBranch( int nOpcode );
bool _6502_IsOpcodeValid( int nOpcode );

View File

@ -1069,6 +1069,7 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data
OPCODE_RTS = 0x60,
OPCODE_JMP_NA = 0x6C, // Indirect Absolute
OPCODE_JMP_IAX = 0x7C, // Indexed (Absolute Indirect, X)
OPCODE_LDA_A = 0xAD, // Absolute
OPCODE_NOP = 0xEA, // No operation
};

View File

@ -128,12 +128,14 @@ int GH445_test_PLn(BYTE op)
return 0;
}
int GH445_test_abs(BYTE op, WORD target2)
int GH445_test_abs(BYTE op)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
const WORD target2 = 0x1234;
mem[regs.pc] = op;
mem[(regs.pc+1)&0xFFFF] = (BYTE) (target2&0xff);
mem[(regs.pc+2)&0xFFFF] = (BYTE) ((target2>>8)&0xff);
@ -143,46 +145,153 @@ int GH445_test_abs(BYTE op, WORD target2)
return 0;
}
// NB. bIgnoreJSRJMP == false, ie. TargetAddr[2] gets set
int GH445_test_jsr(void)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = 0x20;
WORD target2 = 0x1234;
mem[regs.pc] = OPCODE_JSR;
mem[(regs.pc+1)&0xFFFF] = (BYTE) (target2&0xff);
mem[(regs.pc+2)&0xFFFF] = (BYTE) ((target2>>8)&0xff);
regs.sp = 0x1FF;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1) return 1;
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1 || TargetAddr[2] != target2) return 1;
regs.sp = 0x100;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != 0x1FF) return 1;
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != 0x1FF || TargetAddr[2] != target2) return 1;
regs.sp = 0x101;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1) return 1;
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1 || TargetAddr[2] != target2) return 1;
return 0;
}
int GH445_test_rts(WORD sp)
int GH445_test_brk(void)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = 0x60;
mem[regs.pc] = OPCODE_BRK;
regs.sp = 0x1FF;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1) return 1;
regs.sp = 0x100;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != 0x1FF) return 1;
regs.sp = 0x101;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1) return 1;
return 0;
}
int GH445_test_rti_rts(WORD sp, const bool isRTI)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = isRTI ? OPCODE_RTI : OPCODE_RTS;
regs.sp = sp;
WORD sp_addr_l = 0x100 + ((regs.sp+1)&0xFF);
WORD sp_addr_h = 0x100 + ((regs.sp+2)&0xFF);
WORD rts_addr = 0x1234;
mem[sp_addr_l] = (BYTE) (rts_addr&0xFF);
mem[sp_addr_h] = (BYTE) ((rts_addr>>8)&0xFF);
rts_addr++; // NB. return addr from stack is incremented before being transferred to PC
WORD sp_addr_p=0, sp_addr_l=0, sp_addr_h=0;
if (isRTI)
{
sp_addr_p = 0x100 + ((regs.sp+1)&0xFF);
sp_addr_l = 0x100 + ((regs.sp+2)&0xFF);
sp_addr_h = 0x100 + ((regs.sp+3)&0xFF);
mem[sp_addr_p] = 0xEA;
}
else
{
sp_addr_l = 0x100 + ((regs.sp+1)&0xFF);
sp_addr_h = 0x100 + ((regs.sp+2)&0xFF);
}
WORD ret_addr = 0x1234;
mem[sp_addr_l] = (BYTE) (ret_addr&0xFF);
mem[sp_addr_h] = (BYTE) ((ret_addr>>8)&0xFF);
if (!isRTI)
ret_addr++; // NB. return addr from stack is incremented before being transferred to PC
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
if (!bRes || TargetAddr[0] != sp_addr_l || TargetAddr[1] != sp_addr_h || TargetAddr[2] != ret_addr) return 1;
return 0;
}
// NB. bIgnoreJSRJMP == false, ie. TargetAddr[2] gets set
int GH445_test_jmp(BYTE op)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
const WORD target16 = 0x1234;
int target0, target1, target2;
if (op == OPCODE_JMP_A)
{
target0 = NO_6502_TARGET;
target1 = NO_6502_TARGET;
target2 = target16;
}
else if (op == OPCODE_JMP_NA)
{
target0 = target16;
target1 = (target16+1)&0xffff;
target2 = 0x5678;
mem[target0] = target2 & 0xff;
mem[target1] = (target2>>8) & 0xff;
}
else if (op == OPCODE_JMP_IAX)
{
target0 = (target16+regs.x)&0xffff;
target1 = (target16+regs.x+1)&0xffff;
target2 = 0xABCD;
mem[target0] = target2 & 0xff;
mem[target1] = (target2>>8) & 0xff;
}
mem[regs.pc] = op;
mem[(regs.pc+1)&0xFFFF] = (BYTE) (target16&0xff);
mem[(regs.pc+2)&0xFFFF] = (BYTE) ((target16>>8)&0xff);
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, false);
if (!bRes || TargetAddr[0] != sp_addr_l || TargetAddr[1] != sp_addr_h || TargetAddr[2] != rts_addr) return 1;
if (!bRes || TargetAddr[0] != target0 || TargetAddr[1] != target1 || TargetAddr[2] != target2) return 1;
return 0;
}
// bIgnoreBranch == true (default)
int GH445_test_Bcc(void)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = 0x10; // BPL next-op
mem[regs.pc+1] = 0;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
if (!bRes || TargetAddr[0] != NO_6502_TARGET || TargetAddr[1] != NO_6502_TARGET || TargetAddr[2] != NO_6502_TARGET) return 1;
mem[regs.pc] = 0x10; // BPL this-op
mem[regs.pc+1] = 0xfe;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
if (!bRes || TargetAddr[0] != NO_6502_TARGET || TargetAddr[1] != NO_6502_TARGET || TargetAddr[2] != NO_6502_TARGET) return 1;
return 0;
}
@ -197,11 +306,11 @@ int GH445_test_sub(bool bIs65C02)
mem[0x200] = 0xDD; // Bad data if SP wrap not working
mem[0x201] = 0xDD;
regs.pc = 0x300;
//
// PHn/PLn
regs.pc = 0x300;
res = GH445_test_PHn(0x08); // PHP
if (res) return res;
res = GH445_test_PHn(0x48); // PHA
@ -231,34 +340,76 @@ int GH445_test_sub(bool bIs65C02)
}
//
// ABS
// LDA abs
regs.pc = 0xFFFD;
res = GH445_test_abs(0xAD, 0x1234); // LDA ABS
res = GH445_test_abs(OPCODE_LDA_A); // LDA ABS
if (res) return res;
regs.pc = 0xFFFE;
res = GH445_test_abs(0xAD, 0x1234); // LDA ABS
res = GH445_test_abs(OPCODE_LDA_A); // LDA ABS
if (res) return res;
regs.pc = 0xFFFF;
res = GH445_test_abs(0xAD, 0x1234); // LDA ABS
res = GH445_test_abs(OPCODE_LDA_A); // LDA ABS
if (res) return res;
//
// JSR ABS
// JSR abs
res = GH445_test_jsr();
if (res) return res;
//
// BRK
mem[_6502_BRK_VECTOR+0] = 0x40; // BRK vector: $FA40
mem[_6502_BRK_VECTOR+1] = 0xFA;
regs.pc = 0x300;
res = GH445_test_brk();
if (res) return res;
//
// RTI
res = GH445_test_rti_rts(0x1FE, true);
if (res) return res;
res = GH445_test_rti_rts(0x1FF, true);
if (res) return res;
res = GH445_test_rti_rts(0x100, true);
if (res) return res;
//
// RTS
res = GH445_test_rts(0x1FE);
res = GH445_test_rti_rts(0x1FE, false);
if (res) return res;
res = GH445_test_rts(0x1FF);
res = GH445_test_rti_rts(0x1FF, false);
if (res) return res;
res = GH445_test_rts(0x100);
res = GH445_test_rti_rts(0x100, false);
if (res) return res;
//
// JMP
res = GH445_test_jmp(OPCODE_JMP_A); // JMP abs
if (res) return res;
res = GH445_test_jmp(OPCODE_JMP_NA); // JMP (abs)
if (res) return res;
if (bIs65C02)
{
regs.x = 0xff;
res = GH445_test_jmp(OPCODE_JMP_IAX); // JMP (abs,x)
if (res) return res;
}
//
// Bcc
res = GH445_test_Bcc();
if (res) return res;
return 0;
@ -280,6 +431,264 @@ int GH445_test(void)
//-------------------------------------
//
// bIncludeNextOpcodeAddress == false, check that:
// . TargetAddr[2] gets set, eg. for LDA abs
// . TargetAddr[2] == NO_6502_TARGET for control flow instructions, eg. BRK,RTI,RTS,JSR,JMP,Bcc
//
int GH451_test_abs(BYTE op)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
const WORD target2 = 0x1234;
mem[regs.pc] = op;
mem[(regs.pc+1)&0xFFFF] = (BYTE) (target2&0xff);
mem[(regs.pc+2)&0xFFFF] = (BYTE) ((target2>>8)&0xff);
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[2] != target2) return 1;
return 0;
}
int GH451_test_jsr(void)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = OPCODE_JSR;
regs.sp = 0x1FF;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1 || TargetAddr[2] != NO_6502_TARGET) return 1;
regs.sp = 0x100;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != 0x1FF || TargetAddr[2] != NO_6502_TARGET) return 1;
regs.sp = 0x101;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1 || TargetAddr[2] != NO_6502_TARGET) return 1;
return 0;
}
int GH451_test_brk(void)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = OPCODE_BRK;
regs.sp = 0x1FF;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1 || TargetAddr[2] != NO_6502_TARGET) return 1;
regs.sp = 0x100;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != 0x1FF || TargetAddr[2] != NO_6502_TARGET) return 1;
regs.sp = 0x101;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != regs.sp || TargetAddr[1] != regs.sp-1 || TargetAddr[2] != NO_6502_TARGET) return 1;
return 0;
}
int GH451_test_rti_rts(WORD sp, const bool isRTI)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = isRTI ? OPCODE_RTI : OPCODE_RTS;
regs.sp = sp;
WORD sp_addr_p=0, sp_addr_l=0, sp_addr_h=0;
if (isRTI)
{
sp_addr_p = 0x100 + ((regs.sp+1)&0xFF);
sp_addr_l = 0x100 + ((regs.sp+2)&0xFF);
sp_addr_h = 0x100 + ((regs.sp+3)&0xFF);
mem[sp_addr_p] = 0xEA;
}
else
{
sp_addr_l = 0x100 + ((regs.sp+1)&0xFF);
sp_addr_h = 0x100 + ((regs.sp+2)&0xFF);
}
WORD ret_addr = 0x1234;
mem[sp_addr_l] = (BYTE) (ret_addr&0xFF);
mem[sp_addr_h] = (BYTE) ((ret_addr>>8)&0xFF);
if (!isRTI)
ret_addr++; // NB. return addr from stack is incremented before being transferred to PC
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != sp_addr_l || TargetAddr[1] != sp_addr_h || TargetAddr[2] != NO_6502_TARGET) return 1;
return 0;
}
// bIgnoreJSRJMP == true
int GH451_test_jmp(BYTE op)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
const WORD target16 = 0x1234;
int target0, target1;
if (op == OPCODE_JMP_A)
{
target0 = NO_6502_TARGET;
target1 = NO_6502_TARGET;
}
else if (op == OPCODE_JMP_NA)
{
target0 = target16;
target1 = (target16+1)&0xffff;
}
else if (op == OPCODE_JMP_IAX)
{
target0 = (target16+regs.x)&0xffff;
target1 = (target16+regs.x+1)&0xffff;
}
mem[regs.pc] = op;
mem[(regs.pc+1)&0xFFFF] = (BYTE) (target16&0xff);
mem[(regs.pc+2)&0xFFFF] = (BYTE) ((target16>>8)&0xff);
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != target0 || TargetAddr[1] != target1 || TargetAddr[2] != NO_6502_TARGET) return 1;
return 0;
}
// bIgnoreBranch == true
int GH451_test_Bcc(void)
{
bool bRes;
int TargetAddr[3];
int TargetBytes;
mem[regs.pc] = 0x10; // BPL next-op
mem[regs.pc+1] = 0;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != NO_6502_TARGET || TargetAddr[1] != NO_6502_TARGET || TargetAddr[2] != NO_6502_TARGET) return 1;
mem[regs.pc] = 0x10; // BPL this-op
mem[regs.pc+1] = 0xfe;
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes, true, true, false);
if (!bRes || TargetAddr[0] != NO_6502_TARGET || TargetAddr[1] != NO_6502_TARGET || TargetAddr[2] != NO_6502_TARGET) return 1;
return 0;
}
int GH451_test_sub(bool bIs65C02)
{
int res;
mem[0x10000] = 0xDD; // Bad data if 64K wrap not working
mem[0x10001] = 0xDD;
mem[0x200] = 0xDD; // Bad data if SP wrap not working
mem[0x201] = 0xDD;
regs.pc = 0x300;
//
// LDA abs
res = GH451_test_abs(OPCODE_LDA_A);
if (res) return res;
//
// JSR abs
res = GH451_test_jsr();
if (res) return res;
//
// BRK
mem[_6502_BRK_VECTOR+0] = 0x40; // BRK vector: $FA40
mem[_6502_BRK_VECTOR+1] = 0xFA;
res = GH451_test_brk();
if (res) return res;
//
// RTI
res = GH451_test_rti_rts(0x1FE, true);
if (res) return res;
res = GH451_test_rti_rts(0x1FF, true);
if (res) return res;
res = GH451_test_rti_rts(0x100, true);
if (res) return res;
//
// RTS
res = GH451_test_rti_rts(0x1FE, false);
if (res) return res;
res = GH451_test_rti_rts(0x1FF, false);
if (res) return res;
res = GH451_test_rti_rts(0x100, false);
if (res) return res;
//
// JMP
res = GH451_test_jmp(OPCODE_JMP_A); // JMP abs
if (res) return res;
res = GH451_test_jmp(OPCODE_JMP_NA); // JMP (abs)
if (res) return res;
if (bIs65C02)
{
regs.x = 0xff;
res = GH451_test_jmp(OPCODE_JMP_IAX); // JMP (abs),x
if (res) return res;
}
//
// Bcc
res = GH451_test_Bcc();
if (res) return res;
return 0;
}
// debugger command 'bpm[r|w] addr16': JSR abs should not trigger a breakpoint at addr16
// . similarly for all other control flow opcodes (eg. Bcc, BRK, JMP, RTI, RTS)
int GH451_test(void)
{
int res;
g_aOpcodes = g_aOpcodes65C02;
res = GH451_test_sub(true);
if (res) return res;
g_aOpcodes = g_aOpcodes6502;
res = GH451_test_sub(false);
return res;
}
//-------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
int res = 1;
@ -289,5 +698,8 @@ int _tmain(int argc, _TCHAR* argv[])
res = GH445_test();
if (res) return res;
res = GH451_test();
if (res) return res;
return 0;
}