From ec1dae57eb76be2f15460592e42c91b96b13c1b8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Feb 2019 19:51:37 -0800 Subject: [PATCH] interp: Fix vbfy prefix handling. --- Core/MIPS/IR/IRCompVFPU.cpp | 2 +- Core/MIPS/MIPSIntVFPU.cpp | 56 ++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/Core/MIPS/IR/IRCompVFPU.cpp b/Core/MIPS/IR/IRCompVFPU.cpp index a0c9aecd9c..f0dee9fd7b 100644 --- a/Core/MIPS/IR/IRCompVFPU.cpp +++ b/Core/MIPS/IR/IRCompVFPU.cpp @@ -1966,7 +1966,7 @@ namespace MIPSComp { } int subop = (op >> 16) & 0x1F; - if (subop == 3) { + if (subop == 3 && n == 4) { // vbfy2 ir.Write(IROp::FAdd, tempregs[0], sregs[0], sregs[2]); ir.Write(IROp::FAdd, tempregs[1], sregs[1], sregs[3]); diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 3d982fb705..a441f2d8ec 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1045,33 +1045,51 @@ namespace MIPSInt EatPrefixes(); } - void Int_Vbfy(MIPSOpcode op) - { - float s[4]; - float d[4]; + void Int_Vbfy(MIPSOpcode op) { + float s[4]{}, t[4]{}, d[4]; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ReadVector(t, sz, vs); + int n = GetNumVectorElements(sz); - if (op & 0x10000) - { + if (op & 0x10000) { // vbfy2 - d[0] = s[0] + s[2]; - d[1] = s[1] + s[3]; - d[2] = s[0] - s[2]; - d[3] = s[1] - s[3]; - } - else - { - d[0] = s[0] + s[1]; - d[1] = s[0] - s[1]; - if (n == 4) { - d[2] = s[2] + s[3]; - d[3] = s[2] - s[3]; + // S prefix forces the negate flags (so z and w are negative.) + u32 sprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX]; + ApplyPrefixST(s, sprefix | 0x000C0000, sz); + + // T prefix forces swizzle (zwxy.) + // That means negate still works, but constants are a bit weird. + u32 tprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX]; + ApplyPrefixST(t, (tprefix & ~0x000000FF) | 0x0000004E, sz); + + // Other sizes don't seem completely predictable. + if (sz != V_Quad) { + ERROR_LOG_REPORT_ONCE(vbfy2, CPU, "vfby2 with incorrect size"); + } + } else { + // vbfy1 + // S prefix forces the negate flags (so y and w are negative.) + u32 sprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX]; + ApplyPrefixST(s, sprefix | 0x000A0000, sz); + + // T prefix forces swizzle (yxwz.) + // That means negate still works, but constants are a bit weird. + u32 tprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX]; + ApplyPrefixST(t, (tprefix & ~0x000000FF) | 0x000000B1, sz); + + if (sz != V_Quad && sz != V_Pair) { + ERROR_LOG_REPORT_ONCE(vbfy2, CPU, "vfby1 with incorrect size"); } } + + d[0] = s[0] + t[0]; + d[1] = s[1] + t[1]; + d[2] = s[2] + t[2]; + d[3] = s[3] + t[3]; + ApplyPrefixD(d, sz); WriteVector(d, sz, vd); PC += 4;