VFPU: make vmfvc see a pending prefix, and actually write its result

Comp_Vmfvc read vfpuCtrl[] straight from the context in all four
backends, while the mfvc path in Comp_Mftv flushes first, with the
comment "In case we have a saved prefix" - so "vpfxs X" followed by
"vmfvc sN, $128" returned the stale value in memory. The IR frontend
flushes only for the three prefix registers, which is the tighter form,
so vmfvc does the same there.

On ARM and ARM64 the fix alone wouldn't have been observable: those two
map the destination with no flags, leaving isDirty false, so the flush
dropped the loaded value without storing it. x86 already passes
MAP_DIRTY | MAP_NOINIT. That part is a fix of its own, but the two are
inseparable in this function - a vmfvc that reads the right value and
then throws it away is no better.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-21 11:32:24 -06:00
1 parent 6c7fc8df37
commit 315d128141
4 files changed
+16 -2

No files matched your search

+3 -1
View File
@@ -1332,11 +1332,13 @@ namespace MIPSComp
int vd = _VD;
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vd);
fpr.MapRegV(vd, MAP_DIRTY | MAP_NOINIT);
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, 0);
VMOV(fpr.V(vd), gpr.R(MIPS_REG_VFPUCC));
} else {
// In case we have a saved prefix.
FlushPrefixV();
ADDI2R(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + imm * 4, SCRATCHREG2);
VLDR(fpr.V(vd), SCRATCHREG1, 0);
}
+3 -1
View File
@@ -1110,11 +1110,13 @@ namespace MIPSComp {
int vd = _VD;
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vd);
fpr.MapRegV(vd, MAP_DIRTY | MAP_NOINIT);
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, 0);
fp.FMOV(fpr.V(vd), gpr.R(MIPS_REG_VFPUCC));
} else {
// In case we have a saved prefix.
FlushPrefixV();
ADDI2R(SCRATCH1_64, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + imm * 4, SCRATCH2);
fp.LDR(32, INDEX_UNSIGNED, fpr.V(vd), SCRATCH1_64, 0);
}
+8
View File
@@ -1318,6 +1318,14 @@ namespace MIPSComp {
int vd = _VD;
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
switch (imm) {
case VFPU_CTRL_DPREFIX:
case VFPU_CTRL_SPREFIX:
case VFPU_CTRL_TPREFIX:
// In case we have a saved prefix.
FlushPrefixV();
break;
}
ir.Write(IROp::VfpuCtrlToReg, IRTEMP_0, imm);
ir.Write(IROp::FMovFromGPR, vfpuBase + voffset[vd], IRTEMP_0);
} else {
+2
View File
@@ -2586,6 +2586,8 @@ void Jit::Comp_Vmfvc(MIPSOpcode op) {
gpr.MapReg(MIPS_REG_VFPUCC, true, false);
MOVD_xmm(fpr.VX(vd), gpr.R(MIPS_REG_VFPUCC));
} else {
// In case we have a saved prefix.
FlushPrefixV();
MOVSS(fpr.VX(vd), MIPSSTATE_VAR_ELEM32(vfpuCtrl[0], imm));
}
fpr.ReleaseSpillLocks();