Merge pull request #9805 from JosJuice/rounding-mode-savestate

PowerPC: Set host CPU rounding mode on init and savestate
This commit is contained in:
Léo Lam 2021-06-13 11:49:29 +02:00 committed by GitHub
commit 8ef4bd682b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 31 deletions

View File

@ -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,

View File

@ -29,8 +29,6 @@ enum PrecisionMode
void SetRoundMode(int mode);
void SetPrecisionMode(PrecisionMode mode);
void SetSIMDMode(int rounding_mode, bool non_ieee_mode);
/*

View File

@ -11,9 +11,6 @@ namespace FPURoundMode
void SetRoundMode(int mode)
{
}
void SetPrecisionMode(PrecisionMode mode)
{
}
void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
{
}

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -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();

View File

@ -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

View File

@ -306,4 +306,6 @@ inline void SetXER_OV(bool value)
void UpdateFPRF(double dvalue);
void RoundingModeUpdated();
} // namespace PowerPC