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.
This commit is contained in:
parent
2a6fffd60e
commit
88f3fec04e
|
@ -32,8 +32,11 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
|
||||||
bool use_c = op5 >= 25; // fmul and all kind of fmaddXX
|
bool use_c = op5 >= 25; // fmul and all kind of fmaddXX
|
||||||
bool use_b = op5 != 25; // fmul uses no B
|
bool use_b = op5 != 25; // fmul uses no B
|
||||||
|
|
||||||
bool inputs_are_singles = fpr.IsSingle(a, !packed) && (!use_b || fpr.IsSingle(b, !packed)) &&
|
const auto inputs_are_singles_func = [&] {
|
||||||
|
return fpr.IsSingle(a, !packed) && (!use_b || fpr.IsSingle(b, !packed)) &&
|
||||||
(!use_c || fpr.IsSingle(c, !packed));
|
(!use_c || fpr.IsSingle(c, !packed));
|
||||||
|
};
|
||||||
|
const bool inputs_are_singles = inputs_are_singles_func();
|
||||||
|
|
||||||
ARM64Reg VA{}, VB{}, VC{}, VD{};
|
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)
|
if (single || packed)
|
||||||
fpr.FixSinglePrecision(d);
|
fpr.FixSinglePrecision(d);
|
||||||
}
|
}
|
||||||
|
@ -196,6 +202,9 @@ void JitArm64::fp_logic(UGeckoInstruction inst)
|
||||||
break;
|
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)
|
void JitArm64::fselx(UGeckoInstruction inst)
|
||||||
|
@ -209,6 +218,7 @@ void JitArm64::fselx(UGeckoInstruction inst)
|
||||||
const u32 c = inst.FC;
|
const u32 c = inst.FC;
|
||||||
const u32 d = inst.FD;
|
const u32 d = inst.FD;
|
||||||
|
|
||||||
|
const bool a_single = fpr.IsSingle(a, true);
|
||||||
if (fpr.IsSingle(a, true))
|
if (fpr.IsSingle(a, true))
|
||||||
{
|
{
|
||||||
const ARM64Reg VA = fpr.R(a, RegType::LowerPairSingle);
|
const ARM64Reg VA = fpr.R(a, RegType::LowerPairSingle);
|
||||||
|
@ -220,15 +230,20 @@ void JitArm64::fselx(UGeckoInstruction inst)
|
||||||
m_float_emit.FCMPE(EncodeRegToDouble(VA));
|
m_float_emit.FCMPE(EncodeRegToDouble(VA));
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool single = fpr.IsSingle(b, true) && fpr.IsSingle(c, true);
|
const bool b_and_c_singles = fpr.IsSingle(b, true) && fpr.IsSingle(c, true);
|
||||||
const RegType type = single ? RegType::LowerPairSingle : RegType::LowerPair;
|
const RegType type = b_and_c_singles ? RegType::LowerPairSingle : RegType::LowerPair;
|
||||||
const auto reg_encoder = single ? EncodeRegToSingle : EncodeRegToDouble;
|
const auto reg_encoder = b_and_c_singles ? EncodeRegToSingle : EncodeRegToDouble;
|
||||||
|
|
||||||
const ARM64Reg VB = fpr.R(b, type);
|
const ARM64Reg VB = fpr.R(b, type);
|
||||||
const ARM64Reg VC = fpr.R(c, type);
|
const ARM64Reg VC = fpr.R(c, type);
|
||||||
const ARM64Reg VD = fpr.RW(d, type);
|
const ARM64Reg VD = fpr.RW(d, type);
|
||||||
|
|
||||||
m_float_emit.FCSEL(reg_encoder(VD), reg_encoder(VC), reg_encoder(VB), CC_GE);
|
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)
|
void JitArm64::frspx(UGeckoInstruction inst)
|
||||||
|
@ -241,7 +256,8 @@ void JitArm64::frspx(UGeckoInstruction inst)
|
||||||
const u32 b = inst.FB;
|
const u32 b = inst.FB;
|
||||||
const u32 d = inst.FD;
|
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.
|
// 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);
|
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));
|
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)
|
void JitArm64::fcmpX(UGeckoInstruction inst)
|
||||||
|
@ -320,6 +339,9 @@ void JitArm64::fcmpX(UGeckoInstruction inst)
|
||||||
SetJumpTarget(continue3);
|
SetJumpTarget(continue3);
|
||||||
}
|
}
|
||||||
SetJumpTarget(continue1);
|
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)
|
void JitArm64::fctiwzx(UGeckoInstruction inst)
|
||||||
|
@ -357,4 +379,7 @@ void JitArm64::fctiwzx(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
m_float_emit.ORR(EncodeRegToDouble(VD), EncodeRegToDouble(VD), EncodeRegToDouble(V0));
|
m_float_emit.ORR(EncodeRegToDouble(VD), EncodeRegToDouble(VD), EncodeRegToDouble(V0));
|
||||||
fpr.Unlock(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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,9 @@ void JitArm64::ps_mergeXX(UGeckoInstruction inst)
|
||||||
ASSERT_MSG(DYNA_REC, 0, "ps_merge - invalid op");
|
ASSERT_MSG(DYNA_REC, 0, "ps_merge - invalid op");
|
||||||
break;
|
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)
|
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);
|
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);
|
fpr.FixSinglePrecision(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +256,10 @@ void JitArm64::ps_maddXX(UGeckoInstruction inst)
|
||||||
ASSERT_MSG(DYNA_REC, 0, "ps_madd - invalid op");
|
ASSERT_MSG(DYNA_REC, 0, "ps_madd - invalid op");
|
||||||
break;
|
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);
|
fpr.FixSinglePrecision(d);
|
||||||
|
|
||||||
if (V0Q != INVALID_REG)
|
if (V0Q != INVALID_REG)
|
||||||
|
@ -291,6 +301,9 @@ void JitArm64::ps_sel(UGeckoInstruction inst)
|
||||||
m_float_emit.MOV(VD, V0);
|
m_float_emit.MOV(VD, V0);
|
||||||
fpr.Unlock(V0Q);
|
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)
|
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);
|
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.FixSinglePrecision(d);
|
||||||
|
|
||||||
fpr.Unlock(V0);
|
fpr.Unlock(V0);
|
||||||
|
|
Loading…
Reference in New Issue