void Jit::Comp_FPUComp(u32 op) { CONDITIONAL_DISABLE; int opc = op & 0xF; if (opc >= 8) opc -= 8; // alias if (opc == 0)//f, sf (signalling false) { MOVI2R(R0, 0); STR(R0, CTXREG, offsetof(MIPSState, fpcond)); return; } int fs = _FS; int ft = _FT; fpr.MapInIn(fs, ft); VCMP(fpr.R(fs), fpr.R(ft)); VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). switch(opc) { case 1: // un, ngle (unordered) SetCC(CC_VS); MOVI2R(R0, 1); SetCC(CC_VC); break; case 2: // eq, seq (equal, ordered) SetCC(CC_EQ); MOVI2R(R0, 1); SetCC(CC_NEQ); break; case 3: // ueq, ngl (equal, unordered) SetCC(CC_EQ); MOVI2R(R0, 1); SetCC(CC_NEQ); MOVI2R(R0, 0); SetCC(CC_VS); MOVI2R(R0, 1); SetCC(CC_AL); STR(R0, CTXREG, offsetof(MIPSState, fpcond)); return; case 4: // olt, lt (less than, ordered) SetCC(CC_LO); MOVI2R(R0, 1); SetCC(CC_HS); break; case 5: // ult, nge (less than, unordered) SetCC(CC_LT); MOVI2R(R0, 1); SetCC(CC_GE); break; case 6: // ole, le (less equal, ordered) SetCC(CC_LS); MOVI2R(R0, 1); SetCC(CC_HI); break; case 7: // ule, ngt (less equal, unordered) SetCC(CC_LE); MOVI2R(R0, 1); SetCC(CC_GT); break; default: Comp_Generic(op); return; } MOVI2R(R0, 0); SetCC(CC_AL); STR(R0, CTXREG, offsetof(MIPSState, fpcond)); }
void Jit::ApplyPrefixD(const u8 *vregs, VectorSize sz) { _assert_(js.prefixDFlag & ArmJitState::PREFIX_KNOWN); if (!js.prefixD) return; int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { if (js.VfpuWriteMask(i)) continue; // TODO: These clampers are wrong - put this into google // and look at the plot: abs(x) - abs(x-0.5) + 0.5 // It's too steep. // Also, they mishandle NaN and Inf. int sat = (js.prefixD >> (i * 2)) & 3; if (sat == 1) { // clamped = fabs(x) - fabs(x-0.5f) + 0.5f; // [ 0, 1] fpr.MapRegV(vregs[i], MAP_DIRTY); MOVI2F(S0, 0.0f, R0); MOVI2F(S1, 1.0f, R0); VCMP(fpr.V(vregs[i]), S0); VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). SetCC(CC_LE); VMOV(fpr.V(vregs[i]), S0); SetCC(CC_AL); VCMP(fpr.V(vregs[i]), S1); VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). SetCC(CC_GT); VMOV(fpr.V(vregs[i]), S1); SetCC(CC_AL); /* VABS(S1, fpr.V(vregs[i])); // S1 = fabs(x) VSUB(fpr.V(vregs[i]), fpr.V(vregs[i]), S0); // S2 = fabs(x-0.5f) {VABD} VABS(fpr.V(vregs[i]), fpr.V(vregs[i])); VSUB(fpr.V(vregs[i]), S1, fpr.V(vregs[i])); // v[i] = S1 - S2 + 0.5f VADD(fpr.V(vregs[i]), fpr.V(vregs[i]), S0);*/ } else if (sat == 3) { fpr.MapRegV(vregs[i], MAP_DIRTY); MOVI2F(S0, -1.0f, R0); MOVI2F(S1, 1.0f, R0); VCMP(fpr.V(vregs[i]), S0); VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). SetCC(CC_LT); VMOV(fpr.V(vregs[i]), S0); SetCC(CC_AL); VCMP(fpr.V(vregs[i]), S1); VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags). SetCC(CC_GT); VMOV(fpr.V(vregs[i]), S1); SetCC(CC_AL); // clamped = fabs(x) - fabs(x-1.0f); // [-1, 1] /* fpr.MapRegV(vregs[i], MAP_DIRTY); MOVI2F(S0, 1.0f, R0); VABS(S1, fpr.V(vregs[i])); // S1 = fabs(x) VSUB(fpr.V(vregs[i]), fpr.V(vregs[i]), S0); // S2 = fabs(x-1.0f) {VABD} VABS(fpr.V(vregs[i]), fpr.V(vregs[i])); VSUB(fpr.V(vregs[i]), S1, fpr.V(vregs[i])); // v[i] = S1 - S2 */ } } }