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);
|
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()
|
string Breakpoint::GetCondition()
|
||||||
|
@ -7,24 +7,35 @@ enum BreakpointType
|
|||||||
Global = 0,
|
Global = 0,
|
||||||
Execute = 1,
|
Execute = 1,
|
||||||
ReadRam = 2,
|
ReadRam = 2,
|
||||||
WriteRam = 4,
|
WriteRam = 3,
|
||||||
ReadVram = 8,
|
ReadVram = 4,
|
||||||
WriteVram = 16,
|
WriteVram = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Breakpoint
|
class Breakpoint
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
enum BreakpointTypeFlags
|
||||||
|
{
|
||||||
|
Global = 0,
|
||||||
|
Execute = 1,
|
||||||
|
ReadRam = 2,
|
||||||
|
WriteRam = 4,
|
||||||
|
ReadVram = 8,
|
||||||
|
WriteVram = 16,
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Breakpoint();
|
Breakpoint();
|
||||||
~Breakpoint();
|
~Breakpoint();
|
||||||
|
|
||||||
bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr);
|
bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr);
|
||||||
BreakpointType GetType();
|
bool HasBreakpointType(BreakpointType type);
|
||||||
string GetCondition();
|
string GetCondition();
|
||||||
void ClearCondition();
|
void ClearCondition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BreakpointType _type;
|
BreakpointTypeFlags _type;
|
||||||
int32_t _addr;
|
int32_t _addr;
|
||||||
bool _isAbsoluteAddr;
|
bool _isAbsoluteAddr;
|
||||||
char _condition[1000];
|
char _condition[1000];
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "ExpressionEvaluator.h"
|
#include "ExpressionEvaluator.h"
|
||||||
|
|
||||||
Debugger* Debugger::Instance = nullptr;
|
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)
|
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;
|
_flags = 0;
|
||||||
|
|
||||||
_hasBreakpoint = false;
|
|
||||||
_bpUpdateNeeded = false;
|
_bpUpdateNeeded = false;
|
||||||
_executionStopped = false;
|
_executionStopped = false;
|
||||||
|
|
||||||
@ -121,27 +121,37 @@ CdlRatios Debugger::GetCdlRatios()
|
|||||||
|
|
||||||
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
||||||
{
|
{
|
||||||
_hasBreakpoint = length > 0;
|
_bpUpdateLock.AcquireSafe();
|
||||||
|
|
||||||
while(_updatingBreakpoints) { }
|
|
||||||
_newBreakpoints.clear();
|
_newBreakpoints.clear();
|
||||||
_newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length);
|
_newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length);
|
||||||
_bpUpdateNeeded = true;
|
_bpUpdateNeeded = true;
|
||||||
|
|
||||||
if(_executionStopped) {
|
if(_executionStopped) {
|
||||||
UpdateBreakpoints();
|
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()
|
void Debugger::UpdateBreakpoints()
|
||||||
{
|
{
|
||||||
_updatingBreakpoints = true;
|
|
||||||
if(_bpUpdateNeeded) {
|
if(_bpUpdateNeeded) {
|
||||||
_globalBreakpoints.clear();
|
_bpUpdateLock.AcquireSafe();
|
||||||
_execBreakpoints.clear();
|
|
||||||
_readBreakpoints.clear();
|
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
|
||||||
_writeBreakpoints.clear();
|
_breakpoints[i].clear();
|
||||||
_readVramBreakpoints.clear();
|
_hasBreakpoint[i] = false;
|
||||||
_writeVramBreakpoints.clear();
|
}
|
||||||
|
|
||||||
ExpressionEvaluator expEval;
|
ExpressionEvaluator expEval;
|
||||||
for(Breakpoint &bp : _newBreakpoints) {
|
for(Breakpoint &bp : _newBreakpoints) {
|
||||||
@ -150,31 +160,16 @@ void Debugger::UpdateBreakpoints()
|
|||||||
bp.ClearCondition();
|
bp.ClearCondition();
|
||||||
}
|
}
|
||||||
|
|
||||||
BreakpointType type = bp.GetType();
|
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
|
||||||
if(type & BreakpointType::Execute) {
|
if(bp.HasBreakpointType((BreakpointType)i)) {
|
||||||
_execBreakpoints.push_back(bp);
|
_breakpoints[i].push_back(bp);
|
||||||
}
|
_hasBreakpoint[i] = true;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_bpUpdateNeeded = false;
|
_bpUpdateNeeded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updatingBreakpoints = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value)
|
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();
|
UpdateBreakpoints();
|
||||||
|
|
||||||
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
|
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
|
||||||
vector<Breakpoint> *breakpoints = nullptr;
|
vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needState = true;
|
bool needState = true;
|
||||||
for(size_t i = 0, len = breakpoints->size(); i < len; i++) {
|
for(size_t i = 0, len = breakpoints.size(); i < len; i++) {
|
||||||
Breakpoint &breakpoint = (*breakpoints)[i];
|
Breakpoint &breakpoint = breakpoints[i];
|
||||||
if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) {
|
if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) {
|
||||||
string condition = breakpoint.GetCondition();
|
string condition = breakpoint.GetCondition();
|
||||||
if(condition.empty()) {
|
if(condition.empty()) {
|
||||||
@ -259,7 +245,7 @@ void Debugger::ProcessStepConditions(uint32_t addr)
|
|||||||
|
|
||||||
void Debugger::PrivateProcessPpuCycle()
|
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
|
//Found a matching breakpoint, stop execution
|
||||||
Step(1);
|
Step(1);
|
||||||
SleepUntilResume();
|
SleepUntilResume();
|
||||||
@ -316,32 +302,21 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!breakDone && _hasBreakpoint) {
|
if(!breakDone) {
|
||||||
BreakOnBreakpoint(type, addr, value);
|
BreakpointType breakpointType = BreakpointType::Execute;
|
||||||
}
|
|
||||||
|
|
||||||
_currentReadAddr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value)
|
|
||||||
{
|
|
||||||
if(_hasBreakpoint) {
|
|
||||||
BreakpointType breakpointType;
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break;
|
case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break;
|
||||||
case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; 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
|
//Found a matching breakpoint, stop execution
|
||||||
Step(1);
|
Step(1);
|
||||||
SleepUntilResume();
|
SleepUntilResume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_currentReadAddr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::SleepUntilResume()
|
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);
|
_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
|
//Found a matching breakpoint, stop execution
|
||||||
Step(1);
|
Step(1);
|
||||||
SleepUntilResume();
|
SleepUntilResume();
|
||||||
|
@ -50,6 +50,8 @@ class Debugger
|
|||||||
private:
|
private:
|
||||||
static Debugger* Instance;
|
static Debugger* Instance;
|
||||||
|
|
||||||
|
const static int BreakpointTypeCount = 6;
|
||||||
|
|
||||||
unique_ptr<Disassembler> _disassembler;
|
unique_ptr<Disassembler> _disassembler;
|
||||||
unique_ptr<CodeDataLogger> _codeDataLogger;
|
unique_ptr<CodeDataLogger> _codeDataLogger;
|
||||||
shared_ptr<Console> _console;
|
shared_ptr<Console> _console;
|
||||||
@ -58,19 +60,15 @@ private:
|
|||||||
shared_ptr<MemoryManager> _memoryManager;
|
shared_ptr<MemoryManager> _memoryManager;
|
||||||
shared_ptr<BaseMapper> _mapper;
|
shared_ptr<BaseMapper> _mapper;
|
||||||
|
|
||||||
atomic<bool> _bpUpdateNeeded;
|
bool _bpUpdateNeeded;
|
||||||
atomic<bool> _updatingBreakpoints;
|
SimpleLock _bpUpdateLock;
|
||||||
|
|
||||||
atomic<bool> _stopFlag;
|
atomic<bool> _stopFlag;
|
||||||
atomic<bool> _executionStopped;
|
atomic<bool> _executionStopped;
|
||||||
atomic<int32_t> _suspendCount;
|
atomic<int32_t> _suspendCount;
|
||||||
vector<Breakpoint> _newBreakpoints;
|
vector<Breakpoint> _newBreakpoints;
|
||||||
vector<Breakpoint> _readBreakpoints;
|
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
|
||||||
vector<Breakpoint> _writeBreakpoints;
|
bool _hasBreakpoint[BreakpointTypeCount];
|
||||||
vector<Breakpoint> _execBreakpoints;
|
|
||||||
vector<Breakpoint> _globalBreakpoints;
|
|
||||||
vector<Breakpoint> _readVramBreakpoints;
|
|
||||||
vector<Breakpoint> _writeVramBreakpoints;
|
|
||||||
atomic<bool> _hasBreakpoint;
|
|
||||||
|
|
||||||
deque<uint32_t> _callstackAbsolute;
|
deque<uint32_t> _callstackAbsolute;
|
||||||
deque<uint32_t> _callstackRelative;
|
deque<uint32_t> _callstackRelative;
|
||||||
@ -105,7 +103,6 @@ private:
|
|||||||
bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value);
|
bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value);
|
||||||
void UpdateCallstack(uint32_t addr);
|
void UpdateCallstack(uint32_t addr);
|
||||||
void ProcessStepConditions(uint32_t addr);
|
void ProcessStepConditions(uint32_t addr);
|
||||||
void BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value);
|
|
||||||
bool SleepUntilResume();
|
bool SleepUntilResume();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user