void Jit64::ps_sign(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITPairedOff); FALLBACK_IF(inst.Rc); int d = inst.FD; int b = inst.FB; fpr.Lock(d, b); if (d != b) { fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), fpr.R(b)); } else { fpr.BindToRegister(d, true); } switch (inst.SUBOP10) { case 40: //neg PXOR(fpr.RX(d), M((void*)&psSignBits)); break; case 136: //nabs POR(fpr.RX(d), M((void*)&psSignBits)); break; case 264: //abs PAND(fpr.RX(d), M((void*)&psAbsMask)); break; } fpr.UnlockAll(); }
void Jit64::ps_sel(UGeckoInstruction inst) { // we can't use (V)BLENDVPD here because it just looks at the sign bit // but we need -0 = +0 INSTRUCTION_START JITDISABLE(bJITPairedOff); 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); MOVAPD(XMM0, fpr.R(a)); PXOR(XMM1, R(XMM1)); // XMM0 = XMM0 < 0 ? all 1s : all 0s CMPPD(XMM0, R(XMM1), LT); MOVAPD(XMM1, R(XMM0)); PAND(XMM0, fpr.R(b)); PANDN(XMM1, fpr.R(c)); POR(XMM0, R(XMM1)); fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), R(XMM0)); fpr.UnlockAll(); }
void Jit64::fsign(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff); FALLBACK_IF(inst.Rc); int d = inst.FD; int b = inst.FB; fpr.Lock(b, d); fpr.BindToRegister(d, true, true); MOVSD(XMM0, fpr.R(b)); switch (inst.SUBOP10) { case 40: // fnegx PXOR(XMM0, M((void*)&psSignBits2)); break; case 264: // fabsx PAND(XMM0, M((void*)&psAbsMask2)); break; case 136: // fnabs POR(XMM0, M((void*)&psSignBits2)); break; default: PanicAlert("fsign bleh"); break; } MOVSD(fpr.R(d), XMM0); fpr.UnlockAll(); }
bool SamplerJitCache::Jit_Decode4444() { MOVD_xmm(fpScratchReg1, R(resultReg)); PUNPCKLBW(fpScratchReg1, R(fpScratchReg1)); if (RipAccessible(color4444mask)) { PAND(fpScratchReg1, M(color4444mask)); // rip accessible } else { Crash(); } MOVSS(fpScratchReg2, R(fpScratchReg1)); MOVSS(fpScratchReg3, R(fpScratchReg1)); PSRLW(fpScratchReg2, 4); PSLLW(fpScratchReg3, 4); POR(fpScratchReg1, R(fpScratchReg2)); POR(fpScratchReg1, R(fpScratchReg3)); MOVD_xmm(R(resultReg), fpScratchReg1); return true; }
void Jit::CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN) { gpr.MapReg(MIPS_REG_FPCOND, false, true); // This means that NaN also means true, e.g. !<> or !>, etc. if (allowNaN) { CopyFPReg(XMM0, fpr.R(lhs)); CopyFPReg(XMM1, fpr.R(lhs)); CMPSS(XMM0, fpr.R(rhs), compare); CMPUNORDSS(XMM1, fpr.R(rhs)); POR(XMM0, R(XMM1)); } else { CopyFPReg(XMM0, fpr.R(lhs)); CMPSS(XMM0, fpr.R(rhs), compare); } MOVD_xmm(gpr.R(MIPS_REG_FPCOND), XMM0); }