Merge pull request #12211 from JosJuice/toggle-dcache
PowerPC: Allow toggling write-back cache during emulation
This commit is contained in:
commit
166d8a1aa3
|
@ -14,6 +14,7 @@ enum class BooleanSetting(
|
||||||
MAIN_SKIP_IPL(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SkipIPL", true),
|
MAIN_SKIP_IPL(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SkipIPL", true),
|
||||||
MAIN_DSP_HLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DSPHLE", true),
|
MAIN_DSP_HLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DSPHLE", true),
|
||||||
MAIN_FASTMEM(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Fastmem", true),
|
MAIN_FASTMEM(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Fastmem", true),
|
||||||
|
MAIN_FASTMEM_ARENA(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FastmemArena", true),
|
||||||
MAIN_CPU_THREAD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUThread", true),
|
MAIN_CPU_THREAD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUThread", true),
|
||||||
MAIN_SYNC_ON_SKIP_IDLE(
|
MAIN_SYNC_ON_SKIP_IDLE(
|
||||||
Settings.FILE_DOLPHIN,
|
Settings.FILE_DOLPHIN,
|
||||||
|
@ -897,12 +898,12 @@ enum class BooleanSetting(
|
||||||
companion object {
|
companion object {
|
||||||
private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
|
private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
|
||||||
MAIN_DSP_HLE,
|
MAIN_DSP_HLE,
|
||||||
|
MAIN_FASTMEM_ARENA,
|
||||||
MAIN_CPU_THREAD,
|
MAIN_CPU_THREAD,
|
||||||
MAIN_ENABLE_CHEATS,
|
MAIN_ENABLE_CHEATS,
|
||||||
MAIN_OVERRIDE_REGION_SETTINGS,
|
MAIN_OVERRIDE_REGION_SETTINGS,
|
||||||
MAIN_MMU,
|
MAIN_MMU,
|
||||||
MAIN_PAUSE_ON_PANIC,
|
MAIN_PAUSE_ON_PANIC,
|
||||||
MAIN_ACCURATE_CPU_CACHE,
|
|
||||||
MAIN_RAM_OVERRIDE_ENABLE,
|
MAIN_RAM_OVERRIDE_ENABLE,
|
||||||
MAIN_CUSTOM_RTC_ENABLE,
|
MAIN_CUSTOM_RTC_ENABLE,
|
||||||
MAIN_DSP_JIT,
|
MAIN_DSP_JIT,
|
||||||
|
|
|
@ -1941,6 +1941,14 @@ class SettingsFragmentPresenter(
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
sl.add(
|
||||||
|
InvertedSwitchSetting(
|
||||||
|
context,
|
||||||
|
BooleanSetting.MAIN_FASTMEM_ARENA,
|
||||||
|
R.string.debug_fastmem_arena,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
sl.add(HeaderSetting(context, R.string.debug_jit_header, 0))
|
sl.add(HeaderSetting(context, R.string.debug_jit_header, 0))
|
||||||
sl.add(
|
sl.add(
|
||||||
|
|
|
@ -399,6 +399,7 @@
|
||||||
<string name="debug_submenu">Debug</string>
|
<string name="debug_submenu">Debug</string>
|
||||||
<string name="debug_warning">Warning: Debug settings will slow emulation</string>
|
<string name="debug_warning">Warning: Debug settings will slow emulation</string>
|
||||||
<string name="debug_fastmem">Disable Fastmem</string>
|
<string name="debug_fastmem">Disable Fastmem</string>
|
||||||
|
<string name="debug_fastmem_arena">Disable Fastmem Arena</string>
|
||||||
<string name="debug_jit_header">Jit</string>
|
<string name="debug_jit_header">Jit</string>
|
||||||
<string name="debug_jitoff">Jit Disabled</string>
|
<string name="debug_jitoff">Jit Disabled</string>
|
||||||
<string name="debug_jitloadstoreoff">Jit Load Store Disabled</string>
|
<string name="debug_jitloadstoreoff">Jit Load Store Disabled</string>
|
||||||
|
|
|
@ -82,9 +82,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInSpace(const u8* ptr) const { return ptr >= region && ptr < (region + region_size); }
|
bool IsInSpace(const u8* ptr) const { return ptr >= region && ptr < (region + region_size); }
|
||||||
// Cannot currently be undone. Will write protect the entire code region.
|
void WriteProtect(bool allow_execute)
|
||||||
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
|
{
|
||||||
void WriteProtect() { Common::WriteProtectMemory(region, region_size, true); }
|
Common::WriteProtectMemory(region, region_size, allow_execute);
|
||||||
|
}
|
||||||
|
void UnWriteProtect(bool allow_execute)
|
||||||
|
{
|
||||||
|
Common::UnWriteProtectMemory(region, region_size, allow_execute);
|
||||||
|
}
|
||||||
void ResetCodePtr() { T::SetCodePtr(region, region + region_size); }
|
void ResetCodePtr() { T::SetCodePtr(region, region + region_size); }
|
||||||
size_t GetSpaceLeft() const
|
size_t GetSpaceLeft() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,7 @@ const Info<PowerPC::CPUCore> MAIN_CPU_CORE{{System::Main, "Core", "CPUCore"},
|
||||||
PowerPC::DefaultCPUCore()};
|
PowerPC::DefaultCPUCore()};
|
||||||
const Info<bool> MAIN_JIT_FOLLOW_BRANCH{{System::Main, "Core", "JITFollowBranch"}, true};
|
const Info<bool> MAIN_JIT_FOLLOW_BRANCH{{System::Main, "Core", "JITFollowBranch"}, true};
|
||||||
const Info<bool> MAIN_FASTMEM{{System::Main, "Core", "Fastmem"}, true};
|
const Info<bool> MAIN_FASTMEM{{System::Main, "Core", "Fastmem"}, true};
|
||||||
|
const Info<bool> MAIN_FASTMEM_ARENA{{System::Main, "Core", "FastmemArena"}, true};
|
||||||
const Info<bool> MAIN_ACCURATE_CPU_CACHE{{System::Main, "Core", "AccurateCPUCache"}, false};
|
const Info<bool> MAIN_ACCURATE_CPU_CACHE{{System::Main, "Core", "AccurateCPUCache"}, false};
|
||||||
const Info<bool> MAIN_DSP_HLE{{System::Main, "Core", "DSPHLE"}, true};
|
const Info<bool> MAIN_DSP_HLE{{System::Main, "Core", "DSPHLE"}, true};
|
||||||
const Info<int> MAIN_MAX_FALLBACK{{System::Main, "Core", "MaxFallback"}, 100};
|
const Info<int> MAIN_MAX_FALLBACK{{System::Main, "Core", "MaxFallback"}, 100};
|
||||||
|
|
|
@ -56,6 +56,7 @@ extern const Info<bool> MAIN_SKIP_IPL;
|
||||||
extern const Info<PowerPC::CPUCore> MAIN_CPU_CORE;
|
extern const Info<PowerPC::CPUCore> MAIN_CPU_CORE;
|
||||||
extern const Info<bool> MAIN_JIT_FOLLOW_BRANCH;
|
extern const Info<bool> MAIN_JIT_FOLLOW_BRANCH;
|
||||||
extern const Info<bool> MAIN_FASTMEM;
|
extern const Info<bool> MAIN_FASTMEM;
|
||||||
|
extern const Info<bool> MAIN_FASTMEM_ARENA;
|
||||||
extern const Info<bool> MAIN_ACCURATE_CPU_CACHE;
|
extern const Info<bool> MAIN_ACCURATE_CPU_CACHE;
|
||||||
// Should really be in the DSP section, but we're kind of stuck with bad decisions made in the past.
|
// Should really be in the DSP section, but we're kind of stuck with bad decisions made in the past.
|
||||||
extern const Info<bool> MAIN_DSP_HLE;
|
extern const Info<bool> MAIN_DSP_HLE;
|
||||||
|
|
|
@ -82,7 +82,7 @@ CachedInterpreter::~CachedInterpreter() = default;
|
||||||
|
|
||||||
void CachedInterpreter::Init()
|
void CachedInterpreter::Init()
|
||||||
{
|
{
|
||||||
RefreshConfig(InitFastmemArena::No);
|
RefreshConfig();
|
||||||
|
|
||||||
m_code.reserve(CODE_SIZE / sizeof(Instruction));
|
m_code.reserve(CODE_SIZE / sizeof(Instruction));
|
||||||
|
|
||||||
|
@ -384,5 +384,5 @@ void CachedInterpreter::ClearCache()
|
||||||
{
|
{
|
||||||
m_code.clear();
|
m_code.clear();
|
||||||
m_block_cache.Clear();
|
m_block_cache.Clear();
|
||||||
RefreshConfig(InitFastmemArena::No);
|
RefreshConfig();
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,7 +251,9 @@ bool Jit64::BackPatch(SContext* ctx)
|
||||||
|
|
||||||
void Jit64::Init()
|
void Jit64::Init()
|
||||||
{
|
{
|
||||||
RefreshConfig(InitFastmemArena::Yes);
|
InitFastmemArena();
|
||||||
|
|
||||||
|
RefreshConfig();
|
||||||
|
|
||||||
EnableBlockLink();
|
EnableBlockLink();
|
||||||
|
|
||||||
|
@ -304,7 +306,8 @@ void Jit64::ClearCache()
|
||||||
m_const_pool.Clear();
|
m_const_pool.Clear();
|
||||||
ClearCodeSpace();
|
ClearCodeSpace();
|
||||||
Clear();
|
Clear();
|
||||||
RefreshConfig(InitFastmemArena::No);
|
RefreshConfig();
|
||||||
|
asm_routines.Regenerate();
|
||||||
ResetFreeMemoryRanges();
|
ResetFreeMemoryRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,15 @@ void Jit64AsmRoutineManager::Init()
|
||||||
{
|
{
|
||||||
m_const_pool.Init(AllocChildCodeSpace(4096), 4096);
|
m_const_pool.Init(AllocChildCodeSpace(4096), 4096);
|
||||||
Generate();
|
Generate();
|
||||||
WriteProtect();
|
WriteProtect(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64AsmRoutineManager::Regenerate()
|
||||||
|
{
|
||||||
|
UnWriteProtect(false);
|
||||||
|
ResetCodePtr();
|
||||||
|
Generate();
|
||||||
|
WriteProtect(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PLAN: no more block numbers - crazy opcodes just contain offset within
|
// PLAN: no more block numbers - crazy opcodes just contain offset within
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
explicit Jit64AsmRoutineManager(Jit64& jit);
|
explicit Jit64AsmRoutineManager(Jit64& jit);
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
void Regenerate();
|
||||||
|
|
||||||
void ResetStack(Gen::X64CodeBlock& emitter);
|
void ResetStack(Gen::X64CodeBlock& emitter);
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
|
||||||
|
|
||||||
FixupBranch exit;
|
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.msr.DR;
|
||||||
const bool fast_check_address = !slowmem && dr_set && m_jit.jo.fastmem_arena;
|
const bool fast_check_address =
|
||||||
|
!slowmem && dr_set && m_jit.jo.fastmem_arena && !m_jit.m_ppc_state.m_enable_dcache;
|
||||||
if (fast_check_address)
|
if (fast_check_address)
|
||||||
{
|
{
|
||||||
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse);
|
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse);
|
||||||
|
@ -541,7 +542,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||||
|
|
||||||
FixupBranch exit;
|
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.msr.DR;
|
||||||
const bool fast_check_address = !slowmem && dr_set && m_jit.jo.fastmem_arena;
|
const bool fast_check_address =
|
||||||
|
!slowmem && dr_set && m_jit.jo.fastmem_arena && !m_jit.m_ppc_state.m_enable_dcache;
|
||||||
if (fast_check_address)
|
if (fast_check_address)
|
||||||
{
|
{
|
||||||
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
|
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
|
||||||
|
|
|
@ -47,7 +47,9 @@ JitArm64::~JitArm64() = default;
|
||||||
|
|
||||||
void JitArm64::Init()
|
void JitArm64::Init()
|
||||||
{
|
{
|
||||||
RefreshConfig(InitFastmemArena::Yes);
|
InitFastmemArena();
|
||||||
|
|
||||||
|
RefreshConfig();
|
||||||
|
|
||||||
const size_t child_code_size = jo.memcheck ? FARCODE_SIZE_MMU : FARCODE_SIZE;
|
const size_t child_code_size = jo.memcheck ? FARCODE_SIZE_MMU : FARCODE_SIZE;
|
||||||
AllocCodeSpace(CODE_SIZE + child_code_size);
|
AllocCodeSpace(CODE_SIZE + child_code_size);
|
||||||
|
@ -155,7 +157,7 @@ void JitArm64::ClearCache()
|
||||||
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
|
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
|
||||||
ClearCodeSpace();
|
ClearCodeSpace();
|
||||||
m_far_code.ClearCodeSpace();
|
m_far_code.ClearCodeSpace();
|
||||||
RefreshConfig(InitFastmemArena::No);
|
RefreshConfig();
|
||||||
|
|
||||||
GenerateAsm();
|
GenerateAsm();
|
||||||
|
|
||||||
|
@ -364,8 +366,8 @@ void JitArm64::EmitStoreMembase(const ARM64Reg& msr)
|
||||||
auto& memory = m_system.GetMemory();
|
auto& memory = m_system.GetMemory();
|
||||||
ARM64Reg WD = gpr.GetReg();
|
ARM64Reg WD = gpr.GetReg();
|
||||||
ARM64Reg XD = EncodeRegTo64(WD);
|
ARM64Reg XD = EncodeRegTo64(WD);
|
||||||
MOVP2R(MEM_REG, jo.fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
|
MOVP2R(MEM_REG, jo.fastmem ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
|
||||||
MOVP2R(XD, jo.fastmem_arena ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
|
MOVP2R(XD, jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
|
||||||
TST(msr, LogicalImm(1 << (31 - 27), 32));
|
TST(msr, LogicalImm(1 << (31 - 27), 32));
|
||||||
CSEL(MEM_REG, MEM_REG, XD, CCFlags::CC_NEQ);
|
CSEL(MEM_REG, MEM_REG, XD, CCFlags::CC_NEQ);
|
||||||
STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
|
STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
|
||||||
|
|
|
@ -233,7 +233,7 @@ protected:
|
||||||
// Only emits fast access code. Must only be used if the guest address is known in advance
|
// Only emits fast access code. Must only be used if the guest address is known in advance
|
||||||
// and IsOptimizableRAMAddress returns true for it, otherwise Dolphin will likely crash!
|
// and IsOptimizableRAMAddress returns true for it, otherwise Dolphin will likely crash!
|
||||||
AlwaysUnsafe,
|
AlwaysUnsafe,
|
||||||
// Best in most cases. If backpatching is possible (!emitting_routine && jo.fastmem_arena):
|
// Best in most cases. If backpatching is possible (!emitting_routine && jo.fastmem):
|
||||||
// Tries to run fast access code, and if that fails, uses backpatching to replace the code
|
// Tries to run fast access code, and if that fails, uses backpatching to replace the code
|
||||||
// with a call to the slow C++ code. Otherwise: Checks whether the fast access code will work,
|
// with a call to the slow C++ code. Otherwise: Checks whether the fast access code will work,
|
||||||
// then branches to either the fast access code or the slow C++ code.
|
// then branches to either the fast access code or the slow C++ code.
|
||||||
|
@ -259,10 +259,10 @@ protected:
|
||||||
//
|
//
|
||||||
// emitting_routine && mode == Auto: X2
|
// emitting_routine && mode == Auto: X2
|
||||||
// emitting_routine && mode == Auto && !(flags & BackPatchInfo::FLAG_STORE): X3
|
// emitting_routine && mode == Auto && !(flags & BackPatchInfo::FLAG_STORE): X3
|
||||||
// emitting_routine && mode != AlwaysSafe && !jo.fastmem_arena: X3
|
// emitting_routine && mode != AlwaysSafe && !jo.fastmem: X3
|
||||||
// mode != AlwaysSafe && !jo.fastmem_arena: X2
|
// mode != AlwaysSafe && !jo.fastmem: X2
|
||||||
// !emitting_routine && mode != AlwaysSafe && !jo.fastmem_arena: X30
|
// !emitting_routine && mode != AlwaysSafe && !jo.fastmem: X30
|
||||||
// !emitting_routine && mode == Auto && jo.fastmem_arena: X30
|
// !emitting_routine && mode == Auto && jo.fastmem: X30
|
||||||
//
|
//
|
||||||
// Furthermore, any callee-saved register which isn't marked in gprs_to_push/fprs_to_push
|
// Furthermore, any callee-saved register which isn't marked in gprs_to_push/fprs_to_push
|
||||||
// may be clobbered if mode != AlwaysUnsafe.
|
// may be clobbered if mode != AlwaysUnsafe.
|
||||||
|
|
|
@ -74,7 +74,7 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
|
||||||
ARM64Reg memory_base = MEM_REG;
|
ARM64Reg memory_base = MEM_REG;
|
||||||
ARM64Reg memory_offset = addr;
|
ARM64Reg memory_offset = addr;
|
||||||
|
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
{
|
{
|
||||||
const ARM64Reg temp = emitting_routine ? ARM64Reg::W3 : ARM64Reg::W30;
|
const ARM64Reg temp = emitting_routine ? ARM64Reg::W3 : ARM64Reg::W30;
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
|
||||||
in_far_code = true;
|
in_far_code = true;
|
||||||
SwitchToFarCode();
|
SwitchToFarCode();
|
||||||
|
|
||||||
if (jo.fastmem_arena && !emitting_routine)
|
if (jo.fastmem && !emitting_routine)
|
||||||
{
|
{
|
||||||
FastmemArea* fastmem_area = &m_fault_to_handler[fastmem_end];
|
FastmemArea* fastmem_area = &m_fault_to_handler[fastmem_end];
|
||||||
fastmem_area->fastmem_code = fastmem_start;
|
fastmem_area->fastmem_code = fastmem_start;
|
||||||
|
|
|
@ -28,7 +28,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
|
||||||
{
|
{
|
||||||
// We want to make sure to not get LR as a temp register
|
// We want to make sure to not get LR as a temp register
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
gpr.BindToRegister(dest, dest == (u32)addr || dest == (u32)offsetReg, false);
|
gpr.BindToRegister(dest, dest == (u32)addr || dest == (u32)offsetReg, false);
|
||||||
|
@ -124,7 +124,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
|
||||||
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
||||||
if (!update || early_update)
|
if (!update || early_update)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
if (!jo.memcheck)
|
if (!jo.memcheck)
|
||||||
regs_in_use[DecodeReg(dest_reg)] = 0;
|
regs_in_use[DecodeReg(dest_reg)] = 0;
|
||||||
|
@ -166,7 +166,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
|
||||||
{
|
{
|
||||||
// We want to make sure to not get LR as a temp register
|
// We want to make sure to not get LR as a temp register
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
ARM64Reg RS = gpr.R(value);
|
ARM64Reg RS = gpr.R(value);
|
||||||
|
@ -272,7 +272,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
if (!update || early_update)
|
if (!update || early_update)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
|
|
||||||
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
||||||
|
@ -335,7 +335,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +519,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
||||||
s32 offset = inst.SIMM_16;
|
s32 offset = inst.SIMM_16;
|
||||||
|
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
// MMU games make use of a >= d despite this being invalid according to the PEM.
|
// MMU games make use of a >= d despite this being invalid according to the PEM.
|
||||||
|
@ -554,7 +554,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
||||||
BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
|
BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
|
||||||
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
||||||
regs_in_use[DecodeReg(addr_reg)] = 0;
|
regs_in_use[DecodeReg(addr_reg)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
if (!jo.memcheck)
|
if (!jo.memcheck)
|
||||||
regs_in_use[DecodeReg(dest_reg)] = 0;
|
regs_in_use[DecodeReg(dest_reg)] = 0;
|
||||||
|
@ -567,7 +567,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
if (!a_is_addr_base_reg)
|
if (!a_is_addr_base_reg)
|
||||||
gpr.Unlock(addr_base_reg);
|
gpr.Unlock(addr_base_reg);
|
||||||
|
@ -582,7 +582,7 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
||||||
s32 offset = inst.SIMM_16;
|
s32 offset = inst.SIMM_16;
|
||||||
|
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
ARM64Reg addr_reg = ARM64Reg::W1;
|
ARM64Reg addr_reg = ARM64Reg::W1;
|
||||||
|
@ -615,7 +615,7 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
||||||
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
regs_in_use[DecodeReg(addr_reg)] = 0;
|
regs_in_use[DecodeReg(addr_reg)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
|
|
||||||
EmitBackpatchRoutine(flags, MemAccessMode::Auto, src_reg, EncodeRegTo64(addr_reg), regs_in_use,
|
EmitBackpatchRoutine(flags, MemAccessMode::Auto, src_reg, EncodeRegTo64(addr_reg), regs_in_use,
|
||||||
|
@ -623,7 +623,7 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
if (!a_is_addr_base_reg)
|
if (!a_is_addr_base_reg)
|
||||||
gpr.Unlock(addr_base_reg);
|
gpr.Unlock(addr_base_reg);
|
||||||
|
@ -818,12 +818,12 @@ void JitArm64::dcbz(UGeckoInstruction inst)
|
||||||
int a = inst.RA, b = inst.RB;
|
int a = inst.RA, b = inst.RB;
|
||||||
|
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
Common::ScopeGuard register_guard([&] {
|
Common::ScopeGuard register_guard([&] {
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -892,7 +892,7 @@ void JitArm64::dcbz(UGeckoInstruction inst)
|
||||||
BitSet32 gprs_to_push = gpr.GetCallerSavedUsed();
|
BitSet32 gprs_to_push = gpr.GetCallerSavedUsed();
|
||||||
BitSet32 fprs_to_push = fpr.GetCallerSavedUsed();
|
BitSet32 fprs_to_push = fpr.GetCallerSavedUsed();
|
||||||
gprs_to_push[DecodeReg(ARM64Reg::W0)] = 0;
|
gprs_to_push[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gprs_to_push[DecodeReg(ARM64Reg::W2)] = 0;
|
gprs_to_push[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
|
|
||||||
EmitBackpatchRoutine(BackPatchInfo::FLAG_ZERO_256, MemAccessMode::Auto, ARM64Reg::W0,
|
EmitBackpatchRoutine(BackPatchInfo::FLAG_ZERO_256, MemAccessMode::Auto, ARM64Reg::W0,
|
||||||
|
|
|
@ -79,7 +79,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
|
||||||
|
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
fpr.Lock(ARM64Reg::Q0);
|
fpr.Lock(ARM64Reg::Q0);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
const ARM64Reg VD = fpr.RW(inst.FD, type, false);
|
const ARM64Reg VD = fpr.RW(inst.FD, type, false);
|
||||||
|
@ -168,7 +168,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
|
||||||
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
||||||
if (!update || early_update)
|
if (!update || early_update)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0;
|
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0;
|
||||||
if (!jo.memcheck)
|
if (!jo.memcheck)
|
||||||
|
@ -194,7 +194,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
|
||||||
fpr.Unlock(ARM64Reg::Q0);
|
fpr.Unlock(ARM64Reg::Q0);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
|
|
||||||
ARM64Reg addr_reg = ARM64Reg::W1;
|
ARM64Reg addr_reg = ARM64Reg::W1;
|
||||||
|
@ -372,7 +372,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
if (!update || early_update)
|
if (!update || early_update)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
|
||||||
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0;
|
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0;
|
||||||
|
|
||||||
|
@ -428,6 +428,6 @@ void JitArm64::stfXX(UGeckoInstruction inst)
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
fpr.Unlock(ARM64Reg::Q0);
|
fpr.Unlock(ARM64Reg::Q0);
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ void JitArm64::psq_lXX(UGeckoInstruction inst)
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
JITDISABLE(bJITLoadStorePairedOff);
|
JITDISABLE(bJITLoadStorePairedOff);
|
||||||
|
|
||||||
// If we have a fastmem arena, the asm routines assume address translation is on.
|
// If fastmem is enabled, the asm routines assume address translation is on.
|
||||||
FALLBACK_IF(!js.assumeNoPairedQuantize && jo.fastmem_arena && !m_ppc_state.msr.DR);
|
FALLBACK_IF(!js.assumeNoPairedQuantize && jo.fastmem && !m_ppc_state.msr.DR);
|
||||||
|
|
||||||
// X30 is LR
|
// X30 is LR
|
||||||
// X0 is the address
|
// X0 is the address
|
||||||
|
@ -44,7 +44,7 @@ void JitArm64::psq_lXX(UGeckoInstruction inst)
|
||||||
gpr.Lock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W3);
|
gpr.Lock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W3);
|
||||||
fpr.Lock(ARM64Reg::Q1);
|
fpr.Lock(ARM64Reg::Q1);
|
||||||
}
|
}
|
||||||
else if (!jo.fastmem_arena)
|
else if (!jo.fastmem)
|
||||||
{
|
{
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ void JitArm64::psq_lXX(UGeckoInstruction inst)
|
||||||
// Wipe the registers we are using as temporaries
|
// Wipe the registers we are using as temporaries
|
||||||
if (!update || early_update)
|
if (!update || early_update)
|
||||||
gprs_in_use[DecodeReg(ARM64Reg::W0)] = false;
|
gprs_in_use[DecodeReg(ARM64Reg::W0)] = false;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gprs_in_use[DecodeReg(ARM64Reg::W2)] = false;
|
gprs_in_use[DecodeReg(ARM64Reg::W2)] = false;
|
||||||
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = false;
|
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = false;
|
||||||
if (!jo.memcheck)
|
if (!jo.memcheck)
|
||||||
|
@ -136,7 +136,7 @@ void JitArm64::psq_lXX(UGeckoInstruction inst)
|
||||||
gpr.Unlock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W3);
|
gpr.Unlock(ARM64Reg::W1, ARM64Reg::W2, ARM64Reg::W3);
|
||||||
fpr.Unlock(ARM64Reg::Q1);
|
fpr.Unlock(ARM64Reg::Q1);
|
||||||
}
|
}
|
||||||
else if (!jo.fastmem_arena)
|
else if (!jo.fastmem)
|
||||||
{
|
{
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
}
|
}
|
||||||
|
@ -147,8 +147,8 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
JITDISABLE(bJITLoadStorePairedOff);
|
JITDISABLE(bJITLoadStorePairedOff);
|
||||||
|
|
||||||
// If we have a fastmem arena, the asm routines assume address translation is on.
|
// If fastmem is enabled, the asm routines assume address translation is on.
|
||||||
FALLBACK_IF(!js.assumeNoPairedQuantize && jo.fastmem_arena && !m_ppc_state.msr.DR);
|
FALLBACK_IF(!js.assumeNoPairedQuantize && jo.fastmem && !m_ppc_state.msr.DR);
|
||||||
|
|
||||||
// X30 is LR
|
// X30 is LR
|
||||||
// X0 contains the scale
|
// X0 contains the scale
|
||||||
|
@ -199,9 +199,9 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
if (!js.assumeNoPairedQuantize || !jo.fastmem_arena)
|
if (!js.assumeNoPairedQuantize || !jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W2);
|
gpr.Lock(ARM64Reg::W2);
|
||||||
if (!js.assumeNoPairedQuantize && !jo.fastmem_arena)
|
if (!js.assumeNoPairedQuantize && !jo.fastmem)
|
||||||
gpr.Lock(ARM64Reg::W3);
|
gpr.Lock(ARM64Reg::W3);
|
||||||
|
|
||||||
constexpr ARM64Reg scale_reg = ARM64Reg::W0;
|
constexpr ARM64Reg scale_reg = ARM64Reg::W0;
|
||||||
|
@ -241,7 +241,7 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
|
||||||
gprs_in_use[DecodeReg(ARM64Reg::W0)] = false;
|
gprs_in_use[DecodeReg(ARM64Reg::W0)] = false;
|
||||||
if (!update || early_update)
|
if (!update || early_update)
|
||||||
gprs_in_use[DecodeReg(ARM64Reg::W1)] = false;
|
gprs_in_use[DecodeReg(ARM64Reg::W1)] = false;
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gprs_in_use[DecodeReg(ARM64Reg::W2)] = false;
|
gprs_in_use[DecodeReg(ARM64Reg::W2)] = false;
|
||||||
|
|
||||||
u32 flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_FLOAT | BackPatchInfo::FLAG_SIZE_32;
|
u32 flags = BackPatchInfo::FLAG_STORE | BackPatchInfo::FLAG_FLOAT | BackPatchInfo::FLAG_SIZE_32;
|
||||||
|
@ -275,9 +275,9 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
|
||||||
|
|
||||||
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
|
||||||
fpr.Unlock(ARM64Reg::Q0);
|
fpr.Unlock(ARM64Reg::Q0);
|
||||||
if (!js.assumeNoPairedQuantize || !jo.fastmem_arena)
|
if (!js.assumeNoPairedQuantize || !jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W2);
|
gpr.Unlock(ARM64Reg::W2);
|
||||||
if (!js.assumeNoPairedQuantize && !jo.fastmem_arena)
|
if (!js.assumeNoPairedQuantize && !jo.fastmem)
|
||||||
gpr.Unlock(ARM64Reg::W3);
|
gpr.Unlock(ARM64Reg::W3);
|
||||||
if (!js.assumeNoPairedQuantize)
|
if (!js.assumeNoPairedQuantize)
|
||||||
fpr.Unlock(ARM64Reg::Q1);
|
fpr.Unlock(ARM64Reg::Q1);
|
||||||
|
|
|
@ -724,7 +724,7 @@ void JitArm64::GenerateQuantizedStores()
|
||||||
// X0 is the scale
|
// X0 is the scale
|
||||||
// X1 is the address
|
// X1 is the address
|
||||||
// X2 is a temporary
|
// X2 is a temporary
|
||||||
// X3 is a temporary if jo.fastmem_arena is false (used in EmitBackpatchRoutine)
|
// X3 is a temporary if jo.fastmem is false (used in EmitBackpatchRoutine)
|
||||||
// X30 is LR
|
// X30 is LR
|
||||||
// Q0 is the register
|
// Q0 is the register
|
||||||
// Q1 is a temporary
|
// Q1 is a temporary
|
||||||
|
@ -733,7 +733,7 @@ void JitArm64::GenerateQuantizedStores()
|
||||||
BitSet32 gprs_to_push = CALLER_SAVED_GPRS & ~BitSet32{0, 2};
|
BitSet32 gprs_to_push = CALLER_SAVED_GPRS & ~BitSet32{0, 2};
|
||||||
if (!jo.memcheck)
|
if (!jo.memcheck)
|
||||||
gprs_to_push &= ~BitSet32{1};
|
gprs_to_push &= ~BitSet32{1};
|
||||||
if (!jo.fastmem_arena)
|
if (!jo.fastmem)
|
||||||
gprs_to_push &= ~BitSet32{3};
|
gprs_to_push &= ~BitSet32{3};
|
||||||
BitSet32 fprs_to_push = BitSet32(0xFFFFFFFF) & ~BitSet32{0, 1};
|
BitSet32 fprs_to_push = BitSet32(0xFFFFFFFF) & ~BitSet32{0, 1};
|
||||||
ARM64FloatEmitter float_emit(this);
|
ARM64FloatEmitter float_emit(this);
|
||||||
|
|
|
@ -115,7 +115,7 @@ bool JitBase::DoesConfigNeedRefresh()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitBase::RefreshConfig(InitFastmemArena init_fastmem_arena)
|
void JitBase::RefreshConfig()
|
||||||
{
|
{
|
||||||
for (const auto& [member, config_info] : JIT_SETTINGS)
|
for (const auto& [member, config_info] : JIT_SETTINGS)
|
||||||
this->*member = Config::Get(*config_info);
|
this->*member = Config::Get(*config_info);
|
||||||
|
@ -132,12 +132,6 @@ void JitBase::RefreshConfig(InitFastmemArena init_fastmem_arena)
|
||||||
analyzer.SetFloatExceptionsEnabled(m_enable_float_exceptions);
|
analyzer.SetFloatExceptionsEnabled(m_enable_float_exceptions);
|
||||||
analyzer.SetDivByZeroExceptionsEnabled(m_enable_div_by_zero_exceptions);
|
analyzer.SetDivByZeroExceptionsEnabled(m_enable_div_by_zero_exceptions);
|
||||||
|
|
||||||
if (init_fastmem_arena != InitFastmemArena::No)
|
|
||||||
{
|
|
||||||
auto& memory = m_system.GetMemory();
|
|
||||||
jo.fastmem_arena = m_fastmem_enabled && memory.InitFastmemArena();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool any_watchpoints = m_system.GetPowerPC().GetMemChecks().HasAny();
|
bool any_watchpoints = m_system.GetPowerPC().GetMemChecks().HasAny();
|
||||||
jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints) &&
|
jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints) &&
|
||||||
EMM::IsExceptionHandlerSupported();
|
EMM::IsExceptionHandlerSupported();
|
||||||
|
@ -146,6 +140,12 @@ void JitBase::RefreshConfig(InitFastmemArena init_fastmem_arena)
|
||||||
jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions;
|
jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JitBase::InitFastmemArena()
|
||||||
|
{
|
||||||
|
auto& memory = m_system.GetMemory();
|
||||||
|
jo.fastmem_arena = Config::Get(Config::MAIN_FASTMEM_ARENA) && memory.InitFastmemArena();
|
||||||
|
}
|
||||||
|
|
||||||
void JitBase::InitBLROptimization()
|
void JitBase::InitBLROptimization()
|
||||||
{
|
{
|
||||||
m_enable_blr_optimization =
|
m_enable_blr_optimization =
|
||||||
|
|
|
@ -163,14 +163,10 @@ protected:
|
||||||
|
|
||||||
static const std::array<std::pair<bool JitBase::*, const Config::Info<bool>*>, 22> JIT_SETTINGS;
|
static const std::array<std::pair<bool JitBase::*, const Config::Info<bool>*>, 22> JIT_SETTINGS;
|
||||||
|
|
||||||
enum class InitFastmemArena
|
|
||||||
{
|
|
||||||
No,
|
|
||||||
Yes,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool DoesConfigNeedRefresh();
|
bool DoesConfigNeedRefresh();
|
||||||
void RefreshConfig(InitFastmemArena init_fastmem_arena);
|
void RefreshConfig();
|
||||||
|
|
||||||
|
void InitFastmemArena();
|
||||||
|
|
||||||
void InitBLROptimization();
|
void InitBLROptimization();
|
||||||
void ProtectStack();
|
void ProtectStack();
|
||||||
|
|
|
@ -105,15 +105,21 @@ void JitInterface::UpdateMembase()
|
||||||
|
|
||||||
auto& ppc_state = m_system.GetPPCState();
|
auto& ppc_state = m_system.GetPPCState();
|
||||||
auto& memory = m_system.GetMemory();
|
auto& memory = m_system.GetMemory();
|
||||||
|
#ifdef _M_ARM_64
|
||||||
|
// JitArm64 is currently using the no fastmem arena code path even when only fastmem is off.
|
||||||
|
const bool fastmem_arena = m_jit->jo.fastmem;
|
||||||
|
#else
|
||||||
|
const bool fastmem_arena = m_jit->jo.fastmem_arena;
|
||||||
|
#endif
|
||||||
if (ppc_state.msr.DR)
|
if (ppc_state.msr.DR)
|
||||||
{
|
{
|
||||||
ppc_state.mem_ptr =
|
ppc_state.mem_ptr =
|
||||||
m_jit->jo.fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase();
|
fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ppc_state.mem_ptr =
|
ppc_state.mem_ptr =
|
||||||
m_jit->jo.fastmem_arena ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase();
|
fastmem_arena ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -914,6 +914,9 @@ bool MMU::IsOptimizableRAMAddress(const u32 address) const
|
||||||
if (!m_ppc_state.msr.DR)
|
if (!m_ppc_state.msr.DR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (m_ppc_state.m_enable_dcache)
|
||||||
|
return false;
|
||||||
|
|
||||||
// TODO: This API needs to take an access size
|
// TODO: This API needs to take an access size
|
||||||
//
|
//
|
||||||
// We store whether an access can be optimized to an unchecked access
|
// We store whether an access can be optimized to an unchecked access
|
||||||
|
@ -1211,6 +1214,9 @@ u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const
|
||||||
if (!m_ppc_state.msr.DR)
|
if (!m_ppc_state.msr.DR)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (m_ppc_state.m_enable_dcache)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Translate address
|
// Translate address
|
||||||
// If we also optimize for TLB mappings, we'd have to clear the
|
// If we also optimize for TLB mappings, we'd have to clear the
|
||||||
// JitCache on each TLB invalidation.
|
// JitCache on each TLB invalidation.
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Common/FloatUtils.h"
|
#include "Common/FloatUtils.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
|
#include "Core/CPUThreadConfigCallback.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
|
@ -262,8 +263,25 @@ CPUCore DefaultCPUCore()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PowerPCManager::RefreshConfig()
|
||||||
|
{
|
||||||
|
const bool old_enable_dcache = m_ppc_state.m_enable_dcache;
|
||||||
|
|
||||||
|
m_ppc_state.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE);
|
||||||
|
|
||||||
|
if (old_enable_dcache && !m_ppc_state.m_enable_dcache)
|
||||||
|
{
|
||||||
|
INFO_LOG_FMT(POWERPC, "Flushing data cache");
|
||||||
|
m_ppc_state.dCache.FlushAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PowerPCManager::Init(CPUCore cpu_core)
|
void PowerPCManager::Init(CPUCore cpu_core)
|
||||||
{
|
{
|
||||||
|
m_registered_config_callback_id =
|
||||||
|
CPUThreadConfigCallback::AddConfigChangedCallback([this] { RefreshConfig(); });
|
||||||
|
RefreshConfig();
|
||||||
|
|
||||||
m_invalidate_cache_thread_safe =
|
m_invalidate_cache_thread_safe =
|
||||||
m_system.GetCoreTiming().RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
m_system.GetCoreTiming().RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
||||||
|
|
||||||
|
@ -273,8 +291,6 @@ void PowerPCManager::Init(CPUCore cpu_core)
|
||||||
m_ppc_state.iCache.Init();
|
m_ppc_state.iCache.Init();
|
||||||
m_ppc_state.dCache.Init();
|
m_ppc_state.dCache.Init();
|
||||||
|
|
||||||
m_ppc_state.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE);
|
|
||||||
|
|
||||||
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
|
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
|
||||||
m_breakpoints.ClearAllTemporary();
|
m_breakpoints.ClearAllTemporary();
|
||||||
}
|
}
|
||||||
|
@ -307,6 +323,7 @@ void PowerPCManager::ScheduleInvalidateCacheThreadSafe(u32 address)
|
||||||
|
|
||||||
void PowerPCManager::Shutdown()
|
void PowerPCManager::Shutdown()
|
||||||
{
|
{
|
||||||
|
CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id);
|
||||||
InjectExternalCPUCore(nullptr);
|
InjectExternalCPUCore(nullptr);
|
||||||
m_system.GetJitInterface().Shutdown();
|
m_system.GetJitInterface().Shutdown();
|
||||||
m_system.GetInterpreter().Shutdown();
|
m_system.GetInterpreter().Shutdown();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
#include "Core/CPUThreadConfigCallback.h"
|
||||||
#include "Core/Debugger/PPCDebugInterface.h"
|
#include "Core/Debugger/PPCDebugInterface.h"
|
||||||
#include "Core/PowerPC/BreakPoints.h"
|
#include "Core/PowerPC/BreakPoints.h"
|
||||||
#include "Core/PowerPC/ConditionRegister.h"
|
#include "Core/PowerPC/ConditionRegister.h"
|
||||||
|
@ -297,6 +298,7 @@ private:
|
||||||
void InitializeCPUCore(CPUCore cpu_core);
|
void InitializeCPUCore(CPUCore cpu_core);
|
||||||
void ApplyMode();
|
void ApplyMode();
|
||||||
void ResetRegisters();
|
void ResetRegisters();
|
||||||
|
void RefreshConfig();
|
||||||
|
|
||||||
PowerPCState m_ppc_state;
|
PowerPCState m_ppc_state;
|
||||||
|
|
||||||
|
@ -308,6 +310,8 @@ private:
|
||||||
MemChecks m_memchecks;
|
MemChecks m_memchecks;
|
||||||
PPCDebugInterface m_debug_interface;
|
PPCDebugInterface m_debug_interface;
|
||||||
|
|
||||||
|
CPUThreadConfigCallback::ConfigChangedCallbackID m_registered_config_callback_id;
|
||||||
|
|
||||||
CoreTiming::EventType* m_invalidate_cache_thread_safe = nullptr;
|
CoreTiming::EventType* m_invalidate_cache_thread_safe = nullptr;
|
||||||
|
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
|
|
|
@ -139,6 +139,7 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
|
||||||
m_jit_interpreter_core->setEnabled(running);
|
m_jit_interpreter_core->setEnabled(running);
|
||||||
m_jit_block_linking->setEnabled(!running);
|
m_jit_block_linking->setEnabled(!running);
|
||||||
m_jit_disable_cache->setEnabled(!running);
|
m_jit_disable_cache->setEnabled(!running);
|
||||||
|
m_jit_disable_fastmem_arena->setEnabled(!running);
|
||||||
m_jit_clear_cache->setEnabled(running);
|
m_jit_clear_cache->setEnabled(running);
|
||||||
m_jit_log_coverage->setEnabled(!running);
|
m_jit_log_coverage->setEnabled(!running);
|
||||||
m_jit_search_instruction->setEnabled(running);
|
m_jit_search_instruction->setEnabled(running);
|
||||||
|
@ -847,6 +848,12 @@ void MenuBar::AddJITMenu()
|
||||||
connect(m_jit_disable_fastmem, &QAction::toggled,
|
connect(m_jit_disable_fastmem, &QAction::toggled,
|
||||||
[](bool enabled) { Config::SetBaseOrCurrent(Config::MAIN_FASTMEM, !enabled); });
|
[](bool enabled) { Config::SetBaseOrCurrent(Config::MAIN_FASTMEM, !enabled); });
|
||||||
|
|
||||||
|
m_jit_disable_fastmem_arena = m_jit->addAction(tr("Disable Fastmem Arena"));
|
||||||
|
m_jit_disable_fastmem_arena->setCheckable(true);
|
||||||
|
m_jit_disable_fastmem_arena->setChecked(!Config::Get(Config::MAIN_FASTMEM_ARENA));
|
||||||
|
connect(m_jit_disable_fastmem_arena, &QAction::toggled,
|
||||||
|
[](bool enabled) { Config::SetBaseOrCurrent(Config::MAIN_FASTMEM_ARENA, !enabled); });
|
||||||
|
|
||||||
m_jit_clear_cache = m_jit->addAction(tr("Clear Cache"), this, &MenuBar::ClearCache);
|
m_jit_clear_cache = m_jit->addAction(tr("Clear Cache"), this, &MenuBar::ClearCache);
|
||||||
|
|
||||||
m_jit->addSeparator();
|
m_jit->addSeparator();
|
||||||
|
|
|
@ -264,6 +264,7 @@ private:
|
||||||
QAction* m_jit_block_linking;
|
QAction* m_jit_block_linking;
|
||||||
QAction* m_jit_disable_cache;
|
QAction* m_jit_disable_cache;
|
||||||
QAction* m_jit_disable_fastmem;
|
QAction* m_jit_disable_fastmem;
|
||||||
|
QAction* m_jit_disable_fastmem_arena;
|
||||||
QAction* m_jit_clear_cache;
|
QAction* m_jit_clear_cache;
|
||||||
QAction* m_jit_log_coverage;
|
QAction* m_jit_log_coverage;
|
||||||
QAction* m_jit_search_instruction;
|
QAction* m_jit_search_instruction;
|
||||||
|
|
|
@ -255,7 +255,6 @@ void AdvancedPane::Update()
|
||||||
m_cpu_emulation_engine_combobox->setEnabled(!running);
|
m_cpu_emulation_engine_combobox->setEnabled(!running);
|
||||||
m_enable_mmu_checkbox->setEnabled(!running);
|
m_enable_mmu_checkbox->setEnabled(!running);
|
||||||
m_pause_on_panic_checkbox->setEnabled(!running);
|
m_pause_on_panic_checkbox->setEnabled(!running);
|
||||||
m_accurate_cpu_cache_checkbox->setEnabled(!running);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
QFont bf = font();
|
QFont bf = font();
|
||||||
|
|
|
@ -56,7 +56,7 @@ VertexLoaderARM64::VertexLoaderARM64(const TVtxDesc& vtx_desc, const VAT& vtx_at
|
||||||
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
|
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
|
||||||
ClearCodeSpace();
|
ClearCodeSpace();
|
||||||
GenerateVertexLoader();
|
GenerateVertexLoader();
|
||||||
WriteProtect();
|
WriteProtect(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the register to use as the base and an offset from that register.
|
// Returns the register to use as the base and an offset from that register.
|
||||||
|
|
|
@ -49,7 +49,7 @@ VertexLoaderX64::VertexLoaderX64(const TVtxDesc& vtx_desc, const VAT& vtx_att)
|
||||||
AllocCodeSpace(4096);
|
AllocCodeSpace(4096);
|
||||||
ClearCodeSpace();
|
ClearCodeSpace();
|
||||||
GenerateVertexLoader();
|
GenerateVertexLoader();
|
||||||
WriteProtect();
|
WriteProtect(true);
|
||||||
|
|
||||||
Common::JitRegister::Register(region, GetCodePtr(), "VertexLoaderX64\nVtx desc: \n{}\nVAT:\n{}",
|
Common::JitRegister::Register(region, GetCodePtr(), "VertexLoaderX64\nVtx desc: \n{}\nVAT:\n{}",
|
||||||
vtx_desc, vtx_att);
|
vtx_desc, vtx_att);
|
||||||
|
|
Loading…
Reference in New Issue