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 (r5900Debug.isCpuPaused())
|
||||||
{
|
{
|
||||||
if (CBreakPoints::IsAddressBreakPoint(r5900Debug.getPC()))
|
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||||
r5900Debug.resumeCpu();
|
r5900Debug.resumeCpu();
|
||||||
} else
|
} else
|
||||||
r5900Debug.pauseCpu();
|
r5900Debug.pauseCpu();
|
||||||
|
|
|
@ -1271,7 +1271,7 @@ int cop2flags(u32 code)
|
||||||
void dynarecCheckBreakpoint()
|
void dynarecCheckBreakpoint()
|
||||||
{
|
{
|
||||||
u32 pc = cpuRegs.pc;
|
u32 pc = cpuRegs.pc;
|
||||||
if (CBreakPoints::CheckSkipFirst(pc))
|
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||||
|
@ -1282,6 +1282,63 @@ void dynarecCheckBreakpoint()
|
||||||
recExitExecution();
|
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)
|
void recompileNextInstruction(int delayslot)
|
||||||
{
|
{
|
||||||
static u8 s_bFlushReg = 1;
|
static u8 s_bFlushReg = 1;
|
||||||
|
@ -1301,6 +1358,54 @@ void recompileNextInstruction(int delayslot)
|
||||||
MOV32ItoR(EAX, pc); // acts as a tag for delimiting recompiled instructions when viewing x86 disasm.
|
MOV32ItoR(EAX, pc); // acts as a tag for delimiting recompiled instructions when viewing x86 disasm.
|
||||||
|
|
||||||
cpuRegs.code = *(int *)s_pCode;
|
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) {
|
if (!delayslot) {
|
||||||
pc += 4;
|
pc += 4;
|
||||||
g_cpuFlushedPC = false;
|
g_cpuFlushedPC = false;
|
||||||
|
@ -1551,6 +1656,44 @@ bool skipMPEG_By_Pattern(u32 sPC) {
|
||||||
return 0;
|
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 )
|
static void __fastcall recRecompile( const u32 startpc )
|
||||||
{
|
{
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
|
@ -1631,7 +1774,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
s_branchTo = -1;
|
s_branchTo = -1;
|
||||||
|
|
||||||
// compile breakpoints as individual blocks
|
// compile breakpoints as individual blocks
|
||||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
if (needsBreakpoint(i))
|
||||||
{
|
{
|
||||||
s_nEndBlock = i + 4;
|
s_nEndBlock = i + 4;
|
||||||
goto StartRecomp;
|
goto StartRecomp;
|
||||||
|
@ -1641,7 +1784,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
||||||
|
|
||||||
// stop before breakpoints
|
// stop before breakpoints
|
||||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
if (needsBreakpoint(i))
|
||||||
{
|
{
|
||||||
s_nEndBlock = i;
|
s_nEndBlock = i;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue