We've done it!

Ladies and gentlemen, we have working conditional breakpoints! And they're
*fast*!

The command to use is "breakif". It takes one argument, the condition.
You can use curly braces if you want to include spaces in your arguments
(they don't do anything except help readability).

On the Athlon 2100, I was able to run the emulator at full speed, using
100% of the CPU, with *20* expressions of the form:

	breakif a==101||a==102||a==103||a==104||a==105

Around 25 expressions, the game started getting noticeably jerky, but was
still playable. With 1 to 5 expressions, there was *no* noticeable increase
in CPU usage!

Actually, this can probably be improved on: I used gcc 3.2.2 for
this. With 3.3.x or 4.0.x, it should be even faster.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@665 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-07-17 02:26:50 +00:00
parent c592a1e47b
commit 14d08d4302
6 changed files with 93 additions and 8 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: CpuDebug.hxx,v 1.5 2005-07-15 02:59:00 urchlay Exp $
// $Id: CpuDebug.hxx,v 1.6 2005-07-17 02:26:49 urchlay Exp $
//============================================================================
#ifndef CPU_DEBUG_HXX
@ -48,6 +48,9 @@ class CpuDebug : public DebuggerSystem
void saveOldState();
// I know, we ain't supposed to do this...
M6502 &m6502() { return mySystem->m6502(); }
int disassemble(int address, char* buffer, EquateList* equateList);
int dPeek(int address);

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.61 2005-07-17 00:03:59 stephena Exp $
// $Id: DebuggerParser.cxx,v 1.62 2005-07-17 02:26:49 urchlay Exp $
//============================================================================
#include "bspf.hxx"
@ -21,6 +21,7 @@
#include "CpuDebug.hxx"
#include "DebuggerParser.hxx"
#include "YaccParser.hxx"
#include "M6502.hxx"
#include "DebuggerParser.hxx"
@ -51,12 +52,20 @@ Command DebuggerParser::commands[] = {
{
"break",
"Set/clear breakpoint at address (default=pc)",
"Set/clear breakpoint at address (default: current pc)",
false,
{ kARG_WORD, kARG_END_ARGS },
&DebuggerParser::executeBreak
},
{
"breakif",
"Set/clear breakpoint on condition",
true,
{ kARG_WORD, kARG_END_ARGS },
&DebuggerParser::executeBreakif
},
{
"c",
"Carry Flag: set (to 0 or 1), or toggle (no arg)",
@ -1085,6 +1094,18 @@ void DebuggerParser::executeBreak() {
commandResult += debugger->valueToString(bp);
}
// "breakif"
void DebuggerParser::executeBreakif() {
int res = YaccParser::parse(argStrings[0].c_str());
if(res == 0) {
// I hate this().method().chaining().crap()
debugger->cpuDebug().m6502().addCondBreak(
YaccParser::getResult(), argStrings[0] );
} else {
commandResult = red("invalid expression");
}
}
// "c"
void DebuggerParser::executeC() {
if(argCount == 0)
@ -1096,6 +1117,7 @@ void DebuggerParser::executeC() {
// "clearbreaks"
void DebuggerParser::executeClearbreaks() {
debugger->clearAllBreakPoints();
debugger->cpuDebug().m6502().clearCondBreaks();
commandResult = "all breakpoints cleared";
}

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.hxx,v 1.32 2005-07-17 00:04:00 stephena Exp $
// $Id: DebuggerParser.hxx,v 1.33 2005-07-17 02:26:49 urchlay Exp $
//============================================================================
#ifndef DEBUGGER_PARSER_HXX
@ -95,6 +95,7 @@ class DebuggerParser
void executeBank();
void executeBase();
void executeBreak();
void executeBreakif();
void executeC();
void executeClearbreaks();
void executeCleartraps();

View File

@ -13,10 +13,11 @@
// 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.8 2005-07-01 04:22:37 urchlay Exp $
// $Id: M6502.cxx,v 1.9 2005-07-17 02:26:50 urchlay Exp $
//============================================================================
#include "M6502.hxx"
#include "Expression.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
@ -50,6 +51,8 @@ M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::~M6502()
{
myBreakConds.clear();
myBreakCondNames.clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -99,6 +102,42 @@ void M6502::stop()
myExecutionStatus |= StopExecutionBit;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::addCondBreak(Expression *e, string name)
{
myBreakConds.push_back(e);
myBreakCondNames.push_back(name);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::delCondBreak(int brk)
{
myBreakConds.remove_at(brk);
myBreakCondNames.remove_at(brk);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::clearCondBreaks()
{
myBreakConds.clear();
myBreakCondNames.clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int M6502::evalCondBreaks()
{
for(int i=0; i<myBreakConds.size(); i++) {
Expression *e = myBreakConds[i];
if(e->evaluate()) {
string name = myBreakCondNames[i]; // TODO: use this
cerr << "breakpoint due to condition: " << name << endl;
return i;
}
}
return -1; // no break hit
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::AddressingMode M6502::addressingMode(uInt8 opcode) const
{

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.8 2005-07-07 18:56:41 stephena Exp $
// $Id: M6502.hxx,v 1.9 2005-07-17 02:26:50 urchlay Exp $
//============================================================================
#ifndef M6502_HXX
@ -25,10 +25,15 @@ class Serializer;
class Deserializer;
class Debugger;
class CpuDebug;
class Expression;
#include "bspf.hxx"
#include "System.hxx"
#include "PackedBitArray.hxx"
#include "Array.hxx"
#include "StringList.hxx"
typedef GUI::Array<Expression*> ExpressionList;
/**
This is an abstract base class for classes that emulate the
@ -36,7 +41,7 @@ class CpuDebug;
has a 64K addressing space.
@author Bradford W. Mott
@version $Id: M6502.hxx,v 1.8 2005-07-07 18:56:41 stephena Exp $
@version $Id: M6502.hxx,v 1.9 2005-07-17 02:26:50 urchlay Exp $
*/
class M6502
{
@ -182,6 +187,11 @@ class M6502
void setTraps(PackedBitArray *read, PackedBitArray *write);
int totalInstructionCount() { return myTotalInstructionCount; }
void addCondBreak(Expression *e, string name);
void delCondBreak(int brk);
void clearCondBreaks();
int evalCondBreaks();
protected:
/**
Get the 8-bit value of the Processor Status register.
@ -267,5 +277,8 @@ class M6502
bool justHitTrap;
int myTotalInstructionCount;
StringList myBreakCondNames;
ExpressionList myBreakConds;
};
#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: M6502Hi.cxx,v 1.10 2005-07-10 02:16:01 stephena Exp $
// $Id: M6502Hi.cxx,v 1.11 2005-07-17 02:26:50 urchlay Exp $
//============================================================================
#include "M6502Hi.hxx"
@ -104,6 +104,13 @@ bool M6502High::execute(uInt32 number)
}
}
if(evalCondBreaks() > -1)
{
if(myDebugger->start()) {
return true;
}
}
#ifdef DEBUG
debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif