mirror of https://github.com/stella-emu/stella.git
add 'breaklabel' command for 16 bit address breaks in all banks
This commit is contained in:
parent
0048beaa89
commit
628baef1d2
|
@ -27,8 +27,10 @@ BreakpointMap::BreakpointMap(void)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void BreakpointMap::add(const Breakpoint& breakpoint, const uInt32 flags)
|
||||
{
|
||||
Breakpoint bp = convertBreakpoint(breakpoint);
|
||||
|
||||
myInitialized = true;
|
||||
myMap[breakpoint] = flags;
|
||||
myMap[bp] = flags;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -40,7 +42,14 @@ void BreakpointMap::add(const uInt16 addr, const uInt8 bank, const uInt32 flags)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void BreakpointMap::erase(const Breakpoint& breakpoint)
|
||||
{
|
||||
myMap.erase(breakpoint);
|
||||
// 16 bit breakpoint
|
||||
if(!myMap.erase(breakpoint))
|
||||
{
|
||||
// 13 bit breakpoint
|
||||
Breakpoint bp13(breakpoint.addr & ADDRESS_MASK, breakpoint.bank);
|
||||
|
||||
myMap.erase(bp13);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -52,10 +61,18 @@ void BreakpointMap::erase(const uInt16 addr, const uInt8 bank)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 BreakpointMap::get(const Breakpoint& breakpoint) const
|
||||
{
|
||||
// 16 bit breakpoint
|
||||
auto find = myMap.find(breakpoint);
|
||||
if(find != myMap.end())
|
||||
return find->second;
|
||||
|
||||
// 13 bit breakpoint
|
||||
Breakpoint bp13(breakpoint.addr & ADDRESS_MASK, breakpoint.bank);
|
||||
|
||||
find = myMap.find(bp13);
|
||||
if(find != myMap.end())
|
||||
return find->second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -66,10 +83,17 @@ uInt32 BreakpointMap::get(uInt16 addr, uInt8 bank) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool BreakpointMap::check(const Breakpoint & breakpoint) const
|
||||
bool BreakpointMap::check(const Breakpoint& breakpoint) const
|
||||
{
|
||||
// 16 bit breakpoint
|
||||
auto find = myMap.find(breakpoint);
|
||||
if(find != myMap.end())
|
||||
return true;
|
||||
|
||||
// 13 bit breakpoint
|
||||
Breakpoint bp13(breakpoint.addr & ADDRESS_MASK, breakpoint.bank);
|
||||
|
||||
find = myMap.find(bp13);
|
||||
return (find != myMap.end());
|
||||
}
|
||||
|
||||
|
@ -90,3 +114,12 @@ BreakpointMap::BreakpointList BreakpointMap::getBreakpoints() const
|
|||
|
||||
return map;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
BreakpointMap::Breakpoint BreakpointMap::convertBreakpoint(const Breakpoint& breakpoint)
|
||||
{
|
||||
if(breakpoint.bank == ANY_BANK)
|
||||
return Breakpoint(breakpoint.addr, ANY_BANK);
|
||||
else
|
||||
return Breakpoint(breakpoint.addr & ADDRESS_MASK, breakpoint.bank);
|
||||
}
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
class BreakpointMap
|
||||
{
|
||||
private:
|
||||
static const uInt16 ADDRESS_MASK = 0x1fff; // either 0x1fff or 0xffff (not needed then)
|
||||
static const uInt16 ADDRESS_MASK = 0x1fff; // either 0x1fff or 0xffff (not needed then)
|
||||
|
||||
public:
|
||||
// breakpoint flags
|
||||
static const uInt32 ONE_SHOT = 1 << 0; // used to 'trace' command
|
||||
static const uInt32 ONE_SHOT = 1 << 0; // used for 'trace' command
|
||||
|
||||
static const uInt8 ANY_BANK = 255; // breakpoint valid in any bank
|
||||
|
||||
struct Breakpoint
|
||||
{
|
||||
|
@ -44,13 +46,20 @@ public:
|
|||
Breakpoint()
|
||||
: addr(0), bank(0) { }
|
||||
Breakpoint(const Breakpoint& bp)
|
||||
: addr(bp.addr & ADDRESS_MASK), bank(bp.bank) { }
|
||||
: addr(bp.addr), bank(bp.bank) { }
|
||||
explicit Breakpoint(uInt16 c_addr, uInt8 c_bank)
|
||||
: addr(c_addr & ADDRESS_MASK), bank(c_bank) { }
|
||||
: addr(c_addr), bank(c_bank) { }
|
||||
|
||||
bool operator==(const Breakpoint& other) const
|
||||
{
|
||||
return (addr == other.addr && bank == other.bank);
|
||||
if(addr == other.addr)
|
||||
{
|
||||
if(bank == ANY_BANK || other.bank == ANY_BANK)
|
||||
return true;
|
||||
else
|
||||
return bank == other.bank;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator<(const Breakpoint& other) const
|
||||
{
|
||||
|
@ -89,10 +98,12 @@ public:
|
|||
size_t size() { return myMap.size(); }
|
||||
|
||||
private:
|
||||
Breakpoint convertBreakpoint(const Breakpoint& breakpoint);
|
||||
|
||||
struct BreakpointHash {
|
||||
size_t operator()(const Breakpoint& bp) const {
|
||||
return std::hash<uInt64>()(
|
||||
uInt64(bp.addr) * 13 + uInt64(bp.bank)
|
||||
uInt64(bp.addr) * 13 // only check for address, bank check via == operator
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -335,7 +335,7 @@ int Debugger::trace()
|
|||
if(!checkBreakPoint(targetPC, bank))
|
||||
{
|
||||
// add temporary breakpoint and remove later
|
||||
setBreakPoint(targetPC, bank, true);
|
||||
setBreakPoint(targetPC, bank, BreakpointMap::ONE_SHOT);
|
||||
}
|
||||
|
||||
unlockSystem();
|
||||
|
@ -351,19 +351,19 @@ int Debugger::trace()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::setBreakPoint(uInt16 addr, Int8 bank, bool oneShot)
|
||||
bool Debugger::setBreakPoint(uInt16 addr, uInt8 bank, uInt32 flags)
|
||||
{
|
||||
bool exists = checkBreakPoint(addr, bank);
|
||||
|
||||
if(exists)
|
||||
return false;
|
||||
|
||||
breakPoints().add(addr, bank, oneShot ? BreakpointMap::ONE_SHOT : 0);
|
||||
breakPoints().add(addr, bank, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::clearBreakPoint(uInt16 addr, Int8 bank)
|
||||
bool Debugger::clearBreakPoint(uInt16 addr, uInt8 bank)
|
||||
{
|
||||
bool exists = checkBreakPoint(addr, bank);
|
||||
|
||||
|
@ -375,13 +375,13 @@ bool Debugger::clearBreakPoint(uInt16 addr, Int8 bank)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::checkBreakPoint(uInt16 addr, Int8 bank)
|
||||
bool Debugger::checkBreakPoint(uInt16 addr, uInt8 bank)
|
||||
{
|
||||
return breakPoints().check(addr, bank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::toggleBreakPoint(uInt16 addr, Int8 bank)
|
||||
bool Debugger::toggleBreakPoint(uInt16 addr, uInt8 bank)
|
||||
{
|
||||
if(checkBreakPoint(addr, bank))
|
||||
clearBreakPoint(addr, bank);
|
||||
|
|
|
@ -162,29 +162,29 @@ class Debugger : public DialogContainer
|
|||
|
||||
Returns true if successfully set
|
||||
*/
|
||||
bool setBreakPoint(uInt16 addr, Int8 bank = ANY_BANK,
|
||||
bool oneShot = false);
|
||||
bool setBreakPoint(uInt16 addr, uInt8 bank = ANY_BANK,
|
||||
uInt32 flags = 0);
|
||||
|
||||
/**
|
||||
Clears a breakpoint.
|
||||
|
||||
Returns true if successfully cleared
|
||||
*/
|
||||
bool clearBreakPoint(uInt16 addr, Int8 bank);
|
||||
bool clearBreakPoint(uInt16 addr, uInt8 bank);
|
||||
|
||||
/**
|
||||
Toggles a breakpoint
|
||||
|
||||
Returns new state of breakpoint
|
||||
*/
|
||||
bool toggleBreakPoint(uInt16 addr, Int8 bank);
|
||||
bool toggleBreakPoint(uInt16 addr, uInt8 bank);
|
||||
|
||||
/**
|
||||
Checks for a breakpoint.
|
||||
|
||||
Returns true if existing, else false
|
||||
*/
|
||||
bool checkBreakPoint(uInt16 addr, Int8 bank);
|
||||
bool checkBreakPoint(uInt16 addr, uInt8 bank);
|
||||
|
||||
/**
|
||||
Run the debugger command and return the result.
|
||||
|
|
|
@ -807,6 +807,23 @@ void DebuggerParser::executeBreakif()
|
|||
commandResult << red("invalid expression");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "breaklabel"
|
||||
void DebuggerParser::executeBreaklabel()
|
||||
{
|
||||
uInt16 addr;
|
||||
|
||||
if(argCount == 0)
|
||||
addr = debugger.cpuDebug().pc();
|
||||
else
|
||||
addr = args[0];
|
||||
|
||||
bool set = debugger.toggleBreakPoint(addr, BreakpointMap::ANY_BANK);
|
||||
|
||||
commandResult << (set ? "set" : "cleared");
|
||||
commandResult << " breakpoint at $" << Base::HEX4 << addr << " (no mirrors)";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "c"
|
||||
void DebuggerParser::executeC()
|
||||
|
@ -1461,7 +1478,11 @@ void DebuggerParser::executeListbreaks()
|
|||
{
|
||||
if(count % 6)
|
||||
buf << ", ";
|
||||
buf << debugger.cartDebug().getLabel(bp.addr, true, 4) << " #" << int(bp.bank);
|
||||
buf << debugger.cartDebug().getLabel(bp.addr, true, 4);
|
||||
if(bp.bank != 255)
|
||||
buf << " #" << int(bp.bank);
|
||||
else
|
||||
buf << " *";
|
||||
if(!(++count % 6)) buf << endl;
|
||||
}
|
||||
}
|
||||
|
@ -2322,11 +2343,21 @@ DebuggerParser::Command DebuggerParser::commands[NumCommands] = {
|
|||
"Set/clear breakpoint on <condition>",
|
||||
"Condition can include multiple items, see documentation\nExample: breakif _scan>100",
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeBreakif)
|
||||
},
|
||||
|
||||
{
|
||||
"breaklabel",
|
||||
"Set/clear breakpoint on [address] (no mirrors, all banks)",
|
||||
"Example: breaklabel, breaklabel MainLoop",
|
||||
false,
|
||||
true,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeBreaklabel)
|
||||
},
|
||||
|
||||
{
|
||||
"c",
|
||||
"Carry Flag: set (0 or 1), or toggle (no arg)",
|
||||
|
|
|
@ -88,7 +88,7 @@ class DebuggerParser
|
|||
};
|
||||
|
||||
// List of commands available
|
||||
static constexpr uInt32 NumCommands = 94;
|
||||
static constexpr uInt32 NumCommands = 95;
|
||||
struct Command {
|
||||
string cmdString;
|
||||
string description;
|
||||
|
@ -143,6 +143,7 @@ class DebuggerParser
|
|||
void executeBase();
|
||||
void executeBreak();
|
||||
void executeBreakif();
|
||||
void executeBreaklabel();
|
||||
void executeC();
|
||||
void executeCheat();
|
||||
void executeClearbreaks();
|
||||
|
|
Loading…
Reference in New Issue