mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-18 14:25:38 +00:00
CPU/Recompiler: Prevent using fastmem when cache is isolated
No point even trying since it's just going to fault.
This commit is contained in:
parent
922d320523
commit
e087e6f3a2
|
@ -77,7 +77,7 @@ static std::wstring s_write_directory;
|
|||
static PVOID s_veh_handle = nullptr;
|
||||
static bool s_in_crash_handler = false;
|
||||
|
||||
static LONG ExceptionHandler(PEXCEPTION_POINTERS exi)
|
||||
static LONG NTAPI ExceptionHandler(PEXCEPTION_POINTERS exi)
|
||||
{
|
||||
if (s_in_crash_handler)
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
|
|
@ -307,7 +307,14 @@ CPUFastmemMode GetFastmemMode()
|
|||
|
||||
u8* GetFastmemBase()
|
||||
{
|
||||
return m_fastmem_base;
|
||||
#ifdef WITH_MMAP_FASTMEM
|
||||
if (m_fastmem_mode == CPUFastmemMode::MMap)
|
||||
return m_fastmem_base;
|
||||
#endif
|
||||
if (m_fastmem_mode == CPUFastmemMode::LUT)
|
||||
return reinterpret_cast<u8*>(m_fastmem_lut);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UpdateFastmemViews(CPUFastmemMode mode)
|
||||
|
@ -346,7 +353,6 @@ void UpdateFastmemViews(CPUFastmemMode mode)
|
|||
}
|
||||
|
||||
Log_InfoPrintf("Fastmem base: %p", m_fastmem_base);
|
||||
CPU::g_state.fastmem_base = m_fastmem_base;
|
||||
}
|
||||
|
||||
auto MapRAM = [](u32 base_address) {
|
||||
|
@ -423,7 +429,6 @@ void UpdateFastmemViews(CPUFastmemMode mode)
|
|||
Assert(m_fastmem_lut);
|
||||
|
||||
Log_InfoPrintf("Fastmem base (software): %p", m_fastmem_lut);
|
||||
CPU::g_state.fastmem_base = reinterpret_cast<u8*>(m_fastmem_lut);
|
||||
}
|
||||
|
||||
auto MapRAM = [](u32 base_address) {
|
||||
|
|
|
@ -785,6 +785,7 @@ bool InitializeFastmem()
|
|||
}
|
||||
|
||||
Bus::UpdateFastmemViews(mode);
|
||||
CPU::UpdateFastmemBase();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -792,6 +793,7 @@ void ShutdownFastmem()
|
|||
{
|
||||
Common::PageFaultHandler::RemoveHandler(&s_host_code_map);
|
||||
Bus::UpdateFastmemViews(CPUFastmemMode::Disabled);
|
||||
CPU::UpdateFastmemBase();
|
||||
}
|
||||
|
||||
#ifdef WITH_MMAP_FASTMEM
|
||||
|
|
|
@ -99,6 +99,8 @@ void Initialize()
|
|||
s_last_breakpoint_check_pc = INVALID_BREAKPOINT_PC;
|
||||
s_single_step = false;
|
||||
|
||||
UpdateFastmemBase();
|
||||
|
||||
GTE::Initialize();
|
||||
|
||||
if (g_settings.gpu_pgxp_enable)
|
||||
|
@ -131,6 +133,7 @@ void Reset()
|
|||
g_state.cop0_regs.cause.bits = 0;
|
||||
|
||||
ClearICache();
|
||||
UpdateFastmemBase();
|
||||
|
||||
GTE::Reset();
|
||||
|
||||
|
@ -195,6 +198,14 @@ bool DoState(StateWrapper& sw)
|
|||
return !sw.HasError();
|
||||
}
|
||||
|
||||
void UpdateFastmemBase()
|
||||
{
|
||||
if (g_state.cop0_regs.sr.Isc)
|
||||
g_state.fastmem_base = nullptr;
|
||||
else
|
||||
g_state.fastmem_base = Bus::GetFastmemBase();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE void SetPC(u32 new_pc)
|
||||
{
|
||||
DebugAssert(Common::IsAlignedPow2(new_pc, 4));
|
||||
|
@ -1973,14 +1984,6 @@ bool InterpretInstructionPGXP()
|
|||
return g_state.exception_raised;
|
||||
}
|
||||
|
||||
void UpdateFastmemMapping()
|
||||
{
|
||||
if (g_state.cop0_regs.sr.Isc)
|
||||
g_state.fastmem_base = nullptr;
|
||||
else
|
||||
g_state.fastmem_base = Bus::GetFastmemBase();
|
||||
}
|
||||
|
||||
} // namespace Recompiler::Thunks
|
||||
|
||||
} // namespace CPU
|
||||
|
|
|
@ -94,6 +94,7 @@ void Shutdown();
|
|||
void Reset();
|
||||
bool DoState(StateWrapper& sw);
|
||||
void ClearICache();
|
||||
void UpdateFastmemBase();
|
||||
|
||||
/// Executes interpreter loop.
|
||||
void Execute();
|
||||
|
|
|
@ -2433,7 +2433,11 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
|||
EmitFunctionCall(nullptr, &PGXP::CPU_MFC0, Value::FromConstantU32(cbi.instruction.bits), value);
|
||||
|
||||
m_register_cache.WriteGuestRegisterDelayed(cbi.instruction.r.rt, std::move(value));
|
||||
SpeculativeWriteReg(cbi.instruction.r.rt, std::nullopt);
|
||||
|
||||
if (reg == Cop0Reg::SR)
|
||||
SpeculativeWriteReg(cbi.instruction.r.rt, m_speculative_constants.cop0_sr);
|
||||
else
|
||||
SpeculativeWriteReg(cbi.instruction.r.rt, std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2465,6 +2469,9 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
|||
EmitFunctionCall(nullptr, &PGXP::CPU_MTC0, Value::FromConstantU32(cbi.instruction.bits), value, value);
|
||||
}
|
||||
|
||||
if (reg == Cop0Reg::SR)
|
||||
m_speculative_constants.cop0_sr = SpeculativeReadReg(cbi.instruction.r.rt);
|
||||
|
||||
// changing SR[Isc] needs to update fastmem views
|
||||
if (reg == Cop0Reg::SR && g_settings.IsUsingFastmem())
|
||||
{
|
||||
|
@ -2475,8 +2482,8 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
|||
EmitXor(old_value.host_reg, old_value.host_reg, value);
|
||||
EmitBranchIfBitClear(old_value.host_reg, RegSize_32, 16, &skip_fastmem_update);
|
||||
m_register_cache.InhibitAllocation();
|
||||
EmitFunctionCall(nullptr, &Thunks::UpdateFastmemMapping, m_register_cache.GetCPUPtr());
|
||||
EmitUpdateMembasePointer();
|
||||
EmitFunctionCall(nullptr, &UpdateFastmemBase, m_register_cache.GetCPUPtr());
|
||||
EmitUpdateFastmemBase();
|
||||
EmitBindLabel(&skip_fastmem_update);
|
||||
m_register_cache.UninhibitAllocation();
|
||||
}
|
||||
|
@ -2785,12 +2792,15 @@ void CodeGenerator::InitSpeculativeRegs()
|
|||
{
|
||||
for (u8 i = 0; i < static_cast<u8>(Reg::count); i++)
|
||||
m_speculative_constants.regs[i] = g_state.regs.r[i];
|
||||
|
||||
m_speculative_constants.cop0_sr = g_state.cop0_regs.sr.bits;
|
||||
}
|
||||
|
||||
void CodeGenerator::InvalidateSpeculativeValues()
|
||||
{
|
||||
m_speculative_constants.regs.fill(std::nullopt);
|
||||
m_speculative_constants.memory.clear();
|
||||
m_speculative_constants.cop0_sr.reset();
|
||||
}
|
||||
|
||||
CodeGenerator::SpeculativeValue CodeGenerator::SpeculativeReadReg(Reg reg)
|
||||
|
@ -2844,4 +2854,13 @@ void CodeGenerator::SpeculativeWriteMemory(u32 address, SpeculativeValue value)
|
|||
m_speculative_constants.memory.emplace(address, value);
|
||||
}
|
||||
|
||||
bool CodeGenerator::SpeculativeIsCacheIsolated()
|
||||
{
|
||||
if (!m_speculative_constants.cop0_sr.has_value())
|
||||
return false;
|
||||
|
||||
const Cop0Registers::SR sr{m_speculative_constants.cop0_sr.value()};
|
||||
return sr.Isc;
|
||||
}
|
||||
|
||||
} // namespace CPU::Recompiler
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
void EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, const Value& value);
|
||||
void EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, const Value& value,
|
||||
bool in_far_code);
|
||||
void EmitUpdateMembasePointer();
|
||||
void EmitUpdateFastmemBase();
|
||||
|
||||
// Unconditional branch to pointer. May allocate a scratch register.
|
||||
void EmitBranch(const void* address, bool allow_scratch = true);
|
||||
|
@ -264,6 +264,7 @@ private:
|
|||
{
|
||||
std::array<SpeculativeValue, static_cast<u8>(Reg::count)> regs;
|
||||
std::unordered_map<PhysicalMemoryAddress, SpeculativeValue> memory;
|
||||
SpeculativeValue cop0_sr;
|
||||
};
|
||||
|
||||
void InitSpeculativeRegs();
|
||||
|
@ -272,6 +273,7 @@ private:
|
|||
void SpeculativeWriteReg(Reg reg, SpeculativeValue value);
|
||||
SpeculativeValue SpeculativeReadMemory(u32 address);
|
||||
void SpeculativeWriteMemory(VirtualMemoryAddress address, SpeculativeValue value);
|
||||
bool SpeculativeIsCacheIsolated();
|
||||
|
||||
SpeculativeConstants m_speculative_constants;
|
||||
};
|
||||
|
|
|
@ -1170,7 +1170,7 @@ Value CodeGenerator::GetFastmemStoreBase()
|
|||
return val;
|
||||
}
|
||||
|
||||
void CodeGenerator::EmitUpdateMembasePointer()
|
||||
void CodeGenerator::EmitUpdateFastmemBase()
|
||||
{
|
||||
if (m_fastmem_load_base_in_register)
|
||||
{
|
||||
|
|
|
@ -1728,7 +1728,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi,
|
|||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::EmitUpdateMembasePointer()
|
||||
void CodeGenerator::EmitUpdateFastmemBase()
|
||||
{
|
||||
m_emit->Ldr(GetFastmemBasePtrReg(), a64::MemOperand(GetCPUPtrReg(), offsetof(State, fastmem_base)));
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void CodeGenerator::EmitStoreInterpreterLoadDelay(Reg reg, const Value& value)
|
|||
Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const Value& address,
|
||||
const SpeculativeValue& address_spec, RegSize size)
|
||||
{
|
||||
if (address.IsConstant())
|
||||
if (address.IsConstant() && !SpeculativeIsCacheIsolated())
|
||||
{
|
||||
TickCount read_ticks;
|
||||
void* ptr = GetDirectReadMemoryPointer(
|
||||
|
@ -61,17 +61,20 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const
|
|||
|
||||
Value result = m_register_cache.AllocateScratch(HostPointerSize);
|
||||
|
||||
const bool use_fastmem = address_spec ? Bus::CanUseFastmemForAddress(*address_spec) : true;
|
||||
const bool use_fastmem =
|
||||
(address_spec ? Bus::CanUseFastmemForAddress(*address_spec) : true) && !SpeculativeIsCacheIsolated();
|
||||
if (address_spec)
|
||||
{
|
||||
if (!use_fastmem)
|
||||
Log_DevPrintf("Non-constant load at 0x%08X, speculative address 0x%08X, using fastmem = %s", cbi.pc,
|
||||
*address_spec, use_fastmem ? "yes" : "no");
|
||||
{
|
||||
Log_ProfilePrintf("Non-constant load at 0x%08X, speculative address 0x%08X, using fastmem = %s", cbi.pc,
|
||||
*address_spec, use_fastmem ? "yes" : "no");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_DevPrintf("Non-constant load at 0x%08X, speculative address UNKNOWN, using fastmem = %s", cbi.pc,
|
||||
use_fastmem ? "yes" : "no");
|
||||
Log_ProfilePrintf("Non-constant load at 0x%08X, speculative address UNKNOWN, using fastmem = %s", cbi.pc,
|
||||
use_fastmem ? "yes" : "no");
|
||||
}
|
||||
|
||||
if (g_settings.IsUsingFastmem() && use_fastmem)
|
||||
|
@ -113,7 +116,7 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const
|
|||
void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const Value& address,
|
||||
const SpeculativeValue& address_spec, const Value& value)
|
||||
{
|
||||
if (address.IsConstant())
|
||||
if (address.IsConstant() && !SpeculativeIsCacheIsolated())
|
||||
{
|
||||
void* ptr = GetDirectWriteMemoryPointer(
|
||||
static_cast<u32>(address.constant_value),
|
||||
|
@ -128,17 +131,20 @@ void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const
|
|||
|
||||
AddPendingCycles(true);
|
||||
|
||||
const bool use_fastmem = address_spec ? Bus::CanUseFastmemForAddress(*address_spec) : true;
|
||||
const bool use_fastmem =
|
||||
(address_spec ? Bus::CanUseFastmemForAddress(*address_spec) : true) && !SpeculativeIsCacheIsolated();
|
||||
if (address_spec)
|
||||
{
|
||||
if (!use_fastmem)
|
||||
Log_DevPrintf("Non-constant store at 0x%08X, speculative address 0x%08X, using fastmem = %s", cbi.pc,
|
||||
*address_spec, use_fastmem ? "yes" : "no");
|
||||
{
|
||||
Log_ProfilePrintf("Non-constant store at 0x%08X, speculative address 0x%08X, using fastmem = %s", cbi.pc,
|
||||
*address_spec, use_fastmem ? "yes" : "no");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_DevPrintf("Non-constant store at 0x%08X, speculative address UNKNOWN, using fastmem = %s", cbi.pc,
|
||||
use_fastmem ? "yes" : "no");
|
||||
Log_ProfilePrintf("Non-constant store at 0x%08X, speculative address UNKNOWN, using fastmem = %s", cbi.pc,
|
||||
use_fastmem ? "yes" : "no");
|
||||
}
|
||||
|
||||
if (g_settings.IsUsingFastmem() && use_fastmem)
|
||||
|
|
|
@ -2313,7 +2313,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi,
|
|||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::EmitUpdateMembasePointer()
|
||||
void CodeGenerator::EmitUpdateFastmemBase()
|
||||
{
|
||||
m_emit->mov(GetFastmemBasePtrReg(), m_emit->qword[GetCPUPtrReg() + offsetof(CPU::State, fastmem_base)]);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@ void UncheckedWriteMemoryByte(u32 address, u8 value);
|
|||
void UncheckedWriteMemoryHalfWord(u32 address, u16 value);
|
||||
void UncheckedWriteMemoryWord(u32 address, u32 value);
|
||||
|
||||
void UpdateFastmemMapping();
|
||||
|
||||
} // namespace Recompiler::Thunks
|
||||
|
||||
} // namespace CPU
|
||||
|
|
Loading…
Reference in a new issue