Merge remote-tracking branch 'upstream/master' into newmaster
This commit is contained in:
commit
2b40967589
6 changed files with 482 additions and 84 deletions
|
@ -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, false );
|
||||
|
||||
if (nBytes)
|
||||
{
|
||||
for (iTarget = 0; iTarget < NUM_TARGETS; iTarget++ )
|
||||
|
|
|
@ -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
|
||||
|
@ -124,11 +124,11 @@ const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ] =
|
|||
{"RTS", 0 , SR}, {"ADC", AM_IZX, R_}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // 60 .. 63
|
||||
{"STZ", AM_Z , _W}, {"ADC", AM_Z , R_}, {"ROR", AM_Z , RW}, {"nop", 0 , 0 }, // 64 .. 67
|
||||
{"PLA", 0 , SR}, {"ADC", AM_M , im}, {"ROR", 0 , 0}, {"nop", 0 , 0 }, // 68 .. 6B
|
||||
{"JMP", AM_NA , 0}, {"ADC", AM_A , R_}, {"ROR", AM_A , RW}, {"nop", 0 , 0 }, // 6C .. 6F
|
||||
{"JMP", AM_NA , R_}, {"ADC", AM_A , R_}, {"ROR", AM_A , RW}, {"nop", 0 , 0 }, // 6C .. 6F
|
||||
{"BVS", AM_R , 0}, {"ADC", AM_NZY, R_}, {"ADC", AM_NZ , R_}, {"nop", 0 , 0 }, // 70 .. 73
|
||||
{"STZ", AM_ZX , _W}, {"ADC", AM_ZX , R_}, {"ROR", AM_ZX , RW}, {"nop", 0 , 0 }, // 74 .. 77
|
||||
{"SEI", 0 , 0}, {"ADC", AM_AY , R_}, {"PLY", 0 , SR}, {"nop", 0 , 0 }, // 78 .. 7B
|
||||
{"JMP", AM_IAX, 0}, {"ADC", AM_AX , R_}, {"ROR", AM_AX , RW}, {"nop", 0 , 0 }, // 7C .. 7F
|
||||
{"JMP", AM_IAX, R_}, {"ADC", AM_AX , R_}, {"ROR", AM_AX , RW}, {"nop", 0 , 0 }, // 7C .. 7F
|
||||
|
||||
{"BRA", AM_R , 0}, {"STA", AM_IZX, _W}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // 80 .. 83
|
||||
{"STY", AM_Z , _W}, {"STA", AM_Z , _W}, {"STX", AM_Z , _W}, {"nop", 0 , 0 }, // 84 .. 87
|
||||
|
@ -246,7 +246,7 @@ Fx BEQ r SBC (d),Y sbc (z) --- --- SBC d,X INC z,X --- SED SBC a,Y
|
|||
{"RTS", 0 , SR}, {"ADC", AM_IZX, R_}, {"hlt", 0 , 0}, {"rra", AM_IZX, RW}, // 60 .. 63
|
||||
{"nop", AM_Z , 0}, {"ADC", AM_Z , R_}, {"ROR", AM_Z , RW}, {"rra", AM_Z , RW}, // 64 .. 67
|
||||
{"PLA", 0 , SR}, {"ADC", AM_M , im}, {"ROR", 0 , 0}, {"arr", AM_M , im}, // 68 .. 6B
|
||||
{"JMP", AM_NA , 0}, {"ADC", AM_A , R_}, {"ROR", AM_A , RW}, {"rra", AM_A , RW}, // 6C .. 6F
|
||||
{"JMP", AM_NA , R_}, {"ADC", AM_A , R_}, {"ROR", AM_A , RW}, {"rra", AM_A , RW}, // 6C .. 6F
|
||||
{"BVS", AM_R , 0}, {"ADC", AM_NZY, R_}, {"hlt", 0 , 0}, {"rra", AM_NZY, RW}, // 70 .. 73
|
||||
{"nop", AM_ZX , 0}, {"ADC", AM_ZX , R_}, {"ROR", AM_ZX , RW}, {"rra", AM_ZX , RW}, // 74 .. 77
|
||||
{"SEI", 0 , 0}, {"ADC", AM_AY , R_}, {"nop", 0 , 0}, {"rra", AM_AY , RW}, // 78 .. 7B
|
||||
|
@ -584,21 +584,19 @@ 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 bIgnoreBranch /*= true*/, bool bIncludeNextOpcodeAddress /*= true*/ )
|
||||
{
|
||||
bool bStatus = false;
|
||||
|
||||
if (! pTargetPartial_)
|
||||
return bStatus;
|
||||
return false;
|
||||
|
||||
if (! pTargetPartial2_)
|
||||
return bStatus;
|
||||
return false;
|
||||
|
||||
if (! pTargetPointer_)
|
||||
return bStatus;
|
||||
return false;
|
||||
|
||||
// if (! pTargetBytes_)
|
||||
// return bStatus;
|
||||
// return false;
|
||||
|
||||
*pTargetPartial_ = NO_6502_TARGET;
|
||||
*pTargetPartial2_ = NO_6502_TARGET;
|
||||
|
@ -607,8 +605,6 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
|
|||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 0;
|
||||
|
||||
bStatus = true;
|
||||
|
||||
BYTE nOpcode = mem[nAddress];
|
||||
BYTE nTarget8 = mem[(nAddress+1)&0xFFFF];
|
||||
WORD nTarget16 = (mem[(nAddress+2)&0xFFFF]<<8) | nTarget8;
|
||||
|
@ -657,29 +653,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
|
||||
if (nOpcode == OPCODE_JSR) // JSR?
|
||||
case AM_A: // Absolute
|
||||
if (nOpcode == OPCODE_JSR)
|
||||
{
|
||||
*pTargetPartial_ = _6502_STACK_BEGIN + ((regs.sp+0) & 0xFF);
|
||||
*pTargetPartial2_ = _6502_STACK_BEGIN + ((regs.sp-1) & 0xFF);
|
||||
}
|
||||
|
||||
*pTargetPointer_ = nTarget16;
|
||||
if (bIncludeNextOpcodeAddress || (nOpcode != OPCODE_JSR && nOpcode != OPCODE_JMP_A))
|
||||
*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 +700,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 +733,7 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
|
|||
break;
|
||||
|
||||
case AM_R:
|
||||
if (! bIgnoreBranch)
|
||||
if (!bIgnoreBranch)
|
||||
{
|
||||
*pTargetPartial_ = nTarget8;
|
||||
*pTargetPointer_ = nAddress + 2;
|
||||
|
@ -769,29 +774,7 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial
|
|||
break;
|
||||
}
|
||||
|
||||
if (bIgnoreJSRJMP)
|
||||
{
|
||||
// If 6502 is jumping, don't show byte [nAddressTarget]
|
||||
if ((*pTargetPointer_ >= 0) && (
|
||||
(nOpcode == OPCODE_JSR ) || // 0x20
|
||||
(nOpcode == OPCODE_JMP_A ))) // 0x4C
|
||||
// (nOpcode == OPCODE_JMP_NA ) || // 0x6C
|
||||
// (nOpcode == OPCODE_JMP_IAX))) // 0x7C
|
||||
{
|
||||
*pTargetPointer_ = NO_6502_TARGET;
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIgnoreNextOpcodeAddress)
|
||||
{
|
||||
*pTargetPointer_ = NO_6502_TARGET;
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 0;
|
||||
}
|
||||
|
||||
return bStatus;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -816,7 +799,7 @@ bool _6502_GetTargetAddress ( const WORD & nAddress, WORD & nTarget_ )
|
|||
int nTargetPointer;
|
||||
WORD nTargetValue = 0; // de-ref
|
||||
int nTargetBytes;
|
||||
_6502_GetTargets( nAddress, &nTargetPartial, &nTargetPointer, &nTargetBytes, false, false );
|
||||
_6502_GetTargets( nAddress, &nTargetPartial, &nTargetPointer, &nTargetBytes, false );
|
||||
|
||||
// if (nTargetPointer == NO_6502_TARGET)
|
||||
// {
|
||||
|
|
|
@ -193,8 +193,8 @@ extern int g_aAssemblerFirstDirective[ NUM_ASSEMBLERS ];
|
|||
int _6502_GetOpmodeOpbyte( const int iAddress, int & iOpmode_, int & nOpbytes_, const DisasmData_t** pData = NULL );
|
||||
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 );
|
||||
bool _6502_GetTargets( WORD nAddress, int *pTargetPartial_, int *pTargetPartial2_, int *pTargetPointer_, int * pBytes_,
|
||||
bool bIgnoreBranch = true, bool bIncludeNextOpcodeAddress = true );
|
||||
bool _6502_GetTargetAddress( const WORD & nAddress, WORD & nTarget_ );
|
||||
bool _6502_IsOpcodeBranch( int nOpcode );
|
||||
bool _6502_IsOpcodeValid( int nOpcode );
|
||||
|
|
|
@ -1341,6 +1341,11 @@ void DrawConsoleInput ()
|
|||
|
||||
// Disassembly ____________________________________________________________________________________
|
||||
|
||||
void GetTargets_IgnoreDirectJSRJMP(const BYTE iOpcode, int& nTargetPointer)
|
||||
{
|
||||
if (iOpcode == OPCODE_JSR || iOpcode == OPCODE_JMP_A)
|
||||
nTargetPointer = NO_6502_TARGET;
|
||||
}
|
||||
|
||||
// Get the data needed to disassemble one line of opcodes. Fills in the DisasmLine info.
|
||||
// Disassembly formatting flags returned
|
||||
|
@ -1525,8 +1530,8 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|||
int nTargetPartial2;
|
||||
int nTargetPointer;
|
||||
WORD nTargetValue = 0; // de-ref
|
||||
int nTargetBytes;
|
||||
_6502_GetTargets( nBaseAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, &nTargetBytes );
|
||||
_6502_GetTargets( nBaseAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, NULL );
|
||||
GetTargets_IgnoreDirectJSRJMP(iOpcode, nTargetPointer); // For *direct* JSR/JMP, don't show 'addr16:byte char'
|
||||
|
||||
if (nTargetPointer != NO_6502_TARGET)
|
||||
{
|
||||
|
@ -1535,13 +1540,12 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|||
nTargetValue = *(mem + nTargetPointer) | (*(mem + ((nTargetPointer + 1) & 0xffff)) << 8);
|
||||
|
||||
// if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
|
||||
// nTargetBytes refers to size of pointer, not size of value
|
||||
// sprintf( sTargetValue_, "%04X", nTargetValue ); // & 0xFFFF
|
||||
|
||||
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
|
||||
sprintf( line_.sTargetPointer, "%04X", nTargetPointer & 0xFFFF );
|
||||
|
||||
if (iOpmode != AM_NA ) // Indirect Absolute
|
||||
if (iOpcode != OPCODE_JMP_NA && iOpcode != OPCODE_JMP_IAX)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_VALUE;
|
||||
if (g_iConfigDisasmTargets & DISASM_TARGET_VAL)
|
||||
|
@ -3214,6 +3218,7 @@ void DrawTargets ( int line)
|
|||
|
||||
int aTarget[3];
|
||||
_6502_GetTargets( regs.pc, &aTarget[0],&aTarget[1],&aTarget[2], NULL );
|
||||
GetTargets_IgnoreDirectJSRJMP(mem[regs.pc], aTarget[2]);
|
||||
|
||||
aTarget[1] = aTarget[2]; // Move down as we only have 2 lines
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
@ -149,40 +151,145 @@ int GH445_test_jsr(void)
|
|||
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;
|
||||
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
|
||||
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;
|
||||
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
|
||||
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;
|
||||
bRes = _6502_GetTargets(regs.pc, &TargetAddr[0], &TargetAddr[1], &TargetAddr[2], &TargetBytes);
|
||||
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
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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 +304,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 +338,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 +429,263 @@ 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, 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, 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, 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, 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, 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, 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, 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, false);
|
||||
if (!bRes || TargetAddr[0] != sp_addr_l || TargetAddr[1] != sp_addr_h || TargetAddr[2] != NO_6502_TARGET) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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, 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, 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, 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 +695,8 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||
res = GH445_test();
|
||||
if (res) return res;
|
||||
|
||||
res = GH451_test();
|
||||
if (res) return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue