Debugger: Performance improvements + refactoring

-Reduce breakpoint check overhead
-Only run SPC/DSP when needed
-Only build disassembly cache when needed
This commit is contained in:
Sour 2019-10-11 16:07:30 -04:00
parent 8a8a1e01e7
commit 7ae6605e77
14 changed files with 177 additions and 80 deletions

View file

@ -6,25 +6,23 @@
#include "DebugUtilities.h"
#include "ExpressionEvaluator.h"
BreakpointManager::BreakpointManager(Debugger *debugger)
BreakpointManager::BreakpointManager(Debugger *debugger, CpuType cpuType)
{
_debugger = debugger;
_cpuType = cpuType;
_hasBreakpoint = false;
}
void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
{
for(int j = 0; j <= (int)DebugUtilities::GetLastCpuType(); j++) {
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
_breakpoints[j][i].clear();
_rpnList[j][i].clear();
_hasBreakpoint[j][i] = false;
}
_hasBreakpoint = false;
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
_breakpoints[i].clear();
_rpnList[i].clear();
_hasBreakpointType[i] = false;
}
_bpExpEval[(int)CpuType::Cpu].reset(new ExpressionEvaluator(_debugger, CpuType::Cpu));
_bpExpEval[(int)CpuType::Spc].reset(new ExpressionEvaluator(_debugger, CpuType::Spc));
_bpExpEval[(int)CpuType::Sa1].reset(new ExpressionEvaluator(_debugger, CpuType::Sa1));
_bpExpEval[(int)CpuType::Gsu].reset(new ExpressionEvaluator(_debugger, CpuType::Gsu));
_bpExpEval.reset(new ExpressionEvaluator(_debugger, _cpuType));
for(uint32_t j = 0; j < count; j++) {
Breakpoint &bp = breakpoints[j];
@ -32,17 +30,22 @@ void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
BreakpointType bpType = (BreakpointType)i;
if((bp.IsMarked() || bp.IsEnabled()) && bp.HasBreakpointType(bpType)) {
CpuType cpuType = bp.GetCpuType();
_breakpoints[(int)cpuType][i].push_back(bp);
if(_cpuType != cpuType) {
continue;
}
_breakpoints[i].push_back(bp);
if(bp.HasCondition()) {
bool success = true;
ExpressionData data = _bpExpEval[(int)cpuType]->GetRpnList(bp.GetCondition(), success);
_rpnList[(int)cpuType][i].push_back(success ? data : ExpressionData());
ExpressionData data = _bpExpEval->GetRpnList(bp.GetCondition(), success);
_rpnList[i].push_back(success ? data : ExpressionData());
} else {
_rpnList[(int)cpuType][i].push_back(ExpressionData());
_rpnList[i].push_back(ExpressionData());
}
_hasBreakpoint[(int)cpuType][i] = true;
_hasBreakpoint = true;
_hasBreakpointType[i] = true;
}
}
}
@ -66,21 +69,21 @@ BreakpointType BreakpointManager::GetBreakpointType(MemoryOperationType type)
}
}
int BreakpointManager::CheckBreakpoint(CpuType cpuType, MemoryOperationInfo operationInfo, AddressInfo &address)
int BreakpointManager::InternalCheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address)
{
BreakpointType type = GetBreakpointType(operationInfo.Type);
if(!_hasBreakpoint[(int)cpuType][(int)type]) {
if(!_hasBreakpointType[(int)type]) {
return -1;
}
DebugState state;
_debugger->GetState(state, false);
EvalResultType resultType;
vector<Breakpoint> &breakpoints = _breakpoints[(int)cpuType][(int)type];
vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
for(size_t i = 0; i < breakpoints.size(); i++) {
if(breakpoints[i].Matches(operationInfo.Address, address)) {
if(!breakpoints[i].HasCondition() || _bpExpEval[(int)cpuType]->Evaluate(_rpnList[(int)cpuType][(int)type][i], state, resultType, operationInfo)) {
if(!breakpoints[i].HasCondition() || _bpExpEval->Evaluate(_rpnList[(int)type][i], state, resultType, operationInfo)) {
return breakpoints[i].GetId();
}
}

View file

@ -15,18 +15,29 @@ private:
static constexpr int BreakpointTypeCount = 3; //Read, Write, Exec
Debugger *_debugger;
CpuType _cpuType;
vector<Breakpoint> _breakpoints[(int)DebugUtilities::GetLastCpuType() + 1][BreakpointTypeCount];
vector<ExpressionData> _rpnList[(int)DebugUtilities::GetLastCpuType() + 1][BreakpointTypeCount];
bool _hasBreakpoint[(int)DebugUtilities::GetLastCpuType() + 1][BreakpointTypeCount] = {};
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
vector<ExpressionData> _rpnList[BreakpointTypeCount];
bool _hasBreakpoint;
bool _hasBreakpointType[BreakpointTypeCount] = {};
unique_ptr<ExpressionEvaluator> _bpExpEval[(int)DebugUtilities::GetLastCpuType() + 1];
unique_ptr<ExpressionEvaluator> _bpExpEval;
BreakpointType GetBreakpointType(MemoryOperationType type);
int InternalCheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address);
public:
BreakpointManager(Debugger *debugger);
BreakpointManager(Debugger *debugger, CpuType cpuType);
void SetBreakpoints(Breakpoint breakpoints[], uint32_t count);
int CheckBreakpoint(CpuType cpuType, MemoryOperationInfo operationInfo, AddressInfo &address);
};
__forceinline int CheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address);
};
__forceinline int BreakpointManager::CheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address)
{
if(!_hasBreakpoint) {
return -1;
}
return InternalCheckBreakpoint(operationInfo, address);
}

View file

@ -718,8 +718,6 @@ void Console::ProcessPpuCycle()
{
if(_debugger) {
_debugger->ProcessPpuCycle();
_spc->Run();
_cart->RunCoprocessors();
}
}

View file

@ -8,6 +8,7 @@
#include "Sa1.h"
#include "TraceLogger.h"
#include "CallstackManager.h"
#include "BreakpointManager.h"
#include "MemoryManager.h"
#include "CodeDataLogger.h"
#include "EmuSettings.h"
@ -18,6 +19,7 @@
#include "BaseCartridge.h"
#include "Console.h"
#include "MemoryAccessCounter.h"
#include "ExpressionEvaluator.h"
CpuDebugger::CpuDebugger(Debugger* debugger, CpuType cpuType)
{
@ -36,6 +38,7 @@ CpuDebugger::CpuDebugger(Debugger* debugger, CpuType cpuType)
_memoryManager = debugger->GetConsole()->GetMemoryManager().get();
_callstackManager.reset(new CallstackManager(debugger));
_breakpointManager.reset(new BreakpointManager(debugger, cpuType));
_step.reset(new StepRequest());
if(GetState().PC == 0) {
@ -58,6 +61,7 @@ void CpuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
BreakSource breakSource = BreakSource::Unspecified;
if(type == MemoryOperationType::ExecOpCode) {
bool needDisassemble = _traceLogger->IsCpuLogged(_cpuType) || _settings->CheckDebuggerFlag(_cpuType == CpuType::Cpu ? DebuggerFlags::CpuDebuggerEnabled : DebuggerFlags::Sa1DebuggerEnabled);
if(addressInfo.Address >= 0) {
if(addressInfo.Type == SnesMemoryType::PrgRom) {
uint8_t flags = CdlFlags::Code | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8));
@ -66,14 +70,18 @@ void CpuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
_codeDataLogger->SetFlags(addressInfo.Address, flags);
}
_disassembler->BuildCache(addressInfo, state.PS & (ProcFlags::IndexMode8 | ProcFlags::MemoryMode8), _cpuType);
if(needDisassemble) {
_disassembler->BuildCache(addressInfo, state.PS & (ProcFlags::IndexMode8 | ProcFlags::MemoryMode8), _cpuType);
}
}
DebugState debugState;
_debugger->GetState(debugState, true);
if(_traceLogger->IsCpuLogged(_cpuType)) {
DebugState debugState;
_debugger->GetState(debugState, true);
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(_cpuType, debugState, disInfo);
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(_cpuType, debugState, disInfo);
}
uint32_t pc = (state.K << 16) | state.PC;
if(_prevOpCode == 0x20 || _prevOpCode == 0x22 || _prevOpCode == 0xFC) {
@ -138,7 +146,7 @@ void CpuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
_eventManager->AddEvent(DebugEventType::Register, operation);
}
_debugger->ProcessBreakConditions(_step->StepCount == 0, _cpuType, operation, addressInfo, breakSource);
_debugger->ProcessBreakConditions(_step->StepCount == 0, _breakpointManager.get(), operation, addressInfo, breakSource);
_scriptManager->ProcessMemoryOperation(addr, value, type);
}
@ -157,7 +165,7 @@ void CpuDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
_debugger->ProcessBreakConditions(false, _cpuType, operation, addressInfo);
_debugger->ProcessBreakConditions(false, _breakpointManager.get(), operation, addressInfo);
_scriptManager->ProcessMemoryOperation(addr, value, type);
}
@ -227,4 +235,9 @@ bool CpuDebugger::IsRegister(uint32_t addr)
shared_ptr<CallstackManager> CpuDebugger::GetCallstackManager()
{
return _callstackManager;
}
BreakpointManager* CpuDebugger::GetBreakpointManager()
{
return _breakpointManager.get();
}

View file

@ -14,6 +14,7 @@ class EmuSettings;
class ScriptManager;
class EventManager;
class MemoryMappings;
class BreakpointManager;
class Sa1;
class CpuDebugger
@ -31,6 +32,7 @@ class CpuDebugger
Sa1* _sa1;
shared_ptr<CallstackManager> _callstackManager;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
CpuType _cpuType;
@ -52,4 +54,5 @@ public:
void Step(int32_t stepCount, StepType type);
void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi);
shared_ptr<CallstackManager> GetCallstackManager();
BreakpointManager* GetBreakpointManager();
};

View file

@ -62,7 +62,6 @@ Debugger::Debugger(shared_ptr<Console> console)
_disassembler.reset(new Disassembler(console, _codeDataLogger, this));
_traceLogger.reset(new TraceLogger(this, _console));
_memoryAccessCounter.reset(new MemoryAccessCounter(this, console.get()));
_breakpointManager.reset(new BreakpointManager(this));
_ppuTools.reset(new PpuTools(_console.get(), _ppu.get()));
_eventManager.reset(new EventManager(this, _cpu.get(), _ppu.get(), _console->GetDmaController().get()));
_scriptManager.reset(new ScriptManager(this));
@ -143,7 +142,7 @@ void Debugger::ProcessWorkRamRead(uint32_t addr, uint8_t value)
AddressInfo addressInfo { (int32_t)addr, SnesMemoryType::WorkRam };
//TODO Make this more flexible/accurate
MemoryOperationInfo operation { 0x7E0000 | addr, value, MemoryOperationType::Read };
ProcessBreakConditions(false, CpuType::Cpu, operation, addressInfo);
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
}
void Debugger::ProcessWorkRamWrite(uint32_t addr, uint8_t value)
@ -151,14 +150,14 @@ void Debugger::ProcessWorkRamWrite(uint32_t addr, uint8_t value)
AddressInfo addressInfo { (int32_t)addr, SnesMemoryType::WorkRam };
//TODO Make this more flexible/accurate
MemoryOperationInfo operation { 0x7E0000 | addr, value, MemoryOperationType::Write };
ProcessBreakConditions(false, CpuType::Cpu, operation, addressInfo);
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
}
void Debugger::ProcessPpuRead(uint16_t addr, uint8_t value, SnesMemoryType memoryType)
{
AddressInfo addressInfo { addr, memoryType };
MemoryOperationInfo operation { addr, value, MemoryOperationType::Read };
ProcessBreakConditions(false, CpuType::Cpu, operation, addressInfo);
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, MemoryOperationType::Read, _memoryManager->GetMasterClock());
}
@ -167,7 +166,7 @@ void Debugger::ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memo
{
AddressInfo addressInfo { addr, memoryType };
MemoryOperationInfo operation { addr, value, MemoryOperationType::Write };
ProcessBreakConditions(false, CpuType::Cpu, operation, addressInfo);
ProcessBreakConditions(false, _cpuDebugger->GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, MemoryOperationType::Write, _memoryManager->GetMasterClock());
}
@ -189,6 +188,13 @@ void Debugger::ProcessPpuCycle()
_step->BreakScanline = -1;
SleepUntilResume(BreakSource::PpuStep);
}
//Catch up SPC/DSP as needed (if we're tracing or debugging those particular CPUs)
if(_traceLogger->IsCpuLogged(CpuType::Spc) || _settings->CheckDebuggerFlag(DebuggerFlags::SpcDebuggerEnabled)) {
_spc->Run();
} else if(_traceLogger->IsCpuLogged(CpuType::NecDsp)) {
_cart->RunCoprocessors();
}
}
void Debugger::ProcessNecDspExec(uint32_t addr, uint32_t value)
@ -260,12 +266,12 @@ void Debugger::SleepUntilResume(BreakSource source, MemoryOperationInfo *operati
_executionStopped = false;
}
void Debugger::ProcessBreakConditions(bool needBreak, CpuType cpuType, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source)
void Debugger::ProcessBreakConditions(bool needBreak, BreakpointManager* bpManager, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source)
{
if(needBreak || _breakRequestCount) {
SleepUntilResume(source);
} else {
int breakpointId = _breakpointManager->CheckBreakpoint(cpuType, operation, addressInfo);
int breakpointId = bpManager->CheckBreakpoint(operation, addressInfo);
if(breakpointId >= 0) {
SleepUntilResume(BreakSource::Breakpoint, &operation, breakpointId);
}
@ -401,11 +407,13 @@ void Debugger::GetState(DebugState &state, bool partialPpuState)
_ppu->GetState(state.Ppu, partialPpuState);
state.Spc = _spc->GetState();
for(int i = 0; i < 8; i++) {
state.DmaChannels[i] = _dmaController->GetChannelConfig(i);
if(!partialPpuState) {
for(int i = 0; i < 8; i++) {
state.DmaChannels[i] = _dmaController->GetChannelConfig(i);
}
state.InternalRegs = _internalRegs->GetState();
state.Alu = _internalRegs->GetAluState();
}
state.InternalRegs = _internalRegs->GetState();
state.Alu = _internalRegs->GetAluState();
if(_cart->GetDsp()) {
state.Dsp = _cart->GetDsp()->GetState();
@ -484,6 +492,18 @@ void Debugger::RefreshCodeCache()
}
}
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
{
_cpuDebugger->GetBreakpointManager()->SetBreakpoints(breakpoints, length);
_spcDebugger->GetBreakpointManager()->SetBreakpoints(breakpoints, length);
if(_gsuDebugger) {
_gsuDebugger->GetBreakpointManager()->SetBreakpoints(breakpoints, length);
}
if(_sa1Debugger) {
_sa1Debugger->GetBreakpointManager()->SetBreakpoints(breakpoints, length);
}
}
shared_ptr<TraceLogger> Debugger::GetTraceLogger()
{
return _traceLogger;
@ -509,11 +529,6 @@ shared_ptr<Disassembler> Debugger::GetDisassembler()
return _disassembler;
}
shared_ptr<BreakpointManager> Debugger::GetBreakpointManager()
{
return _breakpointManager;
}
shared_ptr<PpuTools> Debugger::GetPpuTools()
{
return _ppuTools;

View file

@ -30,6 +30,7 @@ class ScriptManager;
class SpcDebugger;
class CpuDebugger;
class GsuDebugger;
class Breakpoint;
enum class EventType;
enum class EvalResultType : int32_t;
@ -58,7 +59,6 @@ private:
shared_ptr<MemoryAccessCounter> _memoryAccessCounter;
shared_ptr<CodeDataLogger> _codeDataLogger;
shared_ptr<Disassembler> _disassembler;
shared_ptr<BreakpointManager> _breakpointManager;
shared_ptr<PpuTools> _ppuTools;
shared_ptr<EventManager> _eventManager;
shared_ptr<LabelManager> _labelManager;
@ -111,7 +111,7 @@ public:
void BreakRequest(bool release);
void SuspendDebugger(bool release);
void ProcessBreakConditions(bool needBreak, CpuType cpuType, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source = BreakSource::Unspecified);
void ProcessBreakConditions(bool needBreak, BreakpointManager *bpManager, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source = BreakSource::Unspecified);
void GetState(DebugState &state, bool partialPpuState);
@ -121,12 +121,13 @@ public:
void SetCdlData(uint8_t * cdlData, uint32_t length);
void RefreshCodeCache();
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
shared_ptr<TraceLogger> GetTraceLogger();
shared_ptr<MemoryDumper> GetMemoryDumper();
shared_ptr<MemoryAccessCounter> GetMemoryAccessCounter();
shared_ptr<CodeDataLogger> GetCodeDataLogger();
shared_ptr<Disassembler> GetDisassembler();
shared_ptr<BreakpointManager> GetBreakpointManager();
shared_ptr<PpuTools> GetPpuTools();
shared_ptr<EventManager> GetEventManager();
shared_ptr<LabelManager> GetLabelManager();

View file

@ -6,9 +6,12 @@
#include "Gsu.h"
#include "TraceLogger.h"
#include "CallstackManager.h"
#include "BreakpointManager.h"
#include "ExpressionEvaluator.h"
#include "MemoryManager.h"
#include "Debugger.h"
#include "Console.h"
#include "EmuSettings.h"
#include "MemoryAccessCounter.h"
GsuDebugger::GsuDebugger(Debugger* debugger)
@ -19,7 +22,9 @@ GsuDebugger::GsuDebugger(Debugger* debugger)
_memoryAccessCounter = debugger->GetMemoryAccessCounter().get();
_gsu = debugger->GetConsole()->GetCartridge()->GetGsu();
_memoryManager = debugger->GetConsole()->GetMemoryManager().get();
_settings = debugger->GetConsole()->GetSettings().get();
_breakpointManager.reset(new BreakpointManager(debugger, CpuType::Gsu));
_step.reset(new StepRequest());
}
@ -39,15 +44,20 @@ void GsuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
MemoryOperationInfo operation { addr, value, type };
if(type == MemoryOperationType::ExecOpCode) {
DebugState debugState;
_debugger->GetState(debugState, true);
if(_traceLogger->IsCpuLogged(CpuType::Gsu) || _settings->CheckDebuggerFlag(DebuggerFlags::GsuDebuggerEnabled)) {
GsuState gsuState = _gsu->GetState();
_disassembler->BuildCache(addressInfo, gsuState.SFR.GetFlagsHigh() & 0x13, CpuType::Gsu);
_disassembler->BuildCache(addressInfo, debugState.Gsu.SFR.GetFlagsHigh() & 0x13, CpuType::Gsu);
debugState.Gsu.R[15] = addr;
if(_traceLogger->IsCpuLogged(CpuType::Gsu)) {
DebugState debugState;
_debugger->GetState(debugState, true);
debugState.Gsu.R[15] = addr;
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(CpuType::Gsu, debugState, disInfo);
}
}
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(CpuType::Gsu, debugState, disInfo);
_prevOpCode = value;
_prevProgramCounter = addr;
@ -56,7 +66,7 @@ void GsuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
}
_debugger->ProcessBreakConditions(_step->StepCount == 0, CpuType::Gsu, operation, addressInfo);
_debugger->ProcessBreakConditions(_step->StepCount == 0, GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
}
@ -65,7 +75,7 @@ void GsuDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType
{
AddressInfo addressInfo = _gsu->GetMemoryMappings()->GetAbsoluteAddress(addr);
MemoryOperationInfo operation { addr, value, type };
_debugger->ProcessBreakConditions(false, CpuType::Gsu, operation, addressInfo);
_debugger->ProcessBreakConditions(false, GetBreakpointManager(), operation, addressInfo);
_disassembler->InvalidateCache(addressInfo, CpuType::Gsu);
@ -93,3 +103,8 @@ void GsuDebugger::Step(int32_t stepCount, StepType type)
_step.reset(new StepRequest(step));
}
BreakpointManager* GsuDebugger::GetBreakpointManager()
{
return _breakpointManager.get();
}

View file

@ -8,6 +8,8 @@ class TraceLogger;
class Gsu;
class MemoryAccessCounter;
class MemoryManager;
class BreakpointManager;
class EmuSettings;
class GsuDebugger
{
@ -17,7 +19,9 @@ class GsuDebugger
MemoryAccessCounter* _memoryAccessCounter;
MemoryManager* _memoryManager;
Gsu* _gsu;
EmuSettings* _settings;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
uint8_t _prevOpCode = 0xFF;
@ -32,4 +36,6 @@ public:
void ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type);
void Run();
void Step(int32_t stepCount, StepType type);
BreakpointManager* GetBreakpointManager();
};

View file

@ -99,7 +99,13 @@ uint16_t Ppu::GetCycle()
{
//"normally dots 323 and 327 are 6 master cycles instead of 4."
uint16_t hClock = _memoryManager->GetHClock();
return (hClock - ((hClock > 1292) << 1) - ((hClock > 1310) << 1)) >> 2;
if(hClock <= 1292) {
return hClock >> 2;
} else if(hClock <= 1310) {
return (hClock >> 2) + 1;
} else {
return (hClock >> 2) + 2;
}
}
uint16_t Ppu::GetNmiScanline()

View file

@ -5,10 +5,13 @@
#include "Spc.h"
#include "TraceLogger.h"
#include "CallstackManager.h"
#include "BreakpointManager.h"
#include "MemoryManager.h"
#include "Debugger.h"
#include "Console.h"
#include "MemoryAccessCounter.h"
#include "ExpressionEvaluator.h"
#include "EmuSettings.h"
SpcDebugger::SpcDebugger(Debugger* debugger)
{
@ -18,8 +21,10 @@ SpcDebugger::SpcDebugger(Debugger* debugger)
_memoryAccessCounter = debugger->GetMemoryAccessCounter().get();
_spc = debugger->GetConsole()->GetSpc().get();
_memoryManager = debugger->GetConsole()->GetMemoryManager().get();
_settings = debugger->GetConsole()->GetSettings().get();
_callstackManager.reset(new CallstackManager(debugger));
_breakpointManager.reset(new BreakpointManager(debugger, CpuType::Spc));
_step.reset(new StepRequest());
}
@ -39,38 +44,44 @@ void SpcDebugger::ProcessRead(uint16_t addr, uint8_t value, MemoryOperationType
MemoryOperationInfo operation { addr, value, type };
if(type == MemoryOperationType::ExecOpCode) {
_disassembler->BuildCache(addressInfo, 0, CpuType::Spc);
SpcState spcState = _spc->GetState();
DebugState debugState;
_debugger->GetState(debugState, true);
if(_traceLogger->IsCpuLogged(CpuType::Spc) || _settings->CheckDebuggerFlag(DebuggerFlags::SpcDebuggerEnabled)) {
_disassembler->BuildCache(addressInfo, 0, CpuType::Spc);
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(CpuType::Spc, debugState, disInfo);
if(_traceLogger->IsCpuLogged(CpuType::Spc)) {
DebugState debugState;
_debugger->GetState(debugState, true);
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(CpuType::Spc, debugState, disInfo);
}
}
if(_prevOpCode == 0x3F || _prevOpCode == 0x0F) {
//JSR, BRK
uint8_t opSize = DisassemblyInfo::GetOpSize(_prevOpCode, 0, CpuType::Spc);
uint16_t returnPc = _prevProgramCounter + opSize;
_callstackManager->Push(_prevProgramCounter, debugState.Spc.PC, returnPc, StackFrameFlags::None);
_callstackManager->Push(_prevProgramCounter, spcState.PC, returnPc, StackFrameFlags::None);
} else if(_prevOpCode == 0x6F || _prevOpCode == 0x7F) {
//RTS, RTI
_callstackManager->Pop(debugState.Spc.PC);
_callstackManager->Pop(spcState.PC);
}
if(_step->BreakAddress == (int32_t)debugState.Spc.PC && (_prevOpCode == 0x6F || _prevOpCode == 0x7F)) {
if(_step->BreakAddress == (int32_t)spcState.PC && (_prevOpCode == 0x6F || _prevOpCode == 0x7F)) {
//RTS/RTI found, if we're on the expected return address, break immediately (for step over/step out)
_step->StepCount = 0;
}
_prevOpCode = value;
_prevProgramCounter = debugState.Spc.PC;
_prevProgramCounter = spcState.PC;
if(_step->StepCount > 0) {
_step->StepCount--;
}
}
_debugger->ProcessBreakConditions(_step->StepCount == 0, CpuType::Spc, operation, addressInfo);
_debugger->ProcessBreakConditions(_step->StepCount == 0, GetBreakpointManager(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
}
@ -79,7 +90,7 @@ void SpcDebugger::ProcessWrite(uint16_t addr, uint8_t value, MemoryOperationType
{
AddressInfo addressInfo { addr, SnesMemoryType::SpcRam }; //Writes never affect the SPC ROM
MemoryOperationInfo operation { addr, value, type };
_debugger->ProcessBreakConditions(false, CpuType::Spc, operation, addressInfo);
_debugger->ProcessBreakConditions(false, GetBreakpointManager(), operation, addressInfo);
_disassembler->InvalidateCache(addressInfo, CpuType::Spc);
@ -119,4 +130,9 @@ void SpcDebugger::Step(int32_t stepCount, StepType type)
shared_ptr<CallstackManager> SpcDebugger::GetCallstackManager()
{
return _callstackManager;
}
BreakpointManager* SpcDebugger::GetBreakpointManager()
{
return _breakpointManager.get();
}

View file

@ -9,6 +9,8 @@ class Spc;
class CallstackManager;
class MemoryAccessCounter;
class MemoryManager;
class BreakpointManager;
class EmuSettings;
class SpcDebugger
{
@ -18,8 +20,10 @@ class SpcDebugger
MemoryAccessCounter* _memoryAccessCounter;
MemoryManager* _memoryManager;
Spc* _spc;
EmuSettings* _settings;
shared_ptr<CallstackManager> _callstackManager;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
uint8_t _prevOpCode = 0xFF;
@ -35,4 +39,5 @@ public:
void Run();
void Step(int32_t stepCount, StepType type);
shared_ptr<CallstackManager> GetCallstackManager();
BreakpointManager* GetBreakpointManager();
};

View file

@ -56,7 +56,7 @@ extern "C"
DllExport void __stdcall ClearTraceLog() { GetDebugger()->GetTraceLogger()->Clear(); }
DllExport const char* GetExecutionTrace(uint32_t lineCount) { return GetDebugger()->GetTraceLogger()->GetExecutionTrace(lineCount); }
DllExport void __stdcall SetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->GetBreakpointManager()->SetBreakpoints(breakpoints, length); }
DllExport void __stdcall SetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->SetBreakpoints(breakpoints, length); }
DllExport int32_t __stdcall EvaluateExpression(char* expression, CpuType cpuType, EvalResultType *resultType, bool useCache) { return GetDebugger()->EvaluateExpression(expression, cpuType, *resultType, useCache); }
DllExport void __stdcall GetCallstack(CpuType cpuType, StackFrameInfo *callstackArray, uint32_t &callstackSize) { GetDebugger()->GetCallstackManager(cpuType)->GetCallstack(callstackArray, callstackSize); }

View file

@ -34,6 +34,7 @@ endif
GCCOPTIONS=-fPIC -Wall --std=c++14 -O3 $(MESENFLAGS)
CCOPTIONS=-fPIC -Wall -O3 $(MESENFLAGS)
LINKOPTIONS=
ifeq ($(MESENPLATFORM),x86)
MESENPLATFORM=x86
@ -61,6 +62,10 @@ ifeq ($(PGO),optimize)
GCCOPTIONS += ${PROFILE_USE_FLAG}
endif
ifeq ($(STATICLINK),true)
LINKOPTIONS += -static-libgcc -static-libstdc++
endif
OBJFOLDER=obj.$(MESENPLATFORM)
SHAREDLIB=libMesenSCore.$(MESENPLATFORM).dll
LIBRETROLIB=mesen-s_libretro.$(MESENPLATFORM).so
@ -139,14 +144,14 @@ InteropDLL/$(OBJFOLDER)/%.o: InteropDLL/%.cpp
InteropDLL/$(OBJFOLDER)/$(SHAREDLIB): $(SEVENZIPOBJ) $(LUAOBJ) $(UTILOBJ) $(COREOBJ) $(LIBEVDEVOBJ) $(LINUXOBJ) $(DLLOBJ)
mkdir -p bin
mkdir -p InteropDLL/$(OBJFOLDER)
$(CPPC) $(GCCOPTIONS) -Wl,-z,defs -shared -o $(SHAREDLIB) $(DLLOBJ) $(SEVENZIPOBJ) $(LUAOBJ) $(LINUXOBJ) $(LIBEVDEVOBJ) $(UTILOBJ) $(COREOBJ) $(SDL2INC) -pthread $(FSLIB) $(SDL2LIB) $(LIBEVDEVLIB)
$(CPPC) $(GCCOPTIONS) $(LINKOPTIONS) -Wl,-z,defs -shared -o $(SHAREDLIB) $(DLLOBJ) $(SEVENZIPOBJ) $(LUAOBJ) $(LINUXOBJ) $(LIBEVDEVOBJ) $(UTILOBJ) $(COREOBJ) $(SDL2INC) -pthread $(FSLIB) $(SDL2LIB) $(LIBEVDEVLIB)
cp $(SHAREDLIB) bin/pgohelperlib.so
mv $(SHAREDLIB) InteropDLL/$(OBJFOLDER)
Libretro/$(OBJFOLDER)/$(LIBRETROLIB): $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) Libretro/libretro.cpp
mkdir -p bin
mkdir -p Libretro/$(OBJFOLDER)
$(CPPC) $(GCCOPTIONS) -Wl,-z,defs -shared -o $(LIBRETROLIB) Libretro/*.cpp $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) -pthread
$(CPPC) $(GCCOPTIONS) $(LINKOPTIONS) -Wl,-z,defs -shared -o $(LIBRETROLIB) Libretro/*.cpp $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) -pthread
cp $(LIBRETROLIB) bin/pgohelperlib.so
mv $(LIBRETROLIB) Libretro/$(OBJFOLDER)