mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-03 19:25:18 +02:00
Implement vocp on ARM and x86.
This commit is contained in:
@@ -126,7 +126,6 @@ enum
|
||||
|
||||
class XEmitter;
|
||||
|
||||
// RIP addressing does not benefit from micro op fusion on Core arch
|
||||
struct OpArg
|
||||
{
|
||||
OpArg() {} // dummy op arg, used for storage
|
||||
|
||||
@@ -250,6 +250,8 @@ namespace MIPSComp
|
||||
{
|
||||
case 50: //lv.s // VI(vt) = Memory::Read_U32(addr);
|
||||
{
|
||||
// TODO: Fastpath like FPULS.
|
||||
|
||||
// CC might be set by slow path below, so load regs first.
|
||||
fpr.MapRegV(vt, MAP_DIRTY | MAP_NOINIT);
|
||||
if (gpr.IsImm(rs)) {
|
||||
@@ -1837,4 +1839,50 @@ namespace MIPSComp
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_Vocp(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
if (js.HasUnknownPrefix() || disablePrefixes) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
// Actually, not sure that this instruction accepts an S prefix. We don't apply it in the
|
||||
// interpreter. But whatever.
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
|
||||
MIPSReg tempregs[4];
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (!IsOverlapSafe(dregs[i], i, n, sregs)) {
|
||||
tempregs[i] = fpr.GetTempV();
|
||||
} else {
|
||||
tempregs[i] = dregs[i];
|
||||
}
|
||||
}
|
||||
|
||||
MOVI2F(S0, 1.0f, R0);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
fpr.MapDirtyInV(tempregs[i], sregs[i]);
|
||||
// Let's do it integer registers for now. NEON later.
|
||||
// There's gotta be a shorter way, can't find one though that takes
|
||||
// care of NaNs like the interpreter (ignores them and just operates on the bits).
|
||||
VSUB(fpr.V(tempregs[i]), S0, fpr.V(sregs[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (dregs[i] != tempregs[i]) {
|
||||
fpr.MapDirtyInV(dregs[i], tempregs[i]);
|
||||
VMOV(fpr.V(dregs[i]), fpr.V(tempregs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ public:
|
||||
void Comp_Vfim(MIPSOpcode op);
|
||||
void Comp_VCrossQuat(MIPSOpcode op);
|
||||
void Comp_Vsgn(MIPSOpcode op);
|
||||
void Comp_Vocp(MIPSOpcode op);
|
||||
|
||||
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||
|
||||
|
||||
@@ -737,7 +737,7 @@ const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . .......
|
||||
INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
//4
|
||||
INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // one's complement
|
||||
INSTR("vocp", &Jit::Comp_Vocp, Dis_Vbfy, Int_Vocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // one's complement
|
||||
INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vfad", &Jit::Comp_Vhoriz, Dis_Vfad, Int_Vfad, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
|
||||
@@ -1117,4 +1117,8 @@ namespace MIPSComp
|
||||
void Jit::Comp_Vsgn(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
}
|
||||
void Jit::Comp_Vocp(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@ namespace MIPSComp
|
||||
void Comp_Vfim(MIPSOpcode op);
|
||||
void Comp_VCrossQuat(MIPSOpcode op);
|
||||
void Comp_Vsgn(MIPSOpcode op);
|
||||
void Comp_Vocp(MIPSOpcode op);
|
||||
|
||||
|
||||
// Utility compilation functions
|
||||
|
||||
@@ -1178,7 +1178,7 @@ void Jit::Comp_Vh2f(MIPSOpcode op) {
|
||||
X64Reg tempR = fpr.GetFreeXReg();
|
||||
|
||||
MOVSS(XMM0, fpr.V(sregs[0]));
|
||||
if (sz != V_Single) {
|
||||
if (sz != V_Single) {
|
||||
MOVSS(XMM1, fpr.V(sregs[1]));
|
||||
PUNPCKLDQ(XMM0, R(XMM1));
|
||||
}
|
||||
@@ -1452,6 +1452,55 @@ void Jit::Comp_Vsgn(MIPSOpcode op) {
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
|
||||
void Jit::Comp_Vocp(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
if (js.HasUnknownPrefix())
|
||||
DISABLE;
|
||||
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
|
||||
X64Reg tempxregs[4];
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (!IsOverlapSafeAllowS(dregs[i], i, n, sregs))
|
||||
{
|
||||
int reg = fpr.GetTempV();
|
||||
fpr.MapRegV(reg, MAP_NOINIT | MAP_DIRTY);
|
||||
fpr.SpillLockV(reg);
|
||||
tempxregs[i] = fpr.VX(reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpr.MapRegV(dregs[i], (dregs[i] == sregs[i] ? 0 : MAP_NOINIT) | MAP_DIRTY);
|
||||
fpr.SpillLockV(dregs[i]);
|
||||
tempxregs[i] = fpr.VX(dregs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MOVSS(XMM1, M((void *)&one));
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
MOVSS(XMM0, R(XMM1));
|
||||
SUBSS(XMM0, fpr.V(sregs[i]));
|
||||
MOVSS(tempxregs[i], R(XMM0));
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (!fpr.V(dregs[i]).IsSimpleReg(tempxregs[i]))
|
||||
MOVSS(fpr.V(dregs[i]), tempxregs[i]);
|
||||
}
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
|
||||
void Jit::Comp_VV2Op(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
@@ -2101,5 +2150,4 @@ void Jit::Comp_VRot(MIPSOpcode op) {
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ public:
|
||||
void Comp_Vfim(MIPSOpcode op);
|
||||
void Comp_VCrossQuat(MIPSOpcode op);
|
||||
void Comp_Vsgn(MIPSOpcode op);
|
||||
void Comp_Vocp(MIPSOpcode op);
|
||||
|
||||
void Comp_DoNothing(MIPSOpcode op);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user