Merge pull request #1438 from pj64d-merge/memlocks
[Debugger] Add memory locks feature (interpreter)
This commit is contained in:
commit
1a6c579d3e
|
@ -321,6 +321,13 @@ void CInterpreterCPU::ExecuteCPU()
|
|||
if (CDebugSettings::HaveDebugger())
|
||||
{
|
||||
g_Debugger->CPUStepStarted();
|
||||
|
||||
if (SkipOp())
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SkipOp, false);
|
||||
PROGRAM_COUNTER += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000)
|
||||
|
|
|
@ -238,6 +238,21 @@ CBreakpoints::BPSTATE CBreakpoints::WriteBPExists64(uint32_t address)
|
|||
return BP_NOT_SET;
|
||||
}
|
||||
|
||||
CBreakpoints::BPSTATE CBreakpoints::WriteBPExistsInChunk(uint32_t address, uint32_t nBytes)
|
||||
{
|
||||
uint32_t endAddr = address + nBytes;
|
||||
|
||||
for (breakpoints_t::iterator breakpoint = m_WriteMem.begin(); breakpoint != m_WriteMem.end(); breakpoint++)
|
||||
{
|
||||
uint32_t wbpAddr = breakpoint->first;
|
||||
if (wbpAddr >= address && wbpAddr < endAddr)
|
||||
{
|
||||
return BP_SET;
|
||||
}
|
||||
}
|
||||
return BP_NOT_SET;
|
||||
}
|
||||
|
||||
CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRemoveTemp)
|
||||
{
|
||||
breakpoints_t::const_iterator itr = m_Execution.find(address);
|
||||
|
@ -283,3 +298,35 @@ void CBreakpoints::UpdateAlignedWriteBP()
|
|||
m_WriteMem64.insert(breakpoints_t::value_type((itr->first & ~0x7), false));
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakpoints::ToggleMemLock(uint32_t address)
|
||||
{
|
||||
if (m_MemLocks.count(address) == 0)
|
||||
{
|
||||
m_MemLocks.insert(address);
|
||||
return;
|
||||
}
|
||||
m_MemLocks.erase(address);
|
||||
}
|
||||
|
||||
bool CBreakpoints::MemLockExists(uint32_t address, int nBytes)
|
||||
{
|
||||
for (memlocks_t::const_iterator itr = m_MemLocks.begin(); itr != m_MemLocks.end(); itr++)
|
||||
{
|
||||
if (*itr >= address && *itr < (address + nBytes))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CBreakpoints::ClearMemLocks()
|
||||
{
|
||||
m_MemLocks.clear();
|
||||
}
|
||||
|
||||
size_t CBreakpoints::NumMemLocks()
|
||||
{
|
||||
return m_MemLocks.size();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ public:
|
|||
typedef std::map<uint32_t /*address*/, bool /*bTemporary*/> breakpoints_t;
|
||||
typedef breakpoints_t::const_iterator breakpoint_t;
|
||||
|
||||
typedef std::set<uint32_t> memlocks_t;
|
||||
|
||||
enum BPSTATE
|
||||
{
|
||||
BP_NOT_SET,
|
||||
|
@ -40,6 +42,7 @@ public:
|
|||
BPSTATE WriteBPExists16(uint32_t address);
|
||||
BPSTATE WriteBPExists32(uint32_t address);
|
||||
BPSTATE WriteBPExists64(uint32_t address);
|
||||
BPSTATE WriteBPExistsInChunk(uint32_t address, uint32_t nBytes);
|
||||
BPSTATE ExecutionBPExists(uint32_t address, bool bRemoveTemp = false);
|
||||
|
||||
bool RBPAdd(uint32_t address);
|
||||
|
@ -59,6 +62,11 @@ public:
|
|||
|
||||
void BPClear();
|
||||
|
||||
void ToggleMemLock(uint32_t address);
|
||||
bool MemLockExists(uint32_t address, int nBytes);
|
||||
void ClearMemLocks(void);
|
||||
size_t NumMemLocks(void);
|
||||
|
||||
private:
|
||||
void UpdateAlignedWriteBP(void);
|
||||
void UpdateAlignedReadBP(void);
|
||||
|
@ -66,4 +74,6 @@ private:
|
|||
breakpoints_t m_ReadMem, m_ReadMem16, m_ReadMem32, m_ReadMem64;
|
||||
breakpoints_t m_WriteMem, m_WriteMem16, m_WriteMem32, m_WriteMem64;
|
||||
breakpoints_t m_Execution;
|
||||
|
||||
memlocks_t m_MemLocks;
|
||||
};
|
|
@ -583,7 +583,7 @@ void CDebugCommandsView::ShowAddress(uint32_t address, bool top)
|
|||
const char* annotation = NULL;
|
||||
bool bLoadStoreAnnotation = false;
|
||||
|
||||
if (OpInfo.IsLoadStore())
|
||||
if (OpInfo.IsLoadStoreCommand())
|
||||
{
|
||||
for (int offset = -4; offset > -24; offset -= 4)
|
||||
{
|
||||
|
@ -1413,7 +1413,7 @@ LRESULT CDebugCommandsView::OnCommandListRightClicked(NMHDR* pNMHDR)
|
|||
EnableMenuItem(hPopupMenu, ID_POPUPMENU_FOLLOWJUMP, MF_DISABLED | MF_GRAYED);
|
||||
}
|
||||
|
||||
if (m_SelectedOpInfo.IsLoadStore())
|
||||
if (m_SelectedOpInfo.IsLoadStoreCommand())
|
||||
{
|
||||
m_FollowAddress = g_Reg->m_GPR[m_SelectedOpCode.base].UW[0] + (int16_t)m_SelectedOpCode.offset;
|
||||
}
|
||||
|
|
|
@ -219,6 +219,14 @@ LRESULT CDebugMemoryView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL&
|
|||
m_Breakpoints->WBPClear();
|
||||
RefreshMemory(true);
|
||||
break;
|
||||
case ID_POPUPMENU_TOGGLELOCK:
|
||||
m_Breakpoints->ToggleMemLock(m_CtxMenuAddr);
|
||||
RefreshMemory(true);
|
||||
break;
|
||||
case ID_POPUPMENU_CLEARLOCKS:
|
||||
m_Breakpoints->ClearMemLocks();
|
||||
RefreshMemory(true);
|
||||
break;
|
||||
case ID_POPUPMENU_VIEWDISASM:
|
||||
m_Debugger->Debug_ShowCommandsLocation(m_CtxMenuAddr, true);
|
||||
break;
|
||||
|
@ -248,6 +256,10 @@ LRESULT CDebugMemoryView::OnMemoryRightClicked(LPNMHDR lpNMHDR)
|
|||
{
|
||||
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARALLBPS, MF_DISABLED | MF_GRAYED);
|
||||
}
|
||||
if (m_Breakpoints->NumMemLocks() == 0)
|
||||
{
|
||||
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARLOCKS, MF_DISABLED | MF_GRAYED);
|
||||
}
|
||||
|
||||
POINT mouse;
|
||||
GetCursorPos(&mouse);
|
||||
|
@ -721,12 +733,17 @@ void CDebugMemoryView::SelectColors(uint32_t vaddr, bool changed, COLORREF& bgCo
|
|||
|
||||
CSymbols::LeaveCriticalSection();
|
||||
|
||||
bool bLocked = m_Breakpoints->MemLockExists(vaddr, 1);
|
||||
bool bHaveReadBP = m_Breakpoints->ReadBPExists8(vaddr) == CBreakpoints::BP_SET;
|
||||
bool bHaveWriteBP = m_Breakpoints->WriteBPExists8(vaddr) == CBreakpoints::BP_SET;
|
||||
|
||||
fgHiColor = RGB(0x00, 0x00, 0x00);
|
||||
|
||||
if (bHaveReadBP && bHaveWriteBP)
|
||||
if (bLocked)
|
||||
{
|
||||
bgColor = RGB(0xDD, 0xAA, 0xAA);
|
||||
}
|
||||
else if (bHaveReadBP && bHaveWriteBP)
|
||||
{
|
||||
bgColor = RGB(0xAA, 0xDD, 0xDD);
|
||||
}
|
||||
|
|
|
@ -394,14 +394,13 @@ void CDebuggerUI::CPUStepStarted()
|
|||
|
||||
// Memory breakpoints
|
||||
|
||||
OPCODE Opcode = R4300iOp::m_Opcode;
|
||||
uint32_t op = Opcode.op;
|
||||
COpInfo opInfo(R4300iOp::m_Opcode);
|
||||
|
||||
if (op >= R4300i_LDL && op <= R4300i_SD && op != R4300i_CACHE) // Read and write instructions
|
||||
if (opInfo.IsLoadStoreCommand()) // Read and write instructions
|
||||
{
|
||||
uint32_t memoryAddress = g_Reg->m_GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
|
||||
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
|
||||
|
||||
if ((op <= R4300i_LWU || (op >= R4300i_LL && op <= R4300i_LD))) // Read instructions
|
||||
if (opInfo.IsLoadCommand()) // Read instructions
|
||||
{
|
||||
m_ScriptSystem->HookCPURead()->InvokeByParamInRange(memoryAddress);
|
||||
|
||||
|
@ -419,21 +418,20 @@ void CDebuggerUI::CPUStepStarted()
|
|||
{
|
||||
uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF;
|
||||
uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000;
|
||||
uint32_t dmaLen = g_Reg->m_GPR[Opcode.rt].UW[0] + 1;
|
||||
uint32_t endAddr = dmaRamAddr + dmaLen;
|
||||
|
||||
uint32_t dmaLen = opInfo.GetStoreValueUnsigned() + 1;
|
||||
|
||||
m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen);
|
||||
|
||||
CBreakpoints::breakpoints_t breakpoints = m_Breakpoints->WriteMem();
|
||||
for (CBreakpoints::breakpoints_t::iterator breakpoint = breakpoints.begin(); breakpoint != breakpoints.end(); breakpoint++)
|
||||
if (m_Breakpoints->WriteBPExistsInChunk(dmaRamAddr, dmaLen))
|
||||
{
|
||||
uint32_t wbpAddr = breakpoint->first;
|
||||
if (wbpAddr >= dmaRamAddr && wbpAddr < endAddr)
|
||||
{
|
||||
goto breakpoint_hit;
|
||||
}
|
||||
goto breakpoint_hit;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SkipOp, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,15 @@ public:
|
|||
|
||||
OPCODE m_OpCode;
|
||||
|
||||
COpInfo()
|
||||
{
|
||||
}
|
||||
|
||||
inline COpInfo(OPCODE opcode):
|
||||
m_OpCode(opcode)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsStaticJump()
|
||||
{
|
||||
// j, jal
|
||||
|
@ -131,11 +140,16 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsLoadStore()
|
||||
inline bool IsLoadStoreCommand()
|
||||
{
|
||||
return (m_OpCode.op >= R4300i_LDL && m_OpCode.op <= R4300i_SD && m_OpCode.op != R4300i_CACHE);
|
||||
}
|
||||
|
||||
inline bool IsLoadCommand()
|
||||
{
|
||||
return (m_OpCode.op <= R4300i_LWU || (m_OpCode.op >= R4300i_LL && m_OpCode.op <= R4300i_LD));
|
||||
}
|
||||
|
||||
bool IsStackShift()
|
||||
{
|
||||
return (m_OpCode.op == R4300i_ADDIU || m_OpCode.op == R4300i_ADDI) && m_OpCode.rt == 29;
|
||||
|
@ -323,4 +337,53 @@ public:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline uint32_t GetLoadStoreAddress()
|
||||
{
|
||||
return g_Reg->m_GPR[m_OpCode.base].UW[0] + (int16_t)m_OpCode.offset;
|
||||
}
|
||||
|
||||
inline uint32_t GetStoreValueUnsigned()
|
||||
{
|
||||
return g_Reg->m_GPR[m_OpCode.rt].UW[0];
|
||||
}
|
||||
|
||||
inline int NumBytesToLoad()
|
||||
{
|
||||
switch (m_OpCode.op)
|
||||
{
|
||||
case R4300i_LB:
|
||||
case R4300i_LBU:
|
||||
return 1;
|
||||
case R4300i_LH:
|
||||
case R4300i_LHU:
|
||||
return 2;
|
||||
case R4300i_LD:
|
||||
case R4300i_LDL:
|
||||
case R4300i_LDR:
|
||||
case R4300i_LDC1:
|
||||
return 8;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
inline int NumBytesToStore()
|
||||
{
|
||||
switch (m_OpCode.op)
|
||||
{
|
||||
case R4300i_SB:
|
||||
return 1;
|
||||
case R4300i_SH:
|
||||
return 2;
|
||||
case R4300i_SD:
|
||||
case R4300i_SDL:
|
||||
case R4300i_SDR:
|
||||
case R4300i_SDC1:
|
||||
case R4300i_SDC2:
|
||||
return 8;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -685,7 +685,7 @@ BEGIN
|
|||
PUSHBUTTON "...",IDC_SYMBOLS_BTN,357,1,17,15
|
||||
PUSHBUTTON "Skip",IDC_SKIP_BTN,376,1,27,15,WS_DISABLED
|
||||
PUSHBUTTON "Step",IDC_STEP_BTN,404,1,27,15,WS_DISABLED
|
||||
PUSHBUTTON "St.Ovr", IDC_STEPOVER_BTN, 432, 1, 27, 15, WS_DISABLED
|
||||
PUSHBUTTON "St.Ovr",IDC_STEPOVER_BTN,432,1,27,15,WS_DISABLED
|
||||
PUSHBUTTON "Go",IDC_GO_BTN,460,1,27,15,WS_DISABLED
|
||||
LTEXT "PC",IDC_PC_STATIC,292,24,8,9
|
||||
EDITTEXT IDC_PC_EDIT,303,22,44,12,ES_UPPERCASE | ES_AUTOHSCROLL,WS_EX_RIGHT
|
||||
|
@ -1735,6 +1735,9 @@ BEGIN
|
|||
MENUITEM "Toggle write breakpoint", ID_POPUPMENU_TOGGLEWBP
|
||||
MENUITEM "Clear all breakpoints", ID_POPUPMENU_CLEARALLBPS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Toggle lock", ID_POPUPMENU_TOGGLELOCK
|
||||
MENUITEM "Clear locks", ID_POPUPMENU_CLEARLOCKS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "View disassembly...", ID_POPUPMENU_VIEWDISASM
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Add symbol...", ID_POPUPMENU_ADDSYMBOL
|
||||
|
|
|
@ -621,6 +621,8 @@
|
|||
#define ID_POPUPMENU_VIEWMEMORY 40036
|
||||
#define ID_POPUPMENU_TOGGLEBP 40039
|
||||
#define ID_POPUPMENU_CLEARBPS 40040
|
||||
#define ID_POPUPMENU_TOGGLELOCK 40041
|
||||
#define ID_POPUPMENU_CLEARLOCKS 40042
|
||||
#define ID_POPUPMENU_ROMDIRECTORY 40137
|
||||
#define ID_POPUPMENU_REFRESHROMLIST 40138
|
||||
#define ID_POPUPMENU_PLAYGAME 40152
|
||||
|
@ -636,7 +638,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 194
|
||||
#define _APS_NEXT_COMMAND_VALUE 40041
|
||||
#define _APS_NEXT_COMMAND_VALUE 40043
|
||||
#define _APS_NEXT_CONTROL_VALUE 1445
|
||||
#define _APS_NEXT_SYMED_VALUE 102
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue