From 88f3fec04e3e3b277d071aa0db19cbe77db2696e Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 24 Jan 2021 14:10:04 +0100 Subject: [PATCH] JitArm64: Add asserts for unexpected single to float conversions If the register pressure is high when allocating registers, Arm64FPRCache may spill a guest register which we are going to allocate later during the current instruction, which has the side effect of turning it into double precision. This will have bad consequences if we are assuming that it is single precision, so let's add some asserts to detect if that ever happens. --- .../JitArm64/JitArm64_FloatingPoint.cpp | 37 ++++++++++++++++--- .../Core/PowerPC/JitArm64/JitArm64_Paired.cpp | 16 ++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp index 8a4eddaf5e..942342707d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp @@ -32,8 +32,11 @@ void JitArm64::fp_arith(UGeckoInstruction inst) bool use_c = op5 >= 25; // fmul and all kind of fmaddXX bool use_b = op5 != 25; // fmul uses no B - bool inputs_are_singles = fpr.IsSingle(a, !packed) && (!use_b || fpr.IsSingle(b, !packed)) && - (!use_c || fpr.IsSingle(c, !packed)); + const auto inputs_are_singles_func = [&] { + return fpr.IsSingle(a, !packed) && (!use_b || fpr.IsSingle(b, !packed)) && + (!use_c || fpr.IsSingle(c, !packed)); + }; + const bool inputs_are_singles = inputs_are_singles_func(); ARM64Reg VA{}, VB{}, VC{}, VD{}; @@ -117,6 +120,9 @@ void JitArm64::fp_arith(UGeckoInstruction inst) } } + ASSERT_MSG(DYNA_REC, inputs_are_singles == inputs_are_singles_func(), + "Register allocation turned singles into doubles in the middle of fp_arith"); + if (single || packed) fpr.FixSinglePrecision(d); } @@ -196,6 +202,9 @@ void JitArm64::fp_logic(UGeckoInstruction inst) break; } } + + ASSERT_MSG(DYNA_REC, single == fpr.IsSingle(b, !packed), + "Register allocation turned singles into doubles in the middle of fp_logic"); } void JitArm64::fselx(UGeckoInstruction inst) @@ -209,6 +218,7 @@ void JitArm64::fselx(UGeckoInstruction inst) const u32 c = inst.FC; const u32 d = inst.FD; + const bool a_single = fpr.IsSingle(a, true); if (fpr.IsSingle(a, true)) { const ARM64Reg VA = fpr.R(a, RegType::LowerPairSingle); @@ -220,15 +230,20 @@ void JitArm64::fselx(UGeckoInstruction inst) m_float_emit.FCMPE(EncodeRegToDouble(VA)); } - const bool single = fpr.IsSingle(b, true) && fpr.IsSingle(c, true); - const RegType type = single ? RegType::LowerPairSingle : RegType::LowerPair; - const auto reg_encoder = single ? EncodeRegToSingle : EncodeRegToDouble; + const bool b_and_c_singles = fpr.IsSingle(b, true) && fpr.IsSingle(c, true); + const RegType type = b_and_c_singles ? RegType::LowerPairSingle : RegType::LowerPair; + const auto reg_encoder = b_and_c_singles ? EncodeRegToSingle : EncodeRegToDouble; const ARM64Reg VB = fpr.R(b, type); const ARM64Reg VC = fpr.R(c, type); const ARM64Reg VD = fpr.RW(d, type); m_float_emit.FCSEL(reg_encoder(VD), reg_encoder(VC), reg_encoder(VB), CC_GE); + + ASSERT_MSG(DYNA_REC, + a_single == fpr.IsSingle(a, true) && + b_and_c_singles == (fpr.IsSingle(b, true) && fpr.IsSingle(c, true)), + "Register allocation turned singles into doubles in the middle of fselx"); } void JitArm64::frspx(UGeckoInstruction inst) @@ -241,7 +256,8 @@ void JitArm64::frspx(UGeckoInstruction inst) const u32 b = inst.FB; const u32 d = inst.FD; - if (fpr.IsSingle(b, true)) + const bool single = fpr.IsSingle(b, true); + if (single) { // Source is already in single precision, so no need to do anything but to copy to PSR1. const ARM64Reg VB = fpr.R(b, RegType::LowerPairSingle); @@ -257,6 +273,9 @@ void JitArm64::frspx(UGeckoInstruction inst) m_float_emit.FCVT(32, 64, EncodeRegToDouble(VD), EncodeRegToDouble(VB)); } + + ASSERT_MSG(DYNA_REC, b == d || single == fpr.IsSingle(b, true), + "Register allocation turned singles into doubles in the middle of frspx"); } void JitArm64::fcmpX(UGeckoInstruction inst) @@ -320,6 +339,9 @@ void JitArm64::fcmpX(UGeckoInstruction inst) SetJumpTarget(continue3); } SetJumpTarget(continue1); + + ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a, true) && fpr.IsSingle(b, true)), + "Register allocation turned singles into doubles in the middle of fcmpX"); } void JitArm64::fctiwzx(UGeckoInstruction inst) @@ -357,4 +379,7 @@ void JitArm64::fctiwzx(UGeckoInstruction inst) } m_float_emit.ORR(EncodeRegToDouble(VD), EncodeRegToDouble(VD), EncodeRegToDouble(V0)); fpr.Unlock(V0); + + ASSERT_MSG(DYNA_REC, b == d || single == fpr.IsSingle(b, true), + "Register allocation turned singles into doubles in the middle of fctiwzx"); } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp index faa58e6ad0..00cd92c39b 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp @@ -66,6 +66,9 @@ void JitArm64::ps_mergeXX(UGeckoInstruction inst) ASSERT_MSG(DYNA_REC, 0, "ps_merge - invalid op"); break; } + + ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b)), + "Register allocation turned singles into doubles in the middle of ps_mergeXX"); } void JitArm64::ps_mulsX(UGeckoInstruction inst) @@ -92,6 +95,9 @@ void JitArm64::ps_mulsX(UGeckoInstruction inst) m_float_emit.FMUL(size, reg_encoder(VD), reg_encoder(VA), reg_encoder(VC), upper ? 1 : 0); + ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(c)), + "Register allocation turned singles into doubles in the middle of ps_mulsX"); + fpr.FixSinglePrecision(d); } @@ -250,6 +256,10 @@ void JitArm64::ps_maddXX(UGeckoInstruction inst) ASSERT_MSG(DYNA_REC, 0, "ps_madd - invalid op"); break; } + + ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)), + "Register allocation turned singles into doubles in the middle of ps_maddXX"); + fpr.FixSinglePrecision(d); if (V0Q != INVALID_REG) @@ -291,6 +301,9 @@ void JitArm64::ps_sel(UGeckoInstruction inst) m_float_emit.MOV(VD, V0); fpr.Unlock(V0Q); } + + ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)), + "Register allocation turned singles into doubles in the middle of ps_sel"); } void JitArm64::ps_sumX(UGeckoInstruction inst) @@ -330,6 +343,9 @@ void JitArm64::ps_sumX(UGeckoInstruction inst) m_float_emit.INS(size, VD, upper ? 1 : 0, V0, upper ? 1 : 0); } + ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)), + "Register allocation turned singles into doubles in the middle of ps_sumX"); + fpr.FixSinglePrecision(d); fpr.Unlock(V0);