Breakpoints now work again.

This commit is contained in:
Jean-Philip Desjardins 2018-07-21 20:49:58 -04:00
parent 050bf0f854
commit 3210ffecfa
11 changed files with 89 additions and 28 deletions

View File

@ -188,6 +188,8 @@ void CBasicBlock::CompileRange(CMipsJitter* jitter)
return;
}
CompileProlog(jitter);
for(uint32 address = m_begin; address <= m_end; address += 4)
{
m_context.m_pArch->CompileInstruction(
@ -202,6 +204,24 @@ void CBasicBlock::CompileRange(CMipsJitter* jitter)
CompileEpilog(jitter);
}
void CBasicBlock::CompileProlog(CMipsJitter* jitter)
{
#ifdef DEBUGGER_INCLUDED
if(HasBreakpoint())
{
jitter->PushCtx();
jitter->Call(reinterpret_cast<void*>(&BreakpointFilter), 1, Jitter::CJitter::RETURN_VALUE_32);
jitter->PushCst(0);
jitter->BeginIf(Jitter::CONDITION_EQ);
{
jitter->JumpTo(reinterpret_cast<void*>(&BreakpointHandler));
}
jitter->EndIf();
}
#endif
}
void CBasicBlock::CompileEpilog(CMipsJitter* jitter)
{
//Update cycle quota
@ -358,11 +378,31 @@ void CBasicBlock::HandleExternalFunctionReference(uintptr_t symbol, uint32 offse
}
}
bool CBasicBlock::HasBreakpoint() const
{
for(auto breakpointAddress : m_context.m_breakpoints)
{
if(breakpointAddress >= GetBeginAddress() && breakpointAddress <= GetEndAddress()) return true;
}
return false;
}
void CBasicBlock::EmptyBlockHandler(CMIPS* context)
{
context->m_emptyBlockHandler(context);
}
uint32 CBasicBlock::BreakpointFilter(CMIPS* context)
{
return context->m_executor->FilterBreakpoint();
}
void CBasicBlock::BreakpointHandler(CMIPS* context)
{
assert(context->m_State.nHasException == MIPS_EXCEPTION_NONE);
context->m_State.nHasException = MIPS_EXCEPTION_BREAKPOINT;
}
void CBasicBlock::NextBlockTrampoline(CMIPS* context)
{
}

View File

@ -75,12 +75,17 @@ protected:
CMIPS& m_context;
virtual void CompileRange(CMipsJitter*);
void CompileProlog(CMipsJitter*);
void CompileEpilog(CMipsJitter*);
private:
void HandleExternalFunctionReference(uintptr_t, uint32);
bool HasBreakpoint() const;
static void EmptyBlockHandler(CMIPS*);
static uint32 BreakpointFilter(CMIPS*);
static void BreakpointHandler(CMIPS*);
static void NextBlockTrampoline(CMIPS*);
#ifdef AOT_BUILD_CACHE

View File

@ -48,17 +48,25 @@ public:
int Execute(int cycles) override
{
m_context.m_State.cycleQuota = cycles;
#ifdef DEBUGGER_INCLUDED
m_mustBreak = false;
m_initQuota = cycles;
#endif
while(m_context.m_State.nHasException == 0)
{
uint32 address = m_context.m_State.nPC & m_addressMask;
auto block = m_blockLookup.FindBlockAt(address);
#ifdef DEBUGGER_INCLUDED
if(!m_breakpointsDisabledOnce && MustBreak()) break;
m_breakpointsDisabledOnce = false;
#endif
block->Execute();
}
m_context.m_State.nHasException &= ~MIPS_EXECUTION_STATUS_QUOTADONE;
#ifdef DEBUGGER_INCLUDED
if(m_context.m_State.nHasException == MIPS_EXCEPTION_BREAKPOINT)
{
m_mustBreak = true;
m_context.m_State.nHasException = MIPS_EXCEPTION_NONE;
}
m_breakpointsDisabledOnce = false;
#endif
return m_context.m_State.cycleQuota;
}
@ -75,31 +83,32 @@ public:
m_pendingBlockLinks.clear();
}
void ClearActiveBlocksInRange(uint32 start, uint32 end) override
void ClearActiveBlocksInRange(uint32 start, uint32 end, bool executing) override
{
ClearActiveBlocksInRangeInternal(start, end, nullptr);
CBasicBlock* currentBlock = nullptr;
if(executing)
{
currentBlock = FindBlockStartingAt(m_context.m_State.nPC);
assert(!currentBlock->IsEmpty());
}
ClearActiveBlocksInRangeInternal(start, end, currentBlock);
}
#ifdef DEBUGGER_INCLUDED
bool MustBreak() const override
{
uint32 currentPc = m_context.m_State.nPC & m_addressMask;
auto block = m_blockLookup.FindBlockAt(currentPc);
for(auto breakPointAddress : m_context.m_breakpoints)
{
if(currentPc == breakPointAddress) return true;
if(block != NULL)
{
if(breakPointAddress >= block->GetBeginAddress() && breakPointAddress <= block->GetEndAddress()) return true;
}
}
return false;
return m_mustBreak;
}
void DisableBreakpointsOnce() override
{
m_breakpointsDisabledOnce = true;
}
bool FilterBreakpoint() override
{
return ((m_initQuota == m_context.m_State.cycleQuota) && m_breakpointsDisabledOnce);
}
#endif
protected:
@ -303,6 +312,8 @@ protected:
BlockLookupType m_blockLookup;
#ifdef DEBUGGER_INCLUDED
bool m_mustBreak = false;
bool m_breakpointsDisabledOnce = false;
int m_initQuota = 0;
#endif
};

View File

@ -54,9 +54,12 @@ void CMIPS::ToggleBreakpoint(uint32 address)
if(m_breakpoints.find(address) != m_breakpoints.end())
{
m_breakpoints.erase(address);
return;
}
m_breakpoints.insert(address);
else
{
m_breakpoints.insert(address);
}
m_executor->ClearActiveBlocksInRange(address, address + 4, false);
}
int32 CMIPS::GetBranch(uint16 nData)

View File

@ -41,6 +41,7 @@ enum
MIPS_EXCEPTION_IDLE,
MIPS_EXCEPTION_RETURNFROMEXCEPTION,
MIPS_EXCEPTION_CALLMS,
MIPS_EXCEPTION_BREAKPOINT,
};
#define MIPS_EXECUTION_STATUS_QUOTADONE 0x80

View File

@ -8,10 +8,11 @@ public:
virtual ~CMipsExecutor() = default;
virtual void Reset() = 0;
virtual int Execute(int) = 0;
virtual void ClearActiveBlocksInRange(uint32 start, uint32 end) = 0;
virtual void ClearActiveBlocksInRange(uint32 start, uint32 end, bool executing) = 0;
#ifdef DEBUGGER_INCLUDED
virtual bool MustBreak() const = 0;
virtual void DisableBreakpointsOnce() = 0;
virtual bool FilterBreakpoint() = 0;
#endif
};

View File

@ -99,13 +99,11 @@ void CEeExecutor::Reset()
CGenericMipsExecutor::Reset();
}
void CEeExecutor::ClearActiveBlocksInRange(uint32 start, uint32 end)
void CEeExecutor::ClearActiveBlocksInRange(uint32 start, uint32 end, bool executing)
{
uint32 rangeSize = end - start;
SetMemoryProtected(m_ram + start, rangeSize, false);
auto currentBlock = FindBlockStartingAt(m_context.m_State.nPC);
assert(!currentBlock->IsEmpty());
ClearActiveBlocksInRangeInternal(start, end, currentBlock);
CGenericMipsExecutor::ClearActiveBlocksInRange(start, end, executing);
}
BasicBlockPtr CEeExecutor::BlockFactory(CMIPS& context, uint32 start, uint32 end)
@ -126,7 +124,7 @@ bool CEeExecutor::HandleAccessFault(intptr_t ptr)
if(addr >= 0 && addr < PS2::EE_RAM_SIZE)
{
addr &= ~(m_pageSize - 1);
ClearActiveBlocksInRange(addr, addr + m_pageSize);
ClearActiveBlocksInRange(addr, addr + m_pageSize, true);
return true;
}
return false;

View File

@ -21,7 +21,7 @@ public:
void RemoveExceptionHandler();
void Reset() override;
void ClearActiveBlocksInRange(uint32, uint32) override;
void ClearActiveBlocksInRange(uint32, uint32, bool) override;
BasicBlockPtr BlockFactory(CMIPS&, uint32, uint32) override;

View File

@ -160,7 +160,7 @@ void CVpu::ExecuteMicroProgram(uint32 nAddress)
void CVpu::InvalidateMicroProgram()
{
m_ctx->m_executor->ClearActiveBlocksInRange(0, (m_number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE);
m_ctx->m_executor->ClearActiveBlocksInRange(0, (m_number == 0) ? PS2::MICROMEM0SIZE : PS2::MICROMEM1SIZE, false);
}
void CVpu::ProcessXgKick(uint32 address)

View File

@ -11,6 +11,8 @@ CVuBasicBlock::CVuBasicBlock(CMIPS& context, uint32 begin, uint32 end)
void CVuBasicBlock::CompileRange(CMipsJitter* jitter)
{
CompileProlog(jitter);
assert((m_begin & 0x07) == 0);
assert(((m_end + 4) & 0x07) == 0);
auto arch = static_cast<CMA_VU*>(m_context.m_pArch);

View File

@ -660,7 +660,7 @@ int32 CIopBios::UnloadModule(uint32 loadedModuleId)
//TODO: Remove module from IOP module list?
//TODO: Invalidate MIPS analysis range?
m_cpu.m_executor->ClearActiveBlocksInRange(loadedModule->start, loadedModule->end);
m_cpu.m_executor->ClearActiveBlocksInRange(loadedModule->start, loadedModule->end, false);
//TODO: Check return value here.
m_sysmem->FreeMemory(loadedModule->start);