x86 jit: Implement vs2i (similar to vh2f but simpler)

This commit is contained in:
Henrik Rydgard 2013-10-07 21:59:23 +02:00
parent cd57e8a09d
commit 8f620c30ab

View File

@ -1184,6 +1184,76 @@ void Jit::Comp_Vh2f(MIPSOpcode op) {
fpr.ReleaseSpillLocks();
}
void Jit::Comp_Vx2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
if (js.HasUnknownPrefix())
DISABLE;
switch ((op >> 16) & 3) {
case 0: // vuc2i
case 1: // vc2i
case 2: // vus2i
DISABLE;
case 3: // vs2i - used heavily by GTA
break;
default:
DISABLE;
}
// OK this is vs2i. Unpacks pairs of 16-bit integers into 32-bit integers, with the values
// at the top.
// Let's do this similarly as h2f - we do a solution that works for both singles and pairs
// then use it for both.
VectorSize sz = GetVecSize(op);
VectorSize outsize;
switch (sz) {
case V_Single:
outsize = V_Pair;
break;
case V_Pair:
outsize = V_Quad;
break;
default:
DISABLE;
}
u8 sregs[4], dregs[4];
GetVectorRegsPrefixS(sregs, sz, _VS);
GetVectorRegsPrefixD(dregs, outsize, _VD);
MOVSS(XMM1, fpr.V(sregs[0]));
if (sz != V_Single) {
MOVSS(XMM0, fpr.V(sregs[1]));
PUNPCKLDQ(XMM1, R(XMM0));
}
// Unpack 16-bit words into 32-bit words, upper position, and we're done!
XORPS(XMM0, R(XMM0));
PUNPCKLWD(XMM0, R(XMM1));
// Done! TODO: The rest of this should be possible to extract into a function.
fpr.MapRegsV(dregs, outsize, MAP_NOINIT | MAP_DIRTY);
// TODO: Could apply D-prefix in parallel here...
MOVSS(fpr.V(dregs[0]), XMM0);
SHUFPS(XMM0, R(XMM0), _MM_SHUFFLE(3, 3, 2, 1));
MOVSS(fpr.V(dregs[1]), XMM0);
if (sz != V_Single) {
SHUFPS(XMM0, R(XMM0), _MM_SHUFFLE(3, 3, 2, 1));
MOVSS(fpr.V(dregs[2]), XMM0);
SHUFPS(XMM0, R(XMM0), _MM_SHUFFLE(3, 3, 2, 1));
MOVSS(fpr.V(dregs[3]), XMM0);
}
ApplyPrefixD(dregs, outsize);
gpr.UnlockAllX();
fpr.ReleaseSpillLocks();
}
extern const double mulTableVf2i[32] = {
(1ULL<<0),(1ULL<<1),(1ULL<<2),(1ULL<<3),
(1ULL<<4),(1ULL<<5),(1ULL<<6),(1ULL<<7),
@ -1805,10 +1875,6 @@ void Jit::Comp_Vi2x(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_Vx2i(MIPSOpcode op) {
DISABLE;
}
void Jit::Comp_Vhoriz(MIPSOpcode op) {
DISABLE;
}