diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index 8e469a8a..4c12c51c 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -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 diff --git a/source/Debugger/Debug.h b/source/Debugger/Debug.h index 8dc3f84d..1ec7b215 100644 --- a/source/Debugger/Debug.h +++ b/source/Debugger/Debug.h @@ -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; diff --git a/source/Debugger/DebugDefs.h b/source/Debugger/DebugDefs.h index 8f85430d..d3b63581 100644 --- a/source/Debugger/DebugDefs.h +++ b/source/Debugger/DebugDefs.h @@ -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; diff --git a/source/Debugger/Debugger_Assembler.cpp b/source/Debugger/Debugger_Assembler.cpp index 3fb211a6..350fa207 100644 --- a/source/Debugger/Debugger_Assembler.cpp +++ b/source/Debugger/Debugger_Assembler.cpp @@ -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 diff --git a/source/Debugger/Debugger_Commands.cpp b/source/Debugger/Debugger_Commands.cpp index f28cb050..a55ada30 100644 --- a/source/Debugger/Debugger_Commands.cpp +++ b/source/Debugger/Debugger_Commands.cpp @@ -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 diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index d97ae25f..66fd81c8 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -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 diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp index 372bb9ba..be71b92d 100644 --- a/source/Debugger/Debugger_Help.cpp +++ b/source/Debugger/Debugger_Help.cpp @@ -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: "); + Help_Range(); + break; // Config - Load / Save case CMD_CONFIG_LOAD: ConsoleColorizePrint( sText, " Usage: [\"filename\"]" ); diff --git a/source/Debugger/Debugger_Types.h b/source/Debugger/Debugger_Types.h index 87fa931c..952b7ab9 100644 --- a/source/Debugger/Debugger_Types.h +++ b/source/Debugger/Debugger_Types.h @@ -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