mirror of
https://github.com/libretro/Play-.git
synced 2025-02-18 18:48:25 +00:00
Breakpoints now work again.
This commit is contained in:
parent
050bf0f854
commit
3210ffecfa
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -41,6 +41,7 @@ enum
|
||||
MIPS_EXCEPTION_IDLE,
|
||||
MIPS_EXCEPTION_RETURNFROMEXCEPTION,
|
||||
MIPS_EXCEPTION_CALLMS,
|
||||
MIPS_EXCEPTION_BREAKPOINT,
|
||||
};
|
||||
|
||||
#define MIPS_EXECUTION_STATUS_QUOTADONE 0x80
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user