From 61bf556e5b839775b7f6a59c67590c3d056eb802 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Fri, 6 Oct 2017 23:06:59 +0200 Subject: [PATCH 01/12] it compiles again --- src/debugger/Debugger.cxx | 53 ++++++++ src/debugger/Debugger.hxx | 14 +- src/debugger/DebuggerParser.cxx | 202 +++++++++++++++++++++-------- src/debugger/DebuggerParser.hxx | 14 +- src/emucore/M6502.cxx | 53 ++++++++ src/emucore/M6502.hxx | 29 ++++- src/windows/Stella.vcxproj | 1 + src/windows/Stella.vcxproj.filters | 3 + 8 files changed, 309 insertions(+), 60 deletions(-) diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index ef8119ee6..ec9e1d302 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -387,6 +387,26 @@ void Debugger::toggleTrap(uInt16 t) toggleWriteTrap(t); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::addReadTrap(uInt16 t) +{ + readTraps().initialize(); + readTraps().add(t); +} + +void Debugger::addWriteTrap(uInt16 t) +{ + writeTraps().initialize(); + writeTraps().add(t); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::addTrap(uInt16 t) +{ + addReadTrap(t); + addWriteTrap(t); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Debugger::readTrap(uInt16 t) { @@ -399,6 +419,39 @@ bool Debugger::writeTrap(uInt16 t) return writeTraps().isInitialized() && writeTraps().isSet(t); } +/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::toggleReadTrapIf(uInt16 t) +{ + readTrapIfs().initialize(); + readTrapIfs().toggle(t); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::toggleWriteTrapIf(uInt16 t) +{ + writeTrapIfs().initialize(); + writeTrapIfs().toggle(t); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::toggleTrapIf(uInt16 t) +{ + toggleReadTrapIf(t); + toggleWriteTrapIf(t); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Debugger::readTrapIf(uInt16 t) +{ + return readTrapIfs().isInitialized() && readTrapIfs().isSet(t); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Debugger::writeTrapIf(uInt16 t) +{ + return writeTrapIfs().isInitialized() && writeTrapIfs().isSet(t); +}*/ + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::nextScanline(int lines) { diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index bdefeb719..5decd30ab 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -145,8 +145,10 @@ class Debugger : public DialogContainer TiaOutputWidget& tiaOutput() const { return myDialog->tiaOutput(); } PackedBitArray& breakPoints() const { return mySystem.m6502().breakPoints(); } - PackedBitArray& readTraps() const { return mySystem.m6502().readTraps(); } - PackedBitArray& writeTraps() const { return mySystem.m6502().writeTraps(); } + TrapArray& readTraps() const { return mySystem.m6502().readTraps(); } + TrapArray& writeTraps() const { return mySystem.m6502().writeTraps(); } + /*PackedBitArray& readTrapIfs() const { return mySystem.m6502().readTrapIfs(); } + PackedBitArray& writeTrapIfs() const { return mySystem.m6502().writeTrapIfs(); }*/ /** Run the debugger command and return the result. @@ -259,8 +261,16 @@ class Debugger : public DialogContainer void toggleReadTrap(uInt16 t); void toggleWriteTrap(uInt16 t); void toggleTrap(uInt16 t); + void addReadTrap(uInt16 t); + void addWriteTrap(uInt16 t); + void addTrap(uInt16 t); bool readTrap(uInt16 t); bool writeTrap(uInt16 t); + /*void toggleReadTrapIf(uInt16 t); + void toggleWriteTrapIf(uInt16 t); + void toggleTrapIf(uInt16 t); + bool readTrapIf(uInt16 t); + bool writeTrapIf(uInt16 t);*/ void clearAllTraps(); // Set a bunch of RAM locations at once diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index c1a4b12ac..5cebb73f7 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -548,7 +548,7 @@ string DebuggerParser::trapStatus(uInt32 addr, bool& enabled) string result; result += Base::toString(addr); result += ": "; - bool r = debugger.readTrap(addr); + bool r = debugger.readTrap(addr); // TODO trapif bool w = debugger.writeTrap(addr); enabled = r || w; if(r && w) @@ -591,7 +591,7 @@ bool DebuggerParser::saveScriptFile(string file) for(uInt32 i = 0; i < 0x10000; ++i) { - bool r = debugger.readTrap(i); + bool r = debugger.readTrap(i); // TODO trapif bool w = debugger.writeTrap(i); if(r && w) @@ -745,7 +745,9 @@ void DebuggerParser::executeClearconfig() void DebuggerParser::executeCleartraps() { myTraps.clear(); + myTrapIfs.clear(); // TODO trapif debugger.clearAllTraps(); + //debugger.cpuDebug().m6502().clearCondTraps(); commandResult << "all traps cleared"; } @@ -861,6 +863,14 @@ void DebuggerParser::executeDelfunction() commandResult << "function " << argStrings[0] << " built-in or not found"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "deltrapif" +void DebuggerParser::executeDeltrapif() +{ + //debugger.cpuDebug().m6502().delCondTrap(args[0]); + // TODO trapif +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "delwatch" void DebuggerParser::executeDelwatch() @@ -1129,11 +1139,40 @@ void DebuggerParser::executeListtraps() { if(myTraps.size() > 0) { + commandResult << "traps:\n"; bool enabled = true; + uInt32 i = 0; + for(const auto& trap: myTraps) - commandResult << trapStatus(trap, enabled) << " + mirrors" << endl; + { + commandResult << trapStatus(trap, enabled) << " + mirrors"; + if(i != (myTraps.size() - 1)) commandResult << endl; + i++; + } } - else + // TODO trapif + /*if(myTrapIfs.size() > 0) + { + StringList conds = debugger.cpuDebug().m6502().getCondTrapNames(); + commandResult << "trapifs:\n"; + if(myTrapIfs.size() != conds.size()) + { + // should never happen + commandResult << "ERROR! trapif condition size != address ranges size"; + return; + } + bool enabled = true; + uInt32 i = 0; + + for(const auto& trap : myTrapIfs) + { + commandResult << i << ": " << conds[i] << ", "; + //commandResult << trapStatus(trap.address, enabled, true) << " + mirrors"; + if(i != (myTrapIfs.size() - 1)) commandResult << endl; + i++; + } + }*/ + if(myTraps.size() == 0 && myTrapIfs.size() == 0) commandResult << "no traps set"; } @@ -1482,58 +1521,71 @@ void DebuggerParser::executeTrace() // "trap" void DebuggerParser::executeTrap() { - if(argCount > 2) - { - commandResult << red("Command takes one or two arguments") << endl; - return; - } + executeTraps(true, true); +} - uInt32 beg = args[0]; - uInt32 end = argCount == 2 ? args[1] : beg; - if(beg > 0xFFFF || end > 0xFFFF) - { - commandResult << red("One or more addresses are invalid") << endl; - return; - } - - for(uInt32 addr = beg; addr <= end; ++addr) - executeTrapRW(addr, true, true); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "trapif" +void DebuggerParser::executeTrapif() +{ + executeTraps(true, true, true, "trapif"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapread" void DebuggerParser::executeTrapread() { - if(argCount > 2) - { - commandResult << red("Command takes one or two arguments") << endl; - return; - } + executeTraps(true, false); +} - uInt32 beg = args[0]; - uInt32 end = argCount == 2 ? args[1] : beg; - if(beg > 0xFFFF || end > 0xFFFF) - { - commandResult << red("One or more addresses are invalid") << endl; - return; - } - - for(uInt32 addr = beg; addr <= end; ++addr) - executeTrapRW(addr, true, false); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "trapreadif" +void DebuggerParser::executeTrapreadif() +{ + executeTraps(true, false, true, "trapreadif"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapwrite" void DebuggerParser::executeTrapwrite() { - if(argCount > 2) + executeTraps(false, true); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "trapwriteif" +void DebuggerParser::executeTrapwriteif() +{ + executeTraps(false, true, true, "trapwriteif"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Wrapper function for trap(if)s +void DebuggerParser::executeTraps(bool read, bool write, bool cond, string command) +{ + int ofs = cond ? 1 : 0; + + if(argCount > ofs + 2) { - commandResult << red("Command takes one or two arguments") << endl; + commandResult << (cond ? red("Command takes two or three arguments") : red("Command takes one or two arguments")) << endl; return; } - uInt32 beg = args[0]; - uInt32 end = argCount == 2 ? args[1] : beg; + /*if(cond) + { + int res = YaccParser::parse(argStrings[0].c_str()); + if(res == 0) + { + uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( + YaccParser::getResult(), argStrings[0]); + commandResult << "Added " << command << " " << Base::toString(ret) << ", "; + } + else + commandResult << red("invalid expression"); + }*/ + + uInt32 beg = args[ofs]; + uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; if(beg > 0xFFFF || end > 0xFFFF) { commandResult << red("One or more addresses are invalid") << endl; @@ -1541,12 +1593,12 @@ void DebuggerParser::executeTrapwrite() } for(uInt32 addr = beg; addr <= end; ++addr) - executeTrapRW(addr, false, true); + executeTrapRW(addr, read, write, cond); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // wrapper function for trap/trapread/trapwrite commands -void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write) +void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond) { switch(debugger.cartDebug().addressType(addr)) { @@ -1557,7 +1609,7 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write) if((i & 0x1080) == 0x0000) { if(read && (i & 0x000F) == addr) - debugger.toggleReadTrap(i); + debugger.toggleReadTrap(i); if(write && (i & 0x003F) == addr) debugger.toggleWriteTrap(i); } @@ -1570,8 +1622,10 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write) { if((i & 0x1080) == 0x0080 && (i & 0x0200) != 0x0000 && (i & 0x02FF) == addr) { - if(read) debugger.toggleReadTrap(i); - if(write) debugger.toggleWriteTrap(i); + if(read) + debugger.toggleReadTrap(i); + if(write) + debugger.toggleWriteTrap(i); } } break; @@ -1582,8 +1636,10 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write) { if((i & 0x1080) == 0x0080 && (i & 0x0200) == 0x0000 && (i & 0x00FF) == addr) { - if(read) debugger.toggleReadTrap(i); - if(write) debugger.toggleWriteTrap(i); + if(read) + debugger.toggleReadTrap(i); + if(write) + debugger.toggleWriteTrap(i); } } break; @@ -1596,8 +1652,10 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write) { if((i % 0x2000 >= 0x1000) && (i & 0x0FFF) == (addr & 0x0FFF)) { - if(read) debugger.toggleReadTrap(i); - if(write) debugger.toggleWriteTrap(i); + if(read) + debugger.toggleReadTrap(i); + if(write) + debugger.toggleWriteTrap(i); } } } @@ -1607,10 +1665,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write) bool trapEnabled = false; const string& result = trapStatus(addr, trapEnabled); - if(trapEnabled) myTraps.insert(addr); - else myTraps.erase(addr); - - commandResult << result << " + mirrors" << endl; + + if(trapEnabled) cond ? myTrapIfs.push_back(addr) : myTraps.insert(addr); + else cond ? myTrapIfs.size() : myTraps.erase(addr); // TODO trapif } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1891,6 +1948,16 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeDelfunction) }, + { + "deltrapif", + "Delete conditional trapif ", + "Example: deltrapif 0", + true, + false, + { kARG_WORD, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeDeltrapif) + }, + { "delwatch", "Delete watch ", @@ -2333,6 +2400,17 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeTrap) }, + { + "trapif", + "On trap R/W access to address(es) xx [yy]", + "Set a conditional R/W trap on the given address(es) and all mirrors\nCondition can include multiple items.\n" + "Example: trapif _scan>100 GRP0, trapif _bank==1 f000 f100", + true, + false, + { kARG_WORD, kARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executeTrapif) + }, + { "trapread", "Trap read access to address(es) xx [yy]", @@ -2344,6 +2422,17 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeTrapread) }, + { + "trapreadif", + "On trap read access to address(es) xx [yy]", + "Set a conditional read trap on the given address(es) and all mirrors\nCondition can include multiple items.\n" + "Example: trapreadif _scan>100 GRP0, trapreadif _bank==1 f000 f100", + true, + false, + { kARG_WORD, kARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executeTrapreadif) + }, + { "trapwrite", "Trap write access to address(es) xx [yy]", @@ -2355,6 +2444,17 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeTrapwrite) }, + { + "trapwriteif", + "On trap write access to address(es) xx [yy]", + "Set a conditional write trap on the given address(es) and all mirrors\nCondition can include multiple items.\n" + "Example: trapwriteif _scan>100 GRP0, trapwriteif _bank==1 f000 f100", + true, + false, + { kARG_WORD, kARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executeTrapwriteif) + }, + { "type", "Show disassembly type for address xx [yy]", diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index e9e403ac0..66ebcae42 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -68,7 +68,7 @@ class DebuggerParser bool saveScriptFile(string file); private: - enum { kNumCommands = 72 }; + enum { kNumCommands = 76 }; // Constants for argument processing enum { @@ -100,7 +100,7 @@ class DebuggerParser parameters parms[10]; std::function executor; }; - + // Reference to our debugger object Debugger& debugger; @@ -119,6 +119,7 @@ class DebuggerParser // Keep track of traps (read and/or write) std::set myTraps; + std::vector myTrapIfs; string trapStatus(uInt32 addr, bool& enabled); // List of available command methods @@ -140,6 +141,7 @@ class DebuggerParser void executeDebugColors(); void executeDefine(); void executeDelbreakif(); + void executeDeltrapif(); void executeDelfunction(); void executeDelwatch(); void executeDisasm(); @@ -184,9 +186,13 @@ class DebuggerParser void executeTia(); void executeTrace(); void executeTrap(); + void executeTrapif(); void executeTrapread(); - void executeTrapwrite(); - void executeTrapRW(uInt32 addr, bool read, bool write); // not exposed by debugger + void executeTrapreadif(); + void executeTrapwrite(); + void executeTrapwriteif(); + void executeTraps(bool read, bool write, bool cond = false, string command = ""); + void executeTrapRW(uInt32 addr, bool read, bool write, bool cond = false); // not exposed by debugger void executeType(); void executeUHex(); void executeUndef(); diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index 6aa430eec..ce9a08544 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -128,6 +128,16 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags) myHitTrapInfo.message = "RTrap: "; myHitTrapInfo.address = address; } + /*if(myReadTrapIfs.isInitialized() && myReadTrapIfs.isSet(address)) + { + int cond = evalCondTraps(); + if(cond > -1) + { + myJustHitTrapFlag = true; + myHitTrapInfo.message = "RTrapIf (" + myTrapCondNames[cond] + "): "; + myHitTrapInfo.address = address; + } + }*/ #endif // DEBUGGER_SUPPORT uInt8 result = mySystem->peek(address, flags); @@ -155,6 +165,17 @@ inline void M6502::poke(uInt16 address, uInt8 value, uInt8 flags) myHitTrapInfo.message = "WTrap: "; myHitTrapInfo.address = address; } + /*if(myWriteTrapIfs.isInitialized() && myWriteTrapIfs.isSet(address)) + { + int cond = evalCondTraps(); + if(cond > -1) + { + myJustHitTrapFlag = true; + myHitTrapInfo.message = "WTrapIf (" + myTrapCondNames[cond] + "): "; + myHitTrapInfo.address = address; + } + }*/ + #endif // DEBUGGER_SUPPORT mySystem->poke(address, value, flags); @@ -437,4 +458,36 @@ const StringList& M6502::getCondBreakNames() const { return myBreakCondNames; } + +/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 M6502::addCondTrap(Expression* e, const string& name) +{ + //myTrapConds.emplace_back(e); + myTrapCondNames.push_back(name); + return uInt32(myTrapConds.size() - 1); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void M6502::delCondTrap(uInt32 brk) +{ + if(brk < myTrapConds.size()) + { + myTrapConds.erase(brk); + //Vec::removeAt(myTrapConds, brk); + Vec::removeAt(myTrapCondNames, brk); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void M6502::clearCondTraps() +{ + myTrapConds.clear(); + myTrapCondNames.clear(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const StringList& M6502::getCondTrapNames() const +{ + return myTrapCondNames; +}*/ #endif // DEBUGGER_SUPPORT diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index b22a5727f..7e21ea5c5 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -24,6 +24,7 @@ #include "Expression.hxx" #include "PackedBitArray.hxx" + #include "TrapArray.hxx" #endif class Settings; @@ -207,13 +208,23 @@ class M6502 : public Serializable void attach(Debugger& debugger); PackedBitArray& breakPoints() { return myBreakPoints; } - PackedBitArray& readTraps() { return myReadTraps; } - PackedBitArray& writeTraps() { return myWriteTraps; } + //PackedBitArray& readTraps() { return myReadTraps; } + //PackedBitArray& writeTraps() { return myWriteTraps; } + //PackedBitArray& readTrapIfs() { return myReadTrapIfs; } + //PackedBitArray& writeTrapIfs() { return myWriteTrapIfs; } + TrapArray& readTraps() { return myReadTraps; } + TrapArray& writeTraps() { return myWriteTraps; } uInt32 addCondBreak(Expression* e, const string& name); void delCondBreak(uInt32 brk); void clearCondBreaks(); const StringList& getCondBreakNames() const; + + /*uInt32 addCondTrap(Expression* e, const string& name); + void delCondTrap(uInt32 brk); + void clearCondTraps(); + const StringList& getCondTrapNames() const;*/ + #endif // DEBUGGER_SUPPORT private: @@ -359,11 +370,21 @@ class M6502 : public Serializable return -1; // no break hit } + /*Int32 evalCondTraps() + { + for(uInt32 i = 0; i < myTrapConds.size(); i++) + if(myTrapConds[i]->evaluate()) + return i; + + return -1; // no trapif hit + }*/ + /// Pointer to the debugger for this processor or the null pointer Debugger* myDebugger; // Addresses for which the specified action should occur - PackedBitArray myBreakPoints, myReadTraps, myWriteTraps; + PackedBitArray myBreakPoints;// , myReadTraps, myWriteTraps, myReadTrapIfs, myWriteTrapIfs; + TrapArray myReadTraps, myWriteTraps; // Did we just now hit a trap? bool myJustHitTrapFlag; @@ -375,6 +396,8 @@ class M6502 : public Serializable vector> myBreakConds; StringList myBreakCondNames; + //std::map> myTrapConds; + //StringList myTrapCondNames; #endif // DEBUGGER_SUPPORT private: diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 54e8a5635..f4cf3e333 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -575,6 +575,7 @@ + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index fcedc20ed..de22defe1 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -1751,6 +1751,9 @@ Header Files\debugger + + Header Files\debugger + From f862e1c97d88aa01caa86b2cdd80366c59136406 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 7 Oct 2017 14:17:34 +0200 Subject: [PATCH 02/12] progress... --- src/debugger/CartDebug.cxx | 2 +- src/debugger/CartDebug.hxx | 6 ++++++ src/debugger/Debugger.cxx | 6 ++++-- src/debugger/DebuggerParser.cxx | 31 +++++++++++++++++++++++-------- src/emucore/M6502.cxx | 9 ++++----- src/emucore/M6502.hxx | 33 ++++++++++++++++++++++++--------- src/yacc/YaccParser.cxx | 4 ++++ 7 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 79f8abe7a..515d79a98 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -171,7 +171,7 @@ int CartDebug::readFromWritePort() // port address space AND the last access was actually a read (the latter // differentiates between reads that are normally part of a write cycle vs. // ones that are illegal) - if(mySystem.m6502().lastReadAddress() && + if(mySystem.m6502().lastRealReadAddress() && (mySystem.getPageAccessType(addr) & System::PA_WRITE) == System::PA_WRITE) return addr; else diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 3c178dd44..c9c0531ff 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -30,6 +30,7 @@ class CartDebugWidget; #include "Cart.hxx" #include "DebuggerSystem.hxx" #include "System.hxx" +#include "M6502.hxx" // Function type for CartDebug instance methods class CartDebug; @@ -127,6 +128,11 @@ class CartDebug : public DebuggerSystem // write port area. int readFromWritePort(); + // Return the address of the last CPU read + int lastReadAddress() { return mySystem.m6502().lastReadAddress(); } + // Return the address of the last CPU write + int lastWriteAddress() { return mySystem.m6502().lastWriteAddress(); } + // The following two methods are meant to be used together // First, a call is made to disassemble(), which updates the disassembly // list; it will figure out when an actual complete disassembly is diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index ec9e1d302..c73e002fc 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -85,7 +85,6 @@ static const char* const builtin_functions[][3] = { { "_diff0a", "*SWCHB & $40", "Left diff. set to A (hard)" }, { "_diff1b", "!(*SWCHB & $80)", "Right diff. set to B (easy)" }, { "_diff1a", "*SWCHB & $80", "Right diff. set to A (hard)" }, - // empty string marks end of list, do not remove { 0, 0, 0 } }; @@ -104,7 +103,10 @@ static const char* const pseudo_registers[][2] = { { "_rwport", "Address at which a read from a write port occurred" }, { "_scan", "Current scanline count" }, { "_vblank", "Whether vertical blank is enabled (1 or 0)" }, - { "_vsync", "Whether vertical sync is enabled (1 or 0)" }, + { "_vsync", "Whether vertical sync is enabled (1 or 0)" }, + // CPU address access functions: + { "_lastread", "last CPU read address" }, + { "_lastwrite", "last CPU write address" }, // empty string marks end of list, do not remove { 0, 0 } diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 5cebb73f7..719aafbef 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1571,21 +1571,36 @@ void DebuggerParser::executeTraps(bool read, bool write, bool cond, string comma return; } - /*if(cond) - { - int res = YaccParser::parse(argStrings[0].c_str()); + uInt32 beg = args[ofs]; + uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; + + if(cond) + { + // create: (condition) && (_lastread >= f000 && _lastread <= f100) + // add address range condition(s) to provided condition + stringstream buf; + buf << "(" << argStrings[0] << ")&&("; + if(read) + buf << "_lastread>=" << Base::toString(beg) << "&&_lastread<=" << Base::toString(end); + if (read && write) + buf << "||"; + if (write) + buf << "_lastwrite>=" << Base::toString(beg) << "&&_lastwrite<=" << Base::toString(end); + buf << ")"; + string condition = buf.str(); + + //int res = YaccParser::parse(argStrings[0].c_str()); + int res = YaccParser::parse(condition.c_str()); if(res == 0) { uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( - YaccParser::getResult(), argStrings[0]); - commandResult << "Added " << command << " " << Base::toString(ret) << ", "; + YaccParser::getResult(), condition); + commandResult << "Added " << command << " " << Base::toString(ret); } else commandResult << red("invalid expression"); - }*/ + } - uInt32 beg = args[ofs]; - uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; if(beg > 0xFFFF || end > 0xFFFF) { commandResult << red("One or more addresses are invalid") << endl; diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index ce9a08544..16ce43f35 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -459,10 +459,10 @@ const StringList& M6502::getCondBreakNames() const return myBreakCondNames; } -/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 M6502::addCondTrap(Expression* e, const string& name) { - //myTrapConds.emplace_back(e); + myTrapConds.emplace_back(e); myTrapCondNames.push_back(name); return uInt32(myTrapConds.size() - 1); } @@ -472,8 +472,7 @@ void M6502::delCondTrap(uInt32 brk) { if(brk < myTrapConds.size()) { - myTrapConds.erase(brk); - //Vec::removeAt(myTrapConds, brk); + Vec::removeAt(myTrapConds, brk); Vec::removeAt(myTrapCondNames, brk); } } @@ -489,5 +488,5 @@ void M6502::clearCondTraps() const StringList& M6502::getCondTrapNames() const { return myTrapCondNames; -}*/ +} #endif // DEBUGGER_SUPPORT diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index 7e21ea5c5..77c15423e 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -145,11 +145,25 @@ class M6502 : public Serializable @return The address of the last read */ - uInt16 lastReadAddress() const { + uInt16 lastRealReadAddress() const { return myLastPokeAddress ? (myLastPokeAddress != myLastPeekAddress ? myLastPeekAddress : 0) : myLastPeekAddress; - } + } + + /** + Return the last address that was part of a read/peek. + + @return The address of the last read + */ + uInt16 lastReadAddress() const { return myLastPeekAddress; } + + /** + Return the last address that was part of a write/poke. + + @return The address of the last write + */ + uInt16 lastWriteAddress() const { return myLastPokeAddress; } /** Return the source of the address that was used for a write/poke. @@ -215,16 +229,17 @@ class M6502 : public Serializable TrapArray& readTraps() { return myReadTraps; } TrapArray& writeTraps() { return myWriteTraps; } + // methods for 'breakif' handling uInt32 addCondBreak(Expression* e, const string& name); void delCondBreak(uInt32 brk); void clearCondBreaks(); const StringList& getCondBreakNames() const; - /*uInt32 addCondTrap(Expression* e, const string& name); + // methods for 'trapif' handling + uInt32 addCondTrap(Expression* e, const string& name); void delCondTrap(uInt32 brk); void clearCondTraps(); - const StringList& getCondTrapNames() const;*/ - + const StringList& getCondTrapNames() const; #endif // DEBUGGER_SUPPORT private: @@ -370,14 +385,14 @@ class M6502 : public Serializable return -1; // no break hit } - /*Int32 evalCondTraps() + Int32 evalCondTraps() { for(uInt32 i = 0; i < myTrapConds.size(); i++) if(myTrapConds[i]->evaluate()) return i; return -1; // no trapif hit - }*/ + } /// Pointer to the debugger for this processor or the null pointer Debugger* myDebugger; @@ -396,8 +411,8 @@ class M6502 : public Serializable vector> myBreakConds; StringList myBreakCondNames; - //std::map> myTrapConds; - //StringList myTrapCondNames; + vector> myTrapConds; + StringList myTrapCondNames; #endif // DEBUGGER_SUPPORT private: diff --git a/src/yacc/YaccParser.cxx b/src/yacc/YaccParser.cxx index 6a010b720..862970584 100644 --- a/src/yacc/YaccParser.cxx +++ b/src/yacc/YaccParser.cxx @@ -206,6 +206,10 @@ CartMethod getCartSpecial(char* ch) return &CartDebug::getBank; else if(BSPF::equalsIgnoreCase(ch, "_rwport")) return &CartDebug::readFromWritePort; + else if(BSPF::equalsIgnoreCase(ch, "_lastread")) + return &CartDebug::lastReadAddress; + else if(BSPF::equalsIgnoreCase(ch, "_lastwrite")) + return &CartDebug::lastWriteAddress; else return 0; } From c6593e6c585cac7198a19fd23c7941bceea47d51 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 7 Oct 2017 18:25:56 +0200 Subject: [PATCH 03/12] this should be working --- src/debugger/Debugger.cxx | 24 +++- src/debugger/Debugger.hxx | 12 +- src/debugger/DebuggerParser.cxx | 236 +++++++++++++++++++------------- src/debugger/DebuggerParser.hxx | 21 ++- src/emucore/M6502.cxx | 46 +++---- src/emucore/M6502.hxx | 4 +- 6 files changed, 202 insertions(+), 141 deletions(-) diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index c73e002fc..aee0a7d6f 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -368,7 +368,7 @@ bool Debugger::breakPoint(uInt16 bp) return breakPoints().isSet(bp); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::toggleReadTrap(uInt16 t) { readTraps().initialize(); @@ -387,7 +387,7 @@ void Debugger::toggleTrap(uInt16 t) { toggleReadTrap(t); toggleWriteTrap(t); -} +}*/ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::addReadTrap(uInt16 t) @@ -409,6 +409,26 @@ void Debugger::addTrap(uInt16 t) addWriteTrap(t); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::removeReadTrap(uInt16 t) +{ + readTraps().initialize(); + readTraps().remove(t); +} + +void Debugger::removeWriteTrap(uInt16 t) +{ + writeTraps().initialize(); + writeTraps().remove(t); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Debugger::removeTrap(uInt16 t) +{ + removeReadTrap(t); + removeWriteTrap(t); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Debugger::readTrap(uInt16 t) { diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index 5decd30ab..e142888b6 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -258,19 +258,17 @@ class Debugger : public DialogContainer void toggleBreakPoint(uInt16 bp); bool breakPoint(uInt16 bp); - void toggleReadTrap(uInt16 t); + /*void toggleReadTrap(uInt16 t); void toggleWriteTrap(uInt16 t); - void toggleTrap(uInt16 t); + void toggleTrap(uInt16 t);*/ void addReadTrap(uInt16 t); void addWriteTrap(uInt16 t); void addTrap(uInt16 t); + void removeReadTrap(uInt16 t); + void removeWriteTrap(uInt16 t); + void removeTrap(uInt16 t); bool readTrap(uInt16 t); bool writeTrap(uInt16 t); - /*void toggleReadTrapIf(uInt16 t); - void toggleWriteTrapIf(uInt16 t); - void toggleTrapIf(uInt16 t); - bool readTrapIf(uInt16 t); - bool writeTrapIf(uInt16 t);*/ void clearAllTraps(); // Set a bunch of RAM locations at once diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 719aafbef..ba92ac8fe 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -542,7 +542,7 @@ string DebuggerParser::eval() return buf.str(); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string DebuggerParser::trapStatus(uInt32 addr, bool& enabled) { string result; @@ -568,7 +568,7 @@ string DebuggerParser::trapStatus(uInt32 addr, bool& enabled) } return result; -} +}*/ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool DebuggerParser::saveScriptFile(string file) @@ -591,7 +591,7 @@ bool DebuggerParser::saveScriptFile(string file) for(uInt32 i = 0; i < 0x10000; ++i) { - bool r = debugger.readTrap(i); // TODO trapif + bool r = debugger.readTrap(i); bool w = debugger.writeTrap(i); if(r && w) @@ -744,10 +744,8 @@ void DebuggerParser::executeClearconfig() // "cleartraps" void DebuggerParser::executeCleartraps() { - myTraps.clear(); - myTrapIfs.clear(); // TODO trapif debugger.clearAllTraps(); - //debugger.cpuDebug().m6502().clearCondTraps(); + debugger.cpuDebug().m6502().clearCondTraps(); commandResult << "all traps cleared"; } @@ -864,11 +862,20 @@ void DebuggerParser::executeDelfunction() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// "deltrapif" -void DebuggerParser::executeDeltrapif() +// "deltrap" +void DebuggerParser::executeDeltrap() { - //debugger.cpuDebug().m6502().delCondTrap(args[0]); - // TODO trapif + int index = args[0]; + + if(debugger.cpuDebug().m6502().delCondTrap(index)) + { + for(uInt32 addr = myTraps[index]->begin; addr <= myTraps[index]->end; ++addr) + executeTrapRW(addr, myTraps[index]->read, myTraps[index]->write, false); + Vec::removeAt(myTraps, index); + commandResult << "removed trap " << Base::toString(index); + } + else + commandResult << "no such trap"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1099,7 +1106,7 @@ void DebuggerParser::executeListbreaks() commandResult << "\nbreakifs:\n"; for(uInt32 i = 0; i < conds.size(); i++) { - commandResult << i << ": " << conds[i]; + commandResult << Base::toString(i) << ": " << conds[i]; if(i != (conds.size() - 1)) commandResult << endl; } } @@ -1137,42 +1144,20 @@ void DebuggerParser::executeListfunctions() // "listtraps" void DebuggerParser::executeListtraps() { - if(myTraps.size() > 0) + StringList names = debugger.cpuDebug().m6502().getCondTrapNames(); + if (names.size() > 0) { - commandResult << "traps:\n"; - bool enabled = true; - uInt32 i = 0; - - for(const auto& trap: myTraps) + for(uInt32 i = 0; i < names.size(); i++) { - commandResult << trapStatus(trap, enabled) << " + mirrors"; - if(i != (myTraps.size() - 1)) commandResult << endl; - i++; + commandResult << Base::toString(i) << ": " << names[i]; + + commandResult << "|" << Base::toString(myTraps[i]->begin) << Base::toString(myTraps[i]->end); + + + if(i != (names.size() - 1)) commandResult << endl; } } - // TODO trapif - /*if(myTrapIfs.size() > 0) - { - StringList conds = debugger.cpuDebug().m6502().getCondTrapNames(); - commandResult << "trapifs:\n"; - if(myTrapIfs.size() != conds.size()) - { - // should never happen - commandResult << "ERROR! trapif condition size != address ranges size"; - return; - } - bool enabled = true; - uInt32 i = 0; - - for(const auto& trap : myTrapIfs) - { - commandResult << i << ": " << conds[i] << ", "; - //commandResult << trapStatus(trap.address, enabled, true) << " + mirrors"; - if(i != (myTrapIfs.size() - 1)) commandResult << endl; - i++; - } - }*/ - if(myTraps.size() == 0 && myTrapIfs.size() == 0) + else commandResult << "no traps set"; } @@ -1521,99 +1506,154 @@ void DebuggerParser::executeTrace() // "trap" void DebuggerParser::executeTrap() { - executeTraps(true, true); + executeTraps(true, true, "trap"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapif" void DebuggerParser::executeTrapif() { - executeTraps(true, true, true, "trapif"); + executeTraps(true, true, "trapif", true); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapread" void DebuggerParser::executeTrapread() { - executeTraps(true, false); + executeTraps(true, false, "trapread"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapreadif" void DebuggerParser::executeTrapreadif() { - executeTraps(true, false, true, "trapreadif"); + executeTraps(true, false, "trapreadif", true); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapwrite" void DebuggerParser::executeTrapwrite() { - executeTraps(false, true); + executeTraps(false, true, "trapwrite"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "trapwriteif" void DebuggerParser::executeTrapwriteif() { - executeTraps(false, true, true, "trapwriteif"); + executeTraps(false, true, "trapwriteif", true); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wrapper function for trap(if)s -void DebuggerParser::executeTraps(bool read, bool write, bool cond, string command) +void DebuggerParser::executeTraps(bool read, bool write, string command, bool hasCond) { - int ofs = cond ? 1 : 0; - - if(argCount > ofs + 2) + if(hasCond) { - commandResult << (cond ? red("Command takes two or three arguments") : red("Command takes one or two arguments")) << endl; - return; + if(argCount < 1 || argCount > 3) + { + commandResult << red("Command takes one to three arguments") << endl; + return; + } + } + else + { + if(argCount > 2) + { + commandResult << red("Command takes one or two arguments") << endl; + return; + } } + int ofs = hasCond ? 1 : 0; uInt32 beg = args[ofs]; uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; - if(cond) - { - // create: (condition) && (_lastread >= f000 && _lastread <= f100) - // add address range condition(s) to provided condition - stringstream buf; - buf << "(" << argStrings[0] << ")&&("; - if(read) - buf << "_lastread>=" << Base::toString(beg) << "&&_lastread<=" << Base::toString(end); - if (read && write) - buf << "||"; - if (write) - buf << "_lastwrite>=" << Base::toString(beg) << "&&_lastwrite<=" << Base::toString(end); - buf << ")"; - string condition = buf.str(); - - //int res = YaccParser::parse(argStrings[0].c_str()); - int res = YaccParser::parse(condition.c_str()); - if(res == 0) - { - uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( - YaccParser::getResult(), condition); - commandResult << "Added " << command << " " << Base::toString(ret); - } - else - commandResult << red("invalid expression"); - } - if(beg > 0xFFFF || end > 0xFFFF) { commandResult << red("One or more addresses are invalid") << endl; return; } + // parenthesize provided and address range condition(s) (begin) + stringstream parserBuf, displayBuf; + if(hasCond) + { + parserBuf << "(" << argStrings[0] << ")&&("; + displayBuf << argStrings[0] << " "; + } + // build nice display string + if(read && write) + { + displayBuf << "read|write"; + } + else if(read) + { + displayBuf << "read"; + } + else if(write) + { + displayBuf << "write"; + } + if(beg != end) + displayBuf << " " << Base::toString(beg) << " " << Base::toString(end); + else + displayBuf << " " << Base::toString(beg); + displayBuf << " + mirrors"; + + // TODO: mirrors + //beg = getBaseMirror(beg); + //end = getBaseMirror(eng); + + // add address range condition(s) to provided condition + if(read) + { + if(beg != end) + parserBuf << "_lastread>=" << Base::toString(beg) << "&&_lastread<=" << Base::toString(end); + else + parserBuf << "_lastread==" << Base::toString(beg); + } + if(read && write) + parserBuf << "||"; + if(write) + { + if(beg != end) + parserBuf << "_lastwrite>=" << Base::toString(beg) << "&&_lastwrite<=" << Base::toString(end); + else + parserBuf << "_lastwrite==" << Base::toString(beg); + } + // parenthesize provided condition (end) + if(hasCond) + parserBuf << ")"; + + // TODO: duplicates + bool add = true; + + string parserCondition = parserBuf.str(); + string displayCondition = displayBuf.str(); + + int res = YaccParser::parse(parserCondition.c_str()); + if(res == 0) + { + uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( + YaccParser::getResult(), displayCondition); + commandResult << "Added " << command << " " << Base::toString(ret); + } + else + { + commandResult << red("invalid expression"); + return; + } + + myTraps.emplace_back(new Trap{ read, write, beg, end }); + for(uInt32 addr = beg; addr <= end; ++addr) - executeTrapRW(addr, read, write, cond); + executeTrapRW(addr, read, write, add); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // wrapper function for trap/trapread/trapwrite commands -void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond) +void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) { switch(debugger.cartDebug().addressType(addr)) { @@ -1624,9 +1664,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond if((i & 0x1080) == 0x0000) { if(read && (i & 0x000F) == addr) - debugger.toggleReadTrap(i); + add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); if(write && (i & 0x003F) == addr) - debugger.toggleWriteTrap(i); + debugger.addWriteTrap(i); } } break; @@ -1638,9 +1678,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond if((i & 0x1080) == 0x0080 && (i & 0x0200) != 0x0000 && (i & 0x02FF) == addr) { if(read) - debugger.toggleReadTrap(i); + debugger.addReadTrap(i); if(write) - debugger.toggleWriteTrap(i); + debugger.addReadTrap(i); } } break; @@ -1652,9 +1692,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond if((i & 0x1080) == 0x0080 && (i & 0x0200) == 0x0000 && (i & 0x00FF) == addr) { if(read) - debugger.toggleReadTrap(i); + debugger.addReadTrap(i); if(write) - debugger.toggleWriteTrap(i); + debugger.addReadTrap(i); } } break; @@ -1668,9 +1708,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond if((i % 0x2000 >= 0x1000) && (i & 0x0FFF) == (addr & 0x0FFF)) { if(read) - debugger.toggleReadTrap(i); + debugger.addReadTrap(i); if(write) - debugger.toggleWriteTrap(i); + debugger.addReadTrap(i); } } } @@ -1678,11 +1718,11 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool cond } } - bool trapEnabled = false; + /*bool trapEnabled = false; const string& result = trapStatus(addr, trapEnabled); if(trapEnabled) cond ? myTrapIfs.push_back(addr) : myTraps.insert(addr); - else cond ? myTrapIfs.size() : myTraps.erase(addr); // TODO trapif + else cond ? myTrapIfs.size() : myTraps.erase(addr); // TODO trapif*/ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1964,13 +2004,13 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { }, { - "deltrapif", - "Delete conditional trapif ", - "Example: deltrapif 0", + "deltrap", + "Delete trap ", + "Example: deltrap 0", true, false, { kARG_WORD, kARG_END_ARGS }, - std::mem_fn(&DebuggerParser::executeDeltrapif) + std::mem_fn(&DebuggerParser::executeDeltrap) }, { diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 66ebcae42..c315d4d96 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -100,6 +100,13 @@ class DebuggerParser parameters parms[10]; std::function executor; }; + struct Trap + { + bool read; + bool write; + uInt32 begin; + uInt32 end; + }; // Reference to our debugger object Debugger& debugger; @@ -117,10 +124,12 @@ class DebuggerParser StringList myWatches; + // Keep track of traps (read and/or write) - std::set myTraps; + vector> myTraps; + /*std::set myTraps; std::vector myTrapIfs; - string trapStatus(uInt32 addr, bool& enabled); + string trapStatus(uInt32 addr, bool& enabled);*/ // List of available command methods void executeA(); @@ -140,9 +149,9 @@ class DebuggerParser void executeData(); void executeDebugColors(); void executeDefine(); - void executeDelbreakif(); - void executeDeltrapif(); + void executeDelbreakif(); void executeDelfunction(); + void executeDeltrap(); void executeDelwatch(); void executeDisasm(); void executeDump(); @@ -191,8 +200,8 @@ class DebuggerParser void executeTrapreadif(); void executeTrapwrite(); void executeTrapwriteif(); - void executeTraps(bool read, bool write, bool cond = false, string command = ""); - void executeTrapRW(uInt32 addr, bool read, bool write, bool cond = false); // not exposed by debugger + void executeTraps(bool read, bool write, string command, bool cond = false); + void executeTrapRW(uInt32 addr, bool read, bool write, bool add = true); // not exposed by debugger void executeType(); void executeUHex(); void executeUndef(); diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index 16ce43f35..9b2ec4096 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -120,28 +120,24 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags) } //////////////////////////////////////////////// mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU); + uInt8 result = mySystem->peek(address, flags); + myLastPeekAddress = address; #ifdef DEBUGGER_SUPPORT if(myReadTraps.isInitialized() && myReadTraps.isSet(address)) { - myJustHitTrapFlag = true; - myHitTrapInfo.message = "RTrap: "; - myHitTrapInfo.address = address; - } - /*if(myReadTrapIfs.isInitialized() && myReadTrapIfs.isSet(address)) - { + //TODO: myLastPeekBaseAddress = baseAddress(myLastPeekAddress); // mirror handling int cond = evalCondTraps(); if(cond > -1) { myJustHitTrapFlag = true; - myHitTrapInfo.message = "RTrapIf (" + myTrapCondNames[cond] + "): "; + myHitTrapInfo.message = "RTrap: "; + //myHitTrapInfo.message = "RTrapIf (" + myTrapCondNames[cond] + "): "; myHitTrapInfo.address = address; } - }*/ + } #endif // DEBUGGER_SUPPORT - uInt8 result = mySystem->peek(address, flags); - myLastPeekAddress = address; return result; } @@ -156,30 +152,24 @@ inline void M6502::poke(uInt16 address, uInt8 value, uInt8 flags) myLastAddress = address; } //////////////////////////////////////////////// - mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU); + mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU); + mySystem->poke(address, value, flags); + myLastPokeAddress = address; #ifdef DEBUGGER_SUPPORT if(myWriteTraps.isInitialized() && myWriteTraps.isSet(address)) { - myJustHitTrapFlag = true; - myHitTrapInfo.message = "WTrap: "; - myHitTrapInfo.address = address; - } - /*if(myWriteTrapIfs.isInitialized() && myWriteTrapIfs.isSet(address)) - { + //TODO: myLastPokeBaseAddress = baseAddress(myLastPokeAddress); // mirror handling int cond = evalCondTraps(); if(cond > -1) { myJustHitTrapFlag = true; - myHitTrapInfo.message = "WTrapIf (" + myTrapCondNames[cond] + "): "; + myHitTrapInfo.message = "WTrap: "; + //myHitTrapInfo.message = "WTrapIf (" + myTrapCondNames[cond] + "): "; myHitTrapInfo.address = address; } - }*/ - -#endif // DEBUGGER_SUPPORT - - mySystem->poke(address, value, flags); - myLastPokeAddress = address; + } +#endif // DEBUGGER_SUPPORT } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -437,13 +427,15 @@ uInt32 M6502::addCondBreak(Expression* e, const string& name) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void M6502::delCondBreak(uInt32 brk) +bool M6502::delCondBreak(uInt32 brk) { if(brk < myBreakConds.size()) { Vec::removeAt(myBreakConds, brk); Vec::removeAt(myBreakCondNames, brk); + return true; } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -468,13 +460,15 @@ uInt32 M6502::addCondTrap(Expression* e, const string& name) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void M6502::delCondTrap(uInt32 brk) +bool M6502::delCondTrap(uInt32 brk) { if(brk < myTrapConds.size()) { Vec::removeAt(myTrapConds, brk); Vec::removeAt(myTrapCondNames, brk); + return true; } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index 77c15423e..d13935761 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -231,13 +231,13 @@ class M6502 : public Serializable // methods for 'breakif' handling uInt32 addCondBreak(Expression* e, const string& name); - void delCondBreak(uInt32 brk); + bool delCondBreak(uInt32 brk); void clearCondBreaks(); const StringList& getCondBreakNames() const; // methods for 'trapif' handling uInt32 addCondTrap(Expression* e, const string& name); - void delCondTrap(uInt32 brk); + bool delCondTrap(uInt32 brk); void clearCondTraps(); const StringList& getCondTrapNames() const; #endif // DEBUGGER_SUPPORT From ffacd7a5e733238048c3a4ca1599c514d1888e6d Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 7 Oct 2017 18:28:44 +0200 Subject: [PATCH 04/12] missed a clear --- src/debugger/DebuggerParser.cxx | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index ba92ac8fe..a4f3a5403 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -746,6 +746,7 @@ void DebuggerParser::executeCleartraps() { debugger.clearAllTraps(); debugger.cpuDebug().m6502().clearCondTraps(); + myTraps.clear(); commandResult << "all traps cleared"; } @@ -871,6 +872,7 @@ void DebuggerParser::executeDeltrap() { for(uInt32 addr = myTraps[index]->begin; addr <= myTraps[index]->end; ++addr) executeTrapRW(addr, myTraps[index]->read, myTraps[index]->write, false); + // @sa666666: please check this: Vec::removeAt(myTraps, index); commandResult << "removed trap " << Base::toString(index); } @@ -1645,6 +1647,7 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha return; } + // @sa666666: please check this: myTraps.emplace_back(new Trap{ read, write, beg, end }); for(uInt32 addr = beg; addr <= end; ++addr) @@ -1666,7 +1669,7 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) if(read && (i & 0x000F) == addr) add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); if(write && (i & 0x003F) == addr) - debugger.addWriteTrap(i); + add ? debugger.addWriteTrap(i) : debugger.removeWriteTrap(i); } } break; @@ -1678,9 +1681,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) if((i & 0x1080) == 0x0080 && (i & 0x0200) != 0x0000 && (i & 0x02FF) == addr) { if(read) - debugger.addReadTrap(i); + add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); if(write) - debugger.addReadTrap(i); + add ? debugger.addWriteTrap(i) : debugger.removeWriteTrap(i); } } break; @@ -1692,9 +1695,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) if((i & 0x1080) == 0x0080 && (i & 0x0200) == 0x0000 && (i & 0x00FF) == addr) { if(read) - debugger.addReadTrap(i); + add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); if(write) - debugger.addReadTrap(i); + add ? debugger.addWriteTrap(i) : debugger.removeWriteTrap(i); } } break; @@ -1708,21 +1711,15 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) if((i % 0x2000 >= 0x1000) && (i & 0x0FFF) == (addr & 0x0FFF)) { if(read) - debugger.addReadTrap(i); + add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); if(write) - debugger.addReadTrap(i); + add ? debugger.addWriteTrap(i) : debugger.removeWriteTrap(i); } } } break; } } - - /*bool trapEnabled = false; - const string& result = trapStatus(addr, trapEnabled); - - if(trapEnabled) cond ? myTrapIfs.push_back(addr) : myTraps.insert(addr); - else cond ? myTrapIfs.size() : myTraps.erase(addr); // TODO trapif*/ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 15925c313c92d67f35dd9cbf19565d27e877f6c4 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 7 Oct 2017 19:30:21 +0200 Subject: [PATCH 05/12] working on formatting --- src/debugger/DebuggerParser.cxx | 35 +++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index a4f3a5403..0a7706c12 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1152,10 +1152,7 @@ void DebuggerParser::executeListtraps() for(uInt32 i = 0; i < names.size(); i++) { commandResult << Base::toString(i) << ": " << names[i]; - - commandResult << "|" << Base::toString(myTraps[i]->begin) << Base::toString(myTraps[i]->end); - - + //commandResult << "|" << Base::toString(myTraps[i]->begin) << " " << Base::toString(myTraps[i]->end); if(i != (names.size() - 1)) commandResult << endl; } } @@ -1597,10 +1594,28 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha { displayBuf << "write"; } + + string label; + stringstream beginLabel, endLabel; + + label = debugger.cartDebug().getLabel(beg, !write); + if(label != "") + { + beginLabel << " ("; + beginLabel << label; + beginLabel << ")"; + } + label = debugger.cartDebug().getLabel(end, !write); + if(label != "") + { + endLabel << " ("; + endLabel << label; + endLabel << ")"; + } + + displayBuf << " " << Base::toString(beg) << beginLabel.str(); if(beg != end) - displayBuf << " " << Base::toString(beg) << " " << Base::toString(end); - else - displayBuf << " " << Base::toString(beg); + displayBuf << " " << Base::toString(end) << endLabel.str(); displayBuf << " + mirrors"; // TODO: mirrors @@ -1631,8 +1646,8 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha // TODO: duplicates bool add = true; - string parserCondition = parserBuf.str(); - string displayCondition = displayBuf.str(); + const string parserCondition = parserBuf.str(); + const string displayCondition = displayBuf.str(); int res = YaccParser::parse(parserCondition.c_str()); if(res == 0) @@ -1655,7 +1670,7 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// wrapper function for trap/trapread/trapwrite commands +// wrapper function for trap(if)/trapread(if)/trapwrite(if) commands void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) { switch(debugger.cartDebug().addressType(addr)) From 41dffe6f78cfa3960ee77c7dad19d232e1683b5f Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 7 Oct 2017 20:22:54 +0200 Subject: [PATCH 06/12] works! TODOs: - identify duplicates and trigger remove when added - mirrored addresses - testing --- src/debugger/DebuggerParser.cxx | 111 ++++++++++++-------------------- src/debugger/DebuggerParser.hxx | 4 +- 2 files changed, 44 insertions(+), 71 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 0a7706c12..7f6d358ec 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -542,33 +542,30 @@ string DebuggerParser::eval() return buf.str(); } -/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string DebuggerParser::trapStatus(uInt32 addr, bool& enabled) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string DebuggerParser::trapStatus(const Trap& trap) { - string result; - result += Base::toString(addr); - result += ": "; - bool r = debugger.readTrap(addr); // TODO trapif - bool w = debugger.writeTrap(addr); - enabled = r || w; - if(r && w) - result += "read|write"; - else if(r) - result += "read"; - else if(w) - result += "write"; - else - result += "none"; + stringstream result; - const string& l = debugger.cartDebug().getLabel(addr, !w); - if(l != "") { - result += " ("; - result += l; - result += ")"; + string lbl = debugger.cartDebug().getLabel(trap.begin, !trap.write); + if(lbl != "") { + result << " ("; + result << lbl; } - return result; -}*/ + if(trap.begin != trap.end) + { + lbl = debugger.cartDebug().getLabel(trap.end, !trap.write); + if(lbl != "") + { + result << " "; + result << lbl; + } + } + result << ")"; + + return result.str(); +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool DebuggerParser::saveScriptFile(string file) @@ -1151,8 +1148,23 @@ void DebuggerParser::executeListtraps() { for(uInt32 i = 0; i < names.size(); i++) { - commandResult << Base::toString(i) << ": " << names[i]; - //commandResult << "|" << Base::toString(myTraps[i]->begin) << " " << Base::toString(myTraps[i]->end); + commandResult << Base::toString(i) << ": "; + + if(myTraps[i]->read && myTraps[i]->write) + commandResult << "read|write"; + else if(myTraps[i]->read) + commandResult << "read"; + else if(myTraps[i]->write) + commandResult << "write"; + else + commandResult << "none"; + + commandResult << " " << names[i]; + commandResult << " " << Base::toString(myTraps[i]->begin); + if (myTraps[i]->begin != myTraps[i]->end) + commandResult << " " << Base::toString(myTraps[i]->end); + commandResult << trapStatus(*myTraps[i]); + commandResult << " + mirrors"; if(i != (names.size() - 1)) commandResult << endl; } } @@ -1551,7 +1563,7 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha { if(argCount < 1 || argCount > 3) { - commandResult << red("Command takes one to three arguments") << endl; + commandResult << red("Command takes one to three arguments"); return; } } @@ -1559,7 +1571,7 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha { if(argCount > 2) { - commandResult << red("Command takes one or two arguments") << endl; + commandResult << red("Command takes one or two arguments"); return; } } @@ -1568,55 +1580,16 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha uInt32 beg = args[ofs]; uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; - if(beg > 0xFFFF || end > 0xFFFF) + if(beg > 0xFFFF || end > 0xFFFF || beg > end) { - commandResult << red("One or more addresses are invalid") << endl; + commandResult << red("One or more addresses are invalid"); return; } // parenthesize provided and address range condition(s) (begin) stringstream parserBuf, displayBuf; if(hasCond) - { parserBuf << "(" << argStrings[0] << ")&&("; - displayBuf << argStrings[0] << " "; - } - // build nice display string - if(read && write) - { - displayBuf << "read|write"; - } - else if(read) - { - displayBuf << "read"; - } - else if(write) - { - displayBuf << "write"; - } - - string label; - stringstream beginLabel, endLabel; - - label = debugger.cartDebug().getLabel(beg, !write); - if(label != "") - { - beginLabel << " ("; - beginLabel << label; - beginLabel << ")"; - } - label = debugger.cartDebug().getLabel(end, !write); - if(label != "") - { - endLabel << " ("; - endLabel << label; - endLabel << ")"; - } - - displayBuf << " " << Base::toString(beg) << beginLabel.str(); - if(beg != end) - displayBuf << " " << Base::toString(end) << endLabel.str(); - displayBuf << " + mirrors"; // TODO: mirrors //beg = getBaseMirror(beg); @@ -1653,7 +1626,7 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha if(res == 0) { uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( - YaccParser::getResult(), displayCondition); + YaccParser::getResult(), argStrings[0]); commandResult << "Added " << command << " " << Base::toString(ret); } else diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index c315d4d96..540d556f1 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -128,8 +128,8 @@ class DebuggerParser // Keep track of traps (read and/or write) vector> myTraps; /*std::set myTraps; - std::vector myTrapIfs; - string trapStatus(uInt32 addr, bool& enabled);*/ + std::vector myTrapIfs;*/ + string trapStatus(const Trap& trap); // List of available command methods void executeA(); From 7b8b121ee5696d139fd7f57f1920a4321301713c Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 7 Oct 2017 23:45:32 +0200 Subject: [PATCH 07/12] detect duplicate traps which will eliminate each other --- src/debugger/DebuggerParser.cxx | 110 ++++++++++++++++++++++++-------- src/debugger/DebuggerParser.hxx | 1 + 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 7f6d358ec..85d01fdc2 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1153,9 +1153,9 @@ void DebuggerParser::executeListtraps() if(myTraps[i]->read && myTraps[i]->write) commandResult << "read|write"; else if(myTraps[i]->read) - commandResult << "read"; + commandResult << "read "; else if(myTraps[i]->write) - commandResult << "write"; + commandResult << " write"; else commandResult << "none"; @@ -1577,10 +1577,10 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha } int ofs = hasCond ? 1 : 0; - uInt32 beg = args[ofs]; - uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; + uInt32 begin = args[ofs]; + uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : begin; - if(beg > 0xFFFF || end > 0xFFFF || beg > end) + if(begin > 0xFFFF || end > 0xFFFF || begin > end) { commandResult << red("One or more addresses are invalid"); return; @@ -1592,54 +1592,113 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha parserBuf << "(" << argStrings[0] << ")&&("; // TODO: mirrors - //beg = getBaseMirror(beg); + //begin = getBaseMirror(begin); //end = getBaseMirror(eng); // add address range condition(s) to provided condition if(read) { - if(beg != end) - parserBuf << "_lastread>=" << Base::toString(beg) << "&&_lastread<=" << Base::toString(end); + if(begin != end) + parserBuf << "_lastread>=" << Base::toString(begin) << "&&_lastread<=" << Base::toString(end); else - parserBuf << "_lastread==" << Base::toString(beg); + parserBuf << "_lastread==" << Base::toString(begin); } if(read && write) parserBuf << "||"; if(write) { - if(beg != end) - parserBuf << "_lastwrite>=" << Base::toString(beg) << "&&_lastwrite<=" << Base::toString(end); + if(begin != end) + parserBuf << "_lastwrite>=" << Base::toString(begin) << "&&_lastwrite<=" << Base::toString(end); else - parserBuf << "_lastwrite==" << Base::toString(beg); + parserBuf << "_lastwrite==" << Base::toString(begin); } // parenthesize provided condition (end) if(hasCond) parserBuf << ")"; - // TODO: duplicates - bool add = true; - const string parserCondition = parserBuf.str(); - const string displayCondition = displayBuf.str(); int res = YaccParser::parse(parserCondition.c_str()); if(res == 0) { - uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( - YaccParser::getResult(), argStrings[0]); - commandResult << "Added " << command << " " << Base::toString(ret); + // duplicates will remove each other + bool add = true; + for(uInt32 i = 0; i < myTraps.size(); i++) + { + if(myTraps[i]->begin == begin && myTraps[i]->end == end && + myTraps[i]->read == read && myTraps[i]->write == write && + myTraps[i]->condition == parserCondition) + { + if(debugger.cpuDebug().m6502().delCondTrap(i)) + { + add = false; + // @sa666666: please check this: + Vec::removeAt(myTraps, i); + commandResult << "Removed trap " << Base::toString(i); + break; + } + commandResult << "Internal error! Duplicate trap removal failed!"; + return; + } + } + if(add) + { + uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( + YaccParser::getResult(), hasCond ? argStrings[0] : " "); + commandResult << "Added trap " << Base::toString(ret); + + // @sa666666: please check this: + myTraps.emplace_back(new Trap{ read, write, begin, end, parserCondition }); + } + + for(uInt32 addr = begin; addr <= end; ++addr) + executeTrapRW(addr, read, write, add); } else { commandResult << red("invalid expression"); - return; } - - // @sa666666: please check this: - myTraps.emplace_back(new Trap{ read, write, beg, end }); +} - for(uInt32 addr = beg; addr <= end; ++addr) - executeTrapRW(addr, read, write, add); +uInt32 getBaseAddress(uInt32 addr, bool read) +{ + // ADDR_TIA write (%xxx0 xxxx 0x?? ????) + if(!read && (addr & 0x1080) == 0x0000) // (addr & 0b 0001 0000 1000 0000) == 0b 0000 0000 0000 0000 + return addr & 0x003f; // 0b 0000 0000 0011 1111 + + // ADDR_TIA read (%xxx0 xxxx 0xxx ????) + if(read && (addr & 0x1080) == 0x0000) // (addr & 0b 0001 0000 1000 0000) == 0b 0000 0000 0000 0000 + return addr & 0x000f; // 0b 0000 0000 0000 1111 + + // ADDR_ZPRAM (%xxx0 xx0x 1??? ????) + if((addr & 0x1280) == 0x0080) // (addr & 0b 0001 0010 1000 0000) == 0b 0000 0000 1000 0000 + return addr & 0x00ff; // 0b 0000 0000 1111 1111 + + // ADDR_ROM + if(addr & 0x1000) + return addr & 0x1fff; // 0b 0001 1111 1111 1111 + + // ADDR_IO read/write I/O registers (%xxx0 xx1x 1xxx x0??) + if((addr & 0x1284) == 0x0280) // (addr & 0b 0001 0010 1000 0100) == 0b 0000 0010 1000 0000 + return addr & 0x0283; // 0b 0000 0010 1000 0011 + + // ADDR_IO write timers (%xxx0 xx1x 1xx1 ?1??) + if(!read && (addr & 0x1294) == 0x0294) // (addr & 0b 0001 0010 1001 0100) == 0b 0000 0010 1001 0100 + return addr & 0x029f; // 0b 0000 0010 1001 1111 + + // ADDR_IO read timers (%xxx0 xx1x 1xxx ?1x0) + if(read && (addr & 0x1285) == 0x0284) // (addr & 0b 0001 0010 1000 0101) == 0b 0000 0010 1000 0100 + return addr & 0x028c; // 0b 0000 0010 1000 1100 + + // ADDR_IO read timer/PA7 interrupt (%xxx0 xx1x 1xxx x1x1) + if(read && (addr & 0x1285) == 0x0285) // (addr & 0b 0001 0010 1000 0101) == 0b 0000 0010 1000 0101 + return addr & 0x0285; // 0b 0000 0010 1000 0101 + + // ADDR_IO write PA7 edge control (%xxx0 xx1x 1xx0 x1??) + if(!read && (addr & 0x1294) == 0x0284) // (addr & 0b 0001 0010 1001 0100) == 0b 0000 0010 1000 0100 + return addr & 0x0287; // 0b 0000 0010 1000 0111 + + return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1654,6 +1713,7 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) { if((i & 0x1080) == 0x0000) { + // @sa666666: This seems wrong. E.g. trapread 40 4f will never trigger if(read && (i & 0x000F) == addr) add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); if(write && (i & 0x003F) == addr) diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 540d556f1..363fe2ecc 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -106,6 +106,7 @@ class DebuggerParser bool write; uInt32 begin; uInt32 end; + string condition; }; // Reference to our debugger object From d15690f5f1f99a95b34a550b8a787b6d27ed29d2 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 8 Oct 2017 10:43:26 +0200 Subject: [PATCH 08/12] added mirrors --- src/debugger/CartDebug.cxx | 2 +- src/debugger/CartDebug.hxx | 8 ++-- src/debugger/Debugger.cxx | 65 +++++++++++++++++------------- src/debugger/Debugger.hxx | 1 + src/debugger/DebuggerParser.cxx | 71 +++++++++------------------------ src/emucore/M6502.cxx | 4 +- src/emucore/M6502.hxx | 9 +++-- src/yacc/YaccParser.cxx | 4 +- 8 files changed, 72 insertions(+), 92 deletions(-) diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 515d79a98..79f8abe7a 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -171,7 +171,7 @@ int CartDebug::readFromWritePort() // port address space AND the last access was actually a read (the latter // differentiates between reads that are normally part of a write cycle vs. // ones that are illegal) - if(mySystem.m6502().lastRealReadAddress() && + if(mySystem.m6502().lastReadAddress() && (mySystem.getPageAccessType(addr) & System::PA_WRITE) == System::PA_WRITE) return addr; else diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index c9c0531ff..a513c678a 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -128,10 +128,10 @@ class CartDebug : public DebuggerSystem // write port area. int readFromWritePort(); - // Return the address of the last CPU read - int lastReadAddress() { return mySystem.m6502().lastReadAddress(); } - // Return the address of the last CPU write - int lastWriteAddress() { return mySystem.m6502().lastWriteAddress(); } + // Return the base (= non-mirrored) address of the last CPU read + int lastReadBaseAddress() { return mySystem.m6502().lastReadBaseAddress(); } + // Return the base (= non-mirrored) address of the last CPU write + int lastWriteBaseAddress() { return mySystem.m6502().lastWriteBaseAddress(); } // The following two methods are meant to be used together // First, a call is made to disassemble(), which updates the disassembly diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index aee0a7d6f..50dc315ae 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -440,39 +440,48 @@ bool Debugger::writeTrap(uInt16 t) { return writeTraps().isInitialized() && writeTraps().isSet(t); } - -/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::toggleReadTrapIf(uInt16 t) -{ - readTrapIfs().initialize(); - readTrapIfs().toggle(t); -} - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::toggleWriteTrapIf(uInt16 t) +uInt32 Debugger::getBaseAddress(uInt32 addr, bool read) { - writeTrapIfs().initialize(); - writeTrapIfs().toggle(t); -} + if((addr & 0x1080) == 0x0000) // (addr & 0b 0001 0000 1000 0000) == 0b 0000 0000 0000 0000 + if(read) + // ADDR_TIA read (%xxx0 xxxx 0xxx ????) + return addr & 0x000f; // 0b 0000 0000 0000 1111 + else + // ADDR_TIA write (%xxx0 xxxx 0x?? ????) + return addr & 0x003f; // 0b 0000 0000 0011 1111 -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::toggleTrapIf(uInt16 t) -{ - toggleReadTrapIf(t); - toggleWriteTrapIf(t); -} + // ADDR_ZPRAM (%xxx0 xx0x 1??? ????) + if((addr & 0x1280) == 0x0080) // (addr & 0b 0001 0010 1000 0000) == 0b 0000 0000 1000 0000 + return addr & 0x00ff; // 0b 0000 0000 1111 1111 -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Debugger::readTrapIf(uInt16 t) -{ - return readTrapIfs().isInitialized() && readTrapIfs().isSet(t); -} + // ADDR_ROM + if(addr & 0x1000) + return addr & 0x1fff; // 0b 0001 1111 1111 1111 -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Debugger::writeTrapIf(uInt16 t) -{ - return writeTrapIfs().isInitialized() && writeTrapIfs().isSet(t); -}*/ + // ADDR_IO read/write I/O registers (%xxx0 xx1x 1xxx x0??) + if((addr & 0x1284) == 0x0280) // (addr & 0b 0001 0010 1000 0100) == 0b 0000 0010 1000 0000 + return addr & 0x0283; // 0b 0000 0010 1000 0011 + + // ADDR_IO write timers (%xxx0 xx1x 1xx1 ?1??) + if(!read && (addr & 0x1294) == 0x0294) // (addr & 0b 0001 0010 1001 0100) == 0b 0000 0010 1001 0100 + return addr & 0x029f; // 0b 0000 0010 1001 1111 + + // ADDR_IO read timers (%xxx0 xx1x 1xxx ?1x0) + if(read && (addr & 0x1285) == 0x0284) // (addr & 0b 0001 0010 1000 0101) == 0b 0000 0010 1000 0100 + return addr & 0x028c; // 0b 0000 0010 1000 1100 + + // ADDR_IO read timer/PA7 interrupt (%xxx0 xx1x 1xxx x1x1) + if(read && (addr & 0x1285) == 0x0285) // (addr & 0b 0001 0010 1000 0101) == 0b 0000 0010 1000 0101 + return addr & 0x0285; // 0b 0000 0010 1000 0101 + + // ADDR_IO write PA7 edge control (%xxx0 xx1x 1xx0 x1??) + if(!read && (addr & 0x1294) == 0x0284) // (addr & 0b 0001 0010 1001 0100) == 0b 0000 0010 1000 0100 + return addr & 0x0287; // 0b 0000 0010 1000 0111 + + return 0; +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::nextScanline(int lines) diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index e142888b6..118a33558 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -216,6 +216,7 @@ class Debugger : public DialogContainer { mySystem.setAccessFlags(addr, flags); } void setBreakPoint(uInt16 bp, bool set); + uInt32 getBaseAddress(uInt32 addr, bool read); bool patchROM(uInt16 addr, uInt8 value); diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 85d01fdc2..3f5f07082 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1144,6 +1144,13 @@ void DebuggerParser::executeListfunctions() void DebuggerParser::executeListtraps() { StringList names = debugger.cpuDebug().m6502().getCondTrapNames(); + + if(myTraps.size() != names.size()) + { + commandResult << "Internal error! Different trap sizes."; + return; + } + if (names.size() > 0) { for(uInt32 i = 0; i < names.size(); i++) @@ -1579,6 +1586,11 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha int ofs = hasCond ? 1 : 0; uInt32 begin = args[ofs]; uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : begin; + // mirrors + uInt32 beginRead = debugger.getBaseAddress(begin, true); + uInt32 endRead = debugger.getBaseAddress(end, true); + uInt32 beginWrite = debugger.getBaseAddress(begin, false); + uInt32 endWrite = debugger.getBaseAddress(end, false); if(begin > 0xFFFF || end > 0xFFFF || begin > end) { @@ -1590,27 +1602,23 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha stringstream parserBuf, displayBuf; if(hasCond) parserBuf << "(" << argStrings[0] << ")&&("; - - // TODO: mirrors - //begin = getBaseMirror(begin); - //end = getBaseMirror(eng); - + // add address range condition(s) to provided condition if(read) { - if(begin != end) - parserBuf << "_lastread>=" << Base::toString(begin) << "&&_lastread<=" << Base::toString(end); + if(beginRead != endRead) + parserBuf << "_lastread>=" << Base::toString(beginRead) << "&&_lastread<=" << Base::toString(endRead); else - parserBuf << "_lastread==" << Base::toString(begin); + parserBuf << "_lastread==" << Base::toString(beginRead); } if(read && write) parserBuf << "||"; if(write) { - if(begin != end) - parserBuf << "_lastwrite>=" << Base::toString(begin) << "&&_lastwrite<=" << Base::toString(end); + if(beginWrite != endWrite) + parserBuf << "_lastwrite>=" << Base::toString(beginWrite) << "&&_lastwrite<=" << Base::toString(endWrite); else - parserBuf << "_lastwrite==" << Base::toString(begin); + parserBuf << "_lastwrite==" << Base::toString(beginWrite); } // parenthesize provided condition (end) if(hasCond) @@ -1660,47 +1668,6 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha } } -uInt32 getBaseAddress(uInt32 addr, bool read) -{ - // ADDR_TIA write (%xxx0 xxxx 0x?? ????) - if(!read && (addr & 0x1080) == 0x0000) // (addr & 0b 0001 0000 1000 0000) == 0b 0000 0000 0000 0000 - return addr & 0x003f; // 0b 0000 0000 0011 1111 - - // ADDR_TIA read (%xxx0 xxxx 0xxx ????) - if(read && (addr & 0x1080) == 0x0000) // (addr & 0b 0001 0000 1000 0000) == 0b 0000 0000 0000 0000 - return addr & 0x000f; // 0b 0000 0000 0000 1111 - - // ADDR_ZPRAM (%xxx0 xx0x 1??? ????) - if((addr & 0x1280) == 0x0080) // (addr & 0b 0001 0010 1000 0000) == 0b 0000 0000 1000 0000 - return addr & 0x00ff; // 0b 0000 0000 1111 1111 - - // ADDR_ROM - if(addr & 0x1000) - return addr & 0x1fff; // 0b 0001 1111 1111 1111 - - // ADDR_IO read/write I/O registers (%xxx0 xx1x 1xxx x0??) - if((addr & 0x1284) == 0x0280) // (addr & 0b 0001 0010 1000 0100) == 0b 0000 0010 1000 0000 - return addr & 0x0283; // 0b 0000 0010 1000 0011 - - // ADDR_IO write timers (%xxx0 xx1x 1xx1 ?1??) - if(!read && (addr & 0x1294) == 0x0294) // (addr & 0b 0001 0010 1001 0100) == 0b 0000 0010 1001 0100 - return addr & 0x029f; // 0b 0000 0010 1001 1111 - - // ADDR_IO read timers (%xxx0 xx1x 1xxx ?1x0) - if(read && (addr & 0x1285) == 0x0284) // (addr & 0b 0001 0010 1000 0101) == 0b 0000 0010 1000 0100 - return addr & 0x028c; // 0b 0000 0010 1000 1100 - - // ADDR_IO read timer/PA7 interrupt (%xxx0 xx1x 1xxx x1x1) - if(read && (addr & 0x1285) == 0x0285) // (addr & 0b 0001 0010 1000 0101) == 0b 0000 0010 1000 0101 - return addr & 0x0285; // 0b 0000 0010 1000 0101 - - // ADDR_IO write PA7 edge control (%xxx0 xx1x 1xx0 x1??) - if(!read && (addr & 0x1294) == 0x0284) // (addr & 0b 0001 0010 1001 0100) == 0b 0000 0010 1000 0100 - return addr & 0x0287; // 0b 0000 0010 1000 0111 - - return 0; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // wrapper function for trap(if)/trapread(if)/trapwrite(if) commands void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index 9b2ec4096..04a93e40d 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -126,7 +126,7 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags) #ifdef DEBUGGER_SUPPORT if(myReadTraps.isInitialized() && myReadTraps.isSet(address)) { - //TODO: myLastPeekBaseAddress = baseAddress(myLastPeekAddress); // mirror handling + myLastPeekBaseAddress = myDebugger->getBaseAddress(myLastPeekAddress, true); // mirror handling int cond = evalCondTraps(); if(cond > -1) { @@ -159,7 +159,7 @@ inline void M6502::poke(uInt16 address, uInt8 value, uInt8 flags) #ifdef DEBUGGER_SUPPORT if(myWriteTraps.isInitialized() && myWriteTraps.isSet(address)) { - //TODO: myLastPokeBaseAddress = baseAddress(myLastPokeAddress); // mirror handling + myLastPokeBaseAddress = myDebugger->getBaseAddress(myLastPokeAddress, false); // mirror handling int cond = evalCondTraps(); if(cond > -1) { diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index d13935761..2c96b1dea 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -145,7 +145,7 @@ class M6502 : public Serializable @return The address of the last read */ - uInt16 lastRealReadAddress() const { + uInt16 lastReadAddress() const { return myLastPokeAddress ? (myLastPokeAddress != myLastPeekAddress ? myLastPeekAddress : 0) : myLastPeekAddress; @@ -156,14 +156,14 @@ class M6502 : public Serializable @return The address of the last read */ - uInt16 lastReadAddress() const { return myLastPeekAddress; } + uInt16 lastReadBaseAddress() const { return myLastPeekBaseAddress; } /** Return the last address that was part of a write/poke. @return The address of the last write */ - uInt16 lastWriteAddress() const { return myLastPokeAddress; } + uInt16 lastWriteBaseAddress() const { return myLastPokeBaseAddress; } /** Return the source of the address that was used for a write/poke. @@ -355,6 +355,9 @@ class M6502 : public Serializable /// Indicates the last address which was accessed specifically /// by a peek or poke command uInt16 myLastPeekAddress, myLastPokeAddress; + /// Indicates the last base (= non-mirrored) address which was + /// accessed specifically by a peek or poke command + uInt16 myLastPeekBaseAddress, myLastPokeBaseAddress; /// Indicates the last address used to access data by a peek command /// for the CPU registers (S/A/X/Y) diff --git a/src/yacc/YaccParser.cxx b/src/yacc/YaccParser.cxx index 862970584..8f88ba239 100644 --- a/src/yacc/YaccParser.cxx +++ b/src/yacc/YaccParser.cxx @@ -207,9 +207,9 @@ CartMethod getCartSpecial(char* ch) else if(BSPF::equalsIgnoreCase(ch, "_rwport")) return &CartDebug::readFromWritePort; else if(BSPF::equalsIgnoreCase(ch, "_lastread")) - return &CartDebug::lastReadAddress; + return &CartDebug::lastReadBaseAddress; else if(BSPF::equalsIgnoreCase(ch, "_lastwrite")) - return &CartDebug::lastWriteAddress; + return &CartDebug::lastWriteBaseAddress; else return 0; } From 90705babd7f84ce69764ac75505a9dd0b995c862 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 8 Oct 2017 12:25:23 +0200 Subject: [PATCH 09/12] debugger start displays labels where possible prevent repeated trap interrupts some old code cleanup --- src/debugger/Debugger.cxx | 26 ++------------------------ src/debugger/Debugger.hxx | 7 +------ src/debugger/DebuggerParser.cxx | 1 + src/emucore/M6502.cxx | 24 ++++++++++++------------ src/emucore/M6502.hxx | 3 ++- 5 files changed, 18 insertions(+), 43 deletions(-) diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index 50dc315ae..1698efbb3 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -168,7 +168,7 @@ FBInitStatus Debugger::initializeVideo() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Debugger::start(const string& message, int address) +bool Debugger::start(const string& message, int address, bool read) { if(myOSystem.eventHandler().enterDebugMode()) { @@ -177,8 +177,7 @@ bool Debugger::start(const string& message, int address) ostringstream buf; buf << message; if(address > -1) - buf << Common::Base::HEX4 << address; - + buf << cartDebug().getLabel(address, read); myDialog->message().setText(buf.str()); return true; } @@ -368,27 +367,6 @@ bool Debugger::breakPoint(uInt16 bp) return breakPoints().isSet(bp); } -/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::toggleReadTrap(uInt16 t) -{ - readTraps().initialize(); - readTraps().toggle(t); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::toggleWriteTrap(uInt16 t) -{ - writeTraps().initialize(); - writeTraps().toggle(t); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::toggleTrap(uInt16 t) -{ - toggleReadTrap(t); - toggleWriteTrap(t); -}*/ - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::addReadTrap(uInt16 t) { diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index 118a33558..635e953ae 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -88,7 +88,7 @@ class Debugger : public DialogContainer @param message Message to display when entering debugger @param address An address associated with the message */ - bool start(const string& message = "", int address = -1); + bool start(const string& message = "", int address = -1, bool read = true); bool startWithFatalError(const string& message = ""); /** @@ -147,8 +147,6 @@ class Debugger : public DialogContainer PackedBitArray& breakPoints() const { return mySystem.m6502().breakPoints(); } TrapArray& readTraps() const { return mySystem.m6502().readTraps(); } TrapArray& writeTraps() const { return mySystem.m6502().writeTraps(); } - /*PackedBitArray& readTrapIfs() const { return mySystem.m6502().readTrapIfs(); } - PackedBitArray& writeTrapIfs() const { return mySystem.m6502().writeTrapIfs(); }*/ /** Run the debugger command and return the result. @@ -259,9 +257,6 @@ class Debugger : public DialogContainer void toggleBreakPoint(uInt16 bp); bool breakPoint(uInt16 bp); - /*void toggleReadTrap(uInt16 t); - void toggleWriteTrap(uInt16 t); - void toggleTrap(uInt16 t);*/ void addReadTrap(uInt16 t); void addWriteTrap(uInt16 t); void addTrap(uInt16 t); diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 3f5f07082..f21f0c9fa 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -586,6 +586,7 @@ bool DebuggerParser::saveScriptFile(string file) if(debugger.breakPoint(i)) out << "break #" << i << endl; + // TODO: new trapif for(uInt32 i = 0; i < 0x10000; ++i) { bool r = debugger.readTrap(i); diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index 04a93e40d..7598a60b0 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -55,6 +55,8 @@ M6502::M6502(const Settings& settings) myLastAddress(0), myLastPeekAddress(0), myLastPokeAddress(0), + myLastPeekBaseAddress(0), + myLastPokeBaseAddress(0), myLastSrcAddressS(-1), myLastSrcAddressA(-1), myLastSrcAddressX(-1), @@ -65,7 +67,7 @@ M6502::M6502(const Settings& settings) { #ifdef DEBUGGER_SUPPORT myDebugger = nullptr; - myJustHitTrapFlag = false; + myJustHitReadTrapFlag = myJustHitWriteTrapFlag = false; #endif } @@ -98,7 +100,7 @@ void M6502::reset() // Load PC from the reset vector PC = uInt16(mySystem->peek(0xfffc)) | (uInt16(mySystem->peek(0xfffd)) << 8); - myLastAddress = myLastPeekAddress = myLastPokeAddress = 0; + myLastAddress = myLastPeekAddress = myLastPokeAddress = myLastPeekBaseAddress = myLastPokeBaseAddress; myLastSrcAddressS = myLastSrcAddressA = myLastSrcAddressX = myLastSrcAddressY = -1; myDataAddressForPoke = 0; @@ -130,9 +132,8 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags) int cond = evalCondTraps(); if(cond > -1) { - myJustHitTrapFlag = true; - myHitTrapInfo.message = "RTrap: "; - //myHitTrapInfo.message = "RTrapIf (" + myTrapCondNames[cond] + "): "; + myJustHitReadTrapFlag = true; + myHitTrapInfo.message = "RTrap(" + myTrapCondNames[cond] + "): "; myHitTrapInfo.address = address; } } @@ -163,9 +164,8 @@ inline void M6502::poke(uInt16 address, uInt8 value, uInt8 flags) int cond = evalCondTraps(); if(cond > -1) { - myJustHitTrapFlag = true; - myHitTrapInfo.message = "WTrap: "; - //myHitTrapInfo.message = "WTrapIf (" + myTrapCondNames[cond] + "): "; + myJustHitWriteTrapFlag = true; + myHitTrapInfo.message = "WTrap(" + myTrapCondNames[cond] + "): "; myHitTrapInfo.address = address; } } @@ -200,11 +200,11 @@ bool M6502::execute(uInt32 number) for(; !myExecutionStatus && (number != 0); --number) { #ifdef DEBUGGER_SUPPORT - if(myJustHitTrapFlag) + if(myJustHitReadTrapFlag || myJustHitWriteTrapFlag) { - if(myDebugger && myDebugger->start(myHitTrapInfo.message, myHitTrapInfo.address)) - { - myJustHitTrapFlag = false; + myJustHitReadTrapFlag = myJustHitWriteTrapFlag = false; + if(myDebugger && myDebugger->start(myHitTrapInfo.message, myHitTrapInfo.address, myJustHitReadTrapFlag)) + { return true; } } diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index 2c96b1dea..2f5ec5c8f 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -405,7 +405,8 @@ class M6502 : public Serializable TrapArray myReadTraps, myWriteTraps; // Did we just now hit a trap? - bool myJustHitTrapFlag; + bool myJustHitReadTrapFlag; + bool myJustHitWriteTrapFlag; struct HitTrapInfo { string message; int address; From 649dada32cd91ff31c1ef35cf49c9f9d0b1d30fe Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 8 Oct 2017 12:50:22 +0200 Subject: [PATCH 10/12] added missing file to source control --- src/debugger/TrapArray.hxx | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/debugger/TrapArray.hxx diff --git a/src/debugger/TrapArray.hxx b/src/debugger/TrapArray.hxx new file mode 100644 index 000000000..778ba4d9f --- /dev/null +++ b/src/debugger/TrapArray.hxx @@ -0,0 +1,55 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef TRAP_ARRAY_HXX +#define TRAP_ARRAY_HXX + +#include "bspf.hxx" + +class TrapArray +{ +public: + TrapArray() : myInitialized(false) {} + + bool isSet(const uInt16 address) const { return myCount[address]; } + bool isClear(const uInt16 address) const { return myCount[address] == 0; } + + void add(const uInt16 address) { myCount[address]++; } + void remove(const uInt16 address) { myCount[address]--; } + //void toggle(uInt16 address) { myCount[address] ? remove(address) : add(address); } // TODO condition + + void initialize() { myInitialized = true; } + void clearAll() { myInitialized = false; memset(myCount, 0, sizeof(myCount)); } + + bool isInitialized() const { return myInitialized; } + +private: + // The actual counts + uInt8 myCount[0x10000]; + + // Indicates whether we should treat this array as initialized + bool myInitialized; + +private: + // Following constructors and assignment operators not supported + TrapArray(const TrapArray&) = delete; + TrapArray(TrapArray&&) = delete; + TrapArray& operator=(const TrapArray&) = delete; + TrapArray& operator=(TrapArray&&) = delete; +}; + +#endif From eb2ae18ce189b26f1a7b07ae341e89113541f5cb Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 8 Oct 2017 14:18:14 +0200 Subject: [PATCH 11/12] added missing initialization --- src/debugger/TrapArray.hxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/debugger/TrapArray.hxx b/src/debugger/TrapArray.hxx index 778ba4d9f..4bbd9ca2e 100644 --- a/src/debugger/TrapArray.hxx +++ b/src/debugger/TrapArray.hxx @@ -32,7 +32,11 @@ public: void remove(const uInt16 address) { myCount[address]--; } //void toggle(uInt16 address) { myCount[address] ? remove(address) : add(address); } // TODO condition - void initialize() { myInitialized = true; } + void initialize() { + if(!myInitialized) + memset(myCount, 0, sizeof(myCount)); + myInitialized = true; + } void clearAll() { myInitialized = false; memset(myCount, 0, sizeof(myCount)); } bool isInitialized() const { return myInitialized; } From 7406c0fd2a4a57435810fbb2ca7fb2943a30420b Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 8 Oct 2017 15:59:00 +0200 Subject: [PATCH 12/12] hides new access functions since they can only used together with traps fixes listtraps formatting (trapStatus) fixes trap addresses (in executeTrapRW, addr & XY is now always used for compares) --- src/debugger/Debugger.cxx | 4 ++-- src/debugger/DebuggerParser.cxx | 40 ++++++++++++++++++--------------- src/yacc/YaccParser.cxx | 4 ++-- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index 1698efbb3..b4d308cb1 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -105,8 +105,8 @@ static const char* const pseudo_registers[][2] = { { "_vblank", "Whether vertical blank is enabled (1 or 0)" }, { "_vsync", "Whether vertical sync is enabled (1 or 0)" }, // CPU address access functions: - { "_lastread", "last CPU read address" }, - { "_lastwrite", "last CPU write address" }, + /*{ "__lastread", "last CPU read address" }, + { "__lastwrite", "last CPU write address" },*/ // empty string marks end of list, do not remove { 0, 0 } diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index f21f0c9fa..7a95211c6 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -545,24 +545,28 @@ string DebuggerParser::eval() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string DebuggerParser::trapStatus(const Trap& trap) { - stringstream result; - - string lbl = debugger.cartDebug().getLabel(trap.begin, !trap.write); - if(lbl != "") { + stringstream result; + string lblb = debugger.cartDebug().getLabel(trap.begin, !trap.write); + string lble = debugger.cartDebug().getLabel(trap.end, !trap.write); + + if(lblb != "") { result << " ("; - result << lbl; + result << lblb; } if(trap.begin != trap.end) { - lbl = debugger.cartDebug().getLabel(trap.end, !trap.write); - if(lbl != "") + if(lble != "") { - result << " "; - result << lbl; + if (lblb != "") + result << " "; + else + result << " ("; + result << lble; } } - result << ")"; + if (lblb != "" || lble != "") + result << ")"; return result.str(); } @@ -1608,18 +1612,18 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha if(read) { if(beginRead != endRead) - parserBuf << "_lastread>=" << Base::toString(beginRead) << "&&_lastread<=" << Base::toString(endRead); + parserBuf << "__lastread>=" << Base::toString(beginRead) << "&&__lastread<=" << Base::toString(endRead); else - parserBuf << "_lastread==" << Base::toString(beginRead); + parserBuf << "__lastread==" << Base::toString(beginRead); } if(read && write) parserBuf << "||"; if(write) { if(beginWrite != endWrite) - parserBuf << "_lastwrite>=" << Base::toString(beginWrite) << "&&_lastwrite<=" << Base::toString(endWrite); + parserBuf << "__lastwrite>=" << Base::toString(beginWrite) << "&&__lastwrite<=" << Base::toString(endWrite); else - parserBuf << "_lastwrite==" << Base::toString(beginWrite); + parserBuf << "__lastwrite==" << Base::toString(beginWrite); } // parenthesize provided condition (end) if(hasCond) @@ -1682,9 +1686,9 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) if((i & 0x1080) == 0x0000) { // @sa666666: This seems wrong. E.g. trapread 40 4f will never trigger - if(read && (i & 0x000F) == addr) + if(read && (i & 0x000F) == (addr & 0x000F)) add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); - if(write && (i & 0x003F) == addr) + if(write && (i & 0x003F) == (addr & 0x003F)) add ? debugger.addWriteTrap(i) : debugger.removeWriteTrap(i); } } @@ -1694,7 +1698,7 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) { for(uInt32 i = 0; i <= 0xFFFF; ++i) { - if((i & 0x1080) == 0x0080 && (i & 0x0200) != 0x0000 && (i & 0x02FF) == addr) + if((i & 0x1280) == 0x0280 && (i & 0x029F) == (addr & 0x029F)) { if(read) add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); @@ -1708,7 +1712,7 @@ void DebuggerParser::executeTrapRW(uInt32 addr, bool read, bool write, bool add) { for(uInt32 i = 0; i <= 0xFFFF; ++i) { - if((i & 0x1080) == 0x0080 && (i & 0x0200) == 0x0000 && (i & 0x00FF) == addr) + if((i & 0x1280) == 0x0080 && (i & 0x00FF) == (addr & 0x00FF)) { if(read) add ? debugger.addReadTrap(i) : debugger.removeReadTrap(i); diff --git a/src/yacc/YaccParser.cxx b/src/yacc/YaccParser.cxx index 8f88ba239..ec16e5523 100644 --- a/src/yacc/YaccParser.cxx +++ b/src/yacc/YaccParser.cxx @@ -206,9 +206,9 @@ CartMethod getCartSpecial(char* ch) return &CartDebug::getBank; else if(BSPF::equalsIgnoreCase(ch, "_rwport")) return &CartDebug::readFromWritePort; - else if(BSPF::equalsIgnoreCase(ch, "_lastread")) + else if(BSPF::equalsIgnoreCase(ch, "__lastread")) return &CartDebug::lastReadBaseAddress; - else if(BSPF::equalsIgnoreCase(ch, "_lastwrite")) + else if(BSPF::equalsIgnoreCase(ch, "__lastwrite")) return &CartDebug::lastWriteBaseAddress; else return 0;