mirror of
https://github.com/libretro/Mesen.git
synced 2025-02-08 01:59:51 +00:00
Debugger: Improved performance (games run about 50% faster with debugger opened compared to before)
This commit is contained in:
parent
5a24608f8f
commit
cf24fdc1d0
@ -15,9 +15,17 @@ bool Breakpoint::Matches(uint32_t memoryAddr, uint32_t absoluteAddr)
|
||||
return _addr == -1 || ((int32_t)memoryAddr == _addr && !_isAbsoluteAddr) || ((int32_t)absoluteAddr == _addr && _isAbsoluteAddr);
|
||||
}
|
||||
|
||||
BreakpointType Breakpoint::GetType()
|
||||
bool Breakpoint::HasBreakpointType(BreakpointType type)
|
||||
{
|
||||
return _type;
|
||||
switch(type) {
|
||||
case BreakpointType::Global: return (_type == BreakpointTypeFlags::Global);
|
||||
case BreakpointType::Execute: return (_type & BreakpointTypeFlags::Execute) == BreakpointTypeFlags::Execute;
|
||||
case BreakpointType::ReadRam: return (_type & BreakpointTypeFlags::ReadRam) == BreakpointTypeFlags::ReadRam;
|
||||
case BreakpointType::WriteRam: return (_type & BreakpointTypeFlags::WriteRam) == BreakpointTypeFlags::WriteRam;
|
||||
case BreakpointType::ReadVram: return (_type & BreakpointTypeFlags::ReadVram) == BreakpointTypeFlags::ReadVram;
|
||||
case BreakpointType::WriteVram: return (_type & BreakpointTypeFlags::WriteVram) == BreakpointTypeFlags::WriteVram;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
string Breakpoint::GetCondition()
|
||||
|
@ -7,24 +7,35 @@ enum BreakpointType
|
||||
Global = 0,
|
||||
Execute = 1,
|
||||
ReadRam = 2,
|
||||
WriteRam = 4,
|
||||
ReadVram = 8,
|
||||
WriteVram = 16,
|
||||
WriteRam = 3,
|
||||
ReadVram = 4,
|
||||
WriteVram = 5,
|
||||
};
|
||||
|
||||
class Breakpoint
|
||||
{
|
||||
private:
|
||||
enum BreakpointTypeFlags
|
||||
{
|
||||
Global = 0,
|
||||
Execute = 1,
|
||||
ReadRam = 2,
|
||||
WriteRam = 4,
|
||||
ReadVram = 8,
|
||||
WriteVram = 16,
|
||||
};
|
||||
|
||||
public:
|
||||
Breakpoint();
|
||||
~Breakpoint();
|
||||
|
||||
bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr);
|
||||
BreakpointType GetType();
|
||||
bool HasBreakpointType(BreakpointType type);
|
||||
string GetCondition();
|
||||
void ClearCondition();
|
||||
|
||||
private:
|
||||
BreakpointType _type;
|
||||
BreakpointTypeFlags _type;
|
||||
int32_t _addr;
|
||||
bool _isAbsoluteAddr;
|
||||
char _condition[1000];
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "ExpressionEvaluator.h"
|
||||
|
||||
Debugger* Debugger::Instance = nullptr;
|
||||
const int Debugger::BreakpointTypeCount;
|
||||
|
||||
Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper)
|
||||
{
|
||||
@ -32,7 +33,6 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
|
||||
|
||||
_flags = 0;
|
||||
|
||||
_hasBreakpoint = false;
|
||||
_bpUpdateNeeded = false;
|
||||
_executionStopped = false;
|
||||
|
||||
@ -121,27 +121,37 @@ CdlRatios Debugger::GetCdlRatios()
|
||||
|
||||
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
||||
{
|
||||
_hasBreakpoint = length > 0;
|
||||
|
||||
while(_updatingBreakpoints) { }
|
||||
_bpUpdateLock.AcquireSafe();
|
||||
|
||||
_newBreakpoints.clear();
|
||||
_newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length);
|
||||
_bpUpdateNeeded = true;
|
||||
|
||||
if(_executionStopped) {
|
||||
UpdateBreakpoints();
|
||||
} else {
|
||||
bool hasBreakpoint[Debugger::BreakpointTypeCount]{ false,false,false,false,false,false };
|
||||
for(Breakpoint &bp : _newBreakpoints) {
|
||||
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
|
||||
hasBreakpoint[i] |= bp.HasBreakpointType((BreakpointType)i);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
|
||||
_hasBreakpoint[i] = hasBreakpoint[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::UpdateBreakpoints()
|
||||
{
|
||||
_updatingBreakpoints = true;
|
||||
if(_bpUpdateNeeded) {
|
||||
_globalBreakpoints.clear();
|
||||
_execBreakpoints.clear();
|
||||
_readBreakpoints.clear();
|
||||
_writeBreakpoints.clear();
|
||||
_readVramBreakpoints.clear();
|
||||
_writeVramBreakpoints.clear();
|
||||
_bpUpdateLock.AcquireSafe();
|
||||
|
||||
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
|
||||
_breakpoints[i].clear();
|
||||
_hasBreakpoint[i] = false;
|
||||
}
|
||||
|
||||
ExpressionEvaluator expEval;
|
||||
for(Breakpoint &bp : _newBreakpoints) {
|
||||
@ -150,31 +160,16 @@ void Debugger::UpdateBreakpoints()
|
||||
bp.ClearCondition();
|
||||
}
|
||||
|
||||
BreakpointType type = bp.GetType();
|
||||
if(type & BreakpointType::Execute) {
|
||||
_execBreakpoints.push_back(bp);
|
||||
}
|
||||
if(type & BreakpointType::ReadRam) {
|
||||
_readBreakpoints.push_back(bp);
|
||||
}
|
||||
if(type & BreakpointType::ReadVram) {
|
||||
_readVramBreakpoints.push_back(bp);
|
||||
}
|
||||
if(type & BreakpointType::WriteRam) {
|
||||
_writeBreakpoints.push_back(bp);
|
||||
}
|
||||
if(type & BreakpointType::WriteVram) {
|
||||
_writeVramBreakpoints.push_back(bp);
|
||||
}
|
||||
if(type == BreakpointType::Global) {
|
||||
_globalBreakpoints.push_back(bp);
|
||||
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
|
||||
if(bp.HasBreakpointType((BreakpointType)i)) {
|
||||
_breakpoints[i].push_back(bp);
|
||||
_hasBreakpoint[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bpUpdateNeeded = false;
|
||||
}
|
||||
|
||||
_updatingBreakpoints = false;
|
||||
}
|
||||
|
||||
bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value)
|
||||
@ -182,20 +177,11 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
|
||||
UpdateBreakpoints();
|
||||
|
||||
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
|
||||
vector<Breakpoint> *breakpoints = nullptr;
|
||||
|
||||
switch(type) {
|
||||
case BreakpointType::Global: breakpoints = &_globalBreakpoints; break;
|
||||
case BreakpointType::Execute: breakpoints = &_execBreakpoints; break;
|
||||
case BreakpointType::ReadRam: breakpoints = &_readBreakpoints; break;
|
||||
case BreakpointType::WriteRam: breakpoints = &_writeBreakpoints; break;
|
||||
case BreakpointType::ReadVram: breakpoints = &_readVramBreakpoints; break;
|
||||
case BreakpointType::WriteVram: breakpoints = &_writeVramBreakpoints; break;
|
||||
}
|
||||
vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
|
||||
|
||||
bool needState = true;
|
||||
for(size_t i = 0, len = breakpoints->size(); i < len; i++) {
|
||||
Breakpoint &breakpoint = (*breakpoints)[i];
|
||||
for(size_t i = 0, len = breakpoints.size(); i < len; i++) {
|
||||
Breakpoint &breakpoint = breakpoints[i];
|
||||
if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) {
|
||||
string condition = breakpoint.GetCondition();
|
||||
if(condition.empty()) {
|
||||
@ -259,7 +245,7 @@ void Debugger::ProcessStepConditions(uint32_t addr)
|
||||
|
||||
void Debugger::PrivateProcessPpuCycle()
|
||||
{
|
||||
if(_hasBreakpoint && HasMatchingBreakpoint(BreakpointType::Global, 0, -1)) {
|
||||
if(_hasBreakpoint[BreakpointType::Global] && HasMatchingBreakpoint(BreakpointType::Global, 0, -1)) {
|
||||
//Found a matching breakpoint, stop execution
|
||||
Step(1);
|
||||
SleepUntilResume();
|
||||
@ -316,32 +302,21 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
|
||||
}
|
||||
}
|
||||
|
||||
if(!breakDone && _hasBreakpoint) {
|
||||
BreakOnBreakpoint(type, addr, value);
|
||||
}
|
||||
|
||||
_currentReadAddr = nullptr;
|
||||
}
|
||||
|
||||
void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value)
|
||||
{
|
||||
if(_hasBreakpoint) {
|
||||
BreakpointType breakpointType;
|
||||
if(!breakDone) {
|
||||
BreakpointType breakpointType = BreakpointType::Execute;
|
||||
switch(type) {
|
||||
case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break;
|
||||
case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break;
|
||||
|
||||
default:
|
||||
case MemoryOperationType::ExecOpCode:
|
||||
case MemoryOperationType::ExecOperand: breakpointType = BreakpointType::Execute; break;
|
||||
}
|
||||
|
||||
if(HasMatchingBreakpoint(breakpointType, addr, (type == MemoryOperationType::ExecOperand) ? -1 : value)) {
|
||||
if(_hasBreakpoint[breakpointType] && HasMatchingBreakpoint(breakpointType, addr, (type == MemoryOperationType::ExecOperand) ? -1 : value)) {
|
||||
//Found a matching breakpoint, stop execution
|
||||
Step(1);
|
||||
SleepUntilResume();
|
||||
}
|
||||
}
|
||||
|
||||
_currentReadAddr = nullptr;
|
||||
}
|
||||
|
||||
bool Debugger::SleepUntilResume()
|
||||
@ -379,7 +354,8 @@ void Debugger::PrivateProcessVramOperation(MemoryOperationType type, uint16_t ad
|
||||
_codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
|
||||
}
|
||||
|
||||
if(_hasBreakpoint && HasMatchingBreakpoint(type == MemoryOperationType::Write ? BreakpointType::WriteVram : BreakpointType::ReadVram, addr, value)) {
|
||||
BreakpointType bpType = type == MemoryOperationType::Write ? BreakpointType::WriteVram : BreakpointType::ReadVram;
|
||||
if(_hasBreakpoint[bpType] && HasMatchingBreakpoint(bpType, addr, value)) {
|
||||
//Found a matching breakpoint, stop execution
|
||||
Step(1);
|
||||
SleepUntilResume();
|
||||
|
@ -50,6 +50,8 @@ class Debugger
|
||||
private:
|
||||
static Debugger* Instance;
|
||||
|
||||
const static int BreakpointTypeCount = 6;
|
||||
|
||||
unique_ptr<Disassembler> _disassembler;
|
||||
unique_ptr<CodeDataLogger> _codeDataLogger;
|
||||
shared_ptr<Console> _console;
|
||||
@ -58,19 +60,15 @@ private:
|
||||
shared_ptr<MemoryManager> _memoryManager;
|
||||
shared_ptr<BaseMapper> _mapper;
|
||||
|
||||
atomic<bool> _bpUpdateNeeded;
|
||||
atomic<bool> _updatingBreakpoints;
|
||||
bool _bpUpdateNeeded;
|
||||
SimpleLock _bpUpdateLock;
|
||||
|
||||
atomic<bool> _stopFlag;
|
||||
atomic<bool> _executionStopped;
|
||||
atomic<int32_t> _suspendCount;
|
||||
vector<Breakpoint> _newBreakpoints;
|
||||
vector<Breakpoint> _readBreakpoints;
|
||||
vector<Breakpoint> _writeBreakpoints;
|
||||
vector<Breakpoint> _execBreakpoints;
|
||||
vector<Breakpoint> _globalBreakpoints;
|
||||
vector<Breakpoint> _readVramBreakpoints;
|
||||
vector<Breakpoint> _writeVramBreakpoints;
|
||||
atomic<bool> _hasBreakpoint;
|
||||
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
|
||||
bool _hasBreakpoint[BreakpointTypeCount];
|
||||
|
||||
deque<uint32_t> _callstackAbsolute;
|
||||
deque<uint32_t> _callstackRelative;
|
||||
@ -105,7 +103,6 @@ private:
|
||||
bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value);
|
||||
void UpdateCallstack(uint32_t addr);
|
||||
void ProcessStepConditions(uint32_t addr);
|
||||
void BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value);
|
||||
bool SleepUntilResume();
|
||||
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user