Skip to content
Permalink
Browse files
Merge pull request #9805 from JosJuice/rounding-mode-savestate
PowerPC: Set host CPU rounding mode on init and savestate
  • Loading branch information
leoetlino committed Jun 13, 2021
2 parents dd26106 + 9db0ebd commit 8ef4bd6
Show file tree
Hide file tree
Showing 9 changed files with 26 additions and 31 deletions.
@@ -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,23 +25,17 @@ 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)
{
// PanicAlert("FPSCR - exceptions enabled. Please report. VE=%i OE=%i UE=%i ZE=%i XE=%i",
// 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

0 comments on commit 8ef4bd6

Please sign in to comment.