mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Debugger: SPC - Invalidate instruction cache on writes even when option to ignore read/writes is turned on
This commit is contained in:
parent
ef1023ed1f
commit
7ca3ae781e
7 changed files with 80 additions and 44 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -12,4 +12,10 @@ enum class MemoryOperationType
|
|||
DummyWrite = 7,
|
||||
PpuRenderingRead = 8,
|
||||
Idle = 9
|
||||
};
|
||||
|
||||
enum class MemoryAccessFlags
|
||||
{
|
||||
None = 0,
|
||||
DspAccess = 1,
|
||||
};
|
Loading…
Add table
Reference in a new issue