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