mirror of https://github.com/stella-emu/stella.git
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:
parent
c592a1e47b
commit
14d08d4302
|
@ -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);
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue