mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-14 00:09:24 +01:00
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:
parent
dc79d68e72
commit
8ed6ea3b07
@ -19,6 +19,7 @@
|
|||||||
#include "DebugInterface.h"
|
#include "DebugInterface.h"
|
||||||
#include "BreakPoints.h"
|
#include "BreakPoints.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "..\..\Core\Src\PowerPC\JitCommon\JitBase.h"
|
||||||
|
|
||||||
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
|
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
|
||||||
{
|
{
|
||||||
@ -70,7 +71,11 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
|
|||||||
void BreakPoints::Add(const TBreakPoint& bp)
|
void BreakPoints::Add(const TBreakPoint& bp)
|
||||||
{
|
{
|
||||||
if (!IsAddressBreakPoint(bp.iAddress))
|
if (!IsAddressBreakPoint(bp.iAddress))
|
||||||
|
{
|
||||||
m_BreakPoints.push_back(bp);
|
m_BreakPoints.push_back(bp);
|
||||||
|
if (jit)
|
||||||
|
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::Add(u32 em_address, bool temp)
|
void BreakPoints::Add(u32 em_address, bool temp)
|
||||||
@ -83,21 +88,35 @@ void BreakPoints::Add(u32 em_address, bool temp)
|
|||||||
pt.iAddress = em_address;
|
pt.iAddress = em_address;
|
||||||
|
|
||||||
m_BreakPoints.push_back(pt);
|
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)
|
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);
|
m_BreakPoints.erase(i);
|
||||||
|
if (jit)
|
||||||
|
jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
||||||
return;
|
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
|
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||||
{
|
{
|
||||||
|
@ -78,7 +78,7 @@ public:
|
|||||||
|
|
||||||
// Remove Breakpoint
|
// Remove Breakpoint
|
||||||
void Remove(u32 _iAddress);
|
void Remove(u32 _iAddress);
|
||||||
void Clear() { m_BreakPoints.clear(); };
|
void Clear();
|
||||||
|
|
||||||
void DeleteByAddress(u32 _Address);
|
void DeleteByAddress(u32 _Address);
|
||||||
|
|
||||||
|
@ -415,9 +415,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
|||||||
|
|
||||||
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
||||||
{
|
{
|
||||||
// Comment out the following to disable breakpoints (speed-up)
|
if (GetState() == CPU_STEPPING)
|
||||||
blockSize = 1;
|
blockSize = 1;
|
||||||
broken_block = true;
|
|
||||||
Trace();
|
Trace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,6 +596,20 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
|||||||
SetJumpTarget(clearInt);
|
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]);
|
Jit64Tables::CompileInstruction(ops[i]);
|
||||||
|
|
||||||
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
|
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
|
||||||
|
@ -1269,7 +1269,8 @@ static const unsigned alwaysUsedList[] = {
|
|||||||
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
|
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
|
||||||
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
|
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
|
||||||
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheckStart,
|
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheckStart,
|
||||||
FPExceptionCheckEnd, ISIException, ExtExceptionCheck, Int3, Tramp, Nop
|
FPExceptionCheckEnd, ISIException, ExtExceptionCheck, BreakPointCheck,
|
||||||
|
Int3, Tramp, Nop
|
||||||
};
|
};
|
||||||
static const unsigned extra8RegList[] = {
|
static const unsigned extra8RegList[] = {
|
||||||
LoadGReg, LoadCR, LoadGQR, LoadFReg, LoadFRegDENToZero,
|
LoadGReg, LoadCR, LoadGQR, LoadFReg, LoadFRegDENToZero,
|
||||||
|
@ -168,7 +168,7 @@ enum Opcode {
|
|||||||
// used for exception checking, at least until someone
|
// used for exception checking, at least until someone
|
||||||
// has a better idea of integrating it
|
// has a better idea of integrating it
|
||||||
FPExceptionCheckStart, FPExceptionCheckEnd,
|
FPExceptionCheckStart, FPExceptionCheckEnd,
|
||||||
ISIException,ExtExceptionCheck,
|
ISIException, ExtExceptionCheck, BreakPointCheck,
|
||||||
// "Opcode" representing a register too far away to
|
// "Opcode" representing a register too far away to
|
||||||
// reference directly; this is a size optimization
|
// reference directly; this is a size optimization
|
||||||
Tramp,
|
Tramp,
|
||||||
@ -414,6 +414,9 @@ public:
|
|||||||
InstLoc EmitExtExceptionCheck(InstLoc pc) {
|
InstLoc EmitExtExceptionCheck(InstLoc pc) {
|
||||||
return EmitUOp(ExtExceptionCheck, pc);
|
return EmitUOp(ExtExceptionCheck, pc);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitBreakPointCheck(InstLoc pc) {
|
||||||
|
return EmitUOp(BreakPointCheck, pc);
|
||||||
|
}
|
||||||
InstLoc EmitRFIExit() {
|
InstLoc EmitRFIExit() {
|
||||||
return FoldZeroOp(RFIExit, 0);
|
return FoldZeroOp(RFIExit, 0);
|
||||||
}
|
}
|
||||||
|
@ -763,6 +763,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
|
|||||||
case FPExceptionCheckEnd:
|
case FPExceptionCheckEnd:
|
||||||
case ISIException:
|
case ISIException:
|
||||||
case ExtExceptionCheck:
|
case ExtExceptionCheck:
|
||||||
|
case BreakPointCheck:
|
||||||
case Int3:
|
case Int3:
|
||||||
case Tramp:
|
case Tramp:
|
||||||
// No liveness effects
|
// No liveness effects
|
||||||
@ -1943,6 +1944,17 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
|
|||||||
Jit->SetJumpTarget(clearInt);
|
Jit->SetJumpTarget(clearInt);
|
||||||
break;
|
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: {
|
case Int3: {
|
||||||
Jit->INT3();
|
Jit->INT3();
|
||||||
break;
|
break;
|
||||||
|
@ -523,8 +523,8 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
|||||||
|
|
||||||
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
||||||
{
|
{
|
||||||
// Comment out the following to disable breakpoints (speed-up)
|
if (GetState() == CPU_STEPPING)
|
||||||
blockSize = 1;
|
blockSize = 1;
|
||||||
Trace();
|
Trace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,6 +653,11 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
|||||||
{
|
{
|
||||||
ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address));
|
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]);
|
JitILTables::CompileInstruction(ops[i]);
|
||||||
|
|
||||||
|
@ -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;
|
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)
|
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);
|
DestroyBlock(it2->second, true);
|
||||||
it2++;
|
it2++;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user