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