From 2832fbeccb49e6a12a6e2c3d134867aa0a77a2cc Mon Sep 17 00:00:00 2001 From: stephena Date: Sun, 4 Sep 2016 23:03:01 +0000 Subject: [PATCH] Added versions of the debugger trap commands that trap on all mirrors, not just the specified address. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3317 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- Changes.txt | 4 + Makefile | 2 +- src/debugger/CartDebug.hxx | 18 ++-- src/debugger/DebuggerParser.cxx | 169 +++++++++++++++++++++++++++----- src/debugger/DebuggerParser.hxx | 9 +- 5 files changed, 165 insertions(+), 37 deletions(-) diff --git a/Changes.txt b/Changes.txt index 98096dbe0..1d68a3e95 100644 --- a/Changes.txt +++ b/Changes.txt @@ -21,6 +21,10 @@ Thanks to Omegamatrix of AtariAge for the bug report and patch to fix the issue. + * Added 'trapm', 'trapreadm', 'trapwritem' commands to debugger prompt. + These are similar to the non-'m' versions, except that they also trap + on all mirrors of the given address. + * Fixed bug in debugger 'reset' command; it wasn't resetting the bankswitching, so after a reset the banks were in an undefined state. diff --git a/Makefile b/Makefile index 6dd012958..7a17d530c 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ srcdir ?= . -DEFINES := +DEFINES := -D_GLIBCXX_USE_CXX11_ABI=1 LDFLAGS := INCLUDES := LIBS := diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 908011a7f..b6718cda1 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -87,6 +87,15 @@ class CartDebug : public DebuggerSystem int fieldwidth; }; + // Determine 'type' of address (ie, what part of the system accessed) + enum AddrType { + ADDR_TIA, + ADDR_IO, + ADDR_ZPRAM, + ADDR_ROM + }; + AddrType addressType(uInt16 addr) const; + public: CartDebug(Debugger& dbg, Console& console, const OSystem& osystem); virtual ~CartDebug() = default; @@ -266,15 +275,6 @@ class CartDebug : public DebuggerSystem using AddrToLabel = std::map; using LabelToAddr = std::map; - // Determine 'type' of address (ie, what part of the system accessed) - enum AddrType { - ADDR_TIA, - ADDR_IO, - ADDR_ZPRAM, - ADDR_ROM - }; - AddrType addressType(uInt16 addr) const; - struct DirectiveTag { DisasmType type; uInt16 start; diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index e81fcfce8..4011c1471 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -567,9 +567,9 @@ string DebuggerParser::trapStatus(int addr) else if(r) result += "read"; else if(w) - result += " write"; + result += "write"; else - result += " none "; + result += "none"; // TODO - technically, we should determine if the label is read or write const string& l = debugger.cartDebug().getLabel(addr, true); @@ -585,9 +585,8 @@ string DebuggerParser::trapStatus(int addr) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool DebuggerParser::saveScriptFile(string file) { - if( file.find_last_of('.') == string::npos ) { + if( file.find_last_of('.') == string::npos ) file += ".stella"; - } ofstream out(file); @@ -1440,36 +1439,26 @@ void DebuggerParser::executeTrace() // "trap" void DebuggerParser::executeTrap() { - uInt32 beg = args[0]; - uInt32 end = argCount >= 2 ? args[1] : beg; - if(beg > end) std::swap(beg, end); - - for(uInt32 i = beg; i <= end; ++i) - { - debugger.toggleReadTrap(i); - debugger.toggleWriteTrap(i); - commandResult << trapStatus(i) << endl; - } + executeTrapRW(true, true); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapread" void DebuggerParser::executeTrapread() { - uInt32 beg = args[0]; - uInt32 end = argCount >= 2 ? args[1] : beg; - if(beg > end) std::swap(beg, end); - - for(uInt32 i = beg; i <= end; ++i) - { - debugger.toggleReadTrap(i); - commandResult << trapStatus(i) << endl; - } + executeTrapRW(true, false); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapwrite" void DebuggerParser::executeTrapwrite() +{ + executeTrapRW(false, true); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// wrapper function for trap/trapread/trapwrite commands +void DebuggerParser::executeTrapRW(bool read, bool write) { uInt32 beg = args[0]; uInt32 end = argCount >= 2 ? args[1] : beg; @@ -1477,11 +1466,116 @@ void DebuggerParser::executeTrapwrite() for(uInt32 i = beg; i <= end; ++i) { - debugger.toggleWriteTrap(i); + if(read) debugger.toggleReadTrap(i); + if(write) debugger.toggleWriteTrap(i); commandResult << trapStatus(i) << endl; } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "trapm" +void DebuggerParser::executeTrapM() +{ + executeTrapMRW(true, true); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "trapreadm" +void DebuggerParser::executeTrapreadM() +{ + executeTrapMRW(true, false); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "trapwritem" +void DebuggerParser::executeTrapwriteM() +{ + executeTrapMRW(false, true); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// wrapper function for trapm/trapreadm/trapwritem commands +void DebuggerParser::executeTrapMRW(bool read, bool write) +{ + uInt32 addr = args[0]; + uInt32 beg = argCount > 1 ? args[1] : 0; + uInt32 end = argCount > 2 ? args[2] : 0xFFFF; + if(beg > end) std::swap(beg, end); + + switch(debugger.cartDebug().addressType(addr)) + { + case CartDebug::ADDR_TIA: + { + for(uInt32 i = beg; i <= end; ++i) + { + if((i & 0x1080) == 0x0000 && (i & 0x003F) == addr) + { + if(read) debugger.toggleReadTrap(i); + if(write) debugger.toggleWriteTrap(i); + } + } + break; + } + case CartDebug::ADDR_IO: + { + for(uInt32 i = beg; i <= end; ++i) + { + if((i & 0x1080) == 0x0080 && (i & 0x0200) != 0x0000 && (i & 0x02FF) == addr) + { + if(read) debugger.toggleReadTrap(i); + if(write) debugger.toggleWriteTrap(i); + } + } + break; + } + case CartDebug::ADDR_ZPRAM: + { + for(uInt32 i = beg; i <= end; ++i) + { + if((i & 0x1080) == 0x0080 && (i & 0x0200) == 0x0000 && (i & 0x00FF) == addr) + { + if(read) debugger.toggleReadTrap(i); + if(write) debugger.toggleWriteTrap(i); + } + } + break; + } + case CartDebug::ADDR_ROM: + { + // Enforce range? + if(argCount > 1) + { + if(beg < addr) beg = addr & 0xF000; + if(end < beg) beg = end; + } + else + { + beg = 0x1000; + end = 0xFFFF; + } + + // Are we in range? + if(!(addr >= beg && addr <= end)) + { + commandResult << "Address " << addr << " is outside range" << endl; + return; + } + for(uInt32 i = beg; i <= end; ++i) + { + if((i % 0x2000 >= 0x1000) && (i & 0x0FFF) == (addr & 0x0FFF)) + { + if(read) debugger.toggleReadTrap(i); + if(write) debugger.toggleWriteTrap(i); + } + } + break; + } + } + + commandResult << trapStatus(addr) << " + mirrors from $" + << Base::HEX4 << beg << " - $" << end << endl; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "type" void DebuggerParser::executeType() @@ -2128,6 +2222,33 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeTrapwrite) }, + { + "trapm", + "Trap read/write access to address xx (+mirrors)", + true, + false, + { kARG_WORD, kARG_MULTI_WORD }, + std::mem_fn(&DebuggerParser::executeTrapM) + }, + + { + "trapreadm", + "Trap read access to address xx (+mirrors)", + true, + false, + { kARG_WORD, kARG_MULTI_WORD }, + std::mem_fn(&DebuggerParser::executeTrapreadM) + }, + + { + "trapwritem", + "Trap write access to address xx (+mirrors)", + true, + false, + { kARG_WORD, kARG_MULTI_WORD }, + std::mem_fn(&DebuggerParser::executeTrapwriteM) + }, + { "type", "Show disassembly type for address xx [to yy]", diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 7645d086f..50260470c 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -70,9 +70,7 @@ class DebuggerParser bool saveScriptFile(string file); private: - enum { - kNumCommands = 70 - }; + enum { kNumCommands = 73 }; // Constants for argument processing enum { @@ -182,6 +180,11 @@ class DebuggerParser void executeTrap(); void executeTrapread(); void executeTrapwrite(); + void executeTrapRW(bool read, bool write); // not exposed by debugger + void executeTrapM(); + void executeTrapreadM(); + void executeTrapwriteM(); + void executeTrapMRW(bool read, bool write); // not exposed by debugger void executeType(); void executeUHex(); void executeUndef();