interp: Fix vbfy prefix handling.

This commit is contained in:
Unknown W. Brackets 2019-02-23 19:51:37 -08:00
parent 2d2c0fab49
commit ec1dae57eb
2 changed files with 38 additions and 20 deletions

View file

@ -1966,7 +1966,7 @@ namespace MIPSComp {
} }
int subop = (op >> 16) & 0x1F; int subop = (op >> 16) & 0x1F;
if (subop == 3) { if (subop == 3 && n == 4) {
// vbfy2 // vbfy2
ir.Write(IROp::FAdd, tempregs[0], sregs[0], sregs[2]); ir.Write(IROp::FAdd, tempregs[0], sregs[0], sregs[2]);
ir.Write(IROp::FAdd, tempregs[1], sregs[1], sregs[3]); ir.Write(IROp::FAdd, tempregs[1], sregs[1], sregs[3]);

View file

@ -1045,33 +1045,51 @@ namespace MIPSInt
EatPrefixes(); EatPrefixes();
} }
void Int_Vbfy(MIPSOpcode op) void Int_Vbfy(MIPSOpcode op) {
{ float s[4]{}, t[4]{}, d[4];
float s[4];
float d[4];
int vd = _VD; int vd = _VD;
int vs = _VS; int vs = _VS;
VectorSize sz = GetVecSize(op); VectorSize sz = GetVecSize(op);
ReadVector(s, sz, vs); ReadVector(s, sz, vs);
ApplySwizzleS(s, sz); ReadVector(t, sz, vs);
int n = GetNumVectorElements(sz); int n = GetNumVectorElements(sz);
if (op & 0x10000) if (op & 0x10000) {
{
// vbfy2 // vbfy2
d[0] = s[0] + s[2]; // S prefix forces the negate flags (so z and w are negative.)
d[1] = s[1] + s[3]; u32 sprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX];
d[2] = s[0] - s[2]; ApplyPrefixST(s, sprefix | 0x000C0000, sz);
d[3] = s[1] - s[3];
// 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 } else {
{ // vbfy1
d[0] = s[0] + s[1]; // S prefix forces the negate flags (so y and w are negative.)
d[1] = s[0] - s[1]; u32 sprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX];
if (n == 4) { ApplyPrefixST(s, sprefix | 0x000A0000, sz);
d[2] = s[2] + s[3];
d[3] = s[2] - s[3]; // 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); ApplyPrefixD(d, sz);
WriteVector(d, sz, vd); WriteVector(d, sz, vd);
PC += 4; PC += 4;