Debugger: SPC - Invalidate instruction cache on writes even when option to ignore read/writes is turned on

This commit is contained in:
Sour 2023-01-29 18:35:06 -05:00
parent ef1023ed1f
commit 7ca3ae781e
7 changed files with 80 additions and 44 deletions

View file

@ -215,7 +215,7 @@ void Debugger::ProcessInstruction()
}
}
template<CpuType type, typename T>
template<CpuType type, MemoryAccessFlags flags, typename T>
void Debugger::ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType)
{
if(_debuggers[(int)type].Debugger->IsStepBack()) {
@ -225,7 +225,7 @@ void Debugger::ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType op
switch(type) {
case CpuType::Snes: GetDebugger<type, SnesDebugger>()->ProcessRead(addr, value, opType); break;
case CpuType::Spc: GetDebugger<type, SpcDebugger>()->ProcessRead(addr, value, opType); break;
case CpuType::Spc: GetDebugger<type, SpcDebugger>()->ProcessRead<flags>(addr, value, opType); break;
case CpuType::NecDsp: GetDebugger<type, NecDspDebugger>()->ProcessRead(addr, value, opType); break;
case CpuType::Sa1: GetDebugger<type, SnesDebugger>()->ProcessRead(addr, value, opType); break;
case CpuType::Gsu: GetDebugger<type, GsuDebugger>()->ProcessRead(addr, value, opType); break;
@ -240,7 +240,7 @@ void Debugger::ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType op
}
}
template<CpuType type, typename T>
template<CpuType type, MemoryAccessFlags flags, typename T>
bool Debugger::ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
{
if(_debuggers[(int)type].Debugger->IsStepBack()) {
@ -250,7 +250,7 @@ bool Debugger::ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType o
switch(type) {
case CpuType::Snes: GetDebugger<type, SnesDebugger>()->ProcessWrite(addr, value, opType); break;
case CpuType::Spc: GetDebugger<type, SpcDebugger>()->ProcessWrite(addr, value, opType); break;
case CpuType::Spc: GetDebugger<type, SpcDebugger>()->ProcessWrite<flags>(addr, value, opType); break;
case CpuType::NecDsp: GetDebugger<type, NecDspDebugger>()->ProcessWrite(addr, value, opType); break;
case CpuType::Sa1: GetDebugger<type, SnesDebugger>()->ProcessWrite(addr, value, opType); break;
case CpuType::Gsu: GetDebugger<type, GsuDebugger>()->ProcessWrite(addr, value, opType); break;
@ -1010,6 +1010,7 @@ template void Debugger::ProcessInstruction<CpuType::Pce>();
template void Debugger::ProcessMemoryRead<CpuType::Snes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Sa1>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Spc>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Spc, MemoryAccessFlags::DspAccess>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Gsu>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::NecDsp>(uint32_t addr, uint32_t& value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::NecDsp>(uint32_t addr, uint16_t& value, MemoryOperationType opType);
@ -1021,6 +1022,7 @@ template void Debugger::ProcessMemoryRead<CpuType::Pce>(uint32_t addr, uint8_t&
template bool Debugger::ProcessMemoryWrite<CpuType::Snes>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template bool Debugger::ProcessMemoryWrite<CpuType::Sa1>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template bool Debugger::ProcessMemoryWrite<CpuType::Spc>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template bool Debugger::ProcessMemoryWrite<CpuType::Spc, MemoryAccessFlags::DspAccess>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template bool Debugger::ProcessMemoryWrite<CpuType::Gsu>(uint32_t addr, uint8_t& value, MemoryOperationType opType);
template bool Debugger::ProcessMemoryWrite<CpuType::NecDsp>(uint32_t addr, uint16_t& value, MemoryOperationType opType);
template bool Debugger::ProcessMemoryWrite<CpuType::Cx4>(uint32_t addr, uint8_t& value, MemoryOperationType opType);

View file

@ -105,8 +105,8 @@ public:
void Release();
template<CpuType type> void ProcessInstruction();
template<CpuType type, typename T> void ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType);
template<CpuType type, typename T> bool ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType);
template<CpuType type, MemoryAccessFlags flags = MemoryAccessFlags::None, typename T> void ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType);
template<CpuType type, MemoryAccessFlags flags = MemoryAccessFlags::None, typename T> bool ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType);
template<CpuType type> void ProcessIdleCycle();
template<CpuType type> void ProcessHaltedCpu();
template<CpuType type, typename T> void ProcessPpuRead(uint16_t addr, T& value, MemoryType memoryType, MemoryOperationType opType);

View file

@ -47,6 +47,7 @@ void SpcDebugger::ProcessConfigChange()
{
_debuggerEnabled = _settings->CheckDebuggerFlag(DebuggerFlags::SpcDebuggerEnabled);
_predictiveBreakpoints = _settings->GetDebugConfig().UsePredictiveBreakpoints;
_ignoreDspReadWrites = _settings->GetDebugConfig().SnesIgnoreDspReadWrites;
}
void SpcDebugger::ProcessInstruction()
@ -105,45 +106,69 @@ void SpcDebugger::ProcessInstruction()
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
}
template<MemoryAccessFlags flags>
void SpcDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType type)
{
AddressInfo addressInfo = _spc->GetAbsoluteAddress(addr);
MemoryOperationInfo operation(addr, value, type, MemoryType::SpcMemory);
if constexpr(flags == MemoryAccessFlags::None) {
//SPC read
AddressInfo addressInfo = _spc->GetAbsoluteAddress(addr);
MemoryOperationInfo operation(addr, value, type, MemoryType::SpcMemory);
if(type == MemoryOperationType::ExecOpCode) {
if(_traceLogger->IsEnabled()) {
SpcState& state = _spc->GetState();
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Spc);
_traceLogger->Log(state, disInfo, operation, addressInfo);
if(type == MemoryOperationType::ExecOpCode) {
if(_traceLogger->IsEnabled()) {
SpcState& state = _spc->GetState();
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Spc);
_traceLogger->Log(state, disInfo, operation, addressInfo);
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
if(_traceLogger->IsEnabled()) {
_traceLogger->LogNonExec(operation, addressInfo);
}
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
} else {
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
if(_traceLogger->IsEnabled()) {
_traceLogger->LogNonExec(operation, addressInfo);
}
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
if(_traceLogger->IsEnabled()) {
_traceLogger->LogNonExec(operation, addressInfo);
}
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
} else {
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
if(_traceLogger->IsEnabled()) {
_traceLogger->LogNonExec(operation, addressInfo);
//DSP read
if(!_ignoreDspReadWrites) {
AddressInfo addressInfo { (int32_t)addr, MemoryType::SpcRam }; //DSP reads never read from the IPL ROM
MemoryOperationInfo operation(addr, value, type, MemoryType::SpcMemory);
_memoryAccessCounter->ProcessMemoryRead(addressInfo, _memoryManager->GetMasterClock());
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
}
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
}
}
template<MemoryAccessFlags flags>
void SpcDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type)
{
AddressInfo addressInfo { (int32_t)addr, MemoryType::SpcRam }; //Writes never affect the SPC ROM
AddressInfo addressInfo { (int32_t)addr, MemoryType::SpcRam }; //Writes never affect the IPL ROM
MemoryOperationInfo operation(addr, value, type, MemoryType::SpcMemory);
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
//Always invalidate cache, even if DSP writes are ignored
_disassembler->InvalidateCache(addressInfo, CpuType::Spc);
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
if(_traceLogger->IsEnabled()) {
_traceLogger->LogNonExec(operation, addressInfo);
if constexpr(flags == MemoryAccessFlags::None) {
//SPC write
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
if(_traceLogger->IsEnabled()) {
_traceLogger->LogNonExec(operation, addressInfo);
}
} else {
//DSP write
if(!_ignoreDspReadWrites) {
_debugger->ProcessBreakConditions(CpuType::Spc, *_step.get(), _breakpointManager.get(), operation, addressInfo);
_memoryAccessCounter->ProcessMemoryWrite(addressInfo, _memoryManager->GetMasterClock());
}
}
}
@ -232,3 +257,9 @@ ITraceLogger* SpcDebugger::GetTraceLogger()
{
return _traceLogger.get();
}
template void SpcDebugger::ProcessRead<MemoryAccessFlags::None>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void SpcDebugger::ProcessRead<MemoryAccessFlags::DspAccess>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void SpcDebugger::ProcessWrite<MemoryAccessFlags::None>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void SpcDebugger::ProcessWrite<MemoryAccessFlags::DspAccess>(uint32_t addr, uint8_t value, MemoryOperationType opType);

View file

@ -35,6 +35,7 @@ class SpcDebugger final : public IDebugger
bool _debuggerEnabled = false;
bool _predictiveBreakpoints = false;
bool _ignoreDspReadWrites = false;
public:
SpcDebugger(Debugger* debugger);
@ -44,7 +45,11 @@ public:
void ProcessConfigChange() override;
void ProcessInstruction();
template<MemoryAccessFlags flags>
void ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType type);
template<MemoryAccessFlags flags>
void ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type);
void Run() override;

View file

@ -348,11 +348,7 @@ uint8_t Spc::DspReadRam(uint16_t addr)
{
uint8_t value = _ram[addr];
#ifndef DUMMYSPC
if(_emu->IsDebugging()) {
if(!_emu->GetSettings()->GetDebugConfig().SnesIgnoreDspReadWrites) {
_emu->ProcessMemoryRead<CpuType::Spc>(addr, value, MemoryOperationType::Read);
}
}
_emu->ProcessMemoryRead<CpuType::Spc, MemoryAccessFlags::DspAccess>(addr, value, MemoryOperationType::Read);
#endif
return value;
}
@ -360,11 +356,7 @@ uint8_t Spc::DspReadRam(uint16_t addr)
void Spc::DspWriteRam(uint16_t addr, uint8_t value)
{
#ifndef DUMMYSPC
if(_emu->IsDebugging()) {
if(!_emu->GetSettings()->GetDebugConfig().SnesIgnoreDspReadWrites) {
_emu->ProcessMemoryWrite<CpuType::Spc>(addr, value, MemoryOperationType::Write);
}
}
_emu->ProcessMemoryWrite<CpuType::Spc, MemoryAccessFlags::DspAccess>(addr, value, MemoryOperationType::Write);
#endif
_ram[addr] = value;
}

View file

@ -246,17 +246,17 @@ public:
}
}
template<CpuType type, typename T> __forceinline void ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType)
template<CpuType type, MemoryAccessFlags flags = MemoryAccessFlags::None, typename T> __forceinline void ProcessMemoryRead(uint32_t addr, T& value, MemoryOperationType opType)
{
if(_debugger) {
_debugger->ProcessMemoryRead<type>(addr, value, opType);
_debugger->ProcessMemoryRead<type, flags>(addr, value, opType);
}
}
template<CpuType type, typename T> __forceinline bool ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
template<CpuType type, MemoryAccessFlags flags = MemoryAccessFlags::None, typename T> __forceinline bool ProcessMemoryWrite(uint32_t addr, T& value, MemoryOperationType opType)
{
if(_debugger) {
return _debugger->ProcessMemoryWrite<type>(addr, value, opType);
return _debugger->ProcessMemoryWrite<type, flags>(addr, value, opType);
}
return true;
}

View file

@ -12,4 +12,10 @@ enum class MemoryOperationType
DummyWrite = 7,
PpuRenderingRead = 8,
Idle = 9
};
enum class MemoryAccessFlags
{
None = 0,
DspAccess = 1,
};