mirror of https://github.com/PCSX2/pcsx2.git
Add breakpoint support to R5900 interpreter
This commit is contained in:
parent
430c617a95
commit
a95e55dc54
|
@ -140,6 +140,7 @@ public:
|
|||
|
||||
static const std::vector<MemCheck> GetMemChecks();
|
||||
static const std::vector<BreakPoint> GetBreakpoints();
|
||||
static const size_t GetNumMemchecks() { return memChecks_.size(); }
|
||||
|
||||
static void Update(u32 addr = 0);
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "Elfheader.h"
|
||||
|
||||
#include "../DebugTools/Breakpoints.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
using namespace R5900; // for OPCODE and OpcodeImpl
|
||||
|
@ -45,8 +47,93 @@ static void debugI()
|
|||
|
||||
//long int runs=0;
|
||||
|
||||
void intBreakpoint(bool memcheck)
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
return;
|
||||
|
||||
if (!memcheck)
|
||||
{
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||
if (cond && !cond->Evaluate())
|
||||
return;
|
||||
}
|
||||
|
||||
CBreakPoints::SetBreakpointTriggered(true);
|
||||
GetCoreThread().PauseSelf();
|
||||
throw Exception::ExitCpuExecute();
|
||||
}
|
||||
|
||||
void intMemcheck(u32 op, u32 bits, bool store)
|
||||
{
|
||||
// compute accessed address
|
||||
u32 start = cpuRegs.GPR.r[(op >> 21) & 0x1F].UD[0];
|
||||
if ((s16)op != 0)
|
||||
start += (s16)op;
|
||||
if (bits == 128)
|
||||
start &= ~0x0F;
|
||||
|
||||
start = standardizeBreakpointAddress(start);
|
||||
u32 end = start + bits/8;
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
auto& check = checks[i];
|
||||
|
||||
if (check.result == 0)
|
||||
continue;
|
||||
if ((check.cond & MEMCHECK_WRITE) == 0 && store == true)
|
||||
continue;
|
||||
if ((check.cond & MEMCHECK_READ) == 0 && store == false)
|
||||
continue;
|
||||
|
||||
if (start < check.end && check.start < end)
|
||||
intBreakpoint(true);
|
||||
}
|
||||
}
|
||||
|
||||
void intCheckMemcheck()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
int needed = isMemcheckNeeded(pc);
|
||||
if (needed == 0)
|
||||
return;
|
||||
|
||||
u32 op = memRead32(needed == 2 ? pc+4 : pc);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
|
||||
bool store = (opcode.flags & IS_STORE) != 0;
|
||||
switch (opcode.flags & MEMTYPE_MASK)
|
||||
{
|
||||
case MEMTYPE_BYTE:
|
||||
intMemcheck(op,8,store);
|
||||
break;
|
||||
case MEMTYPE_HALF:
|
||||
intMemcheck(op,16,store);
|
||||
break;
|
||||
case MEMTYPE_WORD:
|
||||
intMemcheck(op,32,store);
|
||||
break;
|
||||
case MEMTYPE_DWORD:
|
||||
intMemcheck(op,64,store);
|
||||
break;
|
||||
case MEMTYPE_QWORD:
|
||||
intMemcheck(op,128,store);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void execI()
|
||||
{
|
||||
// check if any breakpoints or memchecks are triggered by this instruction
|
||||
if (isBreakpointNeeded(cpuRegs.pc))
|
||||
intBreakpoint(false);
|
||||
|
||||
intCheckMemcheck();
|
||||
|
||||
// interprete instruction
|
||||
cpuRegs.code = memRead32( cpuRegs.pc );
|
||||
if( IsDebugBuild )
|
||||
debugI();
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
#include "Patch.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
#include "../DebugTools/Breakpoints.h"
|
||||
#include "R5900OpcodeTables.h"
|
||||
|
||||
using namespace R5900; // for R5900 disasm tools
|
||||
|
||||
s32 EEsCycle; // used to sync the IOP to the EE
|
||||
|
@ -608,3 +611,44 @@ void __fastcall eeloadReplaceOSDSYS()
|
|||
}
|
||||
// else... uh...?
|
||||
}
|
||||
|
||||
inline bool isBranchOrJump(u32 addr)
|
||||
{
|
||||
u32 op = memRead32(addr);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
|
||||
return (opcode.flags & IS_BRANCH) != 0;
|
||||
}
|
||||
|
||||
// The next two functions return 0 if no breakpoint is needed,
|
||||
// 1 if it's needed on the current pc, 2 if it's needed in the delay slot
|
||||
|
||||
int isBreakpointNeeded(u32 addr)
|
||||
{
|
||||
if (CBreakPoints::IsAddressBreakPoint(addr))
|
||||
return 1;
|
||||
|
||||
// there may be a breakpoint in the delay slot
|
||||
if (isBranchOrJump(addr) && CBreakPoints::IsAddressBreakPoint(addr+4))
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isMemcheckNeeded(u32 pc)
|
||||
{
|
||||
if (CBreakPoints::GetNumMemchecks() == 0)
|
||||
return 0;
|
||||
|
||||
u32 addr = pc;
|
||||
if (isBranchOrJump(addr))
|
||||
addr += 4;
|
||||
|
||||
u32 op = memRead32(addr);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
|
||||
if (opcode.flags & IS_MEMORY)
|
||||
return addr == pc ? 1 : 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -436,6 +436,10 @@ extern void cpuTestINTCInts();
|
|||
extern void cpuTestDMACInts();
|
||||
extern void cpuTestTIMRInts();
|
||||
|
||||
// breakpoint code shared between interpreter and recompiler
|
||||
int isMemcheckNeeded(u32 pc);
|
||||
int isBreakpointNeeded(u32 addr);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Exception Codes
|
||||
|
||||
|
|
|
@ -1356,47 +1356,6 @@ void recMemcheck(u32 op, u32 bits, bool store)
|
|||
}
|
||||
}
|
||||
|
||||
inline bool isBranchOrJump(u32 addr)
|
||||
{
|
||||
u32 op = memRead32(addr);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
|
||||
return (opcode.flags & IS_BRANCH) != 0;
|
||||
}
|
||||
|
||||
// The next two functions return 0 if no breakpoint is needed,
|
||||
// 1 if it's needed on the current pc, 2 if it's needed in the delay slot
|
||||
|
||||
int isBreakpointNeeded(u32 addr)
|
||||
{
|
||||
if (CBreakPoints::IsAddressBreakPoint(addr))
|
||||
return 1;
|
||||
|
||||
// there may be a breakpoint in the delay slot
|
||||
if (isBranchOrJump(addr) && CBreakPoints::IsAddressBreakPoint(addr+4))
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isMemcheckNeeded(u32 pc)
|
||||
{
|
||||
if (CBreakPoints::GetMemChecks().size() == 0)
|
||||
return 0;
|
||||
|
||||
u32 addr = pc;
|
||||
if (isBranchOrJump(addr))
|
||||
addr += 4;
|
||||
|
||||
u32 op = memRead32(addr);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
|
||||
if ((opcode.flags & IS_MEMORY) && (opcode.flags & MEMTYPE_MASK) != 0)
|
||||
return addr == pc ? 1 : 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void encodeBreakpoint()
|
||||
{
|
||||
if (isBreakpointNeeded(pc) != 0)
|
||||
|
|
Loading…
Reference in New Issue