Debugger: BPMR & BPMW (PR #710)

Extended BPM to also support BPMR and BPMW
Fixed BPM[R|W] 0:FFFF (ie. support a range of 0x10000)
This commit is contained in:
TomCh 2019-10-23 05:31:53 +09:00 committed by GitHub
parent 13588165ff
commit 2f64795e2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 106 additions and 30 deletions

View File

@ -62,7 +62,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Bookmark_t g_aBookmarks[ MAX_BOOKMARKS ];
// Breakpoints ________________________________________________________________
// Any Speed Breakpoints
int g_nDebugBreakOnInvalid = 0; // Bit Flags of Invalid Opcode to break on: // iOpcodeType = AM_IMPLIED (BRK), AM_1, AM_2, AM_3
int g_iDebugBreakOnOpcode = 0;
@ -72,7 +71,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
int g_nBreakpoints = 0;
Breakpoint_t g_aBreakpoints[ MAX_BREAKPOINTS ];
// NOTE: Breakpoint_Source_t and g_aBreakpointSource must match!
// NOTE: BreakpointSource_t and g_aBreakpointSource must match!
const char *g_aBreakpointSource[ NUM_BREAKPOINT_SOURCES ] =
{ // Used to be one char, since ArgsCook also uses // TODO/FIXME: Parser use Param[] ?
// Used for both Input & Output!
@ -95,8 +94,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"N", // 1--- ---- Sign
// Misc
"OP", // Opcode/Instruction/Mnemonic
// Memory
"M" // Main
"M", // Mem RW
"M", // Mem READ_ONLY
"M", // Mem WRITE_ONLY
// TODO: M0 ram bank 0, M1 aux ram ?
};
@ -1087,11 +1087,11 @@ bool _CheckBreakpointValue( Breakpoint_t *pBP, int nVal )
bStatus = true;
break;
case BP_OP_EQUAL : // Range is like C++ STL: [,) (inclusive,not-inclusive)
if ((nVal >= pBP->nAddress) && (nVal < (pBP->nAddress + pBP->nLength)))
if ((nVal >= pBP->nAddress) && ((UINT)nVal < (pBP->nAddress + pBP->nLength)))
bStatus = true;
break;
case BP_OP_NOT_EQUAL : // Rnage is: (,] (not-inclusive, inclusive)
if ((nVal < pBP->nAddress) || (nVal >= (pBP->nAddress + pBP->nLength)))
if ((nVal < pBP->nAddress) || ((UINT)nVal >= (pBP->nAddress + pBP->nLength)))
bStatus = true;
break;
case BP_OP_GREATER_THAN :
@ -1141,12 +1141,31 @@ int CheckBreakpointsIO ()
Breakpoint_t *pBP = &g_aBreakpoints[iBreakpoint];
if (_BreakpointValid( pBP ))
{
if (pBP->eSource == BP_SRC_MEM_1)
if (pBP->eSource == BP_SRC_MEM_RW || pBP->eSource == BP_SRC_MEM_READ_ONLY || pBP->eSource == BP_SRC_MEM_WRITE_ONLY)
{
if (_CheckBreakpointValue( pBP, nAddress ))
{
g_uBreakMemoryAddress = (WORD) nAddress;
return BP_HIT_MEM;
BYTE opcode = mem[regs.pc];
if (pBP->eSource == BP_SRC_MEM_RW)
{
return BP_HIT_MEM;
}
else if (pBP->eSource == BP_SRC_MEM_READ_ONLY)
{
if (g_aOpcodes[opcode].nMemoryAccess & (MEM_RI|MEM_R))
return BP_HIT_MEMR;
}
else if (pBP->eSource == BP_SRC_MEM_WRITE_ONLY)
{
if (g_aOpcodes[opcode].nMemoryAccess & (MEM_WI|MEM_W))
return BP_HIT_MEMW;
}
else
{
_ASSERT(0);
}
}
}
}
@ -1335,6 +1354,9 @@ bool _CmdBreakpointAddReg( Breakpoint_t *pBP, BreakpointSource_t iSrc, Breakpoin
if (pBP)
{
_ASSERT(nLen <= _6502_MEM_LEN);
if (nLen > _6502_MEM_LEN) nLen = _6502_MEM_LEN;
pBP->eSource = iSrc;
pBP->eOperator = iCmp;
pBP->nAddress = nAddress;
@ -1470,12 +1492,26 @@ Update_t CmdBreakpointAddIO (int nArgs)
// return UPDATE_BREAKPOINTS | UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t CmdBreakpointAddMem (int nArgs)
Update_t CmdBreakpointAddMemA(int nArgs)
{
BreakpointSource_t iSrc = BP_SRC_MEM_1;
BreakpointOperator_t iCmp = BP_OP_EQUAL ;
return CmdBreakpointAddMem(nArgs);
}
//===========================================================================
Update_t CmdBreakpointAddMemR(int nArgs)
{
return CmdBreakpointAddMem(nArgs, BP_SRC_MEM_READ_ONLY);
}
//===========================================================================
Update_t CmdBreakpointAddMemW(int nArgs)
{
return CmdBreakpointAddMem(nArgs, BP_SRC_MEM_WRITE_ONLY);
}
//===========================================================================
Update_t CmdBreakpointAddMem (int nArgs, BreakpointSource_t bpSrc /*= BP_SRC_MEM_RW*/)
{
BreakpointSource_t iSrc = bpSrc;
BreakpointOperator_t iCmp = BP_OP_EQUAL;
int iArg = 0;
@ -1647,11 +1683,16 @@ void _BWZ_List( const Breakpoint_t * aBreakWatchZero, const int iBWZ ) //, bool
pSymbol = sName;
}
ConsoleBufferPushFormat( sText, " #%d %c %04X %s",
char cBPM = aBreakWatchZero[iBWZ].eSource == BP_SRC_MEM_READ_ONLY ? 'R'
: aBreakWatchZero[iBWZ].eSource == BP_SRC_MEM_WRITE_ONLY ? 'W'
: ' ';
ConsoleBufferPushFormat( sText, " #%d %c %04X %c %s",
// (bZeroBased ? iBWZ + 1 : iBWZ),
iBWZ,
sFlags[ (int) aBreakWatchZero[ iBWZ ].bEnabled ],
aBreakWatchZero[ iBWZ ].nAddress,
cBPM,
pSymbol
);
}
@ -8657,7 +8698,11 @@ void DebugContinueStepping ()
else if (g_bDebugBreakpointHit & BP_HIT_REG)
pszStopReason = TEXT("Register matches value");
else if (g_bDebugBreakpointHit & BP_HIT_MEM)
sprintf_s(szStopMessage, sizeof(szStopMessage), "Memory accessed at $%04X", g_uBreakMemoryAddress);
sprintf_s(szStopMessage, sizeof(szStopMessage), "Memory access at $%04X", g_uBreakMemoryAddress);
else if (g_bDebugBreakpointHit & BP_HIT_MEMW)
sprintf_s(szStopMessage, sizeof(szStopMessage), "Write access at $%04X", g_uBreakMemoryAddress);
else if (g_bDebugBreakpointHit & BP_HIT_MEMR)
sprintf_s(szStopMessage, sizeof(szStopMessage), "Read access 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

View File

@ -29,12 +29,14 @@
// Breakpoints
enum BreakpointHit_t
{
BP_HIT_NONE = 0
,BP_HIT_INVALID = (1 << 0)
,BP_HIT_OPCODE = (1 << 1)
,BP_HIT_REG = (1 << 2)
,BP_HIT_MEM = (1 << 3)
,BP_HIT_PC_READ_FLOATING_BUS_OR_IO_MEM = (1 << 4)
BP_HIT_NONE = 0
, BP_HIT_INVALID = (1 << 0)
, BP_HIT_OPCODE = (1 << 1)
, BP_HIT_REG = (1 << 2)
, BP_HIT_MEM = (1 << 3)
, BP_HIT_MEMR = (1 << 4)
, BP_HIT_MEMW = (1 << 5)
, BP_HIT_PC_READ_FLOATING_BUS_OR_IO_MEM = (1 << 6)
};
extern int g_nBreakpoints;

View File

@ -10,3 +10,4 @@
const unsigned int _6502_BRK_VECTOR = 0xFFFE;
const unsigned int _6502_MEM_BEGIN = 0x0000;
const unsigned int _6502_MEM_END = 0xFFFF;
const unsigned int _6502_MEM_LEN = _6502_MEM_END + 1;

View File

@ -112,7 +112,7 @@ const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ] =
{"SEC", 0 , 0}, {"AND", AM_AY , R_}, {"DEC", 0 , 0}, {"nop", 0 , 0 }, // 38 .. 3B
{"BIT", AM_AX , R_}, {"AND", AM_AX , R_}, {"ROL", AM_AX , RW}, {"nop", 0 , 0 }, // 3C .. 3F
{"RTI", 0 , 0}, {"EOR", AM_IZX, R_}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // 40 .. 43
{"RTI", 0 , SR}, {"EOR", AM_IZX, R_}, {"nop", AM_M , im}, {"nop", 0 , 0 }, // 40 .. 43
{"nop", AM_Z , 0}, {"EOR", AM_Z , R_}, {"LSR", AM_Z , _W}, {"nop", 0 , 0 }, // 44 .. 47
{"PHA", 0 , SW}, {"EOR", AM_M , im}, {"LSR", 0 , 0}, {"nop", 0 , 0 }, // 48 .. 4B
{"JMP", AM_A , 0}, {"EOR", AM_A , R_}, {"LSR", AM_A , _W}, {"nop", 0 , 0 }, // 4C .. 4F
@ -234,7 +234,7 @@ Fx BEQ r SBC (d),Y sbc (z) --- --- SBC d,X INC z,X --- SED SBC a,Y
{"SEC", 0 , 0}, {"AND", AM_AY , R_}, {"nop", 0 , 0}, {"rla", AM_AY , RW}, // 38 .. 3B
{"nop", AM_AX , 0}, {"AND", AM_AX , R_}, {"ROL", AM_AX , RW}, {"rla", AM_AX , RW}, // 3C .. 3F
{"RTI", 0 , 0}, {"EOR", AM_IZX, R_}, {"hlt", 0 , 0}, {"lse", AM_IZX, RW}, // 40 .. 43
{"RTI", 0 , SR}, {"EOR", AM_IZX, R_}, {"hlt", 0 , 0}, {"lse", AM_IZX, RW}, // 40 .. 43
{"nop", AM_Z , 0}, {"EOR", AM_Z , R_}, {"LSR", AM_Z , RW}, {"lse", AM_Z , RW}, // 44 .. 47
{"PHA", 0 , SW}, {"EOR", AM_M , im}, {"LSR", 0 , 0}, {"alr", AM_M , im}, // 48 .. 4B
{"JMP", AM_A , 0}, {"EOR", AM_A , R_}, {"LSR", AM_A , RW}, {"lse", AM_A , RW}, // 4C .. 4F

View File

@ -85,7 +85,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{TEXT("BPR") , CmdBreakpointAddReg , CMD_BREAKPOINT_ADD_REG , "Add breakpoint on register value" }, // NOTE! Different from SoftICE !!!!
{TEXT("BPX") , CmdBreakpointAddPC , CMD_BREAKPOINT_ADD_PC , "Add breakpoint at current instruction" },
{TEXT("BPIO") , CmdBreakpointAddIO , CMD_BREAKPOINT_ADD_IO , "Add breakpoint for IO address $C0xx" },
{TEXT("BPM") , CmdBreakpointAddMem , CMD_BREAKPOINT_ADD_MEM , "Add breakpoint on memory access" }, // SoftICE
{TEXT("BPM") , CmdBreakpointAddMemA , CMD_BREAKPOINT_ADD_MEM , "Add breakpoint on memory access" }, // SoftICE
{TEXT("BPMR") , CmdBreakpointAddMemR , CMD_BREAKPOINT_ADD_MEMR , "Add breakpoint on memory read access" },
{TEXT("BPMW") , CmdBreakpointAddMemW , CMD_BREAKPOINT_ADD_MEMW , "Add breakpoint on memory write access" },
{TEXT("BPC") , CmdBreakpointClear , CMD_BREAKPOINT_CLEAR , "Clear (remove) breakpoint" }, // SoftICE
{TEXT("BPD") , CmdBreakpointDisable , CMD_BREAKPOINT_DISABLE , "Disable breakpoint- it is still in the list, just not active" }, // SoftICE

View File

@ -1078,7 +1078,7 @@ void DrawBreakpoints ( int line )
for (iBreakpoint = 0; iBreakpoint < MAX_BREAKPOINTS; iBreakpoint++ )
{
Breakpoint_t *pBP = &g_aBreakpoints[iBreakpoint];
WORD nLength = pBP->nLength;
UINT nLength = pBP->nLength;
#if DEBUG_FORCE_DISPLAY
nLength = 2;
@ -1179,6 +1179,14 @@ void DrawBreakpoints ( int line )
sprintf( sText, "%04X", nAddress1 );
PrintTextCursorX( sText, rect2 );
if (nLength == 1)
{
if (pBP->eSource == BP_SRC_MEM_READ_ONLY)
PrintTextCursorX("R", rect2);
else if (pBP->eSource == BP_SRC_MEM_WRITE_ONLY)
PrintTextCursorX("W", rect2);
}
if (nLength > 1)
{
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ) );
@ -1211,6 +1219,11 @@ void DrawBreakpoints ( int line )
#endif
sprintf( sText, "%04X", nAddress2 );
PrintTextCursorX( sText, rect2 );
if (pBP->eSource == BP_SRC_MEM_READ_ONLY)
PrintTextCursorX("R", rect2);
else if (pBP->eSource == BP_SRC_MEM_WRITE_ONLY)
PrintTextCursorX("W", rect2);
}
#if !USE_APPLE_FONT

View File

@ -1058,6 +1058,12 @@ Update_t CmdHelpSpecific (int nArgs)
break;
case CMD_BREAKPOINT_LIST:
break;
case CMD_BREAKPOINT_ADD_MEM:
case CMD_BREAKPOINT_ADD_MEMR:
case CMD_BREAKPOINT_ADD_MEMW:
ConsoleColorizePrint(sText, " Usage: <range>");
Help_Range();
break;
// Config - Load / Save
case CMD_CONFIG_LOAD:
ConsoleColorizePrint( sText, " Usage: [\"filename\"]" );

View File

@ -153,7 +153,7 @@
- ? no, not listed
*/
// NOTE: Order must match _PARAM_REGS_*
// NOTE: Order must match Breakpoint_Source_t
// NOTE: Order must match BreakpointSource_t
// NOTE: Order must match g_aBreakpointSource
enum BreakpointSource_t
{
@ -175,7 +175,9 @@
BP_SRC_FLAG_N, // Sign
BP_SRC_OPCODE,
BP_SRC_MEM_1 ,
BP_SRC_MEM_RW,
BP_SRC_MEM_READ_ONLY,
BP_SRC_MEM_WRITE_ONLY,
NUM_BREAKPOINT_SOURCES
};
@ -201,7 +203,7 @@
struct Breakpoint_t
{
WORD nAddress; // for registers, functions as nValue
WORD nLength ;
UINT nLength ;
BreakpointSource_t eSource;
BreakpointOperator_t eOperator;
bool bSet ; // used to be called enabled pre 2.0
@ -323,6 +325,8 @@
// , CMD_BREAKPOINT_EXEC = CMD_BREAKPOINT_ADD_ADDR // alias
, CMD_BREAKPOINT_ADD_IO // break on: [$C000-$C7FF] Load/Store
, CMD_BREAKPOINT_ADD_MEM // break on: [$0000-$FFFF], excluding IO
, CMD_BREAKPOINT_ADD_MEMR // break on read on: [$0000-$FFFF], excluding IO
, CMD_BREAKPOINT_ADD_MEMW // break on write on: [$0000-$FFFF], excluding IO
, CMD_BREAKPOINT_CLEAR
// , CMD_BREAKPOINT_REMOVE = CMD_BREAKPOINT_CLEAR // alias
@ -613,7 +617,10 @@
Update_t CmdBreakpointAddReg (int nArgs);
Update_t CmdBreakpointAddPC (int nArgs);
Update_t CmdBreakpointAddIO (int nArgs);
Update_t CmdBreakpointAddMem (int nArgs);
Update_t CmdBreakpointAddMem (int nArgs, BreakpointSource_t bpSrc = BP_SRC_MEM_RW);
Update_t CmdBreakpointAddMemA (int nArgs);
Update_t CmdBreakpointAddMemR (int nArgs);
Update_t CmdBreakpointAddMemW (int nArgs);
Update_t CmdBreakpointClear (int nArgs);
Update_t CmdBreakpointDisable (int nArgs);
Update_t CmdBreakpointEdit (int nArgs);
@ -1117,7 +1124,7 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data
extern const unsigned int _6502_BRK_VECTOR ;//= 0xFFFE;
extern const unsigned int _6502_MEM_BEGIN ;//= 0x0000;
extern const unsigned int _6502_MEM_END ;//= 0xFFFF;
extern const unsigned int _6502_MEM_LEN ;//= 0x10000;
enum DEVICE_e
{
@ -1301,7 +1308,7 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data
// , PARAM_SIZE // TODO: used by FONT SIZE
// Note: Order must match Breakpoint_Source_t
// Note: Order must match BreakpointSource_t
, _PARAM_REGS_BEGIN = _PARAM_BREAKPOINT_END // Daisy Chain
// Regs
, PARAM_REG_A = _PARAM_REGS_BEGIN