diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 2cf6f7a14..b86df9635 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -835,234 +835,7 @@ void OpDispatchBuilder::CALLAbsoluteOp(OpcodeArgs) { _ExitFunction(JMPPCOffset); // If we get here then leave the function now } -OrderedNode *OpDispatchBuilder::SelectCC(uint8_t OP, OrderedNode *TrueValue, OrderedNode *FalseValue) { - OrderedNode *SrcCond = nullptr; - - auto ZeroConst = _Constant(0); - auto OneConst = _Constant(1); - - switch (OP) { - case 0x0: { // JO - Jump if OF == 1 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC); - SrcCond = _Select(FEXCore::IR::COND_NEQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x1:{ // JNO - Jump if OF == 0 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x2: { // JC - Jump if CF == 1 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC); - SrcCond = _Select(FEXCore::IR::COND_NEQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x3: { // JNC - Jump if CF == 0 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x4: { // JE - Jump if ZF == 1 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - SrcCond = _Select(FEXCore::IR::COND_NEQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x5: { // JNE - Jump if ZF == 0 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x6: { // JNA - Jump if CF == 1 || ZC == 1 - auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC); - auto Check = _Or(IR::SizeToOpSize(std::max(4u, std::max(GetOpSize(Flag1), GetOpSize(Flag2)))), Flag1, Flag2); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Check, OneConst, TrueValue, FalseValue); - break; - } - case 0x7: { // JA - Jump if CF == 0 && ZF == 0 - auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC); - auto Check = _Or(IR::SizeToOpSize(std::max(4u, std::max(GetOpSize(Flag1), GetOpSize(Flag2)))), Flag1, Flag2); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Check, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x8: { // JS - Jump if SF == 1 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC); - SrcCond = _Select(FEXCore::IR::COND_NEQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0x9: { // JNS - Jump if SF == 0 - auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Flag, ZeroConst, TrueValue, FalseValue); - break; - } - case 0xA: { // JP - Jump if PF == 1 - SrcCond = _Select(FEXCore::IR::COND_EQ, LoadPFInverted(), ZeroConst, TrueValue, FalseValue); - break; - } - case 0xB: { // JNP - Jump if PF == 0 - SrcCond = _Select(FEXCore::IR::COND_NEQ, LoadPFInverted(), ZeroConst, TrueValue, FalseValue); - break; - } - case 0xC: { // SF <> OF - auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC); - auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC); - SrcCond = _Select(FEXCore::IR::COND_NEQ, - Flag1, Flag2, TrueValue, FalseValue); - break; - } - case 0xD: { // SF = OF - auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC); - auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Flag1, Flag2, TrueValue, FalseValue); - break; - } - case 0xE: {// ZF = 1 || SF <> OF - auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC); - auto Flag3 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC); - - auto Select1 = _Select(FEXCore::IR::COND_EQ, - Flag1, OneConst, OneConst, ZeroConst); - - auto Select2 = _Select(FEXCore::IR::COND_NEQ, - Flag2, Flag3, OneConst, ZeroConst); - - auto Check = _Or(IR::SizeToOpSize(std::max(4u, std::max(GetOpSize(Select1), GetOpSize(Select2)))), Select1, Select2); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Check, OneConst, TrueValue, FalseValue); - break; - } - case 0xF: {// ZF = 0 && SF = OF - auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC); - auto Flag3 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC); - - auto Select1 = _Select(FEXCore::IR::COND_EQ, - Flag1, ZeroConst, OneConst, ZeroConst); - - auto Select2 = _Select(FEXCore::IR::COND_EQ, - Flag2, Flag3, OneConst, ZeroConst); - - auto Check = _And(IR::SizeToOpSize(std::max(4u, std::max(GetOpSize(Select1), GetOpSize(Select2)))), Select1, Select2); - SrcCond = _Select(FEXCore::IR::COND_EQ, - Check, OneConst, TrueValue, FalseValue); - break; - } - default: - LOGMAN_MSG_A_FMT("Unknown CC Op: 0x{:x}\n", OP); - return nullptr; - } - - // Try folding the flags generation in the select op - if (flagsOp == SelectionFlag::CMP) { - switch(OP) { - // SGT - case 0xF: SrcCond = _Select(FEXCore::IR::COND_SGT, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; - // SLE - case 0xE: SrcCond = _Select(FEXCore::IR::COND_SLE, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; - // SGE - case 0xD: SrcCond = _Select(FEXCore::IR::COND_SGE, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; - // SL - case 0xC: SrcCond = _Select(FEXCore::IR::COND_SLT, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; - - // not sign - //case 0x99: SrcCond = _Select(FEXCore::IR::COND_, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; - // sign - //case 0x98: SrcCond = _Select(FEXCore::IR::COND_, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; - - // UABove - case 0x7: SrcCond = _Select(FEXCore::IR::COND_UGT, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; - // UBE - case 0x6: SrcCond = _Select(FEXCore::IR::COND_ULE, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; - // NE - case 0x5: SrcCond = _Select(FEXCore::IR::COND_NEQ, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; - // EQ/Zero - case 0x4: SrcCond = _Select(FEXCore::IR::COND_EQ, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; - // UAE - case 0x3: SrcCond = _Select(FEXCore::IR::COND_UGE, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; - // UBelow - case 0x2: SrcCond = _Select(FEXCore::IR::COND_ULT, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; - - //default: printf("Missed Condition %04X OP_CMP\n", OP); break; - } - } - else if (flagsOp == SelectionFlag::AND) { - switch(OP) { - case 0x4: SrcCond = _Select(FEXCore::IR::COND_EQ, flagsOpDest, ZeroConst, TrueValue, FalseValue, flagsOpSize); break; - case 0x5: SrcCond = _Select(FEXCore::IR::COND_NEQ, flagsOpDest, ZeroConst, TrueValue, FalseValue, flagsOpSize); break; - //default: printf("Missed Condition %04X OP_AND\n", OP); break; - } - } else if (flagsOp == SelectionFlag::FCMP) { - /* - x86:ZCP - unordered { 11 1 } - greater { 00 0 } - less { 01 0 } - equal { 10 0 } - aarch64: NZCV - unordered { 0 01 1 } - greater { 0 01 0 } - less { 1 00 0 } - equal { 0 11 0 } - */ - - /* - eq = 0, // Z set Equal. - ne = 1, // Z clear Not equal. - cs = 2, // C set Carry set. - cc = 3, // C clear Carry clear. - mi = 4, // N set Negative. - pl = 5, // N clear Positive or zero. - vs = 6, // V set Overflow. - vc = 7, // V clear No overflow. - hi = 8, // C set, Z clear Unsigned higher. - ls = 9, // C clear or Z set Unsigned lower or same. - ge = 10, // N == V Greater or equal. - lt = 11, // N != V Less than. - gt = 12, // Z clear, N == V Greater than. - le = 13, // Z set or N != V Less then or equal - */ - switch(OP) { - case 0x2: // CF == 1 // less or unordered // N==1 OR V==1 // lt - SrcCond = _Select(FEXCore::IR::COND_FLU, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); - break; - case 0x3: // CF == 0 // greater or equal (and not unordered) // N==V // ge - SrcCond = _Select(FEXCore::IR::COND_FGE, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); - break; - case 0x6: // CF == 1 || ZF == 1 // less or equal or unordered // Z==1 OR N!=V // le - SrcCond = _Select(FEXCore::IR::COND_FLEU, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); - break; - case 0x7: // CF == 0 && ZF == 0 // greater (and not unordered) // C==1 AND V=0 // hi - SrcCond = _Select(FEXCore::IR::COND_FGT, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); - break; - case 0xA: // PF = 1 // unordered // V==1 // vs - SrcCond = _Select(FEXCore::IR::COND_FU, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); - break; - case 0xB: // PF = 0 // not unordered // V==0 // vc - SrcCond = _Select(FEXCore::IR::COND_FNU, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); - break; - default: - // TODO: Add more optimized cases - break; - } - } - - return SrcCond; -} - -OrderedNode *OpDispatchBuilder::SelectCCExplicitSize(uint8_t OP, IR::OpSize ResultSize, OrderedNode *TrueValue, OrderedNode *FalseValue) { +OrderedNode *OpDispatchBuilder::SelectCC(uint8_t OP, IR::OpSize ResultSize, OrderedNode *TrueValue, OrderedNode *FalseValue) { OrderedNode *SrcCond = nullptr; auto ZeroConst = _Constant(0); @@ -1298,7 +1071,7 @@ void OpDispatchBuilder::SETccOp(OpcodeArgs) { auto ZeroConst = _Constant(0); auto OneConst = _Constant(1); - auto SrcCond = SelectCC(Op->OP & 0xF, OneConst, ZeroConst); + auto SrcCond = SelectCC(Op->OP & 0xF, OpSize::i64Bit, OneConst, ZeroConst); StoreResult(GPRClass, Op, SrcCond, -1); } @@ -1319,7 +1092,7 @@ void OpDispatchBuilder::CMOVOp(OpcodeArgs) { Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); } - auto SrcCond = SelectCCExplicitSize(Op->OP & 0xF, IR::SizeToOpSize(std::max(4u, GetSrcSize(Op))), Src, Dest); + auto SrcCond = SelectCC(Op->OP & 0xF, IR::SizeToOpSize(std::max(4u, GetSrcSize(Op))), Src, Dest); StoreResult(GPRClass, Op, SrcCond, -1); } @@ -1333,7 +1106,7 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) { auto TakeBranch = _Constant(1); auto DoNotTakeBranch = _Constant(0); - auto SrcCond = SelectCC(Op->OP & 0xF, TakeBranch, DoNotTakeBranch); + auto SrcCond = SelectCC(Op->OP & 0xF, OpSize::i64Bit, TakeBranch, DoNotTakeBranch); // Jump instruction only uses up to 32-bit signed displacement LOGMAN_THROW_A_FMT(Op->Src[0].IsLiteral(), "Src1 needs to be literal here"); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 11fa55cf0..fc2f370c7 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1280,9 +1280,7 @@ private: CachedIndexedNamedVectorConstants.clear(); } - // TODO: SelectCC is duplicated SelectCCExplicitSize. Should get removed once all users are removed. - OrderedNode *SelectCC(uint8_t OP, OrderedNode *TrueValue, OrderedNode *FalseValue); - OrderedNode *SelectCCExplicitSize(uint8_t OP, IR::OpSize ResultSize, OrderedNode *TrueValue, OrderedNode *FalseValue); + OrderedNode *SelectCC(uint8_t OP, IR::OpSize ResultSize, OrderedNode *TrueValue, OrderedNode *FalseValue); /** * @name Deferred RFLAG calculation and generation. diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index cae62d90b..bfd1a1f18 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -1325,7 +1325,7 @@ void OpDispatchBuilder::X87FCMOV(OpcodeArgs) { auto ZeroConst = _Constant(0); auto AllOneConst = _Constant(0xffff'ffff'ffff'ffffull); - OrderedNode *SrcCond = SelectCCExplicitSize(CC, OpSize::i64Bit, AllOneConst, ZeroConst); + OrderedNode *SrcCond = SelectCC(CC, OpSize::i64Bit, AllOneConst, ZeroConst); OrderedNode *VecCond = _VDupFromGPR(16, 8, SrcCond); auto top = GetX87Top();