From c35b863bd9286ee2658a1a944d02b02a13b1ad6c Mon Sep 17 00:00:00 2001 From: tomcw Date: Fri, 4 Aug 2017 20:52:17 +0100 Subject: [PATCH] Debugger: BPM cmd: trigger on stack access for BRK,JSR,PLn,PHn,RTI,RTS (#445) --- source/Debugger/Debug.cpp | 12 +++-- source/Debugger/DebugDefs.h | 2 + source/Debugger/Debugger_Assembler.cpp | 64 ++++++++++++++++++++++++-- source/Debugger/Debugger_Assembler.h | 2 +- source/Debugger/Debugger_Display.cpp | 9 ++-- source/Debugger/Debugger_Types.h | 5 ++ 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index 188dd2362..457183256 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -115,6 +115,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA "* ", // Read/Write }; + static WORD g_uBreakMemoryAddress = 0; // Commands _______________________________________________________________________________________ @@ -1113,10 +1114,11 @@ bool _CheckBreakpointValue( Breakpoint_t *pBP, int nVal ) //=========================================================================== int CheckBreakpointsIO () { - const int NUM_TARGETS = 2; + const int NUM_TARGETS = 3; int aTarget[ NUM_TARGETS ] = { + NO_6502_TARGET, NO_6502_TARGET, NO_6502_TARGET }; @@ -1126,7 +1128,7 @@ int CheckBreakpointsIO () int iTarget; int nAddress; - _6502_GetTargets( regs.pc, &aTarget[0], &aTarget[1], &nBytes ); + _6502_GetTargets( regs.pc, &aTarget[0], &aTarget[1], &aTarget[2], &nBytes, false ); if (nBytes) { @@ -1144,6 +1146,7 @@ int CheckBreakpointsIO () { if (_CheckBreakpointValue( pBP, nAddress )) { + g_uBreakMemoryAddress = (WORD) nAddress; return BP_HIT_MEM; } } @@ -8561,7 +8564,8 @@ void DebugContinueStepping () if (regs.pc == g_nDebugStepUntil || g_bDebugBreakpointHit) { TCHAR sText[ CONSOLE_WIDTH ]; - char* pszStopReason = NULL; + char szStopMessage[CONSOLE_WIDTH]; + char* pszStopReason = szStopMessage; if (regs.pc == g_nDebugStepUntil) pszStopReason = TEXT("PC matches 'Go until' address"); @@ -8572,7 +8576,7 @@ void DebugContinueStepping () else if (g_bDebugBreakpointHit & BP_HIT_REG) pszStopReason = TEXT("Register matches value"); else if (g_bDebugBreakpointHit & BP_HIT_MEM) - pszStopReason = TEXT("Memory accessed"); + sprintf_s(szStopMessage, sizeof(szStopMessage), "Memory accessed at $%04X", g_uBreakMemoryAddress); else if (g_bDebugBreakpointHit & BP_HIT_PC_READ_FLOATING_BUS_OR_IO_MEM) pszStopReason = TEXT("PC reads from floating bus or I/O memory"); else diff --git a/source/Debugger/DebugDefs.h b/source/Debugger/DebugDefs.h index 48edd7f92..8f85430de 100644 --- a/source/Debugger/DebugDefs.h +++ b/source/Debugger/DebugDefs.h @@ -3,8 +3,10 @@ const int _6502_BRANCH_POS = +127; const int _6502_BRANCH_NEG = -128; const unsigned int _6502_ZEROPAGE_END = 0x00FF; + const unsigned int _6502_STACK_BEGIN = 0x0100; const unsigned int _6502_STACK_END = 0x01FF; const unsigned int _6502_IO_BEGIN = 0xC000; const unsigned int _6502_IO_END = 0xC0FF; + const unsigned int _6502_BRK_VECTOR = 0xFFFE; const unsigned int _6502_MEM_BEGIN = 0x0000; const unsigned int _6502_MEM_END = 0xFFFF; diff --git a/source/Debugger/Debugger_Assembler.cpp b/source/Debugger/Debugger_Assembler.cpp index b3faee966..01a476de3 100644 --- a/source/Debugger/Debugger_Assembler.cpp +++ b/source/Debugger/Debugger_Assembler.cpp @@ -94,7 +94,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define SR MEM_S | MEM_RI const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ] = { - {"BRK", 0 , 0}, {"ORA", AM_IZX, R_}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // 00 .. 03 + {"BRK", 0 , SW}, {"ORA", AM_IZX, R_}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // 00 .. 03 {"TSB", AM_Z , _W}, {"ORA", AM_Z , R_}, {"ASL", AM_Z , RW}, {"nop", 0 , 0 }, // 04 .. 07 {"PHP", 0 , SW}, {"ORA", AM_M , im}, {"ASL", 0 , 0}, {"nop", 0 , 0 }, // 08 .. 0B {"TSB", AM_A , _W}, {"ORA", AM_A , R_}, {"ASL", AM_A , RW}, {"nop", 0 , 0 }, // 0C .. 0F @@ -154,7 +154,7 @@ const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ] = {"CPY", AM_A , R_}, {"CMP", AM_A , R_}, {"DEC", AM_A , RW}, {"nop", 0 , 0 }, // CC .. CF {"BNE", AM_R , 0}, {"CMP", AM_NZY, R_}, {"CMP", AM_NZ , 0}, {"nop", 0 , 0 }, // D0 .. D3 {"nop", AM_ZX , 0}, {"CMP", AM_ZX , R_}, {"DEC", AM_ZX , RW}, {"nop", 0 , 0 }, // D4 .. D7 - {"CLD", 0 , 0}, {"CMP", AM_AY , R_}, {"PHX", 0 , 0}, {"nop", 0 , 0 }, // D8 .. DB + {"CLD", 0 , 0}, {"CMP", AM_AY , R_}, {"PHX", 0 , SW}, {"nop", 0 , 0 }, // D8 .. DB {"nop", AM_AX , 0}, {"CMP", AM_AX , R_}, {"DEC", AM_AX , RW}, {"nop", 0 , 0 }, // DC .. DF {"CPX", AM_M , im}, {"SBC", AM_IZX, R_}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // E0 .. E3 @@ -163,7 +163,7 @@ const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ] = {"CPX", AM_A , R_}, {"SBC", AM_A , R_}, {"INC", AM_A , RW}, {"nop", 0 , 0 }, // EC .. EF {"BEQ", AM_R , 0}, {"SBC", AM_NZY, R_}, {"SBC", AM_NZ , 0}, {"nop", 0 , 0 }, // F0 .. F3 {"nop", AM_ZX , 0}, {"SBC", AM_ZX , R_}, {"INC", AM_ZX , RW}, {"nop", 0 , 0 }, // F4 .. F7 - {"SED", 0 , 0}, {"SBC", AM_AY , R_}, {"PLX", 0 , 0}, {"nop", 0 , 0 }, // F8 .. FB + {"SED", 0 , 0}, {"SBC", AM_AY , R_}, {"PLX", 0 , SR}, {"nop", 0 , 0 }, // F8 .. FB {"nop", AM_AX , 0}, {"SBC", AM_AX , R_}, {"INC", AM_AX , RW}, {"nop", 0 , 0 } // FF .. FF }; @@ -216,7 +216,7 @@ Fx BEQ r SBC (d),Y sbc (z) --- --- SBC d,X INC z,X --- SED SBC a,Y (d),Y */ - {"BRK", 0 , 0}, {"ORA", AM_IZX, R_}, {"hlt", 0 , 0 }, {"aso", AM_IZX, RW}, // 00 .. 03 + {"BRK", 0 , SW}, {"ORA", AM_IZX, R_}, {"hlt", 0 , 0 }, {"aso", AM_IZX, RW}, // 00 .. 03 {"nop", AM_Z , R_}, {"ORA", AM_Z , R_}, {"ASL", AM_Z , RW}, {"aso", AM_Z , RW}, // 04 .. 07 {"PHP", 0 , SW}, {"ORA", AM_M , im}, {"ASL", 0 , 0}, {"anc", AM_M , im}, // 08 .. 0B {"nop", AM_AX , 0}, {"ORA", AM_A , R_}, {"ASL", AM_A , RW}, {"aso", AM_A , RW}, // 0C .. 0F @@ -583,13 +583,16 @@ bool _6502_GetStackReturnAddress ( WORD & nAddress_ ) //=========================================================================== -bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPointer_, int * pTargetBytes_, bool bIgnoreJSRJMP, bool bIgnoreBranch ) +bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPartial2_, int *pTargetPointer_, int * pTargetBytes_, bool bIgnoreJSRJMP, bool bIgnoreBranch ) { bool bStatus = false; if (! pTargetPartial_) return bStatus; + if (! pTargetPartial2_) + return bStatus; + if (! pTargetPointer_) return bStatus; @@ -597,6 +600,7 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPointer // return bStatus; *pTargetPartial_ = NO_6502_TARGET; + *pTargetPartial2_ = NO_6502_TARGET; *pTargetPointer_ = NO_6502_TARGET; if (pTargetBytes_) @@ -615,7 +619,57 @@ bool _6502_GetTargets ( WORD nAddress, int *pTargetPartial_, int *pTargetPointer switch (eMode) { + case AM_IMPLIED: + if (g_aOpcodes[ nOpcode ].nMemoryAccess & MEM_S) // Stack R/W? + { + if (nOpcode == OPCODE_RTI || nOpcode == OPCODE_RTS) // RTI or RTS? + { + WORD sp = regs.sp; + + if (nOpcode == OPCODE_RTI) + { + //*pTargetPartial3_ = _6502_STACK_BEGIN + ((sp+1) & 0xFF); // TODO: PLP + ++sp; + } + + *pTargetPartial_ = _6502_STACK_BEGIN + ((sp+1) & 0xFF); + *pTargetPartial2_ = _6502_STACK_BEGIN + ((sp+2) & 0xFF); + nTarget16 = mem[*pTargetPartial_] + (mem[*pTargetPartial2_]<<8); + + if (nOpcode == OPCODE_RTS) + ++nTarget16; + } + else if (nOpcode == OPCODE_BRK) // BRK? + { + *pTargetPartial_ = _6502_STACK_BEGIN + ((regs.sp+0) & 0xFF); + *pTargetPartial2_ = _6502_STACK_BEGIN + ((regs.sp-1) & 0xFF); + //*pTargetPartial3_ = _6502_STACK_BEGIN + ((regs.sp-2) & 0xFF); // TODO: PHP + //*pTargetPartial4_ = _6502_BRK_VECTOR + 0; // TODO + //*pTargetPartial5_ = _6502_BRK_VECTOR + 1; // TODO + nTarget16 = *(LPWORD)(mem + _6502_BRK_VECTOR); + } + else // PHn/PLn + { + if (g_aOpcodes[ nOpcode ].nMemoryAccess & MEM_WI) + nTarget16 = _6502_STACK_BEGIN + ((regs.sp+0) & 0xFF); + else + nTarget16 = _6502_STACK_BEGIN + ((regs.sp+1) & 0xFF); + } + + *pTargetPointer_ = nTarget16; + + if (pTargetBytes_) + *pTargetBytes_ = 1; + } + break; + 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 (pTargetBytes_) *pTargetBytes_ = 2; diff --git a/source/Debugger/Debugger_Assembler.h b/source/Debugger/Debugger_Assembler.h index 61767ed18..613919014 100644 --- a/source/Debugger/Debugger_Assembler.h +++ b/source/Debugger/Debugger_Assembler.h @@ -193,7 +193,7 @@ 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 *pTargetPointer_, int * pBytes_ + bool _6502_GetTargets( WORD nAddress, int *pTargetPartial_, int *pTargetPartial2_, int *pTargetPointer_, int * pBytes_ , const bool bIgnoreJSRJMP = true, bool bIgnoreBranch = true ); bool _6502_GetTargetAddress( const WORD & nAddress, WORD & nTarget_ ); bool _6502_IsOpcodeBranch( int nOpcode ); diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index bfeab4553..3df95596b 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -1506,10 +1506,11 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ ) // Indirect / Indexed int nTargetPartial; + int nTargetPartial2; int nTargetPointer; WORD nTargetValue = 0; // de-ref int nTargetBytes; - _6502_GetTargets( nBaseAddress, &nTargetPartial, &nTargetPointer, &nTargetBytes ); + _6502_GetTargets( nBaseAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, &nTargetBytes ); if (nTargetPointer != NO_6502_TARGET) { @@ -3192,8 +3193,10 @@ void DrawTargets ( int line) if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; - int aTarget[2]; - _6502_GetTargets( regs.pc, &aTarget[0],&aTarget[1], NULL ); + int aTarget[3]; + _6502_GetTargets( regs.pc, &aTarget[0],&aTarget[1],&aTarget[2], NULL ); + + aTarget[1] = aTarget[2]; // Move down as we only have 2 lines RECT rect; int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg; diff --git a/source/Debugger/Debugger_Types.h b/source/Debugger/Debugger_Types.h index 4ca264a0e..66014daba 100644 --- a/source/Debugger/Debugger_Types.h +++ b/source/Debugger/Debugger_Types.h @@ -1049,8 +1049,11 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data { OPCODE_BRA = 0x80, + OPCODE_BRK = 0x00, OPCODE_JSR = 0x20, + OPCODE_RTI = 0x40, OPCODE_JMP_A = 0x4C, // Absolute + OPCODE_RTS = 0x60, OPCODE_JMP_NA = 0x6C, // Indirect Absolute OPCODE_JMP_IAX = 0x7C, // Indexed (Absolute Indirect, X) @@ -1101,9 +1104,11 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data extern const int _6502_BRANCH_POS ;//= +127 extern const int _6502_BRANCH_NEG ;//= -128 extern const unsigned int _6502_ZEROPAGE_END ;//= 0x00FF; + extern const unsigned int _6502_STACK_BEGIN ;//= 0x0100; extern const unsigned int _6502_STACK_END ;//= 0x01FF; extern const unsigned int _6502_IO_BEGIN ;//= 0xC000; extern const unsigned int _6502_IO_END ;//= 0xC0FF; + extern const unsigned int _6502_BRK_VECTOR ;//= 0xFFFE; extern const unsigned int _6502_MEM_BEGIN ;//= 0x0000; extern const unsigned int _6502_MEM_END ;//= 0xFFFF;