diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index da1be2db04..2254aa5640 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -272,6 +272,8 @@ public: void eieio(UGeckoInstruction inst); + void tlbie(UGeckoInstruction inst); + private: void CompileInstruction(PPCAnalyst::CodeOp& op); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index be5458bffc..9399feefd6 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -287,7 +287,7 @@ constexpr std::array 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 }}; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index 51fd336760..1831342276 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -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)); +} diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 9c23112e1c..84cdb35478 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -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); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index 8c80151e91..a85cb28a44 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -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)); +} diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index dc72083d39..2f39087511 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -287,7 +287,7 @@ constexpr std::array 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 }};