mirror of https://github.com/PCSX2/pcsx2.git
Memory breakpoints
This commit is contained in:
parent
074da1fedf
commit
aad9ea0e05
|
@ -171,8 +171,8 @@ void DisassemblyDialog::onBreakRunClicked(wxCommandEvent& evt)
|
|||
{
|
||||
if (r5900Debug.isCpuPaused())
|
||||
{
|
||||
if (CBreakPoints::IsAddressBreakPoint(r5900Debug.getPC()))
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
r5900Debug.resumeCpu();
|
||||
} else
|
||||
r5900Debug.pauseCpu();
|
||||
|
|
|
@ -1271,7 +1271,7 @@ int cop2flags(u32 code)
|
|||
void dynarecCheckBreakpoint()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc))
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
return;
|
||||
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||
|
@ -1282,6 +1282,63 @@ void dynarecCheckBreakpoint()
|
|||
recExitExecution();
|
||||
}
|
||||
|
||||
void dynarecMemcheck()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
return;
|
||||
|
||||
iFlushCall(FLUSH_INTERPRETER);
|
||||
GetCoreThread().PauseSelf();
|
||||
recExitExecution();
|
||||
}
|
||||
|
||||
void recMemcheck(u32 bits, bool store)
|
||||
{
|
||||
iFlushCall(FLUSH_INTERPRETER);
|
||||
|
||||
// compute accessed address
|
||||
_eeMoveGPRtoR(ECX, _Rs_);
|
||||
if (_Imm_ != 0)
|
||||
xADD(ecx, _Imm_);
|
||||
if (bits == 128)
|
||||
xAND(ecx, ~0x0F);
|
||||
|
||||
xMOV(edx,ecx);
|
||||
xADD(edx,bits/8);
|
||||
|
||||
// ecx = access address
|
||||
// edx = access address+size
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
if ((checks[i].cond & MEMCHECK_BREAK) == 0)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store == true)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_READ) == 0 && store == false)
|
||||
continue;
|
||||
|
||||
// logic: memAddress < bpEnd && bpStart < memAddress+memSize
|
||||
|
||||
xMOV(eax,checks[i].end);
|
||||
xCMP(ecx,eax); // address < end
|
||||
xForwardJGE8 next1; // if address >= end then goto next1
|
||||
|
||||
xMOV(eax,checks[i].start);
|
||||
xCMP(eax,edx); // start < address+size
|
||||
xForwardJGE8 next2; // if start >= address+size then goto next2
|
||||
|
||||
// hit the breakpoint
|
||||
xCALL(&dynarecMemcheck);
|
||||
|
||||
next1.SetTarget();
|
||||
next2.SetTarget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void recompileNextInstruction(int delayslot)
|
||||
{
|
||||
static u8 s_bFlushReg = 1;
|
||||
|
@ -1293,14 +1350,62 @@ void recompileNextInstruction(int delayslot)
|
|||
iFlushCall(FLUSH_EVERYTHING);
|
||||
xCALL(&dynarecCheckBreakpoint);
|
||||
}
|
||||
|
||||
|
||||
s_pCode = (int *)PSM( pc );
|
||||
pxAssert(s_pCode);
|
||||
|
||||
|
||||
if( IsDebugBuild )
|
||||
MOV32ItoR(EAX, pc); // acts as a tag for delimiting recompiled instructions when viewing x86 disasm.
|
||||
|
||||
cpuRegs.code = *(int *)s_pCode;
|
||||
|
||||
if (CBreakPoints::GetMemChecks().size() != 0)
|
||||
{
|
||||
switch (cpuRegs.code >> 26)
|
||||
{
|
||||
case 0x20: // lb
|
||||
case 0x24: // lbu
|
||||
recMemcheck(8,false);
|
||||
break;
|
||||
case 0x28: // sb
|
||||
recMemcheck(8,true);
|
||||
break;
|
||||
case 0x21: // lh
|
||||
case 0x25: // lhu
|
||||
recMemcheck(16,false);
|
||||
break;
|
||||
case 0x22: // lwl
|
||||
case 0x23: // lw
|
||||
case 0x26: // lwr
|
||||
recMemcheck(32,false);
|
||||
break;
|
||||
case 0x29: // sh
|
||||
recMemcheck(16,true);
|
||||
break;
|
||||
case 0x2A: // swl
|
||||
case 0x2B: // sw
|
||||
case 0x2E: // swr
|
||||
recMemcheck(32,true);
|
||||
break;
|
||||
case 0x37: // ld
|
||||
case 0x1B: // ldr
|
||||
case 0x1A: // ldl
|
||||
recMemcheck(64,false);
|
||||
break;
|
||||
case 0x3F: // sd
|
||||
case 0x3D: // sdr
|
||||
case 0x2C: // sdl
|
||||
recMemcheck(64,true);
|
||||
break;
|
||||
case 0x1E: // lq
|
||||
recMemcheck(128,false);
|
||||
break;
|
||||
case 0x1F: // sq
|
||||
recMemcheck(128,true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!delayslot) {
|
||||
pc += 4;
|
||||
g_cpuFlushedPC = false;
|
||||
|
@ -1551,6 +1656,44 @@ bool skipMPEG_By_Pattern(u32 sPC) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline bool needsBreakpoint(u32 pc)
|
||||
{
|
||||
if (CBreakPoints::IsAddressBreakPoint(pc))
|
||||
return true;
|
||||
|
||||
if (CBreakPoints::GetMemChecks().size() == 0)
|
||||
return false;
|
||||
|
||||
u32 op = memRead32(pc);
|
||||
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 0x20: // lb
|
||||
case 0x21: // lh
|
||||
case 0x22: // lwl
|
||||
case 0x23: // lw
|
||||
case 0x24: // lbu
|
||||
case 0x25: // lhu
|
||||
case 0x26: // lwr
|
||||
case 0x28: // sb
|
||||
case 0x29: // sh
|
||||
case 0x2A: // swl
|
||||
case 0x2B: // sw
|
||||
case 0x2E: // swr
|
||||
case 0x37: // ld
|
||||
case 0x1B: // ldr
|
||||
case 0x3F: // sd
|
||||
case 0x3D: // sdr
|
||||
case 0x1A: // ldl
|
||||
case 0x2C: // sdl
|
||||
case 0x1E: // lq
|
||||
case 0x1F: // sq
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void __fastcall recRecompile( const u32 startpc )
|
||||
{
|
||||
u32 i = 0;
|
||||
|
@ -1631,7 +1774,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
|||
s_branchTo = -1;
|
||||
|
||||
// compile breakpoints as individual blocks
|
||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
||||
if (needsBreakpoint(i))
|
||||
{
|
||||
s_nEndBlock = i + 4;
|
||||
goto StartRecomp;
|
||||
|
@ -1641,7 +1784,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
|||
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
||||
|
||||
// stop before breakpoints
|
||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
||||
if (needsBreakpoint(i))
|
||||
{
|
||||
s_nEndBlock = i;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue