Merge pull request #11956 from unknownbrackets/vfpu-chunk7

Correct vmfvc/vmtvc decoding, prefixes on vsgn, vdot, vhdp, and matrix init
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2019-04-01 17:09:46 +02:00
commit 3eaead8af1
5 files changed
+154 -94

No files matched your search

+14 -11
View File
@@ -1334,17 +1334,20 @@ namespace MIPSComp
CONDITIONAL_DISABLE(VFPU_XFER);
int vd = _VD;
int imm = (op >> 8) & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vd);
if (imm - 128 == VFPU_CTRL_CC) {
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, 0);
VMOV(fpr.V(vd), gpr.R(MIPS_REG_VFPUCC));
} else {
ADDI2R(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + (imm - 128) * 4, SCRATCHREG2);
ADDI2R(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + imm * 4, SCRATCHREG2);
VLDR(fpr.V(vd), SCRATCHREG1, 0);
}
fpr.ReleaseSpillLocksAndDiscardTemps();
} else {
fpr.MapRegV(vd);
MOVI2F(fpr.V(vd), 0.0f, SCRATCHREG1);
}
}
@@ -1353,23 +1356,23 @@ namespace MIPSComp
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = op & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vs);
if (imm - 128 == VFPU_CTRL_CC) {
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, MAP_DIRTY | MAP_NOINIT);
VMOV(gpr.R(MIPS_REG_VFPUCC), fpr.V(vs));
} else {
ADDI2R(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + (imm - 128) * 4, SCRATCHREG2);
ADDI2R(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + imm * 4, SCRATCHREG2);
VSTR(fpr.V(vs), SCRATCHREG1, 0);
}
fpr.ReleaseSpillLocksAndDiscardTemps();
if (imm - 128 == VFPU_CTRL_SPREFIX) {
if (imm == VFPU_CTRL_SPREFIX) {
js.prefixSFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_TPREFIX) {
} else if (imm == VFPU_CTRL_TPREFIX) {
js.prefixTFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_DPREFIX) {
} else if (imm == VFPU_CTRL_DPREFIX) {
js.prefixDFlag = JitState::PREFIX_UNKNOWN;
}
}
+14 -11
View File
@@ -1067,17 +1067,20 @@ namespace MIPSComp {
CONDITIONAL_DISABLE(VFPU_XFER);
int vd = _VD;
int imm = (op >> 8) & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vd);
if (imm - 128 == VFPU_CTRL_CC) {
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, 0);
fp.FMOV(fpr.V(vd), gpr.R(MIPS_REG_VFPUCC));
} else {
ADDI2R(SCRATCH1_64, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + (imm - 128) * 4, SCRATCH2);
ADDI2R(SCRATCH1_64, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + imm * 4, SCRATCH2);
fp.LDR(32, INDEX_UNSIGNED, fpr.V(vd), SCRATCH1_64, 0);
}
fpr.ReleaseSpillLocksAndDiscardTemps();
} else {
fpr.MapRegV(vd);
fp.MOVI2F(fpr.V(vd), 0.0f, SCRATCH1);
}
}
@@ -1085,23 +1088,23 @@ namespace MIPSComp {
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = op & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vs);
if (imm - 128 == VFPU_CTRL_CC) {
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, MAP_DIRTY | MAP_NOINIT);
fp.FMOV(gpr.R(MIPS_REG_VFPUCC), fpr.V(vs));
} else {
ADDI2R(SCRATCH1_64, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + (imm - 128) * 4, SCRATCH2);
ADDI2R(SCRATCH1_64, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + imm * 4, SCRATCH2);
fp.STR(32, INDEX_UNSIGNED, fpr.V(vs), SCRATCH1_64, 0);
}
fpr.ReleaseSpillLocksAndDiscardTemps();
if (imm - 128 == VFPU_CTRL_SPREFIX) {
if (imm == VFPU_CTRL_SPREFIX) {
js.prefixSFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_TPREFIX) {
} else if (imm == VFPU_CTRL_TPREFIX) {
js.prefixTFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_DPREFIX) {
} else if (imm == VFPU_CTRL_DPREFIX) {
js.prefixDFlag = JitState::PREFIX_UNKNOWN;
}
}
+14 -14
View File
@@ -426,11 +426,11 @@ namespace MIPSComp {
void IRFrontend::Comp_VMatrixInit(MIPSOpcode op) {
CONDITIONAL_DISABLE(VFPU_XFER);
MatrixSize sz = GetMtxSize(op);
if (sz != M_4x4) {
if (sz != M_4x4 || !js.HasNoPrefix()) {
DISABLE;
}
// Matrix init (no prefixes)
// Matrix init (weird prefixes)
// d[N,M] = CONST[N,M]
// Not really about trying here, it will work if enabled.
@@ -960,7 +960,7 @@ namespace MIPSComp {
MIPSGPReg rt = _RT;
switch ((op >> 21) & 0x1f) {
case 3: //mfv / mfvc
// rt = 0, imm = 255 appears to be used as a CPU interlock by some games.
// rt = 0, imm = 255 appears to be used as a CPU interlock by some games.
if (rt != MIPS_REG_ZERO) {
if (imm < 128) { //R(rt) = VI(imm);
ir.Write(IROp::FMovToGPR, rt, vfpuBase + voffset[imm]);
@@ -1021,9 +1021,9 @@ namespace MIPSComp {
// D[0] = VFPU_CTRL[i]
int vd = _VD;
int imm = (op >> 8) & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
ir.Write(IROp::VfpuCtrlToReg, IRTEMP_0, imm - 128);
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
ir.Write(IROp::VfpuCtrlToReg, IRTEMP_0, imm);
ir.Write(IROp::FMovFromGPR, vfpuBase + voffset[vd], IRTEMP_0);
} else {
INVALIDOP;
@@ -1038,22 +1038,22 @@ namespace MIPSComp {
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
if (imm < VFPU_CTRL_MAX) {
u32 mask;
if (GetVFPUCtrlMask(imm - 128, &mask)) {
if (GetVFPUCtrlMask(imm, &mask)) {
if (mask != 0xFFFFFFFF) {
ir.Write(IROp::FMovToGPR, IRTEMP_0, vfpuBase + voffset[imm]);
ir.Write(IROp::AndConst, IRTEMP_0, IRTEMP_0, ir.AddConstant(mask));
ir.Write(IROp::SetCtrlVFPUReg, imm - 128, IRTEMP_0);
ir.Write(IROp::SetCtrlVFPUReg, imm, IRTEMP_0);
} else {
ir.Write(IROp::SetCtrlVFPUFReg, imm - 128, vfpuBase + voffset[vs]);
ir.Write(IROp::SetCtrlVFPUFReg, imm, vfpuBase + voffset[vs]);
}
}
if (imm - 128 == VFPU_CTRL_SPREFIX) {
if (imm == VFPU_CTRL_SPREFIX) {
js.prefixSFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_TPREFIX) {
} else if (imm == VFPU_CTRL_TPREFIX) {
js.prefixTFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_DPREFIX) {
} else if (imm == VFPU_CTRL_DPREFIX) {
js.prefixDFlag = JitState::PREFIX_UNKNOWN;
}
} else {
@@ -1869,7 +1869,7 @@ namespace MIPSComp {
void IRFrontend::Comp_Vsgn(MIPSOpcode op) {
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
if (js.HasUnknownPrefix() || !IsPrefixWithinSize(js.prefixS, op) || !IsPrefixWithinSize(js.prefixT, op)) {
DISABLE;
}
+97 -47
View File
@@ -317,24 +317,20 @@ namespace MIPSInt
PC += 4;
}
void Int_VMatrixInit(MIPSOpcode op)
{
static const float idt[16] =
{
void Int_VMatrixInit(MIPSOpcode op) {
static const float idt[16] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1,
};
static const float zero[16] =
{
static const float zero[16] = {
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
};
static const float one[16] =
{
static const float one[16] = {
1,1,1,1,
1,1,1,1,
1,1,1,1,
@@ -344,8 +340,7 @@ namespace MIPSInt
MatrixSize sz = GetMtxSize(op);
const float *m;
switch ((op >> 16) & 0xF)
{
switch ((op >> 16) & 0xF) {
case 3: m=idt; break; //identity // vmidt
case 6: m=zero; break; // vmzero
case 7: m=one; break; // vmone
@@ -356,7 +351,37 @@ namespace MIPSInt
return;
}
WriteMatrix(m, sz, vd);
// The S prefix generates constants, but only for the final (possibly transposed) row.
if (currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] & 0xF0F00) {
float prefixed[16];
memcpy(prefixed, m, sizeof(prefixed));
int off = GetMatrixSide(sz) - 1;
u32 sprefixRemove = VFPU_ANY_SWIZZLE();
u32 sprefixAdd;
switch ((op >> 16) & 0xF) {
case 3:
{
VFPUConst constX = off == 0 ? VFPUConst::ONE : VFPUConst::ZERO;
VFPUConst constY = off == 1 ? VFPUConst::ONE : VFPUConst::ZERO;
VFPUConst constZ = off == 2 ? VFPUConst::ONE : VFPUConst::ZERO;
VFPUConst constW = off == 3 ? VFPUConst::ONE : VFPUConst::ZERO;
sprefixAdd = VFPU_MAKE_CONSTANTS(constX, constY, constZ, constW);
break;
}
case 6:
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ZERO, VFPUConst::ZERO, VFPUConst::ZERO, VFPUConst::ZERO);
break;
case 7:
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE);
break;
}
ApplyPrefixST(&prefixed[off * 4], VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad);
WriteMatrix(prefixed, sz, vd);
} else {
// Write mask applies to the final (maybe transposed) row. Sat causes hang.
WriteMatrix(m, sz, vd);
}
PC += 4;
EatPrefixes();
}
@@ -642,19 +667,30 @@ namespace MIPSInt
EatPrefixes();
}
void Int_Vsgn(MIPSOpcode op)
{
float s[4], d[4];
void Int_Vsgn(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);
for (int i = 0; i < GetNumVectorElements(sz); i++)
{
// Not sure who would do this, but using abs/neg allows a compare against 3 or -3.
u32 tprefixRemove = VFPU_ANY_SWIZZLE();
u32 tprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ZERO, VFPUConst::ZERO, VFPUConst::ZERO, VFPUConst::ZERO);
ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz);
int n = GetNumVectorElements(sz);
if (n < 4) {
// Compare with a swizzled value out of bounds always produces 0.
memcpy(&s[n], &t[n], sizeof(float) * (4 - n));
}
ApplySwizzleS(s, V_Quad);
for (int i = 0; i < n; i++) {
float diff = s[i] - t[i];
// To handle NaNs correctly, we do this with integer hackery
u32 val;
memcpy(&val, &s[i], sizeof(u32));
memcpy(&val, &diff, sizeof(u32));
if (val == 0 || val == 0x80000000)
d[i] = 0.0f;
else if ((val >> 31) == 0)
@@ -1029,51 +1065,63 @@ namespace MIPSInt
EatPrefixes();
}
void Int_VDot(MIPSOpcode op)
{
float s[4], t[4];
void Int_VDot(MIPSOpcode op) {
float s[4]{}, t[4]{};
float d;
int vd = _VD;
int vs = _VS;
int vt = _VT;
VectorSize sz = GetVecSize(op);
ReadVector(s, sz, vs);
ApplySwizzleS(s, sz);
ApplySwizzleS(s, V_Quad);
ReadVector(t, sz, vt);
ApplySwizzleT(t, sz);
float sum = 0.0f;
int n = GetNumVectorElements(sz);
for (int i = 0; i < n; i++)
{
sum += s[i]*t[i];
ApplySwizzleT(t, V_Quad);
d = 0.0f;
for (int i = 0; i < 4; i++) {
d += s[i] * t[i];
}
d = sum;
ApplyPrefixD(&d,V_Single);
ApplyPrefixD(&d, V_Single);
WriteVector(&d, V_Single, vd);
PC += 4;
EatPrefixes();
}
void Int_VHdp(MIPSOpcode op)
{
float s[4], t[4];
void Int_VHdp(MIPSOpcode op) {
float s[4]{}, t[4]{};
float d;
int vd = _VD;
int vs = _VS;
int vt = _VT;
VectorSize sz = GetVecSize(op);
ReadVector(s, sz, vs);
ApplySwizzleS(s, sz);
ReadVector(t, sz, vt);
ApplySwizzleT(t, sz);
ApplySwizzleT(t, V_Quad);
// S prefix forces constant 1 for the last element (w for quad.)
// Otherwise it is the same as vdot.
u32 sprefixRemove;
u32 sprefixAdd;
if (sz == V_Quad) {
sprefixRemove = VFPU_SWIZZLE(0, 0, 0, 3);
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::NONE, VFPUConst::NONE, VFPUConst::NONE, VFPUConst::ONE);
} else if (sz == V_Triple) {
sprefixRemove = VFPU_SWIZZLE(0, 0, 3, 0);
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::NONE, VFPUConst::NONE, VFPUConst::ONE, VFPUConst::NONE);
} else if (sz == V_Pair) {
sprefixRemove = VFPU_SWIZZLE(0, 3, 0, 0);
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::NONE, VFPUConst::ONE, VFPUConst::NONE, VFPUConst::NONE);
} else {
sprefixRemove = VFPU_SWIZZLE(3, 0, 0, 0);
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::NONE, VFPUConst::NONE, VFPUConst::NONE);
}
ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad);
float sum = 0.0f;
int n = GetNumVectorElements(sz);
for (int i = 0; i < n; i++)
{
sum += (i == n - 1) ? t[i] : s[i]*t[i];
for (int i = 0; i < 4; i++) {
sum += s[i] * t[i];
}
d = my_isnan(sum) ? fabsf(sum) : sum;
ApplyPrefixD(&d,V_Single);
ApplyPrefixD(&d, V_Single);
WriteVector(&d, V_Single, vd);
PC += 4;
EatPrefixes();
@@ -1549,20 +1597,22 @@ namespace MIPSInt
void Int_Vmfvc(MIPSOpcode op) {
int vd = _VD;
int imm = (op >> 8) & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
VI(vd) = currentMIPS->vfpuCtrl[imm - 128];
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
VI(vd) = currentMIPS->vfpuCtrl[imm];
} else {
VI(vd) = 0;
}
PC += 4;
}
void Int_Vmtvc(MIPSOpcode op) {
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = op & 0x7F;
if (imm < VFPU_CTRL_MAX) {
u32 mask;
if (GetVFPUCtrlMask(imm - 128, &mask)) {
currentMIPS->vfpuCtrl[imm - 128] = VI(vs) & mask;
if (GetVFPUCtrlMask(imm, &mask)) {
currentMIPS->vfpuCtrl[imm] = VI(vs) & mask;
}
}
PC += 4;
+15 -11
View File
@@ -2529,38 +2529,42 @@ void Jit::Comp_Mftv(MIPSOpcode op) {
void Jit::Comp_Vmfvc(MIPSOpcode op) {
CONDITIONAL_DISABLE(VFPU_XFER);
int vd = _VD;
int imm = (op >> 8) & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = (op >> 8) & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vd, MAP_DIRTY | MAP_NOINIT);
if (imm - 128 == VFPU_CTRL_CC) {
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, true, false);
MOVD_xmm(fpr.VX(vd), gpr.R(MIPS_REG_VFPUCC));
} else {
MOVSS(fpr.VX(vd), MIPSSTATE_VAR_ELEM32(vfpuCtrl[0], imm - 128));
MOVSS(fpr.VX(vd), MIPSSTATE_VAR_ELEM32(vfpuCtrl[0], imm));
}
fpr.ReleaseSpillLocks();
} else {
fpr.MapRegV(vd, MAP_DIRTY | MAP_NOINIT);
XORPS(fpr.VX(vd), fpr.V(vd));
fpr.ReleaseSpillLocks();
}
}
void Jit::Comp_Vmtvc(MIPSOpcode op) {
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
int imm = op & 0x7F;
if (imm < VFPU_CTRL_MAX) {
fpr.MapRegV(vs, 0);
if (imm - 128 == VFPU_CTRL_CC) {
if (imm == VFPU_CTRL_CC) {
gpr.MapReg(MIPS_REG_VFPUCC, false, true);
MOVD_xmm(gpr.R(MIPS_REG_VFPUCC), fpr.VX(vs));
} else {
MOVSS(MIPSSTATE_VAR_ELEM32(vfpuCtrl[0], imm - 128), fpr.VX(vs));
MOVSS(MIPSSTATE_VAR_ELEM32(vfpuCtrl[0], imm), fpr.VX(vs));
}
fpr.ReleaseSpillLocks();
if (imm - 128 == VFPU_CTRL_SPREFIX) {
if (imm == VFPU_CTRL_SPREFIX) {
js.prefixSFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_TPREFIX) {
} else if (imm == VFPU_CTRL_TPREFIX) {
js.prefixTFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_DPREFIX) {
} else if (imm == VFPU_CTRL_DPREFIX) {
js.prefixDFlag = JitState::PREFIX_UNKNOWN;
}
}