Made M6502 own all breakpoint/trap info instead of sharing pointers to

it with the debugger (this eliminates more new's and empties another d'tor.

Re-wrote PackedBitArray to use a bitset instead of home-made code.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3075 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-11-16 16:13:58 +00:00
parent c997fc3001
commit 29fe39dd99
9 changed files with 82 additions and 201 deletions

View File

@ -115,9 +115,6 @@ Debugger::Debugger(OSystem& osystem, Console& console)
myConsole(console), myConsole(console),
mySystem(console.system()), mySystem(console.system()),
myDialog(nullptr), myDialog(nullptr),
myBreakPoints(nullptr),
myReadTraps(nullptr),
myWriteTraps(nullptr),
myWidth(DebuggerDialog::kSmallFontMinW), myWidth(DebuggerDialog::kSmallFontMinW),
myHeight(DebuggerDialog::kSmallFontMinH) myHeight(DebuggerDialog::kSmallFontMinH)
{ {
@ -130,10 +127,6 @@ Debugger::Debugger(OSystem& osystem, Console& console)
myRiotDebug = make_ptr<RiotDebug>(*this, myConsole); myRiotDebug = make_ptr<RiotDebug>(*this, myConsole);
myTiaDebug = make_ptr<TIADebug>(*this, myConsole); myTiaDebug = make_ptr<TIADebug>(*this, myConsole);
myBreakPoints = new PackedBitArray(0x10000);
myReadTraps = new PackedBitArray(0x10000);
myWriteTraps = new PackedBitArray(0x10000);
// Allow access to this object from any class // Allow access to this object from any class
// Technically this violates pure OO programming, but since I know // Technically this violates pure OO programming, but since I know
// there will only be ever one instance of debugger in Stella, // there will only be ever one instance of debugger in Stella,
@ -144,9 +137,6 @@ Debugger::Debugger(OSystem& osystem, Console& console)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Debugger::~Debugger() Debugger::~Debugger()
{ {
delete myBreakPoints;
delete myReadTraps;
delete myWriteTraps;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -362,41 +352,39 @@ int Debugger::trace()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::toggleBreakPoint(int bp) void Debugger::toggleBreakPoint(int bp)
{ {
mySystem.m6502().setBreakPoints(myBreakPoints); breakPoints().initialize();
if(bp < 0) bp = myCpuDebug->pc(); if(bp < 0) bp = myCpuDebug->pc();
myBreakPoints->toggle(bp); breakPoints().toggle(bp);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setBreakPoint(int bp, bool set) void Debugger::setBreakPoint(int bp, bool set)
{ {
mySystem.m6502().setBreakPoints(myBreakPoints); breakPoints().initialize();
if(bp < 0) bp = myCpuDebug->pc(); if(bp < 0) bp = myCpuDebug->pc();
if(set) if(set) breakPoints().set(bp);
myBreakPoints->set(bp); else breakPoints().clear(bp);
else
myBreakPoints->clear(bp);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::breakPoint(int bp) bool Debugger::breakPoint(int bp)
{ {
if(bp < 0) bp = myCpuDebug->pc(); if(bp < 0) bp = myCpuDebug->pc();
return myBreakPoints->isSet(bp) != 0; return breakPoints().isSet(bp);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::toggleReadTrap(int t) void Debugger::toggleReadTrap(int t)
{ {
mySystem.m6502().setTraps(myReadTraps, myWriteTraps); readTraps().initialize();
myReadTraps->toggle(t); readTraps().toggle(t);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::toggleWriteTrap(int t) void Debugger::toggleWriteTrap(int t)
{ {
mySystem.m6502().setTraps(myReadTraps, myWriteTraps); writeTraps().initialize();
myWriteTraps->toggle(t); writeTraps().toggle(t);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -409,13 +397,13 @@ void Debugger::toggleTrap(int t)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::readTrap(int t) bool Debugger::readTrap(int t)
{ {
return myReadTraps->isSet(t) != 0; return readTraps().isInitialized() && readTraps().isSet(t);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::writeTrap(int t) bool Debugger::writeTrap(int t)
{ {
return myWriteTraps->isSet(t) != 0; return writeTraps().isInitialized() && writeTraps().isSet(t);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -463,19 +451,14 @@ bool Debugger::rewindState()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::clearAllBreakPoints() void Debugger::clearAllBreakPoints()
{ {
delete myBreakPoints; breakPoints().clearAll();
myBreakPoints = new PackedBitArray(0x10000);
mySystem.m6502().setBreakPoints(nullptr);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::clearAllTraps() void Debugger::clearAllTraps()
{ {
delete myReadTraps; readTraps().clearAll();
delete myWriteTraps; writeTraps().clearAll();
myReadTraps = new PackedBitArray(0x10000);
myWriteTraps = new PackedBitArray(0x10000);
mySystem.m6502().setTraps(nullptr, nullptr);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -527,7 +510,7 @@ 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(myBreakPoints->isSet(myCpuDebug->pc())) // if(breakPoints().isSet(myCpuDebug->pc()))
mySystem.m6502().execute(1); mySystem.m6502().execute(1);
} }
@ -548,6 +531,11 @@ bool Debugger::delFunction(const string& name)
if(iter == myFunctions.end()) if(iter == myFunctions.end())
return false; return false;
// We never want to delete built-in functions
for(int i = 0; builtin_functions[i][0] != 0; ++i)
if(name == builtin_functions[i][0])
return false;
myFunctions.erase(name); myFunctions.erase(name);
const auto& def_iter = myFunctionDefs.find(name); const auto& def_iter = myFunctionDefs.find(name);

View File

@ -26,7 +26,6 @@ class CartDebug;
class CpuDebug; class CpuDebug;
class RiotDebug; class RiotDebug;
class TIADebug; class TIADebug;
class M6502;
class TiaInfoWidget; class TiaInfoWidget;
class TiaOutputWidget; class TiaOutputWidget;
class TiaZoomWidget; class TiaZoomWidget;
@ -44,6 +43,7 @@ class ButtonWidget;
#include "DialogContainer.hxx" #include "DialogContainer.hxx"
#include "DebuggerDialog.hxx" #include "DebuggerDialog.hxx"
#include "DebuggerParser.hxx" #include "DebuggerParser.hxx"
#include "M6502.hxx"
#include "System.hxx" #include "System.hxx"
#include "Stack.hxx" #include "Stack.hxx"
#include "bspf.hxx" #include "bspf.hxx"
@ -158,13 +158,14 @@ class Debugger : public DialogContainer
const GUI::Font& lfont() const { return myDialog->lfont(); } const GUI::Font& lfont() const { return myDialog->lfont(); }
const GUI::Font& nlfont() const { return myDialog->nfont(); } const GUI::Font& nlfont() const { return myDialog->nfont(); }
DebuggerParser& parser() const { return *myParser; } DebuggerParser& parser() const { return *myParser; }
PackedBitArray& breakpoints() const { return *myBreakPoints; }
PackedBitArray& readtraps() const { return *myReadTraps; }
PackedBitArray& writetraps() const { return *myWriteTraps; }
PromptWidget& prompt() const { return myDialog->prompt(); } PromptWidget& prompt() const { return myDialog->prompt(); }
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 { return mySystem.m6502().breakPoints(); }
PackedBitArray& readTraps() const { return mySystem.m6502().readTraps(); }
PackedBitArray& writeTraps() const { return mySystem.m6502().writeTraps(); }
/** /**
Run the debugger command and return the result. Run the debugger command and return the result.
*/ */
@ -302,10 +303,6 @@ class Debugger : public DialogContainer
unique_ptr<RiotDebug> myRiotDebug; unique_ptr<RiotDebug> myRiotDebug;
unique_ptr<TIADebug> myTiaDebug; unique_ptr<TIADebug> myTiaDebug;
PackedBitArray* myBreakPoints;
PackedBitArray* myReadTraps;
PackedBitArray* myWriteTraps;
static Debugger* myStaticDebugger; static Debugger* myStaticDebugger;
FunctionMap myFunctions; FunctionMap myFunctions;

View File

@ -869,7 +869,7 @@ void DebuggerParser::executeDelfunction()
if(debugger.delFunction(argStrings[0])) if(debugger.delFunction(argStrings[0]))
commandResult << "removed function " << argStrings[0]; commandResult << "removed function " << argStrings[0];
else else
commandResult << "function " << argStrings[0] << " not found"; commandResult << "function " << argStrings[0] << " built-in or not found";
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1042,7 +1042,7 @@ void DebuggerParser::executeListbreaks()
for(uInt32 i = 0; i < 0x10000; i++) for(uInt32 i = 0; i < 0x10000; i++)
{ {
if(debugger.breakpoints().isSet(i)) if(debugger.breakPoints().isSet(i))
{ {
buf << debugger.cartDebug().getLabel(i, true, 4) << " "; buf << debugger.cartDebug().getLabel(i, true, 4) << " ";
if(! (++count % 8) ) buf << "\n"; if(! (++count % 8) ) buf << "\n";

View File

@ -1,82 +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-2014 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.
//
// $Id$
//============================================================================
#include "bspf.hxx"
#include "PackedBitArray.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PackedBitArray::PackedBitArray(uInt32 length)
: words(length / WORD_SIZE + 1)
{
bits = new uInt32[ words ];
for(uInt32 i = 0; i < words; ++i)
bits[i] = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PackedBitArray::~PackedBitArray()
{
delete[] bits;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 PackedBitArray::isSet(uInt32 bit) const
{
uInt32 word = bit / WORD_SIZE;
bit %= WORD_SIZE;
return (bits[word] & (1 << bit));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 PackedBitArray::isClear(uInt32 bit) const
{
uInt32 word = bit / WORD_SIZE;
bit %= WORD_SIZE;
return !(bits[word] & (1 << bit));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PackedBitArray::toggle(uInt32 bit)
{
uInt32 word = bit / WORD_SIZE;
bit %= WORD_SIZE;
bits[word] ^= (1 << bit);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PackedBitArray::set(uInt32 bit)
{
uInt32 word = bit / WORD_SIZE;
bit %= WORD_SIZE;
bits[word] |= (1 << bit);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PackedBitArray::clear(uInt32 bit)
{
uInt32 word = bit / WORD_SIZE;
bit %= WORD_SIZE;
bits[word] &= (~(1 << bit));
}

View File

@ -17,36 +17,40 @@
// $Id$ // $Id$
//============================================================================ //============================================================================
#ifndef PACKEDBITARRAY_HXX #ifndef PACKED_BIT_ARRAY_HXX
#define PACKEDBITARRAY_HXX #define PACKED_BIT_ARRAY_HXX
#include <bitset>
#include "bspf.hxx" #include "bspf.hxx"
class PackedBitArray class PackedBitArray
{ {
public: public:
PackedBitArray(uInt32 length); PackedBitArray() : myInitialized(false) { }
~PackedBitArray();
uInt32 isSet(uInt32 bit) const; bool isSet(uInt32 bit) const { return myBits[bit]; }
uInt32 isClear(uInt32 bit) const; bool isClear(uInt32 bit) const { return !myBits[bit]; }
void set(uInt32 bit); void set(uInt32 bit) { myBits[bit] = true; }
void clear(uInt32 bit); void clear(uInt32 bit) { myBits[bit] = false; }
void toggle(uInt32 bit); void toggle(uInt32 bit) { myBits.flip(bit); }
void initialize() { myInitialized = true; }
void clearAll() { myInitialized = false; myBits.reset(); }
bool isInitialized() const { return myInitialized; }
private: private:
// Copy constructor and assignment operator not supported // Copy constructor and assignment operator not supported
PackedBitArray(const PackedBitArray&); PackedBitArray(const PackedBitArray&);
PackedBitArray& operator = (const PackedBitArray&); PackedBitArray& operator = (const PackedBitArray&);
// number of unsigned ints (size/wordSize): // The actual bits
uInt32 words; bitset<0x10000> myBits;
// the array itself: // Indicates whether we should treat this bitset as initialized
uInt32* bits; bool myInitialized;
static const uInt32 WORD_SIZE = sizeof(uInt32) * 8;
}; };
#endif #endif

View File

@ -78,7 +78,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(), dbg.breakPoints());
myListIsDirty = false; myListIsDirty = false;
} }

View File

@ -3,7 +3,6 @@ MODULE := src/debugger
MODULE_OBJS := \ MODULE_OBJS := \
src/debugger/Debugger.o \ src/debugger/Debugger.o \
src/debugger/DebuggerParser.o \ src/debugger/DebuggerParser.o \
src/debugger/PackedBitArray.o \
src/debugger/CartDebug.o \ src/debugger/CartDebug.o \
src/debugger/CpuDebug.o \ src/debugger/CpuDebug.o \
src/debugger/DiStella.o \ src/debugger/DiStella.o \

View File

@ -62,11 +62,7 @@ M6502::M6502(const Settings& settings)
myDataAddressForPoke(0) myDataAddressForPoke(0)
{ {
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
myDebugger = nullptr; myDebugger = nullptr;
myBreakPoints = nullptr;
myReadTraps = nullptr;
myWriteTraps = nullptr;
myJustHitTrapFlag = false; myJustHitTrapFlag = false;
#endif #endif
} }
@ -130,14 +126,13 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags)
mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU); mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU);
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
if(myReadTraps != nullptr && myReadTraps->isSet(address)) if(myReadTraps.isInitialized() && myReadTraps.isSet(address))
{ {
myJustHitTrapFlag = true; myJustHitTrapFlag = true;
myHitTrapInfo.message = "RTrap: "; myHitTrapInfo.message = "RTrap: ";
myHitTrapInfo.address = address; myHitTrapInfo.address = address;
} }
//cerr << "addr = " << HEX4 << address << ", flags = " << Debugger::to_bin_8(flags) << endl; #endif // DEBUGGER_SUPPORT
#endif
uInt8 result = mySystem->peek(address, flags); uInt8 result = mySystem->peek(address, flags);
myLastAccessWasRead = true; myLastAccessWasRead = true;
@ -159,13 +154,13 @@ inline void M6502::poke(uInt16 address, uInt8 value)
mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU); mySystem->incrementCycles(SYSTEM_CYCLES_PER_CPU);
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
if(myWriteTraps != nullptr && myWriteTraps->isSet(address)) if(myWriteTraps.isInitialized() && myWriteTraps.isSet(address))
{ {
myJustHitTrapFlag = true; myJustHitTrapFlag = true;
myHitTrapInfo.message = "WTrap: "; myHitTrapInfo.message = "WTrap: ";
myHitTrapInfo.address = address; myHitTrapInfo.address = address;
} }
#endif #endif // DEBUGGER_SUPPORT
mySystem->poke(address, value); mySystem->poke(address, value);
myLastAccessWasRead = false; myLastAccessWasRead = false;
@ -193,10 +188,9 @@ bool M6502::execute(uInt32 number)
} }
} }
if(myBreakPoints) if(myBreakPoints.isInitialized() && myBreakPoints.isSet(PC))
if(myBreakPoints->isSet(PC)) if(myDebugger && myDebugger->start("BP: ", PC))
if(myDebugger && myDebugger->start("BP: ", PC)) return true;
return true;
int cond = evalCondBreaks(); int cond = evalCondBreaks();
if(cond > -1) if(cond > -1)
@ -392,7 +386,7 @@ void M6502::attach(Debugger& debugger)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 M6502::addCondBreak(Expression *e, const string& name) uInt32 M6502::addCondBreak(Expression* e, const string& name)
{ {
myBreakConds.emplace_back(unique_ptr<Expression>(e)); myBreakConds.emplace_back(unique_ptr<Expression>(e));
myBreakCondNames.push_back(name); myBreakCondNames.push_back(name);
@ -421,27 +415,4 @@ const StringList& M6502::getCondBreakNames() const
{ {
return myBreakCondNames; return myBreakCondNames;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 M6502::evalCondBreaks()
{
for(uInt32 i = 0; i < myBreakConds.size(); i++)
if(myBreakConds[i]->evaluate())
return i;
return -1; // no break hit
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::setBreakPoints(PackedBitArray *bp)
{
myBreakPoints = bp;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::setTraps(PackedBitArray *read, PackedBitArray *write)
{
myReadTraps = read;
myWriteTraps = write;
}
#endif // DEBUGGER_SUPPORT #endif // DEBUGGER_SUPPORT

View File

@ -20,19 +20,20 @@
#ifndef M6502_HXX #ifndef M6502_HXX
#define M6502_HXX #define M6502_HXX
class M6502; #ifdef DEBUGGER_SUPPORT
class Debugger; class Debugger;
class CpuDebug; class CpuDebug;
class Expression;
class PackedBitArray; #include "Expression.hxx"
#include "PackedBitArray.hxx"
#endif
class Settings; class Settings;
#include "bspf.hxx" #include "bspf.hxx"
#include "System.hxx" #include "System.hxx"
#include "Serializable.hxx" #include "Serializable.hxx"
typedef vector<unique_ptr<Expression>> ExpressionList;
/** /**
The 6502 is an 8-bit microprocessor that has a 64K addressing space. The 6502 is an 8-bit microprocessor that has a 64K addressing space.
This class provides a high compatibility 6502 microprocessor emulator. This class provides a high compatibility 6502 microprocessor emulator.
@ -202,22 +203,18 @@ class M6502 : public Serializable
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
public: public:
/** // Attach the specified debugger.
Attach the specified debugger.
@param debugger The debugger to attach to the microprocessor.
*/
void attach(Debugger& debugger); void attach(Debugger& debugger);
void setBreakPoints(PackedBitArray* bp); PackedBitArray& breakPoints() { return myBreakPoints; }
void setTraps(PackedBitArray* read, PackedBitArray* write); PackedBitArray& readTraps() { return myReadTraps; }
PackedBitArray& writeTraps() { return myWriteTraps; }
uInt32 addCondBreak(Expression* e, const string& name); uInt32 addCondBreak(Expression* e, const string& name);
void delCondBreak(uInt32 brk); void delCondBreak(uInt32 brk);
void clearCondBreaks(); void clearCondBreaks();
const StringList& getCondBreakNames() const; const StringList& getCondBreakNames() const;
Int32 evalCondBreaks(); #endif // DEBUGGER_SUPPORT
#endif
private: private:
/** /**
@ -349,12 +346,19 @@ class M6502 : public Serializable
static constexpr uInt32 SYSTEM_CYCLES_PER_CPU = 1; static constexpr uInt32 SYSTEM_CYCLES_PER_CPU = 1;
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
Int32 evalCondBreaks() {
for(uInt32 i = 0; i < myBreakConds.size(); i++)
if(myBreakConds[i]->evaluate())
return i;
return -1; // no break hit
};
/// Pointer to the debugger for this processor or the null pointer /// Pointer to the debugger for this processor or the null pointer
Debugger* myDebugger; Debugger* myDebugger;
PackedBitArray* myBreakPoints; // Addresses for which the specified action should occur
PackedBitArray* myReadTraps; PackedBitArray myBreakPoints, myReadTraps, myWriteTraps;
PackedBitArray* myWriteTraps;
// Did we just now hit a trap? // Did we just now hit a trap?
bool myJustHitTrapFlag; bool myJustHitTrapFlag;
@ -364,9 +368,9 @@ class M6502 : public Serializable
}; };
HitTrapInfo myHitTrapInfo; HitTrapInfo myHitTrapInfo;
vector<unique_ptr<Expression>> myBreakConds;
StringList myBreakCondNames; StringList myBreakCondNames;
ExpressionList myBreakConds; #endif // DEBUGGER_SUPPORT
#endif
}; };
#endif #endif