|
|
|
@ -1936,6 +1936,49 @@ void CodeGenerator::EmitCancelInterpreterLoadDelayForReg(Reg reg)
|
|
|
|
|
m_emit->Bind(&skip_cancel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodeGenerator::EmitICacheCheckAndUpdate()
|
|
|
|
|
{
|
|
|
|
|
if (GetSegmentForAddress(m_pc) >= Segment::KSEG1)
|
|
|
|
|
{
|
|
|
|
|
EmitAddCPUStructField(offsetof(State, pending_ticks),
|
|
|
|
|
Value::FromConstantU32(static_cast<u32>(m_block->uncached_fetch_ticks)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const auto& ticks_reg = a64::w0;
|
|
|
|
|
const auto& current_tag_reg = a64::w1;
|
|
|
|
|
const auto& existing_tag_reg = a64::w2;
|
|
|
|
|
|
|
|
|
|
VirtualMemoryAddress current_pc = m_pc & ICACHE_TAG_ADDRESS_MASK;
|
|
|
|
|
m_emit->Ldr(ticks_reg, a64::MemOperand(GetCPUPtrReg(), offsetof(State, pending_ticks)));
|
|
|
|
|
m_emit->Mov(current_tag_reg, current_pc);
|
|
|
|
|
|
|
|
|
|
for (u32 i = 0; i < m_block->icache_line_count; i++, current_pc += ICACHE_LINE_SIZE)
|
|
|
|
|
{
|
|
|
|
|
const TickCount fill_ticks = GetICacheFillTicks(current_pc);
|
|
|
|
|
if (fill_ticks <= 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const u32 line = GetICacheLine(current_pc);
|
|
|
|
|
const u32 offset = offsetof(State, icache_tags) + (line * sizeof(u32));
|
|
|
|
|
|
|
|
|
|
a64::Label cache_hit;
|
|
|
|
|
m_emit->Ldr(existing_tag_reg, a64::MemOperand(GetCPUPtrReg(), offset));
|
|
|
|
|
m_emit->Cmp(existing_tag_reg, current_tag_reg);
|
|
|
|
|
m_emit->B(&cache_hit, a64::eq);
|
|
|
|
|
|
|
|
|
|
m_emit->Str(current_tag_reg, a64::MemOperand(GetCPUPtrReg(), offset));
|
|
|
|
|
EmitAdd(0, 0, Value::FromConstantU32(static_cast<u32>(fill_ticks)), false);
|
|
|
|
|
m_emit->Bind(&cache_hit);
|
|
|
|
|
|
|
|
|
|
if (i != (m_block->icache_line_count - 1))
|
|
|
|
|
m_emit->Add(current_tag_reg, current_tag_reg, ICACHE_LINE_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_emit->Str(ticks_reg, a64::MemOperand(GetCPUPtrReg(), offsetof(State, pending_ticks)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodeGenerator::EmitStallUntilGTEComplete()
|
|
|
|
|
{
|
|
|
|
|
static_assert(offsetof(State, pending_ticks) + sizeof(u32) == offsetof(State, gte_completion_tick));
|
|
|
|
|