Jit: Implement tlbie

Now that tlbie isn't calling into C++ code anymore, what tlbie does is
simple enough that we can reasonably implement it in the JITs.
This commit is contained in:
JosJuice
2026-05-01 14:24:25 +02:00
parent 7d9c712f1b
commit 6af1d59444
6 changed files with 67 additions and 2 deletions

View File

@@ -272,6 +272,8 @@ public:
void eieio(UGeckoInstruction inst);
void tlbie(UGeckoInstruction inst);
private:
void CompileInstruction(PPCAnalyst::CodeOp& op);

View File

@@ -287,7 +287,7 @@ constexpr std::array<Jit64OpTemplate, 107> s_table31{{
{310, &Jit64::FallBackToInterpreter}, // eciwx
{438, &Jit64::FallBackToInterpreter}, // ecowx
{854, &Jit64::eieio}, // eieio
{306, &Jit64::FallBackToInterpreter}, // tlbie
{306, &Jit64::tlbie}, // tlbie
{566, &Jit64::DoNothing}, // tlbsync
}};

View File

@@ -707,3 +707,30 @@ void Jit64::eieio(UGeckoInstruction inst)
if (jo.optimizeGatherPipe && js.fifoBytesSinceCheck > 0)
js.mustCheckFifo = true;
}
void Jit64::tlbie(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
RCOpArg Rb = gpr.Use(inst.RB, RCMode::Read);
RegCache::Realize(Rb);
constexpr decltype(PowerPC::PowerPCState::tlb) tlb;
constexpr size_t tlb_size = sizeof(tlb) / tlb.size();
constexpr size_t tlb_way_size = sizeof(tlb[0]) / tlb[0].size();
static_assert(tlb_way_size == (8 + 1) * 4);
MOV(32, R(RSCRATCH), Rb);
SHR(32, R(RSCRATCH), Imm8(PowerPC::HW_PAGE_INDEX_SHIFT));
AND(32, R(RSCRATCH), Imm8(PowerPC::HW_PAGE_INDEX_MASK));
LEA(32, RSCRATCH, MComplex(RSCRATCH, RSCRATCH, SCALE_8, 0));
MOV(8, PPCSTATE(pagetable_update_pending), Imm8(1));
if (m_ppc_state.msr.DR && jo.fastmem_arena)
MOV(64, R(RMEM), ImmPtr(m_system.GetMemory().GetLogicalBaseWithoutPageTable()));
MOV(64, R(RSCRATCH2), Imm64(-1));
MOV(64, MComplex(RPPCSTATE, RSCRATCH, SCALE_4, PPCSTATE_OFF(tlb)), R(RSCRATCH2));
MOV(64, MComplex(RPPCSTATE, RSCRATCH, SCALE_4, PPCSTATE_OFF(tlb) + tlb_size), R(RSCRATCH2));
}

View File

@@ -145,6 +145,7 @@ public:
void dcbt(UGeckoInstruction inst);
void dcbz(UGeckoInstruction inst);
void eieio(UGeckoInstruction inst);
void tlbie(UGeckoInstruction inst);
// LoadStore floating point
void lfXX(UGeckoInstruction inst);

View File

@@ -1051,3 +1051,38 @@ void JitArm64::eieio(UGeckoInstruction inst)
if (jo.optimizeGatherPipe && js.fifoBytesSinceCheck > 0)
js.mustCheckFifo = true;
}
void JitArm64::tlbie(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
const ARM64Reg RB = gpr.R(inst.RB);
const auto WA = gpr.GetScopedReg();
const auto WB = gpr.GetScopedReg();
const ARM64Reg XA = EncodeRegTo64(WA);
const ARM64Reg XB = EncodeRegTo64(WB);
constexpr u32 index_bits = 6;
static_assert(1 << index_bits == PowerPC::TLB_SIZE / PowerPC::TLB_WAYS);
static_assert((1 << index_bits) - 1 == PowerPC::HW_PAGE_INDEX_MASK);
UBFX(WA, RB, PowerPC::HW_PAGE_INDEX_SHIFT, index_bits);
MOVI2R(WB, 1);
STRB(IndexType::Unsigned, WB, PPC_REG, PPCSTATE_OFF(pagetable_update_pending));
constexpr decltype(PowerPC::PowerPCState::tlb) tlb;
static_assert(sizeof(tlb[0]) / tlb[0].size() == ((1 << 3) + 1) << 2);
ADD(WA, WA, WA, ArithOption(WA, ShiftType::LSL, 3));
ADD(XA, PPC_REG, XA, ArithOption(XA, ShiftType::LSL, 2));
if (m_ppc_state.msr.DR && jo.fastmem)
{
MOVP2R(MEM_REG, m_system.GetMemory().GetLogicalBaseWithoutPageTable());
STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
}
MOVI2R(XB, 0xffff'ffff'ffff'ffff);
STR(IndexType::Unsigned, XB, XA, PPCSTATE_OFF_STD_ARRAY(tlb, 0));
STR(IndexType::Unsigned, XB, XA, PPCSTATE_OFF_STD_ARRAY(tlb, 1));
}

View File

@@ -287,7 +287,7 @@ constexpr std::array<JitArm64OpTemplate, 107> s_table31{{
{310, &JitArm64::FallBackToInterpreter}, // eciwx
{438, &JitArm64::FallBackToInterpreter}, // ecowx
{854, &JitArm64::eieio}, // eieio
{306, &JitArm64::FallBackToInterpreter}, // tlbie
{306, &JitArm64::tlbie}, // tlbie
{566, &JitArm64::DoNothing}, // tlbsync
}};