Implemented data bus state locking, so the debugger won't disturb the

System when it uses peek() to examine memory/TIA/etc.

I'm not entirely sure I put a lockDataBus() call where it will get
executed when the user presses ` to enter the debugger: I put it in
Debugger::start() (does everything call this, or does EventHandler do
something else?), and again in Debugger::state() (which gets called to
build every prompt string).

There are unlockDataBus() calls everywhere in the Debugger where we
execute 6502 code, including Debugger::quit(). Does the EventHandler
call quit() when it exits the debugger (if the user presses ` I mean)?


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@630 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-07-09 23:44:08 +00:00
parent adb22f7b00
commit 6ef90324bf
4 changed files with 60 additions and 9 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: Debugger.cxx,v 1.57 2005-07-08 17:22:40 stephena Exp $ // $Id: Debugger.cxx,v 1.58 2005-07-09 23:44:07 urchlay Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -216,6 +216,9 @@ const string Debugger::cpuState()
string result; string result;
char buf[255]; char buf[255];
// Lock the bus before every prompt, so we don't disturb anything:
mySystem->lockDataBus();
CpuState state = (CpuState&) myCpuDebug->getState(); CpuState state = (CpuState&) myCpuDebug->getState();
CpuState oldstate = (CpuState&) myCpuDebug->getOldState(); CpuState oldstate = (CpuState&) myCpuDebug->getOldState();
@ -489,12 +492,17 @@ bool Debugger::start()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::quit() void Debugger::quit()
{ {
if(myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER) { if(myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER) {
mySystem->unlockDataBus();
// execute one instruction on quit, IF we're // execute one instruction on quit, IF we're
// sitting at a breakpoint. This will get us past it. // sitting at a breakpoint. 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
// FIXME: do this for traps, too
if(breakPoints->isSet(myCpuDebug->pc())) if(breakPoints->isSet(myCpuDebug->pc()))
mySystem->m6502().execute(1); mySystem->m6502().execute(1);
myOSystem->eventHandler().leaveDebugMode(); myOSystem->eventHandler().leaveDebugMode();
} }
} }
@ -517,7 +525,9 @@ int Debugger::step()
saveOldState(); saveOldState();
int cyc = mySystem->cycles(); int cyc = mySystem->cycles();
mySystem->unlockDataBus();
mySystem->m6502().execute(1); mySystem->m6502().execute(1);
mySystem->lockDataBus();
// FIXME - this doesn't work yet, pending a partial rewrite of TIA class // FIXME - this doesn't work yet, pending a partial rewrite of TIA class
myTiaDebug->updateTIA(); myTiaDebug->updateTIA();
@ -542,15 +552,21 @@ int Debugger::step()
int Debugger::trace() int Debugger::trace()
{ {
// 32 is the 6502 JSR instruction: // 32 is the 6502 JSR instruction:
if(mySystem->peek(myCpuDebug->pc()) == 32) { if(mySystem->peek(myCpuDebug->pc()) == 32) {
saveOldState(); saveOldState();
int cyc = mySystem->cycles(); int cyc = mySystem->cycles();
int targetPC = myCpuDebug->pc() + 3; // return address int targetPC = myCpuDebug->pc() + 3; // return address
mySystem->unlockDataBus();
while(myCpuDebug->pc() != targetPC) while(myCpuDebug->pc() != targetPC)
mySystem->m6502().execute(1); mySystem->m6502().execute(1);
mySystem->lockDataBus();
// FIXME - this doesn't work yet, pending a partial rewrite of TIA class // FIXME - this doesn't work yet, pending a partial rewrite of TIA class
myTiaDebug->updateTIA(); myTiaDebug->updateTIA();
myOSystem->frameBuffer().refreshTIA(true); myOSystem->frameBuffer().refreshTIA(true);
@ -645,7 +661,9 @@ string Debugger::disassemble(int start, int lines) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::nextFrame(int frames) { void Debugger::nextFrame(int frames) {
saveOldState(); saveOldState();
mySystem->unlockDataBus();
myOSystem->frameBuffer().advance(frames); myOSystem->frameBuffer().advance(frames);
mySystem->lockDataBus();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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: TIADebug.cxx,v 1.9 2005-07-08 17:22:40 stephena Exp $ // $Id: TIADebug.cxx,v 1.10 2005-07-09 23:44:07 urchlay Exp $
//============================================================================ //============================================================================
#include "System.hxx" #include "System.hxx"
@ -42,7 +42,7 @@ DebuggerState& TIADebug::getState()
{ {
myState.ram.clear(); myState.ram.clear();
for(int i = 0; i < 0x010; ++i) for(int i = 0; i < 0x010; ++i)
myState.ram.push_back(mySystem->peek(i)); myState.ram.push_back(myTIA->peek(i));
return myState; return myState;
} }
@ -52,7 +52,7 @@ void TIADebug::saveOldState()
{ {
myOldState.ram.clear(); myOldState.ram.clear();
for(int i = 0; i < 0x010; ++i) for(int i = 0; i < 0x010; ++i)
myOldState.ram.push_back(mySystem->peek(i)); myOldState.ram.push_back(myTIA->peek(i));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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: System.cxx,v 1.12 2005-07-09 12:52:46 stephena Exp $ // $Id: System.cxx,v 1.13 2005-07-09 23:44:08 urchlay Exp $
//============================================================================ //============================================================================
#include <assert.h> #include <assert.h>
@ -57,6 +57,9 @@ System::System(uInt16 n, uInt16 m)
// Set up (de)serializer in case we are asked to save/load state // Set up (de)serializer in case we are asked to save/load state
serializer = new Serializer(); serializer = new Serializer();
deserializer = new Deserializer(); deserializer = new Deserializer();
// Bus starts out unlocked (in other words, peek() changes myDataBusState)
myDataBusLocked = false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -336,7 +339,8 @@ uInt8 System::peek(uInt16 addr)
result = access.device->peek(addr); result = access.device->peek(addr);
} }
myDataBusState = result; if(!myDataBusLocked)
myDataBusState = result;
return result; return result;
} }
@ -356,5 +360,17 @@ void System::poke(uInt16 addr, uInt8 value)
access.device->poke(addr, value); access.device->poke(addr, value);
} }
myDataBusState = value; if(!myDataBusLocked)
myDataBusState = value;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::lockDataBus() {
myDataBusLocked = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::unlockDataBus() {
myDataBusLocked = false;
}

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: System.hxx,v 1.9 2005-07-09 12:52:46 stephena Exp $ // $Id: System.hxx,v 1.10 2005-07-09 23:44:08 urchlay Exp $
//============================================================================ //============================================================================
#ifndef SYSTEM_HXX #ifndef SYSTEM_HXX
@ -48,7 +48,7 @@ class Deserializer;
dynamic code for that page of memory. dynamic code for that page of memory.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: System.hxx,v 1.9 2005-07-09 12:52:46 stephena Exp $ @version $Id: System.hxx,v 1.10 2005-07-09 23:44:08 urchlay Exp $
*/ */
class System class System
{ {
@ -261,6 +261,18 @@ class System
*/ */
void poke(uInt16 address, uInt8 value); void poke(uInt16 address, uInt8 value);
/**
Lock/unlock the data bus. When the bus is locked, peek() and
poke() don't update the bus state. The bus should be unlocked
while the CPU is running (normal emulation, or when the debugger
is stepping/advancing). It should be locked while the debugger
is active but not running the CPU. This is so the debugger can
use System.peek() to examine memory/registers without changing
the state of the system.
*/
void lockDataBus();
void unlockDataBus();
public: public:
/** /**
Structure used to specify access methods for a page Structure used to specify access methods for a page
@ -343,6 +355,11 @@ class System
// The current state of the Data Bus // The current state of the Data Bus
uInt8 myDataBusState; uInt8 myDataBusState;
// Whether or not peek() updates the data bus state. This
// is true during normal emulation, and false when the
// debugger is active.
bool myDataBusLocked;
// The serializer for the system. Used to save state. // The serializer for the system. Used to save state.
Serializer* serializer; Serializer* serializer;