Update TIA and RIOT state in lockstep with the CPU if any debugger expressions are registered.

This commit is contained in:
Christian Speckner 2017-12-16 21:28:44 +01:00
parent 376daae713
commit e5d7c23412
4 changed files with 66 additions and 8 deletions

View File

@ -20,6 +20,8 @@
#include "Expression.hxx" #include "Expression.hxx"
#include "CartDebug.hxx" #include "CartDebug.hxx"
#include "PackedBitArray.hxx" #include "PackedBitArray.hxx"
#include "TIA.hxx"
#include "M6532.hxx"
// Flags for disassembly types // Flags for disassembly types
#define DISASM_CODE CartDebug::CODE #define DISASM_CODE CartDebug::CODE
@ -65,7 +67,8 @@ M6502::M6502(const Settings& settings)
myLastSrcAddressY(-1), myLastSrcAddressY(-1),
myDataAddressForPoke(0), myDataAddressForPoke(0),
myOnHaltCallback(nullptr), myOnHaltCallback(nullptr),
myHaltRequested(false) myHaltRequested(false),
myStepStateByInstruction(false)
{ {
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
myDebugger = nullptr; myDebugger = nullptr;
@ -197,12 +200,23 @@ inline void M6502::handleHalt()
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::updateStepStateByInstruction()
{
myStepStateByInstruction = myCondBreaks.size() || myCondSaveStates.size() || myTrapConds.size();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool M6502::execute(uInt32 number) bool M6502::execute(uInt32 number)
{ {
// Clear all of the execution status bits except for the fatal error bit // Clear all of the execution status bits except for the fatal error bit
myExecutionStatus &= FatalErrorBit; myExecutionStatus &= FatalErrorBit;
#ifdef DEBUGGER_SUPPORT
TIA& tia = mySystem->tia();
M6532& riot = mySystem->m6532();
#endif
// Loop until execution is stopped or a fatal error occurs // Loop until execution is stopped or a fatal error occurs
for(;;) for(;;)
{ {
@ -258,6 +272,13 @@ bool M6502::execute(uInt32 number)
myExecutionStatus |= FatalErrorBit; myExecutionStatus |= FatalErrorBit;
} }
//cycles = mySystem->cycles() - c0; //cycles = mySystem->cycles() - c0;
#ifdef DEBUGGER_SUPPORT
if (myStepStateByInstruction) {
tia.updateEmulation();
riot.updateEmulation();
}
#endif
} }
// See if we need to handle an interrupt // See if we need to handle an interrupt
@ -367,6 +388,7 @@ bool M6502::save(Serializer& out) const
out.putInt(myLastSrcAddressY); out.putInt(myLastSrcAddressY);
out.putBool(myHaltRequested); out.putBool(myHaltRequested);
out.putBool(myStepStateByInstruction);
} }
catch(...) catch(...)
{ {
@ -417,6 +439,7 @@ bool M6502::load(Serializer& in)
myLastSrcAddressY = in.getInt(); myLastSrcAddressY = in.getInt();
myHaltRequested = in.getBool(); myHaltRequested = in.getBool();
myStepStateByInstruction = in.getBool();
} }
catch(...) catch(...)
{ {
@ -440,6 +463,9 @@ uInt32 M6502::addCondBreak(Expression* e, const string& name)
{ {
myCondBreaks.emplace_back(e); myCondBreaks.emplace_back(e);
myCondBreakNames.push_back(name); myCondBreakNames.push_back(name);
updateStepStateByInstruction();
return uInt32(myCondBreaks.size() - 1); return uInt32(myCondBreaks.size() - 1);
} }
@ -450,6 +476,9 @@ bool M6502::delCondBreak(uInt32 idx)
{ {
Vec::removeAt(myCondBreaks, idx); Vec::removeAt(myCondBreaks, idx);
Vec::removeAt(myCondBreakNames, idx); Vec::removeAt(myCondBreakNames, idx);
updateStepStateByInstruction();
return true; return true;
} }
return false; return false;
@ -460,6 +489,8 @@ void M6502::clearCondBreaks()
{ {
myCondBreaks.clear(); myCondBreaks.clear();
myCondBreakNames.clear(); myCondBreakNames.clear();
updateStepStateByInstruction();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -473,6 +504,9 @@ uInt32 M6502::addCondSaveState(Expression* e, const string& name)
{ {
myCondSaveStates.emplace_back(e); myCondSaveStates.emplace_back(e);
myCondSaveStateNames.push_back(name); myCondSaveStateNames.push_back(name);
updateStepStateByInstruction();
return uInt32(myCondSaveStates.size() - 1); return uInt32(myCondSaveStates.size() - 1);
} }
@ -483,6 +517,9 @@ bool M6502::delCondSaveState(uInt32 idx)
{ {
Vec::removeAt(myCondSaveStates, idx); Vec::removeAt(myCondSaveStates, idx);
Vec::removeAt(myCondSaveStateNames, idx); Vec::removeAt(myCondSaveStateNames, idx);
updateStepStateByInstruction();
return true; return true;
} }
return false; return false;
@ -493,6 +530,8 @@ void M6502::clearCondSaveStates()
{ {
myCondSaveStates.clear(); myCondSaveStates.clear();
myCondSaveStateNames.clear(); myCondSaveStateNames.clear();
updateStepStateByInstruction();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -506,6 +545,9 @@ uInt32 M6502::addCondTrap(Expression* e, const string& name)
{ {
myTrapConds.emplace_back(e); myTrapConds.emplace_back(e);
myTrapCondNames.push_back(name); myTrapCondNames.push_back(name);
updateStepStateByInstruction();
return uInt32(myTrapConds.size() - 1); return uInt32(myTrapConds.size() - 1);
} }
@ -516,6 +558,9 @@ bool M6502::delCondTrap(uInt32 brk)
{ {
Vec::removeAt(myTrapConds, brk); Vec::removeAt(myTrapConds, brk);
Vec::removeAt(myTrapCondNames, brk); Vec::removeAt(myTrapCondNames, brk);
updateStepStateByInstruction();
return true; return true;
} }
return false; return false;
@ -526,6 +571,8 @@ void M6502::clearCondTraps()
{ {
myTrapConds.clear(); myTrapConds.clear();
myTrapCondNames.clear(); myTrapCondNames.clear();
updateStepStateByInstruction();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -312,6 +312,12 @@ class M6502 : public Serializable
*/ */
void handleHalt(); void handleHalt();
/**
Check whether we are required to update hardware (TIA + RIOT) in lockstep
with the CPU and update the flag accordingly.
*/
void updateStepStateByInstruction();
private: private:
/** /**
Bit fields used to indicate that certain conditions need to be Bit fields used to indicate that certain conditions need to be
@ -439,6 +445,8 @@ class M6502 : public Serializable
vector<unique_ptr<Expression>> myTrapConds; vector<unique_ptr<Expression>> myTrapConds;
StringList myTrapCondNames; StringList myTrapCondNames;
bool myStepStateByInstruction;
#endif // DEBUGGER_SUPPORT #endif // DEBUGGER_SUPPORT
private: private:

View File

@ -125,13 +125,16 @@ class M6532 : public Device
*/ */
bool poke(uInt16 address, uInt8 value) override; bool poke(uInt16 address, uInt8 value) override;
/**
* Update RIOT state to the current timestamp.
*/
void updateEmulation();
private: private:
void setTimerRegister(uInt8 data, uInt8 interval); void setTimerRegister(uInt8 data, uInt8 interval);
void setPinState(bool shcha); void setPinState(bool shcha);
void updateEmulation();
// The following are used by the debugger to read INTIM/TIMINT // The following are used by the debugger to read INTIM/TIMINT
// We need separate methods to do this, so the state of the system // We need separate methods to do this, so the state of the system
// isn't changed // isn't changed

View File

@ -443,6 +443,11 @@ class TIA : public Device
*/ */
string name() const override { return "TIA"; } string name() const override { return "TIA"; }
/**
* Run and forward TIA emulation to the current system clock.
*/
void updateEmulation();
private: private:
/** /**
* During each line, the TIA cycles through these two states. * During each line, the TIA cycles through these two states.
@ -481,11 +486,6 @@ class TIA : public Device
*/ */
void onHalt(); void onHalt();
/**
* Run and forward TIA emulation to the current system clock.
*/
void updateEmulation();
/** /**
* Execute colorClocks cycles of TIA simulation. * Execute colorClocks cycles of TIA simulation.
*/ */