diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 6248fee4a..dcba25815 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4874,7 +4874,7 @@ void OpDispatchBuilder::RDRANDOp(OpcodeArgs) { SetCFInverted(CF_inv); } else { // Accelerated path. Invalid is 0 or 1, so set NZCV with a single rmif. - HandleNZCVWrite(1u << 29 /* C */); + HandleNZCVWrite(); _RmifNZCV(CF_inv, (64 - 1) /* rotate bit 0 into bit 1 = C */, 0xf); CFInverted = true; } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 12a350f29..b1658569e 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -117,7 +117,6 @@ public: // If we loaded flags but didn't change them, invalidate the cached copy and move on. // Changes get stored out by CalculateDeferredFlags. CachedNZCV = nullptr; - PossiblySetNZCVBits = ~0U; CFInverted = CFInvertedABI; FlushRegisterCache(); @@ -1329,7 +1328,6 @@ private: Ref CachedNZCV {}; bool NZCVDirty {}; - uint32_t PossiblySetNZCVBits {}; // Set if the host carry is inverted from the guest carry. This is set after // subtraction, because arm64 and x86 have inverted borrow flags, but clear @@ -1579,31 +1577,27 @@ private: return IR::SizeToOpSize(GetSrcSize(Op)); } - // Set flag tracking to prepare for an operation that directly writes NZCV. If - // some bits are known to be zeroed, the PossiblySetNZCVBits mask can be - // passed. Otherwise, it defaults to assuming all bits may be set after - // (this is conservative). - void HandleNZCVWrite(uint32_t _PossiblySetNZCVBits = ~0) { + // Set flag tracking to prepare for an operation that directly writes NZCV. + void HandleNZCVWrite() { InvalidateDeferredFlags(); CachedNZCV = nullptr; - PossiblySetNZCVBits = _PossiblySetNZCVBits; NZCVDirty = false; } // Set flag tracking to prepare for a read-modify-write operation on NZCV. - void HandleNZCV_RMW(uint32_t _PossiblySetNZCVBits = ~0) { + void HandleNZCV_RMW() { CalculateDeferredFlags(); if (NZCVDirty && CachedNZCV) { _StoreNZCV(CachedNZCV); } - HandleNZCVWrite(_PossiblySetNZCVBits); + HandleNZCVWrite(); } // Special case of the above where we are known to zero C/V void HandleNZ00Write() { - HandleNZCVWrite((1u << 31) | (1u << 30)); + HandleNZCVWrite(); // Host carry will be implicitly zeroed, and we want guest carry zeroed as // well. So do not invert. @@ -1625,7 +1619,6 @@ private: void ZeroNZCV() { CachedNZCV = _Constant(0); - PossiblySetNZCVBits = 0; NZCVDirty = true; } @@ -1643,7 +1636,6 @@ private: _SubNZCV(SrcSize, Res, _Constant(0)); } - PossiblySetNZCVBits |= 1u << IndexNZCV(FEXCore::X86State::RFLAG_CF_RAW_LOC); CFInverted = true; } else { _TestNZ(SrcSize, Res, Res); @@ -1662,13 +1654,8 @@ private: void InsertNZCV(unsigned BitOffset, Ref Value, signed FlagOffset, bool MustMask) { signed Bit = IndexNZCV(BitOffset); - // If NZCV is not dirty, we always want to use rmif, it's 1 instruction to - // implement this. But if NZCV is dirty, it might still be cheaper to copy - // the GPR flags to NZCV and rmif. This is a heuristic for cases where we - // expect that 2 instruction sequence to be a win (versus something like - // bfe+mov+bfi+mov which can happen with our RA..). It's not totally - // conservative but it's pretty good in practice. - bool PreferRmif = !NZCVDirty || FlagOffset || MustMask || (PossiblySetNZCVBits & (1u << Bit)); + // Heuristic to choose rmif vs msr. + bool PreferRmif = !NZCVDirty || FlagOffset || MustMask; if (CTX->HostFeatures.SupportsFlagM && PreferRmif) { // Update NZCV @@ -1689,16 +1676,8 @@ private: Value = _Bfe(OpSize::i64Bit, 1, FlagOffset, Value); } - if (PossiblySetNZCVBits == 0) { - SetNZCV(_Lshl(OpSize::i64Bit, Value, _Constant(Bit))); - } else if ((PossiblySetNZCVBits & (1u << Bit)) == 0) { - SetNZCV(_Orlshl(OpSize::i32Bit, GetNZCV(), Value, Bit)); - } else { - SetNZCV(_Bfi(OpSize::i32Bit, 1, Bit, GetNZCV(), Value)); - } + SetNZCV(_Bfi(OpSize::i32Bit, 1, Bit, GetNZCV(), Value)); } - - PossiblySetNZCVBits |= (1u << Bit); } // If we don't care about N/C/V and just need Z, we can test with a simple @@ -1737,7 +1716,6 @@ private: void CarryInvert() { CFInverted ^= true; - PossiblySetNZCVBits |= 1u << IndexNZCV(FEXCore::X86State::RFLAG_CF_RAW_LOC); } template @@ -2048,9 +2026,7 @@ private: Invert ^= CFInverted; } - if (!(PossiblySetNZCVBits & (1u << IndexNZCV(BitOffset)))) { - return _Constant(Invert ? 1 : 0); - } else if (NZCVDirty) { + if (NZCVDirty) { auto Value = _Bfe(OpSize::i32Bit, 1, IndexNZCV(BitOffset), GetNZCV()); if (Invert) { @@ -2157,7 +2133,6 @@ private: // // Our AXFlag emulation on FlagM2-less systems needs V_inv passed. _AXFlag(CTX->HostFeatures.SupportsFlagM2 ? Invalid() : V_inv); - PossiblySetNZCVBits = ~0; CFInverted = true; } @@ -2171,7 +2146,6 @@ private: // Convert to x86 flags, saves us from or'ing after. _AXFlag(Invalid()); - PossiblySetNZCVBits = ~0; CFInverted = true; // Copy the values. @@ -2283,8 +2257,6 @@ private: * @brief Invalidates NZCV. Mostly vestigial. */ void InvalidateDeferredFlags() { - // No NZCV bits will be set, they are all invalid. - PossiblySetNZCVBits = 0; } void ZeroShiftResult(FEXCore::X86Tables::DecodedOp Op) { @@ -2315,7 +2287,6 @@ private: } // Otherwise, prepare to branch. - uint32_t OldSetNZCVBits = PossiblySetNZCVBits; auto Zero = _Constant(0); // If the shift is zero, do not touch the flags. @@ -2350,7 +2321,6 @@ private: SetCurrentCodeBlock(EndBlock); StartNewBlock(); - PossiblySetNZCVBits |= OldSetNZCVBits; } /** diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index dd3b9a64d..b7864c5cc 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -4915,7 +4915,6 @@ void OpDispatchBuilder::PCMPXSTRXOpImpl(OpcodeArgs, bool IsExplicit, bool IsMask // Set all of the necessary flags. NZCV stored in bits 28...31 like the hw op. SetNZCV(IntermediateResult); CFInverted = false; - PossiblySetNZCVBits = ~0; ZeroPF_AF(); } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index 1d357946c..4fab93588 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -319,7 +319,6 @@ void OpDispatchBuilder::FTSTF64(OpcodeArgs) { // Now we do our comparison. _F80StackTest(0); - PossiblySetNZCVBits = ~0; ConvertNZCVToX87(); } @@ -354,7 +353,6 @@ void OpDispatchBuilder::FCOMIF64(OpcodeArgs, IR::OpSize Width, bool Integer, OpD GetNZCV(); _F80CmpValue(b); - PossiblySetNZCVBits = ~0; ConvertNZCVToX87(); } else { HandleNZCVWrite();