mirror of https://github.com/stella-emu/stella.git
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:
parent
c997fc3001
commit
29fe39dd99
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue