| 634 | } |
| 635 | |
| 636 | void OpDispatchBuilder::FCOMI(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispatchBuilder::FCOMIFlags WhichFlags, bool PopTwice) { |
| 637 | Ref arg {}; |
| 638 | Ref b {}; |
| 639 | |
| 640 | Ref Res {}; |
| 641 | if (Op->Src[0].IsNone()) { |
| 642 | // Implicit arg |
| 643 | uint8_t Offset = Op->OP & 7; |
| 644 | Res = _F80CmpStack(Offset); |
| 645 | } else { |
| 646 | if (Width == OpSize::i16Bit || Width == OpSize::i32Bit || Width == OpSize::i64Bit) { |
| 647 | // Memory arg |
| 648 | if (Integer) { |
| 649 | arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); |
| 650 | b = _F80CVTToInt(arg, Width); |
| 651 | } else { |
| 652 | arg = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); |
| 653 | b = _F80CVTTo(arg, Width); |
| 654 | } |
| 655 | } else { |
| 656 | FEX_UNREACHABLE; |
| 657 | } |
| 658 | Res = _F80CmpValue(b); |
| 659 | } |
| 660 | |
| 661 | Ref HostFlag_CF = _Bfe(OpSize::i64Bit, 1, FCMP_FLAG_LT, Res); |
| 662 | Ref HostFlag_ZF = _Bfe(OpSize::i64Bit, 1, FCMP_FLAG_EQ, Res); |
| 663 | Ref HostFlag_Unordered = _Bfe(OpSize::i64Bit, 1, FCMP_FLAG_UNORDERED, Res); |
| 664 | HostFlag_CF = _Or(OpSize::i32Bit, HostFlag_CF, HostFlag_Unordered); |
| 665 | HostFlag_ZF = _Or(OpSize::i32Bit, HostFlag_ZF, HostFlag_Unordered); |
| 666 | |
| 667 | if (WhichFlags == FCOMIFlags::FLAGS_X87) { |
| 668 | SetRFLAG<FEXCore::X86State::X87FLAG_C0_LOC>(HostFlag_CF); |
| 669 | SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(Constant(0)); |
| 670 | SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(HostFlag_Unordered); |
| 671 | SetRFLAG<FEXCore::X86State::X87FLAG_C3_LOC>(HostFlag_ZF); |
| 672 | } else { |
| 673 | // OF, SF, AF, PF all undefined |
| 674 | SetCFDirect(HostFlag_CF); |
| 675 | SetRFLAG<FEXCore::X86State::RFLAG_ZF_RAW_LOC>(HostFlag_ZF); |
| 676 | |
| 677 | // PF is stored inverted, so invert from the host flag. |
| 678 | // TODO: This could perhaps be optimized? |
| 679 | auto PF = _Xor(OpSize::i32Bit, HostFlag_Unordered, Constant(1)); |
| 680 | SetRFLAG<FEXCore::X86State::RFLAG_PF_RAW_LOC>(PF); |
| 681 | } |
| 682 | |
| 683 | // Set Invalid Operation flag when unordered (NaN comparison) |
| 684 | SetRFLAG<FEXCore::X86State::X87FLAG_IE_LOC>(HostFlag_Unordered); |
| 685 | |
| 686 | if (PopTwice) { |
| 687 | _PopStackDestroy(); |
| 688 | _PopStackDestroy(); |
| 689 | } else if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { |
| 690 | _PopStackDestroy(); |
| 691 | } |
| 692 | } |
| 693 | |