Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #12211 from JosJuice/toggle-dcache
PowerPC: Allow toggling write-back cache during emulation
  • Loading branch information
AdmiralCurtiss committed Nov 1, 2023
2 parents b32ac93 + d04e67b commit 166d8a1
Show file tree
Hide file tree
Showing 29 changed files with 147 additions and 78 deletions.
Expand Up @@ -14,6 +14,7 @@ enum class BooleanSetting(
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_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_SYNC_ON_SKIP_IDLE(
Settings.FILE_DOLPHIN,
Expand Down Expand Up @@ -897,12 +898,12 @@ enum class BooleanSetting(
companion object {
private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
MAIN_DSP_HLE,
MAIN_FASTMEM_ARENA,
MAIN_CPU_THREAD,
MAIN_ENABLE_CHEATS,
MAIN_OVERRIDE_REGION_SETTINGS,
MAIN_MMU,
MAIN_PAUSE_ON_PANIC,
MAIN_ACCURATE_CPU_CACHE,
MAIN_RAM_OVERRIDE_ENABLE,
MAIN_CUSTOM_RTC_ENABLE,
MAIN_DSP_JIT,
Expand Down
Expand Up @@ -1941,6 +1941,14 @@ class SettingsFragmentPresenter(
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(
Expand Down
1 change: 1 addition & 0 deletions Source/Android/app/src/main/res/values/strings.xml
Expand Up @@ -399,6 +399,7 @@
<string name="debug_submenu">Debug</string>
<string name="debug_warning">Warning: Debug settings will slow emulation</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_jitoff">Jit Disabled</string>
<string name="debug_jitloadstoreoff">Jit Load Store Disabled</string>
Expand Down
11 changes: 8 additions & 3 deletions Source/Core/Common/CodeBlock.h
Expand Up @@ -82,9 +82,14 @@ class CodeBlock : public T
}

bool IsInSpace(const u8* ptr) const { return ptr >= region && ptr < (region + region_size); }
// Cannot currently be undone. Will write protect the entire code region.
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect() { Common::WriteProtectMemory(region, region_size, true); }
void WriteProtect(bool allow_execute)
{
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); }
size_t GetSpaceLeft() const
{
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/Config/MainSettings.cpp
Expand Up @@ -38,6 +38,7 @@ const Info<PowerPC::CPUCore> MAIN_CPU_CORE{{System::Main, "Core", "CPUCore"},
PowerPC::DefaultCPUCore()};
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_ARENA{{System::Main, "Core", "FastmemArena"}, true};
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<int> MAIN_MAX_FALLBACK{{System::Main, "Core", "MaxFallback"}, 100};
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/Config/MainSettings.h
Expand Up @@ -56,6 +56,7 @@ extern const Info<bool> MAIN_SKIP_IPL;
extern const Info<PowerPC::CPUCore> MAIN_CPU_CORE;
extern const Info<bool> MAIN_JIT_FOLLOW_BRANCH;
extern const Info<bool> MAIN_FASTMEM;
extern const Info<bool> MAIN_FASTMEM_ARENA;
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.
extern const Info<bool> MAIN_DSP_HLE;
Expand Down
Expand Up @@ -82,7 +82,7 @@ CachedInterpreter::~CachedInterpreter() = default;

void CachedInterpreter::Init()
{
RefreshConfig(InitFastmemArena::No);
RefreshConfig();

m_code.reserve(CODE_SIZE / sizeof(Instruction));

Expand Down Expand Up @@ -384,5 +384,5 @@ void CachedInterpreter::ClearCache()
{
m_code.clear();
m_block_cache.Clear();
RefreshConfig(InitFastmemArena::No);
RefreshConfig();
}
7 changes: 5 additions & 2 deletions Source/Core/Core/PowerPC/Jit64/Jit.cpp
Expand Up @@ -251,7 +251,9 @@ bool Jit64::BackPatch(SContext* ctx)

void Jit64::Init()
{
RefreshConfig(InitFastmemArena::Yes);
InitFastmemArena();

RefreshConfig();

EnableBlockLink();

Expand Down Expand Up @@ -304,7 +306,8 @@ void Jit64::ClearCache()
m_const_pool.Clear();
ClearCodeSpace();
Clear();
RefreshConfig(InitFastmemArena::No);
RefreshConfig();
asm_routines.Regenerate();
ResetFreeMemoryRanges();
}

Expand Down
10 changes: 9 additions & 1 deletion Source/Core/Core/PowerPC/Jit64/JitAsm.cpp
Expand Up @@ -32,7 +32,15 @@ void Jit64AsmRoutineManager::Init()
{
m_const_pool.Init(AllocChildCodeSpace(4096), 4096);
Generate();
WriteProtect();
WriteProtect(true);
}

void Jit64AsmRoutineManager::Regenerate()
{
UnWriteProtect(false);
ResetCodePtr();
Generate();
WriteProtect(true);
}

// PLAN: no more block numbers - crazy opcodes just contain offset within
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/PowerPC/Jit64/JitAsm.h
Expand Up @@ -35,6 +35,7 @@ class Jit64AsmRoutineManager : public CommonAsmRoutines
explicit Jit64AsmRoutineManager(Jit64& jit);

void Init();
void Regenerate();

void ResetStack(Gen::X64CodeBlock& emitter);

Expand Down
6 changes: 4 additions & 2 deletions Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp
Expand Up @@ -372,7 +372,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 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)
{
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse);
Expand Down Expand Up @@ -541,7 +542,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 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)
{
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
Expand Down
10 changes: 6 additions & 4 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Expand Up @@ -47,7 +47,9 @@ JitArm64::~JitArm64() = default;

void JitArm64::Init()
{
RefreshConfig(InitFastmemArena::Yes);
InitFastmemArena();

RefreshConfig();

const size_t child_code_size = jo.memcheck ? FARCODE_SIZE_MMU : FARCODE_SIZE;
AllocCodeSpace(CODE_SIZE + child_code_size);
Expand Down Expand Up @@ -155,7 +157,7 @@ void JitArm64::ClearCache()
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
ClearCodeSpace();
m_far_code.ClearCodeSpace();
RefreshConfig(InitFastmemArena::No);
RefreshConfig();

GenerateAsm();

Expand Down Expand Up @@ -364,8 +366,8 @@ void JitArm64::EmitStoreMembase(const ARM64Reg& msr)
auto& memory = m_system.GetMemory();
ARM64Reg WD = gpr.GetReg();
ARM64Reg XD = EncodeRegTo64(WD);
MOVP2R(MEM_REG, jo.fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
MOVP2R(XD, jo.fastmem_arena ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
MOVP2R(MEM_REG, jo.fastmem ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
MOVP2R(XD, jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
TST(msr, LogicalImm(1 << (31 - 27), 32));
CSEL(MEM_REG, MEM_REG, XD, CCFlags::CC_NEQ);
STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr));
Expand Down
10 changes: 5 additions & 5 deletions Source/Core/Core/PowerPC/JitArm64/Jit.h
Expand Up @@ -233,7 +233,7 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonA
// 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!
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
// 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.
Expand All @@ -259,10 +259,10 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonA
//
// emitting_routine && mode == Auto: X2
// emitting_routine && mode == Auto && !(flags & BackPatchInfo::FLAG_STORE): X3
// emitting_routine && mode != AlwaysSafe && !jo.fastmem_arena: X3
// mode != AlwaysSafe && !jo.fastmem_arena: X2
// !emitting_routine && mode != AlwaysSafe && !jo.fastmem_arena: X30
// !emitting_routine && mode == Auto && jo.fastmem_arena: X30
// emitting_routine && mode != AlwaysSafe && !jo.fastmem: X3
// mode != AlwaysSafe && !jo.fastmem: X2
// !emitting_routine && mode != AlwaysSafe && !jo.fastmem: X30
// !emitting_routine && mode == Auto && jo.fastmem: X30
//
// Furthermore, any callee-saved register which isn't marked in gprs_to_push/fprs_to_push
// may be clobbered if mode != AlwaysUnsafe.
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp
Expand Up @@ -74,7 +74,7 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
ARM64Reg memory_base = MEM_REG;
ARM64Reg memory_offset = addr;

if (!jo.fastmem_arena)
if (!jo.fastmem)
{
const ARM64Reg temp = emitting_routine ? ARM64Reg::W3 : ARM64Reg::W30;

Expand Down Expand Up @@ -158,7 +158,7 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
in_far_code = true;
SwitchToFarCode();

if (jo.fastmem_arena && !emitting_routine)
if (jo.fastmem && !emitting_routine)
{
FastmemArea* fastmem_area = &m_fault_to_handler[fastmem_end];
fastmem_area->fastmem_code = fastmem_start;
Expand Down
30 changes: 15 additions & 15 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp
Expand Up @@ -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
gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Lock(ARM64Reg::W2);

gpr.BindToRegister(dest, dest == (u32)addr || dest == (u32)offsetReg, false);
Expand Down Expand Up @@ -124,7 +124,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
if (!update || early_update)
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
if (!jo.fastmem_arena)
if (!jo.fastmem)
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
if (!jo.memcheck)
regs_in_use[DecodeReg(dest_reg)] = 0;
Expand Down Expand Up @@ -166,7 +166,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
}

gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Unlock(ARM64Reg::W2);
}

Expand All @@ -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
gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Lock(ARM64Reg::W2);

ARM64Reg RS = gpr.R(value);
Expand Down Expand Up @@ -272,7 +272,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
if (!update || early_update)
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
if (!jo.fastmem_arena)
if (!jo.fastmem)
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;

u32 access_size = BackPatchInfo::GetFlagSize(flags);
Expand Down Expand Up @@ -335,7 +335,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
}

gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Unlock(ARM64Reg::W2);
}

Expand Down Expand Up @@ -519,7 +519,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
s32 offset = inst.SIMM_16;

gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Lock(ARM64Reg::W2);

// MMU games make use of a >= d despite this being invalid according to the PEM.
Expand Down Expand Up @@ -554,7 +554,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
regs_in_use[DecodeReg(addr_reg)] = 0;
if (!jo.fastmem_arena)
if (!jo.fastmem)
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;
if (!jo.memcheck)
regs_in_use[DecodeReg(dest_reg)] = 0;
Expand All @@ -567,7 +567,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
}

gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Unlock(ARM64Reg::W2);
if (!a_is_addr_base_reg)
gpr.Unlock(addr_base_reg);
Expand All @@ -582,7 +582,7 @@ void JitArm64::stmw(UGeckoInstruction inst)
s32 offset = inst.SIMM_16;

gpr.Lock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Lock(ARM64Reg::W2);

ARM64Reg addr_reg = ARM64Reg::W1;
Expand Down Expand Up @@ -615,15 +615,15 @@ void JitArm64::stmw(UGeckoInstruction inst)
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
regs_in_use[DecodeReg(addr_reg)] = 0;
if (!jo.fastmem_arena)
if (!jo.fastmem)
regs_in_use[DecodeReg(ARM64Reg::W2)] = 0;

EmitBackpatchRoutine(flags, MemAccessMode::Auto, src_reg, EncodeRegTo64(addr_reg), regs_in_use,
fprs_in_use);
}

gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Unlock(ARM64Reg::W2);
if (!a_is_addr_base_reg)
gpr.Unlock(addr_base_reg);
Expand Down Expand Up @@ -818,12 +818,12 @@ void JitArm64::dcbz(UGeckoInstruction inst)
int a = inst.RA, b = inst.RB;

gpr.Lock(ARM64Reg::W0, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Lock(ARM64Reg::W2);

Common::ScopeGuard register_guard([&] {
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
if (!jo.fastmem_arena)
if (!jo.fastmem)
gpr.Unlock(ARM64Reg::W2);
});

Expand Down Expand Up @@ -892,7 +892,7 @@ void JitArm64::dcbz(UGeckoInstruction inst)
BitSet32 gprs_to_push = gpr.GetCallerSavedUsed();
BitSet32 fprs_to_push = fpr.GetCallerSavedUsed();
gprs_to_push[DecodeReg(ARM64Reg::W0)] = 0;
if (!jo.fastmem_arena)
if (!jo.fastmem)
gprs_to_push[DecodeReg(ARM64Reg::W2)] = 0;

EmitBackpatchRoutine(BackPatchInfo::FLAG_ZERO_256, MemAccessMode::Auto, ARM64Reg::W0,
Expand Down

0 comments on commit 166d8a1

Please sign in to comment.