JitArm64: Make fcmpX with flush-to-zero enabled less bad
See the added code comment for details. Fixes Pokémon Battle Revolution not progressing past the title screen.
This commit is contained in:
parent
21ebc176fe
commit
b6cc3c4b6e
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Common/Arm64Emitter.h"
|
#include "Common/Arm64Emitter.h"
|
||||||
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
@ -374,7 +375,19 @@ void JitArm64::fcmpX(UGeckoInstruction inst)
|
||||||
const u32 b = inst.FB;
|
const u32 b = inst.FB;
|
||||||
const int crf = inst.CRFD;
|
const int crf = inst.CRFD;
|
||||||
|
|
||||||
const bool singles = fpr.IsSingle(a, true) && fpr.IsSingle(b, true);
|
// On the GC/Wii CPU, outputs are flushed to zero if FPSCR.NI is set, and inputs are never
|
||||||
|
// flushed to zero. Ideally we would emulate FPSCR.NI by setting FPCR.FZ and FPCR.AH, but
|
||||||
|
// unfortunately FPCR.AH is a very new feature that we can't rely on (as of 2021). For CPUs
|
||||||
|
// without FPCR.AH, the best we can do (without killing the performance by explicitly flushing
|
||||||
|
// outputs using bitwise operations) is to only set FPCR.FZ, which flushes both inputs and
|
||||||
|
// outputs. This may cause problems in some cases, and one such case is Pokémon Battle Revolution,
|
||||||
|
// which does not progress past the title screen if a denormal single compares equal to zero.
|
||||||
|
// Workaround: Perform the comparison using a double operation instead. This ensures that denormal
|
||||||
|
// singles behave correctly in comparisons, but we still have a problem with denormal doubles.
|
||||||
|
const bool input_ftz_workaround =
|
||||||
|
!cpu_info.bAFP && (!js.fpr_is_store_safe[a] || !js.fpr_is_store_safe[b]);
|
||||||
|
|
||||||
|
const bool singles = fpr.IsSingle(a, true) && fpr.IsSingle(b, true) && !input_ftz_workaround;
|
||||||
const RegType type = singles ? RegType::LowerPairSingle : RegType::LowerPair;
|
const RegType type = singles ? RegType::LowerPairSingle : RegType::LowerPair;
|
||||||
const auto reg_encoder = singles ? EncodeRegToSingle : EncodeRegToDouble;
|
const auto reg_encoder = singles ? EncodeRegToSingle : EncodeRegToDouble;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue