diff --git a/Core/MIPS/ARM/ArmCompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp index d602a1ec15..f182ea6cce 100644 --- a/Core/MIPS/ARM/ArmCompVFPU.cpp +++ b/Core/MIPS/ARM/ArmCompVFPU.cpp @@ -2111,4 +2111,8 @@ namespace MIPSComp fpr.ReleaseSpillLocksAndDiscardTemps(); } + void Jit::Comp_ColorConv(MIPSOpcode op) { + DISABLE; + } + } diff --git a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp index b3a6bec5f8..d79f041e84 100644 --- a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp +++ b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp @@ -177,5 +177,9 @@ void Jit::CompNEON_Vocp(MIPSOpcode op) { DISABLE; } +void Jit::CompNEON_ColorConv(MIPSOpcode op) { + DISABLE; +} + } // namespace MIPSComp \ No newline at end of file diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 8a47e8e965..991607962d 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -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(); diff --git a/Core/MIPS/MIPS/MipsJit.h b/Core/MIPS/MIPS/MipsJit.h index 9249b45ae6..99e760eeea 100644 --- a/Core/MIPS/MIPS/MipsJit.h +++ b/Core/MIPS/MIPS/MipsJit.h @@ -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; } diff --git a/Core/MIPS/MIPSCodeUtils.h b/Core/MIPS/MIPSCodeUtils.h index 06445a615a..3df69ad397 100644 --- a/Core/MIPS/MIPSCodeUtils.h +++ b/Core/MIPS/MIPSCodeUtils.h @@ -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 { diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index ff03a09fbc..eccb2898fe 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -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, diff --git a/Core/MIPS/PPC/PpcCompVFPU.cpp b/Core/MIPS/PPC/PpcCompVFPU.cpp index 81dfdc5aa5..2b05d5586e 100644 --- a/Core/MIPS/PPC/PpcCompVFPU.cpp +++ b/Core/MIPS/PPC/PpcCompVFPU.cpp @@ -1209,5 +1209,8 @@ namespace MIPSComp void Jit::Comp_Vocp(MIPSOpcode op) { DISABLE; } + void Jit::Comp_ColorConv(MIPSOpcode op) { + DISABLE; + } } diff --git a/Core/MIPS/fake/FakeJit.h b/Core/MIPS/fake/FakeJit.h index d0014e11c5..152bb593d1 100644 --- a/Core/MIPS/fake/FakeJit.h +++ b/Core/MIPS/fake/FakeJit.h @@ -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; } diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 9e37d238b4..7752f662d4 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -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; +} + } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 04bed3b899..9cc213e062 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -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); diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index 74da185fb8..e1d1378f99 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -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() {