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
## 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 \
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 \
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
$(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
// 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"
@ -44,6 +44,7 @@ Debugger::Debugger(OSystem* osystem)
// Init parser
myParser = new DebuggerParser(this);
equateList = new EquateList();
breakPoints = new PackedBitArray(0xffff);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -51,7 +52,8 @@ Debugger::~Debugger()
{
delete myParser;
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
// use recursion...
// FIXME: TIA framebuffer should be updated during tracing!
void Debugger::trace()
{
// 32 is the 6502 JSR instruction:
@ -345,3 +349,13 @@ EquateList *Debugger::equates() {
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
// 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
@ -29,6 +29,7 @@ class D6502;
#include "DialogContainer.hxx"
#include "M6502.hxx"
#include "EquateList.hxx"
#include "PackedBitArray.hxx"
#include "bspf.hxx"
enum {
@ -47,7 +48,7 @@ enum {
for all debugging operations in Stella (parser, 6502 debugger, etc).
@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
{
@ -94,6 +95,9 @@ class Debugger : public DialogContainer
return out;
}
void toggleBreakPoint(int bp);
bool breakPoint(int bp);
public:
/**
Run the debugger command and return the result.
@ -144,7 +148,8 @@ class Debugger : public DialogContainer
DebuggerParser* myParser;
D6502* myDebugger;
EquateList *equateList;
EquateList *equateList;
PackedBitArray *breakPoints;
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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"
@ -33,7 +33,6 @@ enum {
DebuggerParser::DebuggerParser(Debugger* d)
: debugger(d)
{
equateList = d->equates();
done = false;
}
@ -63,7 +62,7 @@ int DebuggerParser::conv_hex_digit(char d) {
// the hex to an int. Returns -1 on error.
int DebuggerParser::decipher_arg(string &arg) {
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;
if(address >= 0)
return address;
@ -91,7 +90,7 @@ bool DebuggerParser::getArgs(const string& command) {
// cerr << "Parsing \"" << command << "\"" << endl;
while(*c != '\0') {
// cerr << "State " << state << ", *c " << *c << endl;
// cerr << "State " << state << ", *c '" << *c << "'" << endl;
switch(state) {
case kIN_COMMAND:
if(*c == ' ')
@ -266,13 +265,23 @@ string DebuggerParser::run(const string& command) {
result = debugger->dumpTIA();
} else if(subStringMatch(verb, "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 == "?") {
// please leave each option on its own line so they're
// easy to sort - bkw
return
"a xx - Set Accumulator to xx\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"
"d - Toggle Decimal Flag\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
// 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>
@ -100,8 +100,10 @@ static struct Equate hardCodedEquates[] = {
EquateList::EquateList() {
// cerr << sizeof(hardCodedEquates)/sizeof(struct Equate) << endl;
ourVcsEquates = new Equate[ sizeof(hardCodedEquates)/sizeof(struct Equate) ];
for(int i=0; hardCodedEquates[i].label != NULL; i++)
int size = sizeof(hardCodedEquates)/sizeof(struct Equate) + 1;
ourVcsEquates = new Equate[ size ];
// for(int i=0; hardCodedEquates[i].label != NULL; i++)
for(int i=0; i<size; i++)
ourVcsEquates[i] = hardCodedEquates[i];
calcSize();
}
@ -141,10 +143,15 @@ char *EquateList::getFormatted(int addr, int places) {
return buf;
}
int EquateList::getAddress(const char *label) {
for(int i=0; ourVcsEquates[i].label != NULL; i++)
if( strcasecmp(ourVcsEquates[i].label, label) == 0 )
int EquateList::getAddress(const char *lbl) {
// cerr << "getAddress(" << lbl << ")" << endl;
// 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 -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
// 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"
@ -25,6 +25,7 @@ M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
mySystemCyclesPerProcessorCycle(systemCyclesPerProcessorCycle)
{
uInt16 t;
breakPoints = NULL;
// Compute the BCD lookup table
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?
"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
// 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
@ -26,6 +26,7 @@ class Deserializer;
#include "bspf.hxx"
#include "System.hxx"
#include "PackedBitArray.hxx"
/**
This is an abstract base class for classes that emulate the
@ -33,7 +34,7 @@ class Deserializer;
has a 64K addressing space.
@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
{
@ -166,6 +167,9 @@ class M6502
*/
friend ostream& operator<<(ostream& out, const AddressingMode& mode);
public:
void setBreakPoints(PackedBitArray *bp);
protected:
/**
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 C; // C flag for processor status register
PackedBitArray *breakPoints;
/**
Bit fields used to indicate that certain conditions need to be
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
// 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"
@ -73,6 +73,12 @@ bool M6502High::execute(uInt32 number)
uInt16 operandAddress = 0;
uInt8 operand = 0;
if(breakPoints != NULL)
{
if(breakPoints->isSet(PC))
cerr << "hit breakpoint at " << PC << endl;
}
#ifdef DEBUG
debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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"
@ -59,6 +59,12 @@ bool M6502Low::execute(uInt32 number)
uInt16 operandAddress = 0;
uInt8 operand = 0;
if(breakPoints != NULL)
{
if(breakPoints->isSet(PC))
cerr << "hit breakpoint at " << PC << endl;
}
#ifdef DEBUG
debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif