Merge pull request #1678 from shygoo/debugger-opt
[Debugger] Optimize interpreter breakpoint and callback checks
This commit is contained in:
commit
b78a8d182d
|
@ -18,6 +18,7 @@
|
|||
#include <Project64-core/N64System/N64Class.h>
|
||||
|
||||
CBreakpoints::CBreakpoints() :
|
||||
m_bHaveRegBP(false),
|
||||
m_GPRWriteBP(0),
|
||||
m_GPRReadBP(0),
|
||||
m_HIWriteBP(false),
|
||||
|
@ -359,22 +360,17 @@ size_t CBreakpoints::NumMemLocks()
|
|||
return m_MemLocks.size();
|
||||
}
|
||||
|
||||
bool CBreakpoints::HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; }
|
||||
bool CBreakpoints::HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; }
|
||||
bool CBreakpoints::HaveGPRWriteBP(int nReg) { return (m_GPRWriteBP & (1 << nReg)) != 0; }
|
||||
bool CBreakpoints::HaveGPRReadBP(int nReg) { return (m_GPRReadBP & (1 << nReg)) != 0; }
|
||||
void CBreakpoints::ToggleGPRWriteBP(int nReg) { m_GPRWriteBP ^= (1 << nReg); }
|
||||
void CBreakpoints::ToggleGPRReadBP(int nReg) { m_GPRReadBP ^= (1 << nReg); }
|
||||
void CBreakpoints::UpdateHaveRegBP(void)
|
||||
{
|
||||
m_bHaveRegBP = HaveAnyGPRWriteBP() || HaveAnyGPRReadBP() || HaveHIWriteBP() || HaveHIReadBP() || HaveLOWriteBP() || HaveLOReadBP();
|
||||
}
|
||||
|
||||
bool CBreakpoints::HaveHIWriteBP(void) { return m_HIWriteBP; }
|
||||
bool CBreakpoints::HaveHIReadBP(void) { return m_HIReadBP; }
|
||||
bool CBreakpoints::HaveLOWriteBP(void) { return m_LOWriteBP; }
|
||||
bool CBreakpoints::HaveLOReadBP(void) { return m_LOReadBP; }
|
||||
|
||||
void CBreakpoints::ToggleHIWriteBP(void) { m_HIWriteBP = !m_HIWriteBP; }
|
||||
void CBreakpoints::ToggleHIReadBP(void) { m_HIReadBP = !m_HIReadBP; }
|
||||
void CBreakpoints::ToggleLOWriteBP(void) { m_LOWriteBP = !m_LOWriteBP; }
|
||||
void CBreakpoints::ToggleLOReadBP(void) { m_LOReadBP = !m_LOReadBP; }
|
||||
void CBreakpoints::ToggleGPRWriteBP(int nReg) { m_GPRWriteBP ^= (1 << nReg); UpdateHaveRegBP(); }
|
||||
void CBreakpoints::ToggleGPRReadBP(int nReg) { m_GPRReadBP ^= (1 << nReg); UpdateHaveRegBP(); }
|
||||
void CBreakpoints::ToggleHIWriteBP(void) { m_HIWriteBP = !m_HIWriteBP; UpdateHaveRegBP(); }
|
||||
void CBreakpoints::ToggleHIReadBP(void) { m_HIReadBP = !m_HIReadBP; UpdateHaveRegBP(); }
|
||||
void CBreakpoints::ToggleLOWriteBP(void) { m_LOWriteBP = !m_LOWriteBP; UpdateHaveRegBP(); }
|
||||
void CBreakpoints::ToggleLOReadBP(void) { m_LOReadBP = !m_LOReadBP; UpdateHaveRegBP(); }
|
||||
|
||||
void CBreakpoints::PreUpdateBP()
|
||||
{
|
||||
|
|
|
@ -67,17 +67,19 @@ public:
|
|||
void ClearMemLocks(void);
|
||||
size_t NumMemLocks(void);
|
||||
|
||||
bool HaveAnyGPRReadBP(void);
|
||||
bool HaveAnyGPRWriteBP(void);
|
||||
bool HaveGPRWriteBP(int nReg);
|
||||
bool HaveGPRReadBP(int nReg);
|
||||
inline bool HaveRegBP(void) { return m_bHaveRegBP; }
|
||||
inline bool HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; }
|
||||
inline bool HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; }
|
||||
inline bool HaveGPRWriteBP(int nReg) { return (m_GPRWriteBP & (1 << nReg)) != 0; }
|
||||
inline bool HaveGPRReadBP(int nReg) { return (m_GPRReadBP & (1 << nReg)) != 0; }
|
||||
inline bool HaveHIWriteBP(void) { return m_HIWriteBP; }
|
||||
inline bool HaveHIReadBP(void) { return m_HIReadBP; }
|
||||
inline bool HaveLOWriteBP(void) { return m_LOWriteBP; }
|
||||
inline bool HaveLOReadBP(void) { return m_LOReadBP; }
|
||||
|
||||
void UpdateHaveRegBP(void);
|
||||
void ToggleGPRWriteBP(int nReg);
|
||||
void ToggleGPRReadBP(int nReg);
|
||||
|
||||
bool HaveHIWriteBP(void);
|
||||
bool HaveHIReadBP(void);
|
||||
bool HaveLOWriteBP(void);
|
||||
bool HaveLOReadBP(void);
|
||||
void ToggleHIWriteBP(void);
|
||||
void ToggleHIReadBP(void);
|
||||
void ToggleLOWriteBP(void);
|
||||
|
@ -95,6 +97,7 @@ private:
|
|||
|
||||
memlocks_t m_MemLocks;
|
||||
|
||||
bool m_bHaveRegBP;
|
||||
uint32_t m_GPRWriteBP, m_GPRReadBP;
|
||||
bool m_HIWriteBP, m_HIReadBP, m_LOWriteBP, m_LOReadBP;
|
||||
};
|
|
@ -24,28 +24,6 @@ CDebugStackTrace::~CDebugStackTrace()
|
|||
{
|
||||
}
|
||||
|
||||
void CDebugStackTrace::PushEntry(uint32_t routineAddress, uint32_t callingAddress)
|
||||
{
|
||||
if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES)
|
||||
{
|
||||
m_Entries[m_EntriesIndex] = { routineAddress, callingAddress };
|
||||
m_EntriesIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void CDebugStackTrace::PopEntry()
|
||||
{
|
||||
if (m_EntriesIndex > 0)
|
||||
{
|
||||
m_EntriesIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
void CDebugStackTrace::ClearEntries()
|
||||
{
|
||||
m_EntriesIndex = 0;
|
||||
}
|
||||
|
||||
LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
DlgResize_Init();
|
||||
|
|
|
@ -32,9 +32,27 @@ public:
|
|||
|
||||
void Refresh();
|
||||
|
||||
void PushEntry(uint32_t routineAddress, uint32_t callingAddress);
|
||||
void PopEntry();
|
||||
void ClearEntries();
|
||||
inline void PushEntry(uint32_t routineAddress, uint32_t callingAddress)
|
||||
{
|
||||
if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES)
|
||||
{
|
||||
m_Entries[m_EntriesIndex] = { routineAddress, callingAddress };
|
||||
m_EntriesIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
inline void PopEntry()
|
||||
{
|
||||
if (m_EntriesIndex > 0)
|
||||
{
|
||||
m_EntriesIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearEntries()
|
||||
{
|
||||
m_EntriesIndex = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -540,19 +540,19 @@ void CDebuggerUI::HandleCartToRamDMA(void)
|
|||
// Called from the interpreter core at the beginning of every CPU step
|
||||
void CDebuggerUI::CPUStepStarted()
|
||||
{
|
||||
uint32_t pc = g_Reg->m_PROGRAM_COUNTER;
|
||||
COpInfo opInfo(R4300iOp::m_Opcode);
|
||||
bool bStoreOp = opInfo.IsStoreCommand();
|
||||
uint32_t storeAddress = bStoreOp ? opInfo.GetLoadStoreAddress() : 0;
|
||||
|
||||
if (isStepping() && bCPULoggingEnabled())
|
||||
{
|
||||
Debug_RefreshCPULogWindow();
|
||||
}
|
||||
|
||||
uint32_t pc = g_Reg->m_PROGRAM_COUNTER;
|
||||
COpInfo opInfo(R4300iOp::m_Opcode);
|
||||
|
||||
if (opInfo.IsStoreCommand())
|
||||
if(bStoreOp && m_Breakpoints->NumMemLocks() > 0)
|
||||
{
|
||||
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
|
||||
|
||||
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
|
||||
if (m_Breakpoints->MemLockExists(storeAddress, opInfo.NumBytesToStore()))
|
||||
{
|
||||
// Memory is locked, skip op
|
||||
g_Settings->SaveBool(Debugger_SkipOp, true);
|
||||
|
@ -560,37 +560,35 @@ void CDebuggerUI::CPUStepStarted()
|
|||
}
|
||||
}
|
||||
|
||||
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
// Memory events, pi cart -> ram dma
|
||||
if (opInfo.IsLoadStoreCommand()) // Read and write instructions
|
||||
if (m_ScriptSystem->HaveCallbacks())
|
||||
{
|
||||
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
|
||||
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
if (opInfo.IsLoadCommand()) // Read instructions
|
||||
m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
if (bStoreOp)
|
||||
{
|
||||
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(memoryAddress);
|
||||
m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(storeAddress);
|
||||
if (SkipOp()) { return; }
|
||||
}
|
||||
else // Write instructions
|
||||
{
|
||||
m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(memoryAddress);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG
|
||||
{
|
||||
HandleCartToRamDMA();
|
||||
}
|
||||
if (opInfo.IsLoadCommand())
|
||||
{
|
||||
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(opInfo.GetLoadStoreAddress());
|
||||
if (SkipOp()) { return; }
|
||||
}
|
||||
}
|
||||
|
||||
if (bStoreOp && storeAddress == 0xA460000C) // PI_WR_LEN_REG
|
||||
{
|
||||
HandleCartToRamDMA();
|
||||
}
|
||||
|
||||
if (CDebugSettings::ExceptionBreakpoints() != 0)
|
||||
{
|
||||
if (pc == 0x80000000 || pc == 0x80000080 ||
|
||||
|
@ -603,36 +601,39 @@ void CDebuggerUI::CPUStepStarted()
|
|||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->HaveAnyGPRWriteBP())
|
||||
if (m_Breakpoints->HaveRegBP())
|
||||
{
|
||||
int nReg = 0;
|
||||
opInfo.WritesGPR(&nReg);
|
||||
if (m_Breakpoints->HaveAnyGPRWriteBP())
|
||||
{
|
||||
int nReg = 0;
|
||||
opInfo.WritesGPR(&nReg);
|
||||
|
||||
if (nReg != 0 && m_Breakpoints->HaveGPRWriteBP(nReg))
|
||||
if (nReg != 0 && m_Breakpoints->HaveGPRWriteBP(nReg))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->HaveAnyGPRReadBP())
|
||||
{
|
||||
int nReg1 = 0, nReg2 = 0;
|
||||
opInfo.ReadsGPR(&nReg1, &nReg2);
|
||||
|
||||
if ((nReg1 != 0 && m_Breakpoints->HaveGPRReadBP(nReg1)) ||
|
||||
(nReg2 != 0 && m_Breakpoints->HaveGPRReadBP(nReg2)))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->HaveHIWriteBP() && opInfo.WritesHI() ||
|
||||
m_Breakpoints->HaveLOWriteBP() && opInfo.WritesLO() ||
|
||||
m_Breakpoints->HaveHIReadBP() && opInfo.ReadsHI() ||
|
||||
m_Breakpoints->HaveLOReadBP() && opInfo.ReadsLO())
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->HaveAnyGPRReadBP())
|
||||
{
|
||||
int nReg1 = 0, nReg2 = 0;
|
||||
opInfo.ReadsGPR(&nReg1, &nReg2);
|
||||
|
||||
if ((nReg1 != 0 && m_Breakpoints->HaveGPRReadBP(nReg1)) ||
|
||||
(nReg2 != 0 && m_Breakpoints->HaveGPRReadBP(nReg2)))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->HaveHIWriteBP() && opInfo.WritesHI() ||
|
||||
m_Breakpoints->HaveLOWriteBP() && opInfo.WritesLO() ||
|
||||
m_Breakpoints->HaveHIReadBP() && opInfo.ReadsHI() ||
|
||||
m_Breakpoints->HaveLOReadBP() && opInfo.ReadsLO())
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Called before opcode is executed (not called if SkipOp is set)
|
||||
|
@ -647,15 +648,15 @@ void CDebuggerUI::CPUStep()
|
|||
// Called after opcode has been executed
|
||||
void CDebuggerUI::CPUStepEnded()
|
||||
{
|
||||
if (m_StackTrace == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OPCODE Opcode = R4300iOp::m_Opcode;
|
||||
uint32_t op = Opcode.op;
|
||||
uint32_t funct = Opcode.funct;
|
||||
|
||||
if (m_StackTrace == NULL)
|
||||
{
|
||||
m_StackTrace = new CDebugStackTrace(this);
|
||||
}
|
||||
|
||||
if (op == R4300i_JAL || ((op == R4300i_SPECIAL) && (funct == R4300i_SPECIAL_JALR) && (Opcode.rd == 31))) // JAL or JALR RA, x
|
||||
{
|
||||
m_StackTrace->PushEntry(R4300iOp::m_JumpToLocation, g_Reg->m_PROGRAM_COUNTER);
|
||||
|
|
|
@ -17,6 +17,7 @@ int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t pa
|
|||
jsCallback.param4 = param4;
|
||||
jsCallback.bOnce = bOnce;
|
||||
m_Callbacks.push_back(jsCallback);
|
||||
m_ScriptSystem->CallbackAdded();
|
||||
return jsCallback.callbackId;
|
||||
}
|
||||
|
||||
|
@ -122,6 +123,7 @@ void CScriptHook::RemoveById(int callbackId)
|
|||
if (m_Callbacks[i].callbackId == callbackId)
|
||||
{
|
||||
m_Callbacks.erase(m_Callbacks.begin() + i);
|
||||
m_ScriptSystem->CallbackRemoved();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +137,7 @@ void CScriptHook::RemoveByParam(uint32_t param)
|
|||
if (m_Callbacks[i].param == param)
|
||||
{
|
||||
m_Callbacks.erase(m_Callbacks.begin() + i);
|
||||
m_ScriptSystem->CallbackRemoved();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +151,7 @@ void CScriptHook::RemoveByInstance(CScriptInstance* scriptInstance)
|
|||
if (m_Callbacks[i].scriptInstance == scriptInstance)
|
||||
{
|
||||
m_Callbacks.erase(m_Callbacks.begin() + i);
|
||||
m_ScriptSystem->CallbackRemoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ CScriptSystem::CScriptSystem(CDebuggerUI* debugger)
|
|||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
|
||||
m_NextCallbackId = 0;
|
||||
m_NumCallbacks = 0;
|
||||
|
||||
m_Debugger = debugger;
|
||||
|
||||
|
@ -207,4 +208,17 @@ CScriptHook* CScriptSystem::GetHook(const char* hookId)
|
|||
int CScriptSystem::GetNextCallbackId()
|
||||
{
|
||||
return m_NextCallbackId++;
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptSystem::CallbackAdded()
|
||||
{
|
||||
m_NumCallbacks++;
|
||||
}
|
||||
|
||||
void CScriptSystem::CallbackRemoved()
|
||||
{
|
||||
if (m_NumCallbacks > 0)
|
||||
{
|
||||
m_NumCallbacks--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ private:
|
|||
} INSTANCE_ENTRY;
|
||||
|
||||
CDebuggerUI* m_Debugger;
|
||||
|
||||
int m_NumCallbacks;
|
||||
char* m_APIScript;
|
||||
|
||||
vector<HOOKENTRY> m_Hooks;
|
||||
|
@ -103,6 +103,13 @@ public:
|
|||
CScriptHook* GetHook(const char* hookId);
|
||||
|
||||
int GetNextCallbackId();
|
||||
void CallbackAdded();
|
||||
void CallbackRemoved();
|
||||
|
||||
inline int HaveCallbacks()
|
||||
{
|
||||
return m_NumCallbacks != 0;
|
||||
}
|
||||
|
||||
void DeleteStoppedInstances();
|
||||
INSTANCE_STATE GetInstanceState(char* scriptName);
|
||||
|
|
Loading…
Reference in New Issue