make breakpoints consider banks (fixes #512)

This commit is contained in:
Thomas Jentzsch 2019-08-19 22:12:49 +02:00
parent 0215cda991
commit c3f379b45d
12 changed files with 125 additions and 173 deletions

View File

@ -282,7 +282,7 @@ int main(int ac, char* av[])
{ {
Debugger& dbg = theOSystem->debugger(); Debugger& dbg = theOSystem->debugger();
uInt16 bp = uInt16(dbg.stringToValue(localOpts["break"].toString())); uInt16 bp = uInt16(dbg.stringToValue(localOpts["break"].toString()));
dbg.setBreakPoint(bp, true); dbg.setBreakPoint(bp);
} }
#endif #endif
} }

View File

@ -49,13 +49,14 @@
#include "RomWidget.hxx" #include "RomWidget.hxx"
#include "Expression.hxx" #include "Expression.hxx"
#include "PackedBitArray.hxx"
#include "YaccParser.hxx" #include "YaccParser.hxx"
#include "TIA.hxx" #include "TIA.hxx"
#include "Debugger.hxx" #include "Debugger.hxx"
#include "DispatchResult.hxx" #include "DispatchResult.hxx"
using Common::Base;
Debugger* Debugger::myStaticDebugger = nullptr; Debugger* Debugger::myStaticDebugger = nullptr;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -190,18 +191,6 @@ string Debugger::autoExec(StringList* history)
return buf.str(); return buf.str();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PackedBitArray& Debugger::breakPoints() const
{
return mySystem.m6502().breakPoints();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PackedBitArray& Debugger::breakPointFlags() const
{
return mySystem.m6502().breakPointFlags();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TrapArray& Debugger::readTraps() const TrapArray& Debugger::readTraps() const
{ {
@ -336,12 +325,11 @@ int Debugger::trace()
int targetPC = myCpuDebug->pc() + 3; // return address int targetPC = myCpuDebug->pc() + 3; // return address
// set temporary breakpoint at target PC (if not existing already) // set temporary breakpoint at target PC (if not existing already)
breakPoints().initialize(); Int8 bank = myCartDebug->getBank();
if(!breakPoints().isSet(targetPC)) if(checkBreakPoint(targetPC, bank) == NOT_FOUND)
{ {
breakPoints().set(targetPC); // add temporary breakpoint and remove later
breakPointFlags().initialize(); setBreakPoint(targetPC, bank, true, true);
breakPointFlags().set(targetPC);
} }
unlockSystem(); unlockSystem();
@ -357,26 +345,59 @@ int Debugger::trace()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::toggleBreakPoint(uInt16 bp) bool Debugger::setBreakPoint(uInt16 addr, Int8 bank, bool set, bool oneShot)
{ {
breakPoints().initialize(); Int32 id = checkBreakPoint(addr, bank);
breakPoints().toggle(bp);
breakPointFlags().initialize(); if(set)
{
if(id != NOT_FOUND)
return false;
mySystem.m6502().addCondBreak(YaccParser::getResult(), getCondition(addr, bank), oneShot);
}
else
{
if(id == NOT_FOUND)
return false;
m6502().delCondBreak(id);
}
return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setBreakPoint(uInt16 bp, bool set) Int32 Debugger::checkBreakPoint(uInt16 addr, Int8 bank)
{ {
breakPoints().initialize(); string condition = getCondition(addr, bank);
if(set) breakPoints().set(bp);
else breakPoints().clear(bp); for(uInt32 i = 0; i < m6502().getCondBreakNames().size(); ++i)
breakPointFlags().initialize(); if(condition == m6502().getCondBreakNames()[i])
return i;
return NOT_FOUND;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::breakPoint(uInt16 bp) string Debugger::getCondition(uInt16 addr, Int8 bank)
{ {
return breakPoints().isSet(bp); stringstream condition;
condition << "(pc == " << Base::HEX4 << addr << ")";
if(bank != ANY_BANK && myCartDebug->bankCount() > 1)
condition << " && (_bank == #" << int(bank) << ")";
YaccParser::parse(condition.str());
return condition.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::toggleBreakPoint(uInt16 addr, Int8 bank)
{
setBreakPoint(addr, bank, checkBreakPoint(addr, bank) == NOT_FOUND);
return checkBreakPoint(addr, bank) != NOT_FOUND;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -604,12 +625,6 @@ uInt16 Debugger::unwindStates(const uInt16 numStates, string& message)
return windStates(numStates, true, message); return windStates(numStates, true, message);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::clearAllBreakPoints()
{
breakPoints().clearAll();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::clearAllTraps() void Debugger::clearAllTraps()
{ {
@ -688,7 +703,6 @@ void Debugger::setQuitState()
// execute one instruction on quit. If we're // execute one instruction on quit. If we're
// sitting at a breakpoint/trap, this will get us past it. // sitting at a breakpoint/trap, this will get us past it.
// Somehow this feels like a hack to me, but I don't know why // Somehow this feels like a hack to me, but I don't know why
// if(breakPoints().isSet(myCpuDebug->pc()))
mySystem.m6502().execute(1); mySystem.m6502().execute(1);
} }

View File

@ -27,7 +27,6 @@ class TiaZoomWidget;
class EditTextWidget; class EditTextWidget;
class RomWidget; class RomWidget;
class Expression; class Expression;
class PackedBitArray;
class TrapArray; class TrapArray;
class PromptWidget; class PromptWidget;
class ButtonWidget; class ButtonWidget;
@ -74,6 +73,9 @@ class Debugger : public DialogContainer
Debugger(OSystem& osystem, Console& console); Debugger(OSystem& osystem, Console& console);
virtual ~Debugger(); virtual ~Debugger();
private:
static const Int8 ANY_BANK = -1;
public: public:
/** /**
Initialize the debugger dialog container. Initialize the debugger dialog container.
@ -149,11 +151,24 @@ class Debugger : public DialogContainer
RomWidget& rom() const { return myDialog->rom(); } RomWidget& rom() const { return myDialog->rom(); }
TiaOutputWidget& tiaOutput() const { return myDialog->tiaOutput(); } TiaOutputWidget& tiaOutput() const { return myDialog->tiaOutput(); }
PackedBitArray& breakPoints() const;
PackedBitArray& breakPointFlags() const;
TrapArray& readTraps() const; TrapArray& readTraps() const;
TrapArray& writeTraps() const; TrapArray& writeTraps() const;
/**
Sets or clears a breakpoint.
Returns true if successfully set or cleared
*/
bool setBreakPoint(uInt16 addr, Int8 bank = ANY_BANK,
bool set = true, bool oneShot = false);
/**
Checks for a breakpoint.
Returns -1 if not existing, else the Id
*/
Int32 checkBreakPoint(uInt16 addr, Int8 bank);
/** /**
Run the debugger command and return the result. Run the debugger command and return the result.
*/ */
@ -224,7 +239,6 @@ class Debugger : public DialogContainer
int getAccessFlags(uInt16 addr) const; int getAccessFlags(uInt16 addr) const;
void setAccessFlags(uInt16 addr, uInt8 flags); void setAccessFlags(uInt16 addr, uInt8 flags);
void setBreakPoint(uInt16 bp, bool set);
uInt32 getBaseAddress(uInt32 addr, bool read); uInt32 getBaseAddress(uInt32 addr, bool read);
bool patchROM(uInt16 addr, uInt8 value); bool patchROM(uInt16 addr, uInt8 value);
@ -250,6 +264,8 @@ class Debugger : public DialogContainer
*/ */
Dialog* baseDialog() override { return myDialog; } Dialog* baseDialog() override { return myDialog; }
static const Int32 NOT_FOUND = -1;
private: private:
/** /**
Save state of each debugger subsystem and, by default, mark all Save state of each debugger subsystem and, by default, mark all
@ -279,9 +295,9 @@ class Debugger : public DialogContainer
uInt16 rewindStates(const uInt16 numStates, string& message); uInt16 rewindStates(const uInt16 numStates, string& message);
uInt16 unwindStates(const uInt16 numStates, string& message); uInt16 unwindStates(const uInt16 numStates, string& message);
void toggleBreakPoint(uInt16 bp); bool toggleBreakPoint(uInt16 addr, Int8 bank);
string getCondition(uInt16 addr, Int8 bank);
bool breakPoint(uInt16 bp);
void addReadTrap(uInt16 t); void addReadTrap(uInt16 t);
void addWriteTrap(uInt16 t); void addWriteTrap(uInt16 t);
void addTrap(uInt16 t); void addTrap(uInt16 t);
@ -296,7 +312,6 @@ class Debugger : public DialogContainer
string setRAM(IntArray& args); string setRAM(IntArray& args);
void reset(); void reset();
void clearAllBreakPoints();
void saveState(int state); void saveState(int state);
void saveAllStates(); void saveAllStates();

View File

@ -34,7 +34,6 @@
#include "PromptWidget.hxx" #include "PromptWidget.hxx"
#include "RomWidget.hxx" #include "RomWidget.hxx"
#include "ProgressDialog.hxx" #include "ProgressDialog.hxx"
#include "PackedBitArray.hxx"
#include "TimerManager.hxx" #include "TimerManager.hxx"
#include "Vec.hxx" #include "Vec.hxx"
@ -648,10 +647,6 @@ string DebuggerParser::saveScriptFile(string file)
for(const auto& w: myWatches) for(const auto& w: myWatches)
out << "watch " << w << endl; out << "watch " << w << endl;
for(uInt32 i = 0; i < 0x10000; ++i)
if(debugger.breakPoint(i))
out << "break " << Base::toString(i) << endl;
StringList conds = debugger.m6502().getCondBreakNames(); StringList conds = debugger.m6502().getCondBreakNames();
for(const auto& cond : conds) for(const auto& cond : conds)
out << "breakif {" << cond << "}" << endl; out << "breakif {" << cond << "}" << endl;
@ -730,20 +725,35 @@ void DebuggerParser::executeBase()
// "break" // "break"
void DebuggerParser::executeBreak() void DebuggerParser::executeBreak()
{ {
uInt16 bp; uInt16 addr;
Int8 bank;
if(argCount == 0) if(argCount == 0)
bp = debugger.cpuDebug().pc(); addr = debugger.cpuDebug().pc();
else else
bp = args[0]; addr = args[0];
debugger.toggleBreakPoint(bp);
if(argCount < 2)
bank = debugger.cartDebug().getBank();
else
{
bank = args[1];
if(bank >= debugger.cartDebug().bankCount())
{
commandResult << red("invalid bank");
return;
}
}
bool set = debugger.toggleBreakPoint(addr, bank);
debugger.rom().invalidate(); debugger.rom().invalidate();
if(debugger.breakPoint(bp)) if(set)
commandResult << "set"; commandResult << "set";
else else
commandResult << "cleared"; commandResult << "cleared";
commandResult << " breakpoint at " << Base::toString(bp); commandResult << " breakpoint at " << Base::toString(addr) << " in bank " << int(bank);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -764,7 +774,7 @@ void DebuggerParser::executeBreakif()
} }
} }
uInt32 ret = debugger.m6502().addCondBreak( uInt32 ret = debugger.m6502().addCondBreak(
YaccParser::getResult(), argStrings[0] ); YaccParser::getResult(), argStrings[0]);
commandResult << "added breakif " << Base::toString(ret); commandResult << "added breakif " << Base::toString(ret);
} }
else else
@ -810,7 +820,6 @@ void DebuggerParser::executeCheat()
// "clearbreaks" // "clearbreaks"
void DebuggerParser::executeClearbreaks() void DebuggerParser::executeClearbreaks()
{ {
debugger.clearAllBreakPoints();
debugger.m6502().clearCondBreaks(); debugger.m6502().clearCondBreaks();
commandResult << "all breakpoints cleared"; commandResult << "all breakpoints cleared";
} }
@ -1403,21 +1412,9 @@ void DebuggerParser::executeJump()
// "listbreaks" // "listbreaks"
void DebuggerParser::executeListbreaks() void DebuggerParser::executeListbreaks()
{ {
ostringstream buf;
int count = 0; int count = 0;
for(uInt32 i = 0; i <= 0xffff; ++i)
{
if(debugger.breakPoints().isSet(i))
{
buf << debugger.cartDebug().getLabel(i, true, 4) << " ";
if(! (++count % 8) ) buf << endl;
}
}
if(count)
commandResult << "breaks:" << endl << buf.str();
StringList conds = debugger.m6502().getCondBreakNames(); StringList conds = debugger.m6502().getCondBreakNames();
if(conds.size() > 0) if(conds.size() > 0)
{ {
if(count) if(count)
@ -2256,12 +2253,12 @@ DebuggerParser::Command DebuggerParser::commands[NumCommands] = {
{ {
"break", "break",
"Set/clear breakpoint at <address>", "Set/clear breakpoint at <address> and <bank>",
"Command is a toggle, default is current PC\nValid address is 0 - ffff\n" "Command is a toggle, default is current PC and bank\nValid address is 0 - ffff\n"
"Example: break, break f000", "Example: break, break f000, break f000 0",
false, false,
true, true,
{ Parameters::ARG_WORD, Parameters::ARG_END_ARGS }, { Parameters::ARG_WORD, Parameters::ARG_BYTE, Parameters::ARG_END_ARGS },
std::mem_fn(&DebuggerParser::executeBreak) std::mem_fn(&DebuggerParser::executeBreak)
}, },

View File

@ -1,57 +0,0 @@
//============================================================================
//
// 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-2019 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 PACKED_BIT_ARRAY_HXX
#define PACKED_BIT_ARRAY_HXX
#include <bitset>
#include "bspf.hxx"
class PackedBitArray
{
public:
PackedBitArray() : myInitialized(false) { }
bool isSet(uInt16 bit) const { return myBits[bit]; }
bool isClear(uInt16 bit) const { return !myBits[bit]; }
void set(uInt16 bit) { myBits[bit] = true; }
void clear(uInt16 bit) { myBits[bit] = false; }
void toggle(uInt16 bit) { myBits.flip(bit); }
void initialize() { myInitialized = true; }
void clearAll() { myInitialized = false; myBits.reset(); }
bool isInitialized() const { return myInitialized; }
private:
// The actual bits
std::bitset<0x10000> myBits;
// Indicates whether we should treat this bitset as initialized
bool myInitialized;
private:
// Following constructors and assignment operators not supported
PackedBitArray(const PackedBitArray&) = delete;
PackedBitArray(PackedBitArray&&) = delete;
PackedBitArray& operator=(const PackedBitArray&) = delete;
PackedBitArray& operator=(PackedBitArray&&) = delete;
};
#endif

View File

@ -18,7 +18,6 @@
#include "bspf.hxx" #include "bspf.hxx"
#include "Debugger.hxx" #include "Debugger.hxx"
#include "DiStella.hxx" #include "DiStella.hxx"
#include "PackedBitArray.hxx"
#include "Widget.hxx" #include "Widget.hxx"
#include "StellaKeys.hxx" #include "StellaKeys.hxx"
#include "FBSurface.hxx" #include "FBSurface.hxx"
@ -40,8 +39,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
_editMode(false), _editMode(false),
_currentKeyDown(KBDK_UNKNOWN), _currentKeyDown(KBDK_UNKNOWN),
_base(Common::Base::F_DEFAULT), _base(Common::Base::F_DEFAULT),
myDisasm(nullptr), myDisasm(nullptr)//,
myBPState(nullptr)
{ {
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
_bgcolor = kWidColor; _bgcolor = kWidColor;
@ -122,11 +120,9 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListWidget::setList(const CartDebug::Disassembly& disasm, void RomListWidget::setList(const CartDebug::Disassembly& disasm)
const PackedBitArray& state)
{ {
myDisasm = &disasm; myDisasm = &disasm;
myBPState = &state;
// Enable all checkboxes // Enable all checkboxes
for(int i = 0; i < _rows; ++i) for(int i = 0; i < _rows; ++i)
@ -496,7 +492,9 @@ void RomListWidget::drawWidget(bool hilite)
ColorId bytesColor = textColor; ColorId bytesColor = textColor;
// Draw checkboxes for correct lines (takes scrolling into account) // Draw checkboxes for correct lines (takes scrolling into account)
myCheckList[i]->setState(myBPState->isSet(dlist[pos].address)); myCheckList[i]->setState(instance().debugger().
checkBreakPoint(dlist[pos].address, instance().debugger().cartDebug().getBank()) != Debugger::NOT_FOUND);
myCheckList[i]->setDirty(); myCheckList[i]->setDirty();
myCheckList[i]->draw(); myCheckList[i]->draw();

View File

@ -19,7 +19,6 @@
#define ROM_LIST_WIDGET_HXX #define ROM_LIST_WIDGET_HXX
class ScrollBarWidget; class ScrollBarWidget;
class PackedBitArray;
class CheckListWidget; class CheckListWidget;
class RomListSettings; class RomListSettings;
@ -50,7 +49,7 @@ class RomListWidget : public EditableWidget
int x, int y, int w, int h); int x, int y, int w, int h);
virtual ~RomListWidget() = default; virtual ~RomListWidget() = default;
void setList(const CartDebug::Disassembly& disasm, const PackedBitArray& state); void setList(const CartDebug::Disassembly& disasm);
int getSelected() const { return _selectedItem; } int getSelected() const { return _selectedItem; }
int getHighlighted() const { return _highlightedItem; } int getHighlighted() const { return _highlightedItem; }
@ -102,7 +101,6 @@ class RomListWidget : public EditableWidget
Common::Base::Format _base; // base used during editing Common::Base::Format _base; // base used during editing
const CartDebug::Disassembly* myDisasm; const CartDebug::Disassembly* myDisasm;
const PackedBitArray* myBPState;
vector<CheckboxWidget*> myCheckList; vector<CheckboxWidget*> myCheckList;
private: private:

View File

@ -72,7 +72,7 @@ void RomWidget::loadConfig()
myListIsDirty |= cart.disassemble(myListIsDirty); myListIsDirty |= cart.disassemble(myListIsDirty);
if(myListIsDirty) if(myListIsDirty)
{ {
myRomList->setList(cart.disassembly(), dbg.breakPoints()); myRomList->setList(cart.disassembly());
myListIsDirty = false; myListIsDirty = false;
} }
@ -171,7 +171,8 @@ void RomWidget::setBreak(int disasm_line, bool state)
if(disasm_line >= int(list.size())) return; if(disasm_line >= int(list.size())) return;
if(list[disasm_line].address != 0 && list[disasm_line].bytes != "") if(list[disasm_line].address != 0 && list[disasm_line].bytes != "")
instance().debugger().setBreakPoint(list[disasm_line].address, state); instance().debugger().setBreakPoint(list[disasm_line].address,
instance().debugger().cartDebug().getBank(), state);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -19,7 +19,6 @@
#include "Debugger.hxx" #include "Debugger.hxx"
#include "Expression.hxx" #include "Expression.hxx"
#include "CartDebug.hxx" #include "CartDebug.hxx"
#include "PackedBitArray.hxx"
#include "Base.hxx" #include "Base.hxx"
// Flags for disassembly types // Flags for disassembly types
@ -280,24 +279,18 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
return; return;
} }
if(myBreakPoints.isInitialized() && myBreakPoints.isSet(PC)) {
myLastBreakCycle = mySystem->cycles();
// disable a one-shot breakpoint
if(myBreakPoints.isInitialized() && myBreakPointFlags.isSet(PC))
{
myBreakPoints.clear(PC);
myBreakPointFlags.clear(PC);
}
else
result.setDebugger(currentCycles, "BP: ", PC);
return;
}
int cond = evalCondBreaks(); int cond = evalCondBreaks();
if(cond > -1) if(cond > -1)
{ {
ostringstream msg; ostringstream msg;
msg << "CBP[" << Common::Base::HEX2 << cond << "]: " << myCondBreakNames[cond];
// one shot break (trace)?
if(myCondBreakFlags[cond])
{
delCondBreak(cond);
}
else
msg << "BP[" << Common::Base::HEX2 << cond << "]: " << myCondBreakNames[cond];
myLastBreakCycle = mySystem->cycles(); myLastBreakCycle = mySystem->cycles();
result.setDebugger(currentCycles, msg.str()); result.setDebugger(currentCycles, msg.str());
@ -543,10 +536,11 @@ void M6502::attach(Debugger& debugger)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 M6502::addCondBreak(Expression* e, const string& name) uInt32 M6502::addCondBreak(Expression* e, const string& name, bool oneShot)
{ {
myCondBreaks.emplace_back(e); myCondBreaks.emplace_back(e);
myCondBreakNames.push_back(name); myCondBreakNames.push_back(name);
myCondBreakFlags.push_back(oneShot);
updateStepStateByInstruction(); updateStepStateByInstruction();
@ -560,6 +554,7 @@ bool M6502::delCondBreak(uInt32 idx)
{ {
Vec::removeAt(myCondBreaks, idx); Vec::removeAt(myCondBreaks, idx);
Vec::removeAt(myCondBreakNames, idx); Vec::removeAt(myCondBreakNames, idx);
Vec::removeAt(myCondBreakFlags, idx);
updateStepStateByInstruction(); updateStepStateByInstruction();

View File

@ -29,7 +29,6 @@ class DispatchResult;
class CpuDebug; class CpuDebug;
#include "Expression.hxx" #include "Expression.hxx"
#include "PackedBitArray.hxx"
#include "TrapArray.hxx" #include "TrapArray.hxx"
#endif #endif
@ -212,14 +211,11 @@ class M6502 : public Serializable
// Attach the specified debugger. // Attach the specified debugger.
void attach(Debugger& debugger); void attach(Debugger& debugger);
PackedBitArray& breakPoints() { return myBreakPoints; }
// flags used for one-shot breakpoints
PackedBitArray& breakPointFlags() { return myBreakPointFlags; }
TrapArray& readTraps() { return myReadTraps; } TrapArray& readTraps() { return myReadTraps; }
TrapArray& writeTraps() { return myWriteTraps; } TrapArray& writeTraps() { return myWriteTraps; }
// methods for 'breakif' handling // methods for 'breakif' handling
uInt32 addCondBreak(Expression* e, const string& name); uInt32 addCondBreak(Expression* e, const string& name, bool oneShot = false);
bool delCondBreak(uInt32 idx); bool delCondBreak(uInt32 idx);
void clearCondBreaks(); void clearCondBreaks();
const StringList& getCondBreakNames() const; const StringList& getCondBreakNames() const;
@ -399,7 +395,7 @@ class M6502 : public Serializable
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
Int32 evalCondBreaks() { Int32 evalCondBreaks() {
for(uInt32 i = 0; i < myCondBreaks.size(); i++) for(Int32 i = Int32(myCondBreaks.size()) - 1; i >= 0; --i)
if(myCondBreaks[i]->evaluate()) if(myCondBreaks[i]->evaluate())
return i; return i;
@ -408,7 +404,7 @@ class M6502 : public Serializable
Int32 evalCondSaveStates() Int32 evalCondSaveStates()
{ {
for(uInt32 i = 0; i < myCondSaveStates.size(); i++) for(Int32 i = Int32(myCondSaveStates.size()) - 1; i >= 0; --i)
if(myCondSaveStates[i]->evaluate()) if(myCondSaveStates[i]->evaluate())
return i; return i;
@ -417,7 +413,7 @@ class M6502 : public Serializable
Int32 evalCondTraps() Int32 evalCondTraps()
{ {
for(uInt32 i = 0; i < myTrapConds.size(); i++) for(Int32 i = Int32(myTrapConds.size()) - 1; i >= 0; --i)
if(myTrapConds[i]->evaluate()) if(myTrapConds[i]->evaluate())
return i; return i;
@ -428,8 +424,6 @@ class M6502 : public Serializable
Debugger* myDebugger; Debugger* myDebugger;
// Addresses for which the specified action should occur // Addresses for which the specified action should occur
PackedBitArray myBreakPoints;
PackedBitArray myBreakPointFlags;
TrapArray myReadTraps, myWriteTraps; TrapArray myReadTraps, myWriteTraps;
// Did we just now hit a trap? // Did we just now hit a trap?
@ -443,6 +437,7 @@ class M6502 : public Serializable
vector<unique_ptr<Expression>> myCondBreaks; vector<unique_ptr<Expression>> myCondBreaks;
StringList myCondBreakNames; StringList myCondBreakNames;
BoolArray myCondBreakFlags;
vector<unique_ptr<Expression>> myCondSaveStates; vector<unique_ptr<Expression>> myCondSaveStates;
StringList myCondSaveStateNames; StringList myCondSaveStateNames;
vector<unique_ptr<Expression>> myTrapConds; vector<unique_ptr<Expression>> myTrapConds;

View File

@ -1324,7 +1324,6 @@
<ClInclude Include="..\debugger\DebuggerSystem.hxx" /> <ClInclude Include="..\debugger\DebuggerSystem.hxx" />
<ClInclude Include="..\debugger\DiStella.hxx" /> <ClInclude Include="..\debugger\DiStella.hxx" />
<ClInclude Include="..\debugger\Expression.hxx" /> <ClInclude Include="..\debugger\Expression.hxx" />
<ClInclude Include="..\debugger\PackedBitArray.hxx" />
<ClInclude Include="..\debugger\gui\PromptWidget.hxx" /> <ClInclude Include="..\debugger\gui\PromptWidget.hxx" />
<ClInclude Include="..\debugger\gui\RamWidget.hxx" /> <ClInclude Include="..\debugger\gui\RamWidget.hxx" />
<ClInclude Include="..\debugger\RiotDebug.hxx" /> <ClInclude Include="..\debugger\RiotDebug.hxx" />

View File

@ -1226,9 +1226,6 @@
<ClInclude Include="..\debugger\Expression.hxx"> <ClInclude Include="..\debugger\Expression.hxx">
<Filter>Header Files\debugger</Filter> <Filter>Header Files\debugger</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\debugger\PackedBitArray.hxx">
<Filter>Header Files\debugger</Filter>
</ClInclude>
<ClInclude Include="..\debugger\gui\PromptWidget.hxx"> <ClInclude Include="..\debugger\gui\PromptWidget.hxx">
<Filter>Header Files\debugger</Filter> <Filter>Header Files\debugger</Filter>
</ClInclude> </ClInclude>