add 'breaklabel' command for 16 bit address breaks in all banks

This commit is contained in:
Thomas Jentzsch 2019-08-31 11:37:29 +02:00
parent 0048beaa89
commit 628baef1d2
6 changed files with 99 additions and 23 deletions

View File

@ -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);
}

View File

@ -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
);
}
};

View File

@ -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);

View File

@ -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.

View File

@ -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)",

View File

@ -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();