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:
parent
8a8a1e01e7
commit
7ae6605e77
14 changed files with 177 additions and 80 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -718,8 +718,6 @@ void Console::ProcessPpuCycle()
|
|||
{
|
||||
if(_debugger) {
|
||||
_debugger->ProcessPpuCycle();
|
||||
_spc->Run();
|
||||
_cart->RunCoprocessors();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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); }
|
||||
|
||||
|
|
9
makefile
9
makefile
|
@ -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)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue