diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 53a846237f..d444f0f834 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -206,6 +206,7 @@ public: void fmaddXX(UGeckoInstruction inst); void fsign(UGeckoInstruction inst); + void fselx(UGeckoInstruction inst); void stX(UGeckoInstruction inst); //stw sth stb void rlwinmx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index a9c932b8ca..0007915089 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -358,7 +358,7 @@ static GekkoOPTemplate table63_2[] = {20, &Jit64::fp_arith}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, {21, &Jit64::fp_arith}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, {22, &Jit64::FallBackToInterpreter}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}}, - {23, &Jit64::FallBackToInterpreter}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, + {23, &Jit64::fselx}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, {25, &Jit64::fp_arith}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, {26, &Jit64::frsqrtex}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp index 68936082fa..a20dd17e89 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -200,6 +200,39 @@ void Jit64::fsign(UGeckoInstruction inst) fpr.UnlockAll(); } +void Jit64::fselx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITFloatingPointOff); + FALLBACK_IF(inst.Rc); + + int d = inst.FD; + int a = inst.FA; + int b = inst.FB; + int c = inst.FC; + + fpr.Lock(a, b, c, d); + MOVSD(XMM0, fpr.R(a)); + PXOR(XMM1, R(XMM1)); + // XMM0 = XMM0 < 0 ? all 1s : all 0s + CMPSD(XMM0, R(XMM1), LT); + if (cpu_info.bSSE4_1) + { + MOVSD(XMM1, fpr.R(c)); + BLENDVPD(XMM1, fpr.R(b)); + } + else + { + MOVSD(XMM1, R(XMM0)); + PAND(XMM0, fpr.R(b)); + PANDN(XMM1, fpr.R(c)); + POR(XMM1, R(XMM0)); + } + fpr.BindToRegister(d, false); + MOVSD(fpr.RX(d), R(XMM1)); + fpr.UnlockAll(); +} + void Jit64::fmrx(UGeckoInstruction inst) { INSTRUCTION_START