mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 17:59:08 +02:00
x86 JIT: Join adjacent vrot calls together to avoid redundant sin/cos calls. Add a prototype, fix minor issues.
This commit is contained in:
1 parent
7deb8055ee
commit
ac772f25ff
11 files changed
+86
-30
No files matched your search
@@ -2111,4 +2111,8 @@ namespace MIPSComp
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_ColorConv(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -177,5 +177,9 @@ void Jit::CompNEON_Vocp(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
void Jit::CompNEON_ColorConv(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
}
|
||||
// namespace MIPSComp
|
||||
@@ -138,6 +138,7 @@ public:
|
||||
void Comp_VCrossQuat(MIPSOpcode op);
|
||||
void Comp_Vsgn(MIPSOpcode op);
|
||||
void Comp_Vocp(MIPSOpcode op);
|
||||
void Comp_ColorConv(MIPSOpcode op);
|
||||
|
||||
// Non-NEON: VPFX
|
||||
|
||||
@@ -176,6 +177,7 @@ public:
|
||||
void CompNEON_VCrossQuat(MIPSOpcode op);
|
||||
void CompNEON_Vsgn(MIPSOpcode op);
|
||||
void CompNEON_Vocp(MIPSOpcode op);
|
||||
void CompNEON_ColorConv(MIPSOpcode op);
|
||||
|
||||
int Replace_fabsf();
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
void Comp_VCrossQuat(MIPSOpcode op) {}
|
||||
void Comp_Vsgn(MIPSOpcode op) {}
|
||||
void Comp_Vocp(MIPSOpcode op) {}
|
||||
|
||||
void Comp_ColorConv(MIPSOpcode op) {}
|
||||
int Replace_fabsf() { return 0; }
|
||||
|
||||
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
#define MIPS_GET_FT(op) ((op>>16) & 0x1F)
|
||||
#define MIPS_GET_FD(op) ((op>>6 ) & 0x1F)
|
||||
|
||||
#define MIPS_GET_VD(op) (op & 0x7F)
|
||||
#define MIPS_GET_VS(op) ((op>>8) & 0x7F)
|
||||
#define MIPS_GET_VT(op) ((op>>16) & 0x7F)
|
||||
|
||||
|
||||
namespace MIPSCodeUtils
|
||||
{
|
||||
|
||||
@@ -771,9 +771,9 @@ const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . .......
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
//24
|
||||
INVALID,
|
||||
INSTR("vt4444", &Jit::Comp_Generic, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vt5551", &Jit::Comp_Generic, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vt5650", &Jit::Comp_Generic, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vt4444", &Jit::Comp_ColorConv, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vt5551", &Jit::Comp_ColorConv, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vt5650", &Jit::Comp_ColorConv, Dis_ColorConv, Int_ColorConv, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
|
||||
//28
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
|
||||
@@ -1209,5 +1209,8 @@ namespace MIPSComp
|
||||
void Jit::Comp_Vocp(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
void Jit::Comp_ColorConv(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ public:
|
||||
void Comp_VCrossQuat(MIPSOpcode op) {}
|
||||
void Comp_Vsgn(MIPSOpcode op) {}
|
||||
void Comp_Vocp(MIPSOpcode op) {}
|
||||
void Comp_ColorConv(MIPSOpcode op) {}
|
||||
|
||||
int Replace_fabsf() { return 0; }
|
||||
|
||||
|
||||
+60
-26
@@ -2986,6 +2986,39 @@ void Jit::Comp_Vfim(MIPSOpcode op) {
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
|
||||
void Jit::CompVrotShuffle(u8 *dregs, int imm, int n, bool negSin) {
|
||||
char what[4] = { '0', '0', '0', '0' };
|
||||
if (((imm >> 2) & 3) == (imm & 3)) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
what[i] = 'S';
|
||||
}
|
||||
what[(imm >> 2) & 3] = 'S';
|
||||
what[imm & 3] = 'C';
|
||||
|
||||
// TODO: shufps SIMD version
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fpr.MapRegV(dregs[i], MAP_DIRTY | MAP_NOINIT);
|
||||
switch (what[i]) {
|
||||
case 'C': MOVSS(fpr.V(dregs[i]), XMM1); break;
|
||||
case 'S':
|
||||
MOVSS(fpr.V(dregs[i]), XMM0);
|
||||
if (negSin) {
|
||||
XORPS(fpr.VX(dregs[i]), M(&signBitLower));
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
{
|
||||
XORPS(fpr.VX(dregs[i]), fpr.V(dregs[i]));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERROR_LOG(JIT, "Bad what in vrot");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Very heavily used by FF:CC
|
||||
void Jit::Comp_VRot(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
@@ -2997,8 +3030,22 @@ void Jit::Comp_VRot(MIPSOpcode op) {
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 dregs[4];
|
||||
u8 dregs2[4];
|
||||
|
||||
u32 nextOp = Memory::Read_Opcode_JIT(js.compilerPC + 4).encoding;
|
||||
int vd2 = -1;
|
||||
int imm2 = -1;
|
||||
if (false && (nextOp >> 26) == 60 && ((nextOp >> 21) & 0x1F) == 29 && _VS == MIPS_GET_VS(nextOp)) {
|
||||
// Pair of vrot. Let's join them.
|
||||
vd2 = MIPS_GET_VD(nextOp);
|
||||
imm2 = (nextOp >> 16) & 0x1f;
|
||||
NOTICE_LOG(JIT, "Joint VFPU at %08x", js.blockStart);
|
||||
}
|
||||
|
||||
u8 sreg;
|
||||
GetVectorRegs(dregs, sz, vd);
|
||||
if (vd2 >= 0)
|
||||
GetVectorRegs(dregs2, sz, vd2);
|
||||
GetVectorRegs(&sreg, V_Single, vs);
|
||||
|
||||
// Flush SIMD.
|
||||
@@ -3009,44 +3056,31 @@ void Jit::Comp_VRot(MIPSOpcode op) {
|
||||
gpr.FlushBeforeCall();
|
||||
fpr.Flush();
|
||||
|
||||
bool negSin = (imm & 0x10) ? true : false;
|
||||
bool negSin1 = (imm & 0x10) ? true : false;
|
||||
|
||||
#ifdef _M_X64
|
||||
MOVSS(XMM0, fpr.V(sreg));
|
||||
ABI_CallFunction(negSin ? (const void *)&SinCosNegSin : (const void *)&SinCos);
|
||||
ABI_CallFunction(negSin1 ? (const void *)&SinCosNegSin : (const void *)&SinCos);
|
||||
#else
|
||||
// Sigh, passing floats with cdecl isn't pretty, ends up on the stack.
|
||||
ABI_CallFunctionA(negSin ? (const void *)&SinCosNegSin : (const void *)&SinCos, fpr.V(sreg));
|
||||
ABI_CallFunctionA(negSin2 ? (const void *)&SinCosNegSin : (const void *)&SinCos, fpr.V(sreg));
|
||||
#endif
|
||||
|
||||
MOVSS(XMM0, M(&sincostemp[0]));
|
||||
MOVSS(XMM1, M(&sincostemp[1]));
|
||||
|
||||
char what[4] = {'0', '0', '0', '0'};
|
||||
if (((imm >> 2) & 3) == (imm & 3)) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
what[i] = 'S';
|
||||
}
|
||||
what[(imm >> 2) & 3] = 'S';
|
||||
what[imm & 3] = 'C';
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fpr.MapRegV(dregs[i], MAP_DIRTY | MAP_NOINIT);
|
||||
switch (what[i]) {
|
||||
case 'C': MOVSS(fpr.V(dregs[i]), XMM1); break;
|
||||
case 'S': MOVSS(fpr.V(dregs[i]), XMM0); break;
|
||||
case '0':
|
||||
{
|
||||
XORPS(fpr.VX(dregs[i]), fpr.V(dregs[i]));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERROR_LOG(JIT, "Bad what in vrot");
|
||||
break;
|
||||
}
|
||||
CompVrotShuffle(dregs, imm, n, false);
|
||||
if (vd2 != -1) {
|
||||
// If the negsin setting differs between the two joint invocations, we need to flip the second one.
|
||||
bool negSin2 = (imm2 & 0x10) ? true : false;
|
||||
CompVrotShuffle(dregs2, imm2, n, negSin1 != negSin2);
|
||||
js.compilerPC += 4;
|
||||
}
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
|
||||
void Jit::Comp_ColorConv(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -145,6 +145,7 @@ public:
|
||||
void Comp_VCrossQuat(MIPSOpcode op);
|
||||
void Comp_Vsgn(MIPSOpcode op);
|
||||
void Comp_Vocp(MIPSOpcode op);
|
||||
void Comp_ColorConv(MIPSOpcode op);
|
||||
|
||||
void Comp_DoNothing(MIPSOpcode op);
|
||||
|
||||
@@ -236,6 +237,7 @@ private:
|
||||
|
||||
void CompFPTriArith(MIPSOpcode op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters);
|
||||
void CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN = false);
|
||||
void CompVrotShuffle(u8 *dregs, int imm, int n, bool negSin);
|
||||
|
||||
void CallProtectedFunction(const void *func, const OpArg &arg1);
|
||||
void CallProtectedFunction(const void *func, const OpArg &arg1, const OpArg &arg2);
|
||||
|
||||
@@ -758,6 +758,8 @@ int FPURegCache::GetTempVS(u8 *v, VectorSize vsz) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
regs[v[i] + 32].tempLocked = true;
|
||||
}
|
||||
|
||||
return 0; // ??
|
||||
}
|
||||
|
||||
void FPURegCache::Flush() {
|
||||
|
||||
Reference in new issue
Block a user