Sped up the Dolphin debugger in JIT mode by splitting a block only while stepping or when it contains a breakpoint. The block is invalidated when a breakpoint is set or cleared.

Fixed a bug in the JitCache where the JIT icache was not being invalidated when a block containing the instruction was destroyed.
This commit is contained in:
skidau 2012-03-15 21:48:19 +11:00
parent dc79d68e72
commit 8ed6ea3b07
8 changed files with 81 additions and 10 deletions

View File

@ -19,6 +19,7 @@
#include "DebugInterface.h"
#include "BreakPoints.h"
#include <sstream>
#include "..\..\Core\Src\PowerPC\JitCommon\JitBase.h"
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
{
@ -70,7 +71,11 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
void BreakPoints::Add(const TBreakPoint& bp)
{
if (!IsAddressBreakPoint(bp.iAddress))
{
m_BreakPoints.push_back(bp);
if (jit)
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
}
}
void BreakPoints::Add(u32 em_address, bool temp)
@ -83,21 +88,35 @@ void BreakPoints::Add(u32 em_address, bool temp)
pt.iAddress = em_address;
m_BreakPoints.push_back(pt);
if (jit)
jit->GetBlockCache()->InvalidateICache(em_address, 4);
}
}
void BreakPoints::Remove(u32 _iAddress)
void BreakPoints::Remove(u32 em_address)
{
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
{
if (i->iAddress == _iAddress)
if (i->iAddress == em_address)
{
m_BreakPoints.erase(i);
if (jit)
jit->GetBlockCache()->InvalidateICache(em_address, 4);
return;
}
}
}
void BreakPoints::Clear()
{
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
{
if (jit)
jit->GetBlockCache()->InvalidateICache(i->iAddress, 4);
m_BreakPoints.erase(i);
}
}
MemChecks::TMemChecksStr MemChecks::GetStrings() const
{

View File

@ -78,7 +78,7 @@ public:
// Remove Breakpoint
void Remove(u32 _iAddress);
void Clear() { m_BreakPoints.clear(); };
void Clear();
void DeleteByAddress(u32 _Address);

View File

@ -415,9 +415,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
// Comment out the following to disable breakpoints (speed-up)
blockSize = 1;
broken_block = true;
if (GetState() == CPU_STEPPING)
blockSize = 1;
Trace();
}
@ -597,6 +596,20 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
SetJumpTarget(clearInt);
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
MOV(32, M(&PC), Imm32(ops[i].address));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExit(ops[i].address, 0);
SetJumpTarget(noBreakpoint);
}
Jit64Tables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))

View File

@ -1269,7 +1269,8 @@ static const unsigned alwaysUsedList[] = {
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheckStart,
FPExceptionCheckEnd, ISIException, ExtExceptionCheck, Int3, Tramp, Nop
FPExceptionCheckEnd, ISIException, ExtExceptionCheck, BreakPointCheck,
Int3, Tramp, Nop
};
static const unsigned extra8RegList[] = {
LoadGReg, LoadCR, LoadGQR, LoadFReg, LoadFRegDENToZero,

View File

@ -168,7 +168,7 @@ enum Opcode {
// used for exception checking, at least until someone
// has a better idea of integrating it
FPExceptionCheckStart, FPExceptionCheckEnd,
ISIException,ExtExceptionCheck,
ISIException, ExtExceptionCheck, BreakPointCheck,
// "Opcode" representing a register too far away to
// reference directly; this is a size optimization
Tramp,
@ -414,6 +414,9 @@ public:
InstLoc EmitExtExceptionCheck(InstLoc pc) {
return EmitUOp(ExtExceptionCheck, pc);
}
InstLoc EmitBreakPointCheck(InstLoc pc) {
return EmitUOp(BreakPointCheck, pc);
}
InstLoc EmitRFIExit() {
return FoldZeroOp(RFIExit, 0);
}

View File

@ -763,6 +763,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
case FPExceptionCheckEnd:
case ISIException:
case ExtExceptionCheck:
case BreakPointCheck:
case Int3:
case Tramp:
// No liveness effects
@ -1943,6 +1944,17 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->SetJumpTarget(clearInt);
break;
}
case BreakPointCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z);
Jit->WriteExit(InstLoc, 0);
Jit->SetJumpTarget(noBreakpoint);
break;
}
case Int3: {
Jit->INT3();
break;

View File

@ -523,8 +523,8 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
// Comment out the following to disable breakpoints (speed-up)
blockSize = 1;
if (GetState() == CPU_STEPPING)
blockSize = 1;
Trace();
}
@ -653,6 +653,11 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));
}
JitILTables::CompileInstruction(ops[i]);

View File

@ -417,6 +417,24 @@ bool JitBlock::ContainsAddress(u32 em_address)
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(address, 0)), it2 = it1, it;
while (it2 != block_map.end() && it2->first.second < address + length)
{
#ifdef JIT_UNLIMITED_ICACHE
JitBlock &b = blocks[it2->second];
if (b.originalAddress & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
else if (b.originalAddress & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
else
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
#endif
DestroyBlock(it2->second, true);
it2++;
}