Merge pull request #9805 from JosJuice/rounding-mode-savestate
PowerPC: Set host CPU rounding mode on init and savestate
This commit is contained in:
commit
8ef4bd682b
|
@ -41,10 +41,6 @@ void SetRoundMode(int mode)
|
|||
// We don't need to do anything here since SetSIMDMode is always called after calling this
|
||||
}
|
||||
|
||||
void SetPrecisionMode(PrecisionMode mode)
|
||||
{
|
||||
}
|
||||
|
||||
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
|
||||
{
|
||||
// When AH is disabled, FZ controls flush-to-zero for both inputs and outputs. When AH is enabled,
|
||||
|
|
|
@ -29,8 +29,6 @@ enum PrecisionMode
|
|||
|
||||
void SetRoundMode(int mode);
|
||||
|
||||
void SetPrecisionMode(PrecisionMode mode);
|
||||
|
||||
void SetSIMDMode(int rounding_mode, bool non_ieee_mode);
|
||||
|
||||
/*
|
||||
|
|
|
@ -11,9 +11,6 @@ namespace FPURoundMode
|
|||
void SetRoundMode(int mode)
|
||||
{
|
||||
}
|
||||
void SetPrecisionMode(PrecisionMode mode)
|
||||
{
|
||||
}
|
||||
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -22,11 +22,6 @@ void SetRoundMode(int mode)
|
|||
fesetround(rounding_mode_lut[mode]);
|
||||
}
|
||||
|
||||
void SetPrecisionMode(PrecisionMode /* mode */)
|
||||
{
|
||||
// x64 doesn't need this - fpu is done with SSE
|
||||
}
|
||||
|
||||
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
|
||||
{
|
||||
// OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/FPURoundMode.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
@ -625,6 +626,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||
// thread, and then takes over and becomes the video thread
|
||||
Common::SetCurrentThreadName("Video thread");
|
||||
UndeclareAsCPUThread();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
|
||||
// Spawn the CPU thread. The CPU thread will signal the event that boot is complete.
|
||||
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate);
|
||||
|
|
|
@ -87,6 +87,10 @@ static void ExecutePendingJobs(std::unique_lock<std::mutex>& state_lock)
|
|||
|
||||
void Run()
|
||||
{
|
||||
// Updating the host CPU's rounding mode must be done on the CPU thread.
|
||||
// We can't rely on PowerPC::Init doing it, since it's called from EmuThread.
|
||||
PowerPC::RoundingModeUpdated();
|
||||
|
||||
std::unique_lock state_lock(s_state_change_lock);
|
||||
while (s_state != State::PowerDown)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FPURoundMode.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/HW/GPFifo.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
|
@ -26,13 +25,10 @@ mffsx: 80036608
|
|||
mffsx: 80036650 (huh?)
|
||||
|
||||
*/
|
||||
// TODO(ector): More proper handling of SSE state.
|
||||
// That is, set rounding mode etc when entering jit code or the interpreter loop
|
||||
// Restore rounding mode when calling anything external
|
||||
|
||||
static void FPSCRtoFPUSettings(UReg_FPSCR fp)
|
||||
static void FPSCRUpdated(UReg_FPSCR fp)
|
||||
{
|
||||
FPURoundMode::SetRoundMode(fp.RN);
|
||||
PowerPC::RoundingModeUpdated();
|
||||
|
||||
if (fp.VE || fp.OE || fp.UE || fp.ZE || fp.XE)
|
||||
{
|
||||
|
@ -40,9 +36,6 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp)
|
|||
// fp.VE, fp.OE, fp.UE, fp.ZE, fp.XE);
|
||||
// Pokemon Colosseum does this. Gah.
|
||||
}
|
||||
|
||||
// Set SSE rounding mode and denormal handling
|
||||
FPURoundMode::SetSIMDMode(fp.RN, fp.NI);
|
||||
}
|
||||
|
||||
static void UpdateFPSCR(UReg_FPSCR* fpscr)
|
||||
|
@ -57,7 +50,7 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst)
|
|||
u32 b = 0x80000000 >> inst.CRBD;
|
||||
|
||||
FPSCR.Hex &= ~b;
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
FPSCRUpdated(FPSCR);
|
||||
|
||||
if (inst.Rc)
|
||||
PowerPC::ppcState.UpdateCR1();
|
||||
|
@ -74,7 +67,7 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst)
|
|||
else
|
||||
FPSCR |= b;
|
||||
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
FPSCRUpdated(FPSCR);
|
||||
|
||||
if (inst.Rc)
|
||||
PowerPC::ppcState.UpdateCR1();
|
||||
|
@ -89,7 +82,7 @@ void Interpreter::mtfsfix(UGeckoInstruction inst)
|
|||
|
||||
FPSCR = (FPSCR.Hex & ~mask) | (imm >> (4 * field));
|
||||
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
FPSCRUpdated(FPSCR);
|
||||
|
||||
if (inst.Rc)
|
||||
PowerPC::ppcState.UpdateCR1();
|
||||
|
@ -106,7 +99,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst)
|
|||
}
|
||||
|
||||
FPSCR = (FPSCR.Hex & ~m) | (static_cast<u32>(rPS(inst.FB).PS0AsU64()) & m);
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
FPSCRUpdated(FPSCR);
|
||||
|
||||
if (inst.Rc)
|
||||
PowerPC::ppcState.UpdateCR1();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Common/Logging/Log.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HW/CPU.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
|
@ -129,6 +130,7 @@ void DoState(PointerWrap& p)
|
|||
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
RoundingModeUpdated();
|
||||
IBATUpdated();
|
||||
DBATUpdated();
|
||||
}
|
||||
|
@ -180,6 +182,7 @@ static void ResetRegisters()
|
|||
}
|
||||
SetXER({});
|
||||
|
||||
RoundingModeUpdated();
|
||||
DBATUpdated();
|
||||
IBATUpdated();
|
||||
|
||||
|
@ -246,10 +249,6 @@ CPUCore DefaultCPUCore()
|
|||
|
||||
void Init(CPUCore cpu_core)
|
||||
{
|
||||
// NOTE: This function runs on EmuThread, not the CPU Thread.
|
||||
// Changing the rounding mode has a limited effect.
|
||||
FPURoundMode::SetPrecisionMode(FPURoundMode::PREC_53);
|
||||
|
||||
s_invalidate_cache_thread_safe =
|
||||
CoreTiming::RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
||||
|
||||
|
@ -632,4 +631,13 @@ void UpdateFPRF(double dvalue)
|
|||
FPSCR.FPRF = Common::ClassifyDouble(dvalue);
|
||||
}
|
||||
|
||||
void RoundingModeUpdated()
|
||||
{
|
||||
// The rounding mode is separate for each thread, so this must run on the CPU thread
|
||||
ASSERT(Core::IsCPUThread());
|
||||
|
||||
FPURoundMode::SetRoundMode(FPSCR.RN);
|
||||
FPURoundMode::SetSIMDMode(FPSCR.RN, FPSCR.NI);
|
||||
}
|
||||
|
||||
} // namespace PowerPC
|
||||
|
|
|
@ -306,4 +306,6 @@ inline void SetXER_OV(bool value)
|
|||
|
||||
void UpdateFPRF(double dvalue);
|
||||
|
||||
void RoundingModeUpdated();
|
||||
|
||||
} // namespace PowerPC
|
||||
|
|
Loading…
Reference in New Issue