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
|
// 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)
|
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,
|
// 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 SetRoundMode(int mode);
|
||||||
|
|
||||||
void SetPrecisionMode(PrecisionMode mode);
|
|
||||||
|
|
||||||
void SetSIMDMode(int rounding_mode, bool non_ieee_mode);
|
void SetSIMDMode(int rounding_mode, bool non_ieee_mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -11,9 +11,6 @@ namespace FPURoundMode
|
||||||
void SetRoundMode(int mode)
|
void SetRoundMode(int mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void SetPrecisionMode(PrecisionMode mode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
|
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,6 @@ void SetRoundMode(int mode)
|
||||||
fesetround(rounding_mode_lut[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)
|
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
|
||||||
{
|
{
|
||||||
// OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register)
|
// OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "Common/CommonPaths.h"
|
#include "Common/CommonPaths.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Event.h"
|
#include "Common/Event.h"
|
||||||
|
#include "Common/FPURoundMode.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/Flag.h"
|
#include "Common/Flag.h"
|
||||||
#include "Common/Logging/Log.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
|
// thread, and then takes over and becomes the video thread
|
||||||
Common::SetCurrentThreadName("Video thread");
|
Common::SetCurrentThreadName("Video thread");
|
||||||
UndeclareAsCPUThread();
|
UndeclareAsCPUThread();
|
||||||
|
FPURoundMode::LoadDefaultSIMDState();
|
||||||
|
|
||||||
// Spawn the CPU thread. The CPU thread will signal the event that boot is complete.
|
// 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);
|
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()
|
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);
|
std::unique_lock state_lock(s_state_change_lock);
|
||||||
while (s_state != State::PowerDown)
|
while (s_state != State::PowerDown)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/FPURoundMode.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/HW/GPFifo.h"
|
#include "Core/HW/GPFifo.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
@ -26,13 +25,10 @@ mffsx: 80036608
|
||||||
mffsx: 80036650 (huh?)
|
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)
|
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);
|
// fp.VE, fp.OE, fp.UE, fp.ZE, fp.XE);
|
||||||
// Pokemon Colosseum does this. Gah.
|
// Pokemon Colosseum does this. Gah.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set SSE rounding mode and denormal handling
|
|
||||||
FPURoundMode::SetSIMDMode(fp.RN, fp.NI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateFPSCR(UReg_FPSCR* fpscr)
|
static void UpdateFPSCR(UReg_FPSCR* fpscr)
|
||||||
|
@ -57,7 +50,7 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst)
|
||||||
u32 b = 0x80000000 >> inst.CRBD;
|
u32 b = 0x80000000 >> inst.CRBD;
|
||||||
|
|
||||||
FPSCR.Hex &= ~b;
|
FPSCR.Hex &= ~b;
|
||||||
FPSCRtoFPUSettings(FPSCR);
|
FPSCRUpdated(FPSCR);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -74,7 +67,7 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst)
|
||||||
else
|
else
|
||||||
FPSCR |= b;
|
FPSCR |= b;
|
||||||
|
|
||||||
FPSCRtoFPUSettings(FPSCR);
|
FPSCRUpdated(FPSCR);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -89,7 +82,7 @@ void Interpreter::mtfsfix(UGeckoInstruction inst)
|
||||||
|
|
||||||
FPSCR = (FPSCR.Hex & ~mask) | (imm >> (4 * field));
|
FPSCR = (FPSCR.Hex & ~mask) | (imm >> (4 * field));
|
||||||
|
|
||||||
FPSCRtoFPUSettings(FPSCR);
|
FPSCRUpdated(FPSCR);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -106,7 +99,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
FPSCR = (FPSCR.Hex & ~m) | (static_cast<u32>(rPS(inst.FB).PS0AsU64()) & m);
|
FPSCR = (FPSCR.Hex & ~m) | (static_cast<u32>(rPS(inst.FB).PS0AsU64()) & m);
|
||||||
FPSCRtoFPUSettings(FPSCR);
|
FPSCRUpdated(FPSCR);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
@ -129,6 +130,7 @@ void DoState(PointerWrap& p)
|
||||||
|
|
||||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||||
{
|
{
|
||||||
|
RoundingModeUpdated();
|
||||||
IBATUpdated();
|
IBATUpdated();
|
||||||
DBATUpdated();
|
DBATUpdated();
|
||||||
}
|
}
|
||||||
|
@ -180,6 +182,7 @@ static void ResetRegisters()
|
||||||
}
|
}
|
||||||
SetXER({});
|
SetXER({});
|
||||||
|
|
||||||
|
RoundingModeUpdated();
|
||||||
DBATUpdated();
|
DBATUpdated();
|
||||||
IBATUpdated();
|
IBATUpdated();
|
||||||
|
|
||||||
|
@ -246,10 +249,6 @@ CPUCore DefaultCPUCore()
|
||||||
|
|
||||||
void Init(CPUCore cpu_core)
|
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 =
|
s_invalidate_cache_thread_safe =
|
||||||
CoreTiming::RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
CoreTiming::RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
||||||
|
|
||||||
|
@ -632,4 +631,13 @@ void UpdateFPRF(double dvalue)
|
||||||
FPSCR.FPRF = Common::ClassifyDouble(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
|
} // namespace PowerPC
|
||||||
|
|
|
@ -306,4 +306,6 @@ inline void SetXER_OV(bool value)
|
||||||
|
|
||||||
void UpdateFPRF(double dvalue);
|
void UpdateFPRF(double dvalue);
|
||||||
|
|
||||||
|
void RoundingModeUpdated();
|
||||||
|
|
||||||
} // namespace PowerPC
|
} // namespace PowerPC
|
||||||
|
|
Loading…
Reference in New Issue