VFPU: Generate the VFPU's NaN in vbfy, vocp and vsocp on all cores

These are sums, so a NaN result is 0x7F800001 like vadd's (cpu/vfpu/specials).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-14 11:47:33 +02:00
1 parent d5de19a120
commit e0a31e7fbc
5 files changed
+31 -10

No files matched your search

+2
View File
@@ -2421,6 +2421,8 @@ namespace MIPSComp
for (int i = 0; i < n; ++i) {
fpr.MapDirtyInInV(tempregs[i], sregs[i], tregs[i]);
VADD(fpr.V(tempregs[i]), fpr.V(tregs[i]), fpr.V(sregs[i]));
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
EmitVfpuSumNaN(fpr.V(tempregs[i]));
}
for (int i = 0; i < n; ++i) {
+6
View File
@@ -2422,6 +2422,8 @@ namespace MIPSComp {
for (int i = 0; i < n; ++i) {
fpr.MapDirtyInInV(tempregs[i], sregs[i], tregs[i]);
fp.FADD(fpr.V(tempregs[i]), fpr.V(tregs[i]), fpr.V(sregs[i]));
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
EmitVfpuSumNaN(fpr.V(tempregs[i]));
}
for (int i = 0; i < n; ++i) {
@@ -2542,6 +2544,10 @@ namespace MIPSComp {
fp.FSUB(S3, fpr.V(sregs[2]), fpr.V(sregs[3]));
}
}
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
for (int i = 0; i < n; i++) {
EmitVfpuSumNaN((ARM64Reg)(S0 + i));
}
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_NOINIT);
for (int i = 0; i < n; i++) {
+8
View File
@@ -2503,10 +2503,13 @@ namespace MIPSComp {
GetVectorRegsPrefixT(tregs, sz, _VS);
GetVectorRegsPrefixD(dregs, sz, _VD);
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
if (IsVec4(sz, dregs) && IsVec4(sz, sregs) && IsVec4(sz, tregs)) {
ir.Write(IROp::Vec4Add, dregs[0], tregs[0], sregs[0]);
ir.Write(IROp::Vec4VfpuNaN, dregs[0], dregs[0]);
} else if (IsVec3of4(sz, dregs) && IsVec3of4(sz, sregs) && IsVec3of4(sz, tregs) && opts.preferVec4) {
ir.Write(IROp::Vec4Add, IRVTEMP_0, tregs[0], sregs[0]);
ir.Write(IROp::Vec4VfpuNaN, IRVTEMP_0, IRVTEMP_0);
ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7);
} else {
u8 tempregs[4];
@@ -2520,6 +2523,7 @@ namespace MIPSComp {
for (int i = 0; i < n; ++i) {
ir.Write(IROp::FAdd, tempregs[i], tregs[i], sregs[i]);
ir.Write(IROp::FVfpuNaN, tempregs[i], tempregs[i]);
}
for (int i = 0; i < n; ++i) {
if (dregs[i] != tempregs[i]) {
@@ -2642,6 +2646,10 @@ namespace MIPSComp {
INVALIDOP;
}
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
for (int i = 0; i < n; ++i) {
ir.Write(IROp::FVfpuNaN, tempregs[i], tempregs[i]);
}
for (int i = 0; i < n; ++i) {
if (tempregs[i] != dregs[i])
ir.Write(IROp::FMov, dregs[i], tempregs[i]);
+9 -10
View File
@@ -753,8 +753,8 @@ namespace MIPSInt
ApplyPrefixST(mips, t, VFPURewritePrefix(mips, VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz);
for (int i = 0; i < GetNumVectorElements(sz); i++) {
// Always positive NaN. Note that s is always negated from the registers.
d[i] = my_isnan(s[i]) ? fabsf(s[i]) : t[i] + s[i];
// Note that s is always negated from the registers.
d[i] = VfpuSumNaN(t[i] + s[i]);
}
RetainInvalidSwizzleST(mips, d, sz);
ApplyPrefixD(mips, d, sz);
@@ -786,11 +786,11 @@ namespace MIPSInt
ApplyPrefixST(mips, t, VFPURewritePrefix(mips, VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), outSize);
// Essentially D prefix saturation is forced.
d[0] = nanclamp(t[0] + s[0], 0.0f, 1.0f);
d[1] = nanclamp(t[1] + s[1], 0.0f, 1.0f);
d[0] = nanclamp(VfpuSumNaN(t[0] + s[0]), 0.0f, 1.0f);
d[1] = nanclamp(VfpuSumNaN(t[1] + s[1]), 0.0f, 1.0f);
if (outSize == V_Quad) {
d[2] = nanclamp(t[2] + s[2], 0.0f, 1.0f);
d[3] = nanclamp(t[3] + s[3], 0.0f, 1.0f);
d[2] = nanclamp(VfpuSumNaN(t[2] + s[2]), 0.0f, 1.0f);
d[3] = nanclamp(VfpuSumNaN(t[3] + s[3]), 0.0f, 1.0f);
}
ApplyPrefixD(mips, d, sz, true);
WriteVector(mips, d, outSize, vd);
@@ -1335,10 +1335,9 @@ namespace MIPSInt
}
}
d[0] = s[0] + t[0];
d[1] = s[1] + t[1];
d[2] = s[2] + t[2];
d[3] = s[3] + t[3];
for (int i = 0; i < 4; i++) {
d[i] = VfpuSumNaN(s[i] + t[i]);
}
ApplyPrefixD(mips, d, sz);
WriteVector(mips, d, sz, vd);
+6
View File
@@ -2247,6 +2247,8 @@ void Jit::Comp_Vocp(MIPSOpcode op) {
}
ADDSS(XMM0, fpr.V(sregs[i]));
MOVSS(tempxregs[i], R(XMM0));
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
EmitVfpuSumNaN1(tempxregs[i]);
}
for (int i = 0; i < n; ++i) {
@@ -2318,6 +2320,10 @@ void Jit::Comp_Vbfy(MIPSOpcode op) {
DISABLE;
}
// A NaN comes out as the VFPU's (cpu/vfpu/specials).
for (int i = 0; i < n; ++i)
EmitVfpuSumNaN1(tempxregs[i]);
for (int i = 0; i < n; ++i) {
if (!fpr.V(dregs[i]).IsSimpleReg(tempxregs[i]))
MOVSS(fpr.V(dregs[i]), tempxregs[i]);