mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-04-27 18:25:41 -04:00
CPU/Recompiler/ARM: Optimize icache check
This commit is contained in:
parent
e2db78b0ef
commit
5ff9783626
@ -1749,6 +1749,48 @@ void CodeGenerator::EmitCancelInterpreterLoadDelayForReg(Reg reg)
|
|||||||
m_emit->Bind(&skip_cancel);
|
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 = a32::r0;
|
||||||
|
const auto& current_tag_reg = a32::r1;
|
||||||
|
const auto& existing_tag_reg = a32::r2;
|
||||||
|
|
||||||
|
VirtualMemoryAddress current_pc = m_pc & ICACHE_TAG_ADDRESS_MASK;
|
||||||
|
m_emit->ldr(ticks_reg, a32::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));
|
||||||
|
|
||||||
|
a32::Label cache_hit;
|
||||||
|
m_emit->ldr(existing_tag_reg, a32::MemOperand(GetCPUPtrReg(), offset));
|
||||||
|
m_emit->cmp(existing_tag_reg, current_tag_reg);
|
||||||
|
m_emit->B(a32::eq, &cache_hit);
|
||||||
|
|
||||||
|
m_emit->str(current_tag_reg, a32::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, a32::MemOperand(GetCPUPtrReg(), offsetof(State, pending_ticks)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitStallUntilGTEComplete()
|
void CodeGenerator::EmitStallUntilGTEComplete()
|
||||||
{
|
{
|
||||||
static_assert(offsetof(State, pending_ticks) + sizeof(u32) == offsetof(State, gte_completion_tick));
|
static_assert(offsetof(State, pending_ticks) + sizeof(u32) == offsetof(State, gte_completion_tick));
|
||||||
|
@ -1936,6 +1936,49 @@ void CodeGenerator::EmitCancelInterpreterLoadDelayForReg(Reg reg)
|
|||||||
m_emit->Bind(&skip_cancel);
|
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()
|
void CodeGenerator::EmitStallUntilGTEComplete()
|
||||||
{
|
{
|
||||||
static_assert(offsetof(State, pending_ticks) + sizeof(u32) == offsetof(State, gte_completion_tick));
|
static_assert(offsetof(State, pending_ticks) + sizeof(u32) == offsetof(State, gte_completion_tick));
|
||||||
|
@ -160,7 +160,7 @@ void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CPU_X64
|
#if 0 // Not used
|
||||||
|
|
||||||
void CodeGenerator::EmitICacheCheckAndUpdate()
|
void CodeGenerator::EmitICacheCheckAndUpdate()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user