Partial breakpoint support: the "break" command in the console sets &

clears breakpoints, and the 6502 core emits a "hit breakpoint" message
to standard error when it sees a breakpoint. Still TODO is to figure out
how to enter the debugger from within the 6502 core! (Stephen?)


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@509 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-06-16 02:16:26 +00:00
parent 008c49e507
commit c693074377
11 changed files with 183 additions and 23 deletions

View File

@ -13,7 +13,7 @@
## See the file "license" for information on usage and redistribution of ## See the file "license" for information on usage and redistribution of
## this file, and for a DISCLAIMER OF ALL WARRANTIES. ## this file, and for a DISCLAIMER OF ALL WARRANTIES.
## ##
## $Id: makefile,v 1.98 2005-06-16 01:11:26 stephena Exp $ ## $Id: makefile,v 1.99 2005-06-16 02:16:25 urchlay Exp $
##============================================================================ ##============================================================================
##============================================================================ ##============================================================================
@ -164,7 +164,7 @@ GUI_OBJS = Font.o Menu.o Launcher.o \
ProgressDialog.o \ ProgressDialog.o \
DebuggerDialog.o PromptWidget.o CheatWidget.o DebuggerDialog.o PromptWidget.o CheatWidget.o
DBG_OBJS = Debugger.o DebuggerParser.o EquateList.o DBG_OBJS = Debugger.o DebuggerParser.o EquateList.o PackedBitArray.o
CORE_OBJS = Booster.o Cart.o Cart2K.o Cart3F.o Cart4K.o CartAR.o CartDPC.o \ CORE_OBJS = Booster.o Cart.o Cart2K.o Cart3F.o Cart4K.o CartAR.o CartDPC.o \
CartE0.o CartE7.o CartF4.o CartF4SC.o CartF6.o CartF6SC.o \ CartE0.o CartE7.o CartF4.o CartF4SC.o CartF6.o CartF6SC.o \
@ -479,3 +479,6 @@ DebuggerParser.o: $(DBG)/DebuggerParser.cxx $(DBG)/DebuggerParser.hxx
EquateList.o: $(DBG)/EquateList.cxx $(DBG)/EquateList.hxx $(DBG)/Equate.hxx EquateList.o: $(DBG)/EquateList.cxx $(DBG)/EquateList.hxx $(DBG)/Equate.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(DBG)/EquateList.cxx $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(DBG)/EquateList.cxx
PackedBitArray.o: $(DBG)/PackedBitArray.cxx $(DBG)/PackedBitArray.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(DBG)/PackedBitArray.cxx

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.cxx,v 1.9 2005-06-16 00:55:57 stephena Exp $ // $Id: Debugger.cxx,v 1.10 2005-06-16 02:16:25 urchlay Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -44,6 +44,7 @@ Debugger::Debugger(OSystem* osystem)
// Init parser // Init parser
myParser = new DebuggerParser(this); myParser = new DebuggerParser(this);
equateList = new EquateList(); equateList = new EquateList();
breakPoints = new PackedBitArray(0xffff);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -51,7 +52,8 @@ Debugger::~Debugger()
{ {
delete myParser; delete myParser;
delete myDebugger; delete myDebugger;
// delete equateList; delete equateList;
delete breakPoints;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -277,6 +279,8 @@ void Debugger::step()
// to share between stack and variables, I doubt any 2600 games will ever // to share between stack and variables, I doubt any 2600 games will ever
// use recursion... // use recursion...
// FIXME: TIA framebuffer should be updated during tracing!
void Debugger::trace() void Debugger::trace()
{ {
// 32 is the 6502 JSR instruction: // 32 is the 6502 JSR instruction:
@ -345,3 +349,13 @@ EquateList *Debugger::equates() {
return equateList; return equateList;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::toggleBreakPoint(int bp) {
mySystem->m6502().setBreakPoints(breakPoints);
breakPoints->toggle(bp);
}
bool Debugger::breakPoint(int bp) {
return breakPoints->isSet(bp) != 0;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.hxx,v 1.6 2005-06-16 00:20:11 stephena Exp $ // $Id: Debugger.hxx,v 1.7 2005-06-16 02:16:25 urchlay Exp $
//============================================================================ //============================================================================
#ifndef DEBUGGER_HXX #ifndef DEBUGGER_HXX
@ -29,6 +29,7 @@ class D6502;
#include "DialogContainer.hxx" #include "DialogContainer.hxx"
#include "M6502.hxx" #include "M6502.hxx"
#include "EquateList.hxx" #include "EquateList.hxx"
#include "PackedBitArray.hxx"
#include "bspf.hxx" #include "bspf.hxx"
enum { enum {
@ -47,7 +48,7 @@ enum {
for all debugging operations in Stella (parser, 6502 debugger, etc). for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony @author Stephen Anthony
@version $Id: Debugger.hxx,v 1.6 2005-06-16 00:20:11 stephena Exp $ @version $Id: Debugger.hxx,v 1.7 2005-06-16 02:16:25 urchlay Exp $
*/ */
class Debugger : public DialogContainer class Debugger : public DialogContainer
{ {
@ -94,6 +95,9 @@ class Debugger : public DialogContainer
return out; return out;
} }
void toggleBreakPoint(int bp);
bool breakPoint(int bp);
public: public:
/** /**
Run the debugger command and return the result. Run the debugger command and return the result.
@ -145,6 +149,7 @@ class Debugger : public DialogContainer
DebuggerParser* myParser; DebuggerParser* myParser;
D6502* myDebugger; D6502* myDebugger;
EquateList *equateList; EquateList *equateList;
PackedBitArray *breakPoints;
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: DebuggerParser.cxx,v 1.6 2005-06-15 23:45:04 urchlay Exp $ // $Id: DebuggerParser.cxx,v 1.7 2005-06-16 02:16:25 urchlay Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -33,7 +33,6 @@ enum {
DebuggerParser::DebuggerParser(Debugger* d) DebuggerParser::DebuggerParser(Debugger* d)
: debugger(d) : debugger(d)
{ {
equateList = d->equates();
done = false; done = false;
} }
@ -63,7 +62,7 @@ int DebuggerParser::conv_hex_digit(char d) {
// the hex to an int. Returns -1 on error. // the hex to an int. Returns -1 on error.
int DebuggerParser::decipher_arg(string &arg) { int DebuggerParser::decipher_arg(string &arg) {
const char *a = arg.c_str(); const char *a = arg.c_str();
int address = equateList->getAddress(a); int address = debugger->equateList->getAddress(a);
// cerr << "decipher_arg: equateList->getAddress(" << a << ") == " << address << endl; // cerr << "decipher_arg: equateList->getAddress(" << a << ") == " << address << endl;
if(address >= 0) if(address >= 0)
return address; return address;
@ -91,7 +90,7 @@ bool DebuggerParser::getArgs(const string& command) {
// cerr << "Parsing \"" << command << "\"" << endl; // cerr << "Parsing \"" << command << "\"" << endl;
while(*c != '\0') { while(*c != '\0') {
// cerr << "State " << state << ", *c " << *c << endl; // cerr << "State " << state << ", *c '" << *c << "'" << endl;
switch(state) { switch(state) {
case kIN_COMMAND: case kIN_COMMAND:
if(*c == ' ') if(*c == ' ')
@ -266,13 +265,23 @@ string DebuggerParser::run(const string& command) {
result = debugger->dumpTIA(); result = debugger->dumpTIA();
} else if(subStringMatch(verb, "reset")) { } else if(subStringMatch(verb, "reset")) {
debugger->reset(); debugger->reset();
} else if(subStringMatch(verb, "break")) {
if(argCount == 1) {
debugger->toggleBreakPoint(args[0]);
if(debugger->breakPoint(args[0]))
return "Set breakpoint";
else
return "Cleared breakpoint";
} else {
return "one argument required";
}
} else if(subStringMatch(verb, "help") || verb == "?") { } else if(subStringMatch(verb, "help") || verb == "?") {
// please leave each option on its own line so they're // please leave each option on its own line so they're
// easy to sort - bkw // easy to sort - bkw
return return
"a xx - Set Accumulator to xx\n" "a xx - Set Accumulator to xx\n"
// "break - Show all breakpoints\n" // "break - Show all breakpoints\n"
// "break xx - Set/clear breakpoint at address xx\n" "break xx - Set/clear breakpoint at address xx\n"
"c - Toggle Carry Flag\n" "c - Toggle Carry Flag\n"
"d - Toggle Decimal Flag\n" "d - Toggle Decimal Flag\n"
"loadsym f - Load DASM symbols from file f\n" "loadsym f - Load DASM symbols from file f\n"

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EquateList.cxx,v 1.6 2005-06-16 00:20:11 stephena Exp $ // $Id: EquateList.cxx,v 1.7 2005-06-16 02:16:26 urchlay Exp $
//============================================================================ //============================================================================
#include <string> #include <string>
@ -100,8 +100,10 @@ static struct Equate hardCodedEquates[] = {
EquateList::EquateList() { EquateList::EquateList() {
// cerr << sizeof(hardCodedEquates)/sizeof(struct Equate) << endl; // cerr << sizeof(hardCodedEquates)/sizeof(struct Equate) << endl;
ourVcsEquates = new Equate[ sizeof(hardCodedEquates)/sizeof(struct Equate) ]; int size = sizeof(hardCodedEquates)/sizeof(struct Equate) + 1;
for(int i=0; hardCodedEquates[i].label != NULL; i++) ourVcsEquates = new Equate[ size ];
// for(int i=0; hardCodedEquates[i].label != NULL; i++)
for(int i=0; i<size; i++)
ourVcsEquates[i] = hardCodedEquates[i]; ourVcsEquates[i] = hardCodedEquates[i];
calcSize(); calcSize();
} }
@ -141,10 +143,15 @@ char *EquateList::getFormatted(int addr, int places) {
return buf; return buf;
} }
int EquateList::getAddress(const char *label) { int EquateList::getAddress(const char *lbl) {
for(int i=0; ourVcsEquates[i].label != NULL; i++) // cerr << "getAddress(" << lbl << ")" << endl;
if( strcasecmp(ourVcsEquates[i].label, label) == 0 ) // cerr << ourVcsEquates[0].label << endl;
// cerr << "shit" << endl;
for(int i=0; ourVcsEquates[i].label != NULL; i++) {
// cerr << "Looking at " << ourVcsEquates[i].label << endl;
if( strcasecmp(ourVcsEquates[i].label, lbl) == 0 )
return ourVcsEquates[i].address; return ourVcsEquates[i].address;
}
return -1; return -1;
} }

View File

@ -0,0 +1,67 @@
#include "bspf.hxx"
#include "PackedBitArray.hxx"
/*
boolean set();
boolean clear();
void set(int bit);
void clear(int bit);
void toggle(int bit);
*/
PackedBitArray::PackedBitArray(int length) {
size = length;
words = length / wordSize + 1;
bits = new unsigned int[ words ];
// FIXME: find out if this is necessary (does a new array
// start out zeroed already?
for(int i=0; i<words; i++)
bits[i] = 0;
// cerr << "size==" << size << " words==" << words << endl;
}
PackedBitArray::~PackedBitArray() {
delete bits;
}
int PackedBitArray::isSet(unsigned int bit) {
unsigned int word = bit / wordSize;
bit %= wordSize;
return (bits[word] & (1 << bit));
}
int PackedBitArray::isClear(unsigned int bit) {
unsigned int word = bit / wordSize;
bit %= wordSize;
return !(bits[word] & (1 << bit));
}
void PackedBitArray::toggle(unsigned int bit) {
unsigned int word = bit / wordSize;
bit %= wordSize;
// cerr << "word==" << word << ", bit==" << bit << endl;
bits[word] ^= (1 << bit);
}
void PackedBitArray::set(unsigned int bit) {
unsigned int word = bit / wordSize;
bit %= wordSize;
bits[word] |= (1 << bit);
}
void PackedBitArray::clear(unsigned int bit) {
unsigned int word = bit / wordSize;
bit %= wordSize;
bits[word] &= (~(1 << bit));
}

View File

@ -0,0 +1,32 @@
#ifndef PACKEDBITARRAY_HXX
#define PACKEDBITARRAY_HXX
#include "bspf.hxx"
#define wordSize ( (sizeof(unsigned int)) * 8)
class PackedBitArray {
public:
PackedBitArray(int length);
~PackedBitArray();
int isSet(unsigned int bit);
int isClear(unsigned int bit);
void set(unsigned int bit);
void clear(unsigned int bit);
void toggle(unsigned int bit);
private:
// number of bits in the array:
int size;
// number of unsigned ints (size/wordSize):
int words;
// the array itself:
unsigned int *bits;
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: M6502.cxx,v 1.4 2005-06-16 01:11:28 stephena Exp $ // $Id: M6502.cxx,v 1.5 2005-06-16 02:16:26 urchlay Exp $
//============================================================================ //============================================================================
#include "M6502.hxx" #include "M6502.hxx"
@ -25,6 +25,7 @@ M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
mySystemCyclesPerProcessorCycle(systemCyclesPerProcessorCycle) mySystemCyclesPerProcessorCycle(systemCyclesPerProcessorCycle)
{ {
uInt16 t; uInt16 t;
breakPoints = NULL;
// Compute the BCD lookup table // Compute the BCD lookup table
for(t = 0; t < 256; ++t) for(t = 0; t < 256; ++t)
@ -332,3 +333,7 @@ const char* M6502::ourInstructionMnemonicTable[256] = {
"BEQ", "SBC", "n/a", "isb", "nop", "SBC", "INC", "isb", // 0xF? "BEQ", "SBC", "n/a", "isb", "nop", "SBC", "INC", "isb", // 0xF?
"SED", "SBC", "nop", "isb", "nop", "SBC", "INC", "isb" "SED", "SBC", "nop", "isb", "nop", "SBC", "INC", "isb"
}; };
void M6502::setBreakPoints(PackedBitArray *bp) {
breakPoints = bp;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: M6502.hxx,v 1.3 2005-06-16 01:11:28 stephena Exp $ // $Id: M6502.hxx,v 1.4 2005-06-16 02:16:26 urchlay Exp $
//============================================================================ //============================================================================
#ifndef M6502_HXX #ifndef M6502_HXX
@ -26,6 +26,7 @@ class Deserializer;
#include "bspf.hxx" #include "bspf.hxx"
#include "System.hxx" #include "System.hxx"
#include "PackedBitArray.hxx"
/** /**
This is an abstract base class for classes that emulate the This is an abstract base class for classes that emulate the
@ -33,7 +34,7 @@ class Deserializer;
has a 64K addressing space. has a 64K addressing space.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: M6502.hxx,v 1.3 2005-06-16 01:11:28 stephena Exp $ @version $Id: M6502.hxx,v 1.4 2005-06-16 02:16:26 urchlay Exp $
*/ */
class M6502 class M6502
{ {
@ -166,6 +167,9 @@ class M6502
*/ */
friend ostream& operator<<(ostream& out, const AddressingMode& mode); friend ostream& operator<<(ostream& out, const AddressingMode& mode);
public:
void setBreakPoints(PackedBitArray *bp);
protected: protected:
/** /**
Get the 8-bit value of the Processor Status register. Get the 8-bit value of the Processor Status register.
@ -197,6 +201,8 @@ class M6502
bool notZ; // Z flag complement for processor status register bool notZ; // Z flag complement for processor status register
bool C; // C flag for processor status register bool C; // C flag for processor status register
PackedBitArray *breakPoints;
/** /**
Bit fields used to indicate that certain conditions need to be Bit fields used to indicate that certain conditions need to be
handled such as stopping execution, fatal errors, maskable interrupts handled such as stopping execution, fatal errors, maskable interrupts

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: M6502Hi.cxx,v 1.3 2005-06-16 01:11:28 stephena Exp $ // $Id: M6502Hi.cxx,v 1.4 2005-06-16 02:16:26 urchlay Exp $
//============================================================================ //============================================================================
#include "M6502Hi.hxx" #include "M6502Hi.hxx"
@ -73,6 +73,12 @@ bool M6502High::execute(uInt32 number)
uInt16 operandAddress = 0; uInt16 operandAddress = 0;
uInt8 operand = 0; uInt8 operand = 0;
if(breakPoints != NULL)
{
if(breakPoints->isSet(PC))
cerr << "hit breakpoint at " << PC << endl;
}
#ifdef DEBUG #ifdef DEBUG
debugStream << "PC=" << hex << setw(4) << PC << " "; debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: M6502Low.cxx,v 1.3 2005-06-16 01:11:29 stephena Exp $ // $Id: M6502Low.cxx,v 1.4 2005-06-16 02:16:26 urchlay Exp $
//============================================================================ //============================================================================
#include "M6502Low.hxx" #include "M6502Low.hxx"
@ -59,6 +59,12 @@ bool M6502Low::execute(uInt32 number)
uInt16 operandAddress = 0; uInt16 operandAddress = 0;
uInt8 operand = 0; uInt8 operand = 0;
if(breakPoints != NULL)
{
if(breakPoints->isSet(PC))
cerr << "hit breakpoint at " << PC << endl;
}
#ifdef DEBUG #ifdef DEBUG
debugStream << "PC=" << hex << setw(4) << PC << " "; debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif #endif