Merge pull request #11988 from JosJuice/jit-feature-flags

Jit: Replace "msrBits" with "featureFlags" and use for performance monitor
This commit is contained in:
Mai
2023-12-05 03:13:50 -05:00
committed by GitHub
31 changed files with 291 additions and 140 deletions
+3
View File
@@ -460,6 +460,9 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename)
SetupBAT(system, /*is_wii*/ false);
ppc_state.pc = 0x81200150;
PowerPC::MSRUpdated(ppc_state);
return true;
}
+1
View File
@@ -74,6 +74,7 @@ void CBoot::SetupMSR(PowerPC::PowerPCState& ppc_state)
ppc_state.msr.DR = 1;
ppc_state.msr.IR = 1;
ppc_state.msr.FP = 1;
PowerPC::MSRUpdated(ppc_state);
}
void CBoot::SetupHID(PowerPC::PowerPCState& ppc_state, bool is_wii)
@@ -651,6 +651,8 @@ void FifoPlayer::LoadMemory()
ppc_state.spr[SPR_DBAT1U] = 0xc0001fff;
ppc_state.spr[SPR_DBAT1L] = 0x0000002a;
PowerPC::MSRUpdated(ppc_state);
auto& mmu = system.GetMMU();
mmu.DBATUpdated();
mmu.IBATUpdated();
+7 -2
View File
@@ -84,10 +84,15 @@ bool Load()
}
auto& power_pc = system.GetPowerPC();
const PowerPC::CoreMode core_mode = power_pc.GetMode();
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
power_pc.GetPPCState().msr.Hex = 0;
power_pc.GetPPCState().pc = 0x3400;
PowerPC::PowerPCState& ppc_state = power_pc.GetPPCState();
ppc_state.msr.Hex = 0;
ppc_state.pc = 0x3400;
PowerPC::MSRUpdated(ppc_state);
NOTICE_LOG_FMT(IOS, "Loaded MIOS and bootstrapped PPC.");
// IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes
+3
View File
@@ -661,6 +661,7 @@ static void WriteRegister()
break;
case 65:
ppc_state.msr.Hex = re32hex(bufptr);
PowerPC::MSRUpdated(ppc_state);
break;
case 66:
ppc_state.cr.Set(re32hex(bufptr));
@@ -760,6 +761,7 @@ static void WriteRegister()
break;
case 131:
ppc_state.spr[SPR_MMCR0] = re32hex(bufptr);
PowerPC::MMCRUpdated(ppc_state);
break;
case 132:
ppc_state.spr[SPR_PMC1] = re32hex(bufptr);
@@ -772,6 +774,7 @@ static void WriteRegister()
break;
case 135:
ppc_state.spr[SPR_MMCR1] = re32hex(bufptr);
PowerPC::MMCRUpdated(ppc_state);
break;
case 136:
ppc_state.spr[SPR_PMC3] = re32hex(bufptr);
+7
View File
@@ -926,6 +926,13 @@ enum
EXCEPTION_FAKE_MEMCHECK_HIT = 0x00000200,
};
enum CPUEmuFeatureFlags : u32
{
FEATURE_FLAG_MSR_DR = 1 << 0,
FEATURE_FLAG_MSR_IR = 1 << 1,
FEATURE_FLAG_PERFMON = 1 << 2,
};
constexpr s32 SignExt16(s16 x)
{
return (s32)x;
@@ -134,6 +134,9 @@ void Interpreter::rfi(Interpreter& interpreter, UGeckoInstruction inst)
// else
// set NPC to saved offset and resume
ppc_state.npc = SRR0(ppc_state);
PowerPC::MSRUpdated(ppc_state);
interpreter.m_end_block = true;
}
@@ -181,6 +181,8 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst)
ppc_state.msr.Hex = ppc_state.gpr[inst.RS];
PowerPC::MSRUpdated(ppc_state);
// FE0/FE1 may have been set
CheckFPExceptions(ppc_state);
@@ -489,6 +491,11 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
}
break;
case SPR_MMCR0:
case SPR_MMCR1:
MMCRUpdated(ppc_state);
break;
case SPR_THRM1:
case SPR_THRM2:
case SPR_THRM3:
+32 -14
View File
@@ -337,7 +337,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
gpr.Flush();
fpr.Flush();
if (js.op->opinfo->flags & FL_ENDBLOCK)
if (js.op->canEndBlock)
{
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
MOV(32, PPCSTATE(npc), Imm32(js.compilerPC + 4));
@@ -353,7 +353,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
gpr.Reset(js.op->regsOut);
fpr.Reset(js.op->GetFregsOut());
if (js.op->opinfo->flags & FL_ENDBLOCK)
if (js.op->canEndBlock)
{
if (js.isLastInstruction)
{
@@ -445,8 +445,7 @@ bool Jit64::Cleanup()
did_something = true;
}
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0(m_ppc_state).Hex || MMCR1(m_ppc_state).Hex)
if (m_ppc_state.feature_flags & FEATURE_FLAG_PERFMON)
{
ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionCCCP(PowerPC::UpdatePerformanceMonitor, js.downcountAmount, js.numLoadStoreInst,
@@ -483,8 +482,7 @@ void Jit64::FakeBLCall(u32 after)
// We may need to fake the BLR stack on inlined CALL instructions.
// Else we can't return to this location any more.
MOV(64, R(RSCRATCH2),
Imm64(u64(m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK) << 32 | after));
MOV(64, R(RSCRATCH2), Imm64(u64(m_ppc_state.feature_flags) << 32 | after));
PUSH(RSCRATCH2);
FixupBranch skip_exit = CALL();
POP(RSCRATCH2);
@@ -497,8 +495,11 @@ void Jit64::EmitUpdateMembase()
MOV(64, R(RMEM), PPCSTATE(mem_ptr));
}
void Jit64::EmitStoreMembase(const OpArg& msr, X64Reg scratch_reg)
void Jit64::MSRUpdated(const OpArg& msr, X64Reg scratch_reg)
{
ASSERT(!msr.IsSimpleReg(scratch_reg));
// Update mem_ptr
auto& memory = m_system.GetMemory();
if (msr.IsImm())
{
@@ -513,6 +514,26 @@ void Jit64::EmitStoreMembase(const OpArg& msr, X64Reg scratch_reg)
CMOVcc(64, RMEM, R(scratch_reg), CC_Z);
}
MOV(64, PPCSTATE(mem_ptr), R(RMEM));
// Update feature_flags
static_assert(UReg_MSR{}.DR.StartBit() == 4);
static_assert(UReg_MSR{}.IR.StartBit() == 5);
static_assert(FEATURE_FLAG_MSR_DR == 1 << 0);
static_assert(FEATURE_FLAG_MSR_IR == 1 << 1);
const u32 other_feature_flags = m_ppc_state.feature_flags & ~0x3;
if (msr.IsImm())
{
MOV(32, PPCSTATE(feature_flags), Imm32(other_feature_flags | ((msr.Imm32() >> 4) & 0x3)));
}
else
{
MOV(32, R(scratch_reg), msr);
SHR(32, R(scratch_reg), Imm8(4));
AND(32, R(scratch_reg), Imm32(0x3));
if (other_feature_flags != 0)
OR(32, R(scratch_reg), Imm32(other_feature_flags));
MOV(32, PPCSTATE(feature_flags), R(scratch_reg));
}
}
void Jit64::WriteExit(u32 destination, bool bl, u32 after)
@@ -524,8 +545,7 @@ void Jit64::WriteExit(u32 destination, bool bl, u32 after)
if (bl)
{
MOV(64, R(RSCRATCH2),
Imm64(u64(m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK) << 32 | after));
MOV(64, R(RSCRATCH2), Imm64(u64(m_ppc_state.feature_flags) << 32 | after));
PUSH(RSCRATCH2);
}
@@ -582,8 +602,7 @@ void Jit64::WriteExitDestInRSCRATCH(bool bl, u32 after)
if (bl)
{
MOV(64, R(RSCRATCH2),
Imm64(u64(m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK) << 32 | after));
MOV(64, R(RSCRATCH2), Imm64(u64(m_ppc_state.feature_flags) << 32 | after));
PUSH(RSCRATCH2);
}
@@ -611,10 +630,9 @@ void Jit64::WriteBLRExit()
bool disturbed = Cleanup();
if (disturbed)
MOV(32, R(RSCRATCH), PPCSTATE(pc));
const u64 msr_bits = m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK;
if (msr_bits != 0)
if (m_ppc_state.feature_flags != 0)
{
MOV(32, R(RSCRATCH2), Imm32(msr_bits));
MOV(32, R(RSCRATCH2), Imm32(m_ppc_state.feature_flags));
SHL(64, R(RSCRATCH2), Imm8(32));
OR(64, R(RSCRATCH), R(RSCRATCH2));
}
+1 -1
View File
@@ -88,7 +88,7 @@ public:
// Utilities for use by opcodes
void EmitUpdateMembase();
void EmitStoreMembase(const Gen::OpArg& msr, Gen::X64Reg scratch_reg);
void MSRUpdated(const Gen::OpArg& msr, Gen::X64Reg scratch_reg);
void FakeBLCall(u32 after);
void WriteExit(u32 destination, bool bl = false, u32 after = 0);
void JustWriteExit(u32 destination, bool bl, u32 after);
+11 -12
View File
@@ -19,6 +19,7 @@
#include "Core/System.h"
using namespace Gen;
Jit64AsmRoutineManager::Jit64AsmRoutineManager(Jit64& jit) : CommonAsmRoutines(jit)
{
}
@@ -118,19 +119,17 @@ void Jit64AsmRoutineManager::Generate()
{
if (m_jit.GetBlockCache()->GetEntryPoints())
{
MOV(32, R(RSCRATCH2), PPCSTATE(msr));
AND(32, R(RSCRATCH2), Imm32(JitBaseBlockCache::JIT_CACHE_MSR_MASK));
SHL(64, R(RSCRATCH2), Imm8(28));
MOV(32, R(RSCRATCH2), PPCSTATE(feature_flags));
SHL(64, R(RSCRATCH2), Imm8(32));
MOV(32, R(RSCRATCH_EXTRA), PPCSTATE(pc));
OR(64, R(RSCRATCH_EXTRA), R(RSCRATCH2));
u64 icache = reinterpret_cast<u64>(m_jit.GetBlockCache()->GetEntryPoints());
MOV(64, R(RSCRATCH2), Imm64(icache));
// The entry points map is indexed by ((msrBits << 26) | (address >> 2)).
// The map contains 8 byte 64-bit pointers and that means we need to shift
// msr left by 29 bits and address left by 1 bit to get the correct offset
// in the map.
// The entry points map is indexed by ((feature_flags << 30) | (pc >> 2)).
// The map contains 8-byte pointers and that means we need to shift feature_flags
// left by 33 bits and pc left by 1 bit to get the correct offset in the map.
MOV(64, R(RSCRATCH), MComplex(RSCRATCH2, RSCRATCH_EXTRA, SCALE_2, 0));
}
else
@@ -160,17 +159,17 @@ void Jit64AsmRoutineManager::Generate()
if (!m_jit.GetBlockCache()->GetEntryPoints())
{
// Check block.msrBits.
MOV(32, R(RSCRATCH2), PPCSTATE(msr));
AND(32, R(RSCRATCH2), Imm32(JitBaseBlockCache::JIT_CACHE_MSR_MASK));
// Check block.feature_flags.
MOV(32, R(RSCRATCH2), PPCSTATE(feature_flags));
// Also check the block.effectiveAddress. RSCRATCH_EXTRA still has the PC.
SHL(64, R(RSCRATCH_EXTRA), Imm8(32));
OR(64, R(RSCRATCH2), R(RSCRATCH_EXTRA));
static_assert(offsetof(JitBlockData, msrBits) + 4 ==
static_assert(offsetof(JitBlockData, feature_flags) + 4 ==
offsetof(JitBlockData, effectiveAddress));
CMP(64, R(RSCRATCH2), MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlockData, msrBits))));
CMP(64, R(RSCRATCH2),
MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlockData, feature_flags))));
state_mismatch = J_CC(CC_NE);
// Success; branch to the block we found.
@@ -47,6 +47,7 @@ void Jit64::rfi(UGeckoInstruction inst)
gpr.Flush();
fpr.Flush();
// See Interpreter rfi for details
const u32 mask = 0x87C0FFFF;
const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13]
@@ -56,7 +57,9 @@ void Jit64::rfi(UGeckoInstruction inst)
AND(32, R(RSCRATCH), Imm32(mask & clearMSR13));
OR(32, PPCSTATE(msr), R(RSCRATCH));
EmitStoreMembase(R(RSCRATCH), RSCRATCH2);
// Call MSRUpdated to update feature_flags. Only the bits that come from SRR1
// are relevant for this, so it's fine to pass in RSCRATCH in place of msr.
MSRUpdated(R(RSCRATCH), RSCRATCH2);
// NPC = SRR0;
MOV(32, R(RSCRATCH), PPCSTATE_SRR0);
@@ -320,7 +320,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
FixupBranch bat_lookup_failed;
MOV(32, R(effective_address), R(addr));
const u8* loop_start = GetCodePtr();
if (m_ppc_state.msr.IR)
if (m_ppc_state.feature_flags & FEATURE_FLAG_MSR_IR)
{
// Translate effective address to physical address.
bat_lookup_failed = BATAddressLookup(addr, tmp, m_jit.m_mmu.GetIBATTable().data());
@@ -349,7 +349,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
SwitchToFarCode();
SetJumpTarget(invalidate_needed);
if (m_ppc_state.msr.IR)
if (m_ppc_state.feature_flags & FEATURE_FLAG_MSR_IR)
SetJumpTarget(bat_lookup_failed);
BitSet32 registersInUse = CallerSavedRegistersInUse();
@@ -421,7 +421,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
end_dcbz_hack = J_CC(CC_L);
}
bool emit_fast_path = m_ppc_state.msr.DR && m_jit.jo.fastmem_arena;
bool emit_fast_path = (m_ppc_state.feature_flags & FEATURE_FLAG_MSR_DR) && m_jit.jo.fastmem_arena;
if (emit_fast_path)
{
@@ -23,7 +23,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
JITDISABLE(bJITLoadStorePairedOff);
// For performance, the AsmCommon routines assume address translation is on.
FALLBACK_IF(!m_ppc_state.msr.DR);
FALLBACK_IF(!(m_ppc_state.feature_flags & FEATURE_FLAG_MSR_DR));
s32 offset = inst.SIMM_12;
bool indexed = inst.OPCD == 4;
@@ -112,7 +112,7 @@ void Jit64::psq_lXX(UGeckoInstruction inst)
JITDISABLE(bJITLoadStorePairedOff);
// For performance, the AsmCommon routines assume address translation is on.
FALLBACK_IF(!m_ppc_state.msr.DR);
FALLBACK_IF(!(m_ppc_state.feature_flags & FEATURE_FLAG_MSR_DR));
s32 offset = inst.SIMM_12;
bool indexed = inst.OPCD == 4;
@@ -439,7 +439,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
RegCache::Realize(Rs);
MOV(32, PPCSTATE(msr), Rs);
EmitStoreMembase(Rs, RSCRATCH2);
MSRUpdated(Rs, RSCRATCH2);
}
gpr.Flush();
@@ -371,7 +371,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
}
FixupBranch exit;
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || m_jit.m_ppc_state.msr.DR;
const bool dr_set =
(flags & SAFE_LOADSTORE_DR_ON) || (m_jit.m_ppc_state.feature_flags & FEATURE_FLAG_MSR_DR);
const bool fast_check_address =
!force_slow_access && dr_set && m_jit.jo.fastmem_arena && !m_jit.m_ppc_state.m_enable_dcache;
if (fast_check_address)
@@ -544,7 +545,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
}
FixupBranch exit;
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || m_jit.m_ppc_state.msr.DR;
const bool dr_set =
(flags & SAFE_LOADSTORE_DR_ON) || (m_jit.m_ppc_state.feature_flags & FEATURE_FLAG_MSR_DR);
const bool fast_check_address =
!force_slow_access && dr_set && m_jit.jo.fastmem_arena && !m_jit.m_ppc_state.m_enable_dcache;
if (fast_check_address)
+64 -30
View File
@@ -187,7 +187,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
if (js.op->opinfo->flags & FL_ENDBLOCK)
if (js.op->canEndBlock)
{
// also flush the program counter
ARM64Reg WA = gpr.GetReg();
@@ -207,7 +207,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
fpr.ResetRegisters(js.op->GetFregsOut());
gpr.ResetCRRegisters(js.op->crOut);
if (js.op->opinfo->flags & FL_ENDBLOCK)
if (js.op->canEndBlock)
{
if (js.isLastInstruction)
{
@@ -276,8 +276,7 @@ void JitArm64::Cleanup()
SetJumpTarget(exit);
}
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0(m_ppc_state).Hex || MMCR1(m_ppc_state).Hex)
if (m_ppc_state.feature_flags & FEATURE_FLAG_PERFMON)
{
ABI_CallFunction(&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, js.numLoadStoreInst,
js.numFloatingPointInst, &m_ppc_state);
@@ -348,27 +347,61 @@ void JitArm64::EmitUpdateMembase()
LDR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
}
void JitArm64::EmitStoreMembase(u32 msr)
void JitArm64::MSRUpdated(u32 msr)
{
// Update mem_ptr
auto& memory = m_system.GetMemory();
MOVP2R(MEM_REG,
UReg_MSR(msr).DR ?
(jo.fastmem ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase()) :
(jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase()));
STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
// Update feature_flags
static_assert(UReg_MSR{}.DR.StartBit() == 4);
static_assert(UReg_MSR{}.IR.StartBit() == 5);
static_assert(FEATURE_FLAG_MSR_DR == 1 << 0);
static_assert(FEATURE_FLAG_MSR_IR == 1 << 1);
const u32 other_feature_flags = m_ppc_state.feature_flags & ~0x3;
const u32 feature_flags = other_feature_flags | ((msr >> 4) & 0x3);
if (feature_flags == 0)
{
STR(IndexType::Unsigned, ARM64Reg::WZR, PPC_REG, PPCSTATE_OFF(feature_flags));
}
else
{
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, feature_flags);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
gpr.Unlock(WA);
}
}
void JitArm64::EmitStoreMembase(const ARM64Reg& msr)
void JitArm64::MSRUpdated(ARM64Reg msr)
{
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);
// Update mem_ptr
auto& memory = m_system.GetMemory();
ARM64Reg WD = gpr.GetReg();
ARM64Reg XD = EncodeRegTo64(WD);
MOVP2R(MEM_REG, jo.fastmem ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
MOVP2R(XD, jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
MOVP2R(XA, jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
TST(msr, LogicalImm(1 << (31 - 27), 32));
CSEL(MEM_REG, MEM_REG, XD, CCFlags::CC_NEQ);
CSEL(MEM_REG, MEM_REG, XA, CCFlags::CC_NEQ);
STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
gpr.Unlock(WD);
// Update feature_flags
static_assert(UReg_MSR{}.DR.StartBit() == 4);
static_assert(UReg_MSR{}.IR.StartBit() == 5);
static_assert(FEATURE_FLAG_MSR_DR == 1 << 0);
static_assert(FEATURE_FLAG_MSR_IR == 1 << 1);
const u32 other_feature_flags = m_ppc_state.feature_flags & ~0x3;
UBFX(WA, msr, 4, 2);
if (other_feature_flags != 0)
ORR(WA, WA, LogicalImm(32, other_feature_flags));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
gpr.Unlock(WA);
}
void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return,
@@ -383,20 +416,20 @@ void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return
const u8* host_address_after_return;
if (LK)
{
// Push {ARM_PC (64-bit); PPC_PC (32-bit); MSR_BITS (32-bit)} on the stack
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
ARM64Reg reg_to_push = ARM64Reg::X1;
const u64 msr_bits = m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK;
const u64 feature_flags = m_ppc_state.feature_flags;
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
{
MOVI2R(ARM64Reg::X1, msr_bits << 32 | exit_address_after_return);
MOVI2R(ARM64Reg::X1, feature_flags << 32 | exit_address_after_return);
}
else if (msr_bits == 0)
else if (feature_flags == 0)
{
reg_to_push = EncodeRegTo64(exit_address_after_return_reg);
}
else
{
ORRI2R(ARM64Reg::X1, EncodeRegTo64(exit_address_after_return_reg), msr_bits << 32,
ORRI2R(ARM64Reg::X1, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
ARM64Reg::X1);
}
constexpr s32 adr_offset = JitArm64BlockCache::BLOCK_LINK_SIZE + sizeof(u32) * 2;
@@ -487,20 +520,20 @@ void JitArm64::WriteExit(Arm64Gen::ARM64Reg dest, bool LK, u32 exit_address_afte
}
else
{
// Push {ARM_PC (64-bit); PPC_PC (32-bit); MSR_BITS (32-bit)} on the stack
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
ARM64Reg reg_to_push = ARM64Reg::X1;
const u64 msr_bits = m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK;
const u64 feature_flags = m_ppc_state.feature_flags;
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
{
MOVI2R(ARM64Reg::X1, msr_bits << 32 | exit_address_after_return);
MOVI2R(ARM64Reg::X1, feature_flags << 32 | exit_address_after_return);
}
else if (msr_bits == 0)
else if (feature_flags == 0)
{
reg_to_push = EncodeRegTo64(exit_address_after_return_reg);
}
else
{
ORRI2R(ARM64Reg::X1, EncodeRegTo64(exit_address_after_return_reg), msr_bits << 32,
ORRI2R(ARM64Reg::X1, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
ARM64Reg::X1);
}
constexpr s32 adr_offset = sizeof(u32) * 3;
@@ -558,17 +591,17 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
// function has been called!
gpr.Lock(ARM64Reg::W30);
}
// Push {ARM_PC (64-bit); PPC_PC (32-bit); MSR_BITS (32-bit)} on the stack
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
ARM64Reg after_reg = ARM64Reg::INVALID_REG;
ARM64Reg reg_to_push;
const u64 msr_bits = m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK;
const u64 feature_flags = m_ppc_state.feature_flags;
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
{
after_reg = gpr.GetReg();
reg_to_push = EncodeRegTo64(after_reg);
MOVI2R(reg_to_push, msr_bits << 32 | exit_address_after_return);
MOVI2R(reg_to_push, feature_flags << 32 | exit_address_after_return);
}
else if (msr_bits == 0)
else if (feature_flags == 0)
{
reg_to_push = EncodeRegTo64(exit_address_after_return_reg);
}
@@ -576,7 +609,8 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
{
after_reg = gpr.GetReg();
reg_to_push = EncodeRegTo64(after_reg);
ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), msr_bits << 32, reg_to_push);
ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
reg_to_push);
}
ARM64Reg code_reg = gpr.GetReg();
constexpr s32 adr_offset = sizeof(u32) * 3;
@@ -640,16 +674,16 @@ void JitArm64::WriteBLRExit(Arm64Gen::ARM64Reg dest)
Cleanup();
EndTimeProfile(js.curBlock);
// Check if {PPC_PC, MSR_BITS} matches the current state, then RET to ARM_PC.
// Check if {PPC_PC, feature_flags} matches the current state, then RET to ARM_PC.
LDP(IndexType::Post, ARM64Reg::X2, ARM64Reg::X1, ARM64Reg::SP, 16);
const u64 msr_bits = m_ppc_state.msr.Hex & JitBaseBlockCache::JIT_CACHE_MSR_MASK;
if (msr_bits == 0)
const u64 feature_flags = m_ppc_state.feature_flags;
if (feature_flags == 0)
{
CMP(ARM64Reg::X1, EncodeRegTo64(DISPATCHER_PC));
}
else
{
ORRI2R(ARM64Reg::X0, EncodeRegTo64(DISPATCHER_PC), msr_bits << 32, ARM64Reg::X0);
ORRI2R(ARM64Reg::X0, EncodeRegTo64(DISPATCHER_PC), feature_flags << 32, ARM64Reg::X0);
CMP(ARM64Reg::X1, ARM64Reg::X0);
}
FixupBranch no_match = B(CC_NEQ);
+2 -2
View File
@@ -310,8 +310,8 @@ protected:
void EndTimeProfile(JitBlock* b);
void EmitUpdateMembase();
void EmitStoreMembase(u32 msr);
void EmitStoreMembase(const Arm64Gen::ARM64Reg& msr);
void MSRUpdated(u32 msr);
void MSRUpdated(Arm64Gen::ARM64Reg msr);
// Exits
void
@@ -64,11 +64,11 @@ void JitArm64::rfi(UGeckoInstruction inst)
ORR(WA, WA, WC); // rB = Masked MSR OR masked SRR1
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr)); // STR rB in to rA
gpr.Unlock(WB, WC);
EmitStoreMembase(WA);
MSRUpdated(WA);
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF_SPR(SPR_SRR0));
gpr.Unlock(WB, WC);
WriteExceptionExit(WA);
gpr.Unlock(WA);
@@ -727,7 +727,7 @@ void JitArm64::dcbx(UGeckoInstruction inst)
// Translate effective address to physical address.
const u8* loop_start = GetCodePtr();
FixupBranch bat_lookup_failed;
if (m_ppc_state.msr.IR)
if (m_ppc_state.feature_flags & FEATURE_FLAG_MSR_IR)
{
bat_lookup_failed =
BATAddressLookup(physical_addr, effective_addr, WA, m_mmu.GetIBATTable().data());
@@ -756,7 +756,7 @@ void JitArm64::dcbx(UGeckoInstruction inst)
SwitchToFarCode();
SetJumpTarget(invalidate_needed);
if (m_ppc_state.msr.IR)
if (m_ppc_state.feature_flags & FEATURE_FLAG_MSR_IR)
SetJumpTarget(bat_lookup_failed);
BitSet32 gprs_to_push = gpr.GetCallerSavedUsed();

Some files were not shown because too many files have changed in this diff Show More