diff --git a/Core/MIPS/ARM/ArmCompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp index 221003bc52..b377103130 100644 --- a/Core/MIPS/ARM/ArmCompVFPU.cpp +++ b/Core/MIPS/ARM/ArmCompVFPU.cpp @@ -726,4 +726,8 @@ namespace MIPSComp DISABLE; } + void Jit::Comp_Vtfm(u32 op) { + DISABLE; + } + } diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 715b01e929..8c9c78ffaa 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -196,6 +196,7 @@ public: void Comp_VScl(u32 op); void Comp_Vmmul(u32 op); void Comp_Vmscl(u32 op); + void Comp_Vtfm(u32 op); ArmJitBlockCache *GetBlockCache() { return &blocks; } diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index e8cc943e17..66dfee4ca2 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -631,20 +631,20 @@ const MIPSInstruction tableVFPU6[32] = //111100 xxx INSTR("vmmul",&Jit::Comp_Vmmul, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX), INSTR("vmmul",&Jit::Comp_Vmmul, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), //8 - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Vtfm, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), //16 INSTR("vmscl",&Jit::Comp_Vmscl, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX), INSTR("vmscl",&Jit::Comp_Vmscl, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX), diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 86cd1a013b..c371ba6915 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -876,4 +876,62 @@ void Jit::Comp_Vmscl(u32 op) { fpr.ReleaseSpillLocks(); } +void Jit::Comp_Vtfm(u32 op) { + CONDITIONAL_DISABLE; + + // TODO: This probably ignores prefixes? Or maybe uses D? + if (js.MayHavePrefix()) + DISABLE; + + VectorSize sz = GetVecSize(op); + MatrixSize msz = GetMtxSize(op); + int n = GetNumVectorElements(sz); + int ins = (op >> 23) & 7; + + bool homogenous = false; + if (n == ins) + { + n++; + sz = (VectorSize)((int)(sz) + 1); + msz = (MatrixSize)((int)(msz) + 1); + homogenous = true; + } + // Otherwise, n should already be ins + 1. + else if (n != ins + 1) + DISABLE; + + u8 sregs[16], dregs[4], tregs[4]; + GetMatrixRegs(sregs, msz, _VS); + GetVectorRegs(tregs, sz, _VT); + GetVectorRegs(dregs, sz, _VD); + + // TODO: test overlap, optimize. + u8 tempregs[4]; + for (int i = 0; i < n; i++) + { + XORPS(XMM0, R(XMM0)); + for (int k = 0; k < n; k++) + { + MOVSS(XMM1, fpr.V(sregs[i * 4 + k])); + if (!homogenous || k != n - 1) + MULSS(XMM1, fpr.V(tregs[k])); + ADDSS(XMM0, R(XMM1)); + } + + u8 temp = (u8) fpr.GetTempV(); + fpr.MapRegV(temp, MAP_NOINIT | MAP_DIRTY); + MOVSS(fpr.VX(temp), R(XMM0)); + fpr.StoreFromRegisterV(temp); + tempregs[i] = temp; + } + for (int i = 0; i < n; i++) + { + u8 temp = tempregs[i]; + fpr.MapRegV(temp, 0); + MOVSS(fpr.V(dregs[i]), fpr.VX(temp)); + } + + fpr.ReleaseSpillLocks(); +} + } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index fe647a54ec..2590ac20c3 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -206,6 +206,7 @@ public: void Comp_VScl(u32 op); void Comp_Vmmul(u32 op); void Comp_Vmscl(u32 op); + void Comp_Vtfm(u32 op); void Comp_DoNothing(u32 op);