From 2e63c6d547b1b7bb621c4af249ab3c9771dbfa80 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 11:56:07 -0400 Subject: [PATCH 01/16] OpcodeDispatcher: fix inverted CF with blsmsk CF set if SRC = 0 per https://www.felixcloutier.com/x86/blsmsk Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index d130c53fd..28825625d 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1044,7 +1044,7 @@ void OpDispatchBuilder::CalculateFlags_BLSMSK(OrderedNode *Src) { _InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) | (1UL << X86State::RFLAG_AF_RAW_LOC)); - auto CFOp = _Select(IR::COND_NEQ, Src, Zero, One, Zero); + auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero); SetRFLAG(CFOp); } From fe88b904c910a7dcc8e040b019b87020dc998756 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 12:24:31 -0400 Subject: [PATCH 02/16] OpcodeDispatcher: fix missing SF set with blsmsk --- .../Source/Interface/Core/OpcodeDispatcher.cpp | 2 +- FEXCore/Source/Interface/Core/OpcodeDispatcher.h | 15 ++++++++++----- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 10 ++++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 0658150d0..ad6af79f2 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -2175,7 +2175,7 @@ void OpDispatchBuilder::BLSMSKBMIOp(OpcodeArgs) { auto Result = _Xor(Size, _Sub(Size, Src, _Constant(1)), Src); StoreResult(GPRClass, Op, Result, -1); - GenerateFlags_BLSMSK(Op, Src); + GenerateFlags_BLSMSK(Op, Result, Src); } void OpDispatchBuilder::BLSRBMIOp(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 26f467ab1..3043e2745 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1604,11 +1604,11 @@ private: OrderedNode *Res{}; union { - // UMUL, BEXTR, BLSI, BLSMSK, POPCOUNT, TZCNT, LZCNT, RDRAND + // UMUL, BEXTR, BLSI, POPCOUNT, TZCNT, LZCNT, RDRAND struct { } NoSource; - // MUL, BLSR, BZHI + // MUL, BLSR, BLSMSKB, BZHI struct { OrderedNode *Src1; } OneSource; @@ -1740,7 +1740,7 @@ private: void CalculateFlags_RotateLeftImmediate(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src1, uint64_t Shift); void CalculateFlags_BEXTR(OrderedNode *Src); void CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Src); - void CalculateFlags_BLSMSK(OrderedNode *Src); + void CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src); void CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src); void CalculateFlags_POPCOUNT(OrderedNode *Src); void CalculateFlags_BZHI(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src); @@ -2064,11 +2064,16 @@ private: }; } - void GenerateFlags_BLSMSK(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Src) { + void GenerateFlags_BLSMSK(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src) { CurrentDeferredFlags = DeferredFlagData { .Type = FlagsGenerationType::TYPE_BLSMSK, .SrcSize = GetSrcSize(Op), - .Res = Src, + .Res = Res, + .Sources = { + .OneSource = { + .Src1 = Src, + }, + }, }; } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 28825625d..bf272c057 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -444,7 +444,10 @@ void OpDispatchBuilder::CalculateDeferredFlags(uint32_t FlagsToCalculateMask) { CurrentDeferredFlags.Res); break; case FlagsGenerationType::TYPE_BLSMSK: - CalculateFlags_BLSMSK(CurrentDeferredFlags.Res); + CalculateFlags_BLSMSK( + CurrentDeferredFlags.SrcSize, + CurrentDeferredFlags.Res, + CurrentDeferredFlags.Sources.OneSource.Src1); break; case FlagsGenerationType::TYPE_BLSR: CalculateFlags_BLSR( @@ -1028,7 +1031,7 @@ void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Src) { } } -void OpDispatchBuilder::CalculateFlags_BLSMSK(OrderedNode *Src) { +void OpDispatchBuilder::CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { // Now for the flags. auto Zero = _Constant(0); @@ -1046,6 +1049,9 @@ void OpDispatchBuilder::CalculateFlags_BLSMSK(OrderedNode *Src) { auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero); SetRFLAG(CFOp); + + auto SFOp = _Bfe(SizeToOpSize(SrcSize), 1, (SrcSize * 8) - 1, Result); + SetRFLAG(SFOp); } void OpDispatchBuilder::CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { From 9b309b2102c11ec37b825897994c9831dc1a5085 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 25 Jan 2024 18:33:39 -0400 Subject: [PATCH 03/16] OpcodeDispatcher: optimize blsmsk flags Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index bf272c057..b921d1e93 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1032,30 +1032,22 @@ void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Src) { } void OpDispatchBuilder::CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { - // Now for the flags. - - auto Zero = _Constant(0); - auto One = _Constant(1); - - uint32_t FlagsMaskToZero = - (1U << X86State::RFLAG_ZF_RAW_LOC) | - (1U << X86State::RFLAG_OF_RAW_LOC); - - ZeroMultipleFlags(FlagsMaskToZero); - // PF/AF undefined _InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) | (1UL << X86State::RFLAG_AF_RAW_LOC)); + // CF set according to the Src + auto Zero = _Constant(0); + auto One = _Constant(1); auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero); - SetRFLAG(CFOp); - auto SFOp = _Bfe(SizeToOpSize(SrcSize), 1, (SrcSize * 8) - 1, Result); - SetRFLAG(SFOp); + // The output of BLSMSK is always nonzero, so TST will clear Z (along with C + // and O) while setting S. + SetNZ_ZeroCV(SrcSize, Result); + SetRFLAG(CFOp); } void OpDispatchBuilder::CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { - // Now for flags. auto Zero = _Constant(0); auto One = _Constant(1); From 3a19133267f7f4625631a4d2c5e6b4de10a3ee3e Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 14:17:07 -0400 Subject: [PATCH 04/16] OpcodeDispatcher: fix inverted BLSR carry Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index b921d1e93..887c8d51e 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1059,7 +1059,7 @@ void OpDispatchBuilder::CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Result // CF { - auto CFOp = _Select(IR::COND_NEQ, Src, Zero, One, Zero); + auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero); SetRFLAG(CFOp); } } From 93cef53ec05fc0f98aa015cb5a0ad2b8b2cb828d Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 14:17:56 -0400 Subject: [PATCH 05/16] OpcodeDispatcher: optimize blsr flags reorder to avoid nzcv clobber Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 887c8d51e..efb1e1e3d 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1050,18 +1050,14 @@ void OpDispatchBuilder::CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Resu void OpDispatchBuilder::CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { auto Zero = _Constant(0); auto One = _Constant(1); + auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero); SetNZ_ZeroCV(SrcSize, Result); + SetRFLAG(CFOp); // PF/AF undefined _InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) | (1UL << X86State::RFLAG_AF_RAW_LOC)); - - // CF - { - auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero); - SetRFLAG(CFOp); - } } void OpDispatchBuilder::CalculateFlags_POPCOUNT(OrderedNode *Src) { From e8e05252f0faf9f38d91b322ad07fb2ae6e6c672 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 14:30:41 -0400 Subject: [PATCH 06/16] OpcodeDispatcher: optimize BLSI and explain why the suss thing we did before was actually right all along. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index efb1e1e3d..3593f3444 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1005,30 +1005,20 @@ void OpDispatchBuilder::CalculateFlags_BEXTR(OrderedNode *Src) { SetRFLAG(ZeroOp); } -void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Src) { - // Now for the flags: +void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Result) { + // CF is cleared if Src is zero, otherwise it's set. However, Src is zero iff + // Result is zero, so we can test the result instead. So, CF is just the + // inverted ZF. // - // Only CF, SF, ZF and OF are defined as being updated - // CF is cleared if Src is zero, otherwise it's set. - // SF is set to the value of the most significant operand bit of Result. - // OF is always cleared - // ZF is set, as usual, if Result is zero or not. + // ZF/SF/OF set as usual. + SetNZ_ZeroCV(SrcSize, Result); - auto Zero = _Constant(0); - auto One = _Constant(1); - - SetNZ_ZeroCV(SrcSize, Src); + auto CFOp = GetRFLAG(X86State::RFLAG_ZF_RAW_LOC, true /* Invert */); + SetRFLAG(CFOp); // PF/AF undefined _InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) | (1UL << X86State::RFLAG_AF_RAW_LOC)); - - - // CF - { - auto CFOp = _Select(IR::COND_NEQ, Src, Zero, One, Zero); - SetRFLAG(CFOp); - } } void OpDispatchBuilder::CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { From 3dd597a591908d84fb8b04f231dc972073954305 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Wed, 24 Jan 2024 15:14:14 -0400 Subject: [PATCH 07/16] OpcodeDispatcher: optimize lzcnt Signed-off-by: Alyssa Rosenzweig --- .../Source/Interface/Core/OpcodeDispatcher.cpp | 2 +- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ad6af79f2..77f08fbb6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5387,7 +5387,7 @@ void OpDispatchBuilder::LZCNT(OpcodeArgs) { auto Res = _CountLeadingZeroes(OpSizeFromSrc(Op), Src); StoreResult(GPRClass, Op, Res, -1); - GenerateFlags_LZCNT(Op, Src); + GenerateFlags_LZCNT(Op, Res); } void OpDispatchBuilder::MOVBEOp(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 3593f3444..30c8c7942 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1091,18 +1091,16 @@ void OpDispatchBuilder::CalculateFlags_TZCNT(OrderedNode *Src) { SetRFLAG(Src, 0, true); } -void OpDispatchBuilder::CalculateFlags_LZCNT(uint8_t SrcSize, OrderedNode *Src) { +void OpDispatchBuilder::CalculateFlags_LZCNT(uint8_t SrcSize, OrderedNode *Result) { // OF, SF, AF, PF all undefined - ZeroNZCV(); + // Test ZF of result, SF is undefined so this is ok. + SetNZ_ZeroCV(SrcSize, Result); - auto Zero = _Constant(0); - auto ZFResult = _Select(FEXCore::IR::COND_EQ, - Src, Zero, - _Constant(1), Zero); - - // Set flags - SetRFLAG(ZFResult); - SetRFLAG(Src, SrcSize * 8 - 1, true); + // Now set CF if the Result = SrcSize * 8. Since SrcSize is a power-of-two and + // Result is <= SrcSize * 8, we equivalently check if the log2(SrcSize * 8) + // bit is set. No masking is needed because no higher bits could be set. + unsigned CarryBit = FEXCore::ilog2(SrcSize * 8u); + SetRFLAG(Result, CarryBit); } void OpDispatchBuilder::CalculateFlags_RDRAND(OrderedNode *Src) { From f3175848b1a6b5e3ddc654d31709d74cd651b4b6 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 22 Jan 2024 13:16:31 -0400 Subject: [PATCH 08/16] OpcodeDispatcher: use lzcnt flag gen for tzcnt as far as flags go, they're identical: set ZF for zero output, set CF for output = DestSize, undef the rest. merge the impls, so we get the optimized lzcnt impl for tzcnt. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher.cpp | 4 ++-- .../Source/Interface/Core/OpcodeDispatcher.h | 20 ++++------------ .../Interface/Core/OpcodeDispatcher/Flags.cpp | 23 +++---------------- 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 77f08fbb6..8c25b811a 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5378,7 +5378,7 @@ void OpDispatchBuilder::TZCNT(OpcodeArgs) { Src = _FindTrailingZeroes(OpSizeFromSrc(Op), Src); StoreResult(GPRClass, Op, Src, -1); - GenerateFlags_TZCNT(Op, Src); + GenerateFlags_ZCNT(Op, Src); } void OpDispatchBuilder::LZCNT(OpcodeArgs) { @@ -5387,7 +5387,7 @@ void OpDispatchBuilder::LZCNT(OpcodeArgs) { auto Res = _CountLeadingZeroes(OpSizeFromSrc(Op), Src); StoreResult(GPRClass, Op, Res, -1); - GenerateFlags_LZCNT(Op, Res); + GenerateFlags_ZCNT(Op, Res); } void OpDispatchBuilder::MOVBEOp(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 3043e2745..42fa5e0e5 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -102,8 +102,7 @@ public: TYPE_BLSR, TYPE_POPCOUNT, TYPE_BZHI, - TYPE_TZCNT, - TYPE_LZCNT, + TYPE_ZCNT, TYPE_RDRAND, }; @@ -1604,7 +1603,7 @@ private: OrderedNode *Res{}; union { - // UMUL, BEXTR, BLSI, POPCOUNT, TZCNT, LZCNT, RDRAND + // UMUL, BEXTR, BLSI, POPCOUNT, ZCNT, RDRAND struct { } NoSource; @@ -1744,8 +1743,7 @@ private: void CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src); void CalculateFlags_POPCOUNT(OrderedNode *Src); void CalculateFlags_BZHI(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src); - void CalculateFlags_TZCNT(OrderedNode *Src); - void CalculateFlags_LZCNT(uint8_t SrcSize, OrderedNode *Src); + void CalculateFlags_ZCNT(uint8_t SrcSize, OrderedNode *Result); void CalculateFlags_RDRAND(OrderedNode *Src); /** @} */ @@ -2111,17 +2109,9 @@ private: }; } - void GenerateFlags_TZCNT(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Src) { + void GenerateFlags_ZCNT(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Src) { CurrentDeferredFlags = DeferredFlagData { - .Type = FlagsGenerationType::TYPE_TZCNT, - .SrcSize = GetSrcSize(Op), - .Res = Src, - }; - } - - void GenerateFlags_LZCNT(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Src) { - CurrentDeferredFlags = DeferredFlagData { - .Type = FlagsGenerationType::TYPE_LZCNT, + .Type = FlagsGenerationType::TYPE_ZCNT, .SrcSize = GetSrcSize(Op), .Res = Src, }; diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 30c8c7942..e08771f06 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -464,11 +464,8 @@ void OpDispatchBuilder::CalculateDeferredFlags(uint32_t FlagsToCalculateMask) { CurrentDeferredFlags.Res, CurrentDeferredFlags.Sources.OneSource.Src1); break; - case FlagsGenerationType::TYPE_TZCNT: - CalculateFlags_TZCNT(CurrentDeferredFlags.Res); - break; - case FlagsGenerationType::TYPE_LZCNT: - CalculateFlags_LZCNT( + case FlagsGenerationType::TYPE_ZCNT: + CalculateFlags_ZCNT( CurrentDeferredFlags.SrcSize, CurrentDeferredFlags.Res); break; @@ -1077,21 +1074,7 @@ void OpDispatchBuilder::CalculateFlags_BZHI(uint8_t SrcSize, OrderedNode *Result SetRFLAG(Src); } -void OpDispatchBuilder::CalculateFlags_TZCNT(OrderedNode *Src) { - // OF, SF, AF, PF all undefined - ZeroNZCV(); - - auto Zero = _Constant(0); - auto ZFResult = _Select(FEXCore::IR::COND_EQ, - Src, Zero, - _Constant(1), Zero); - - // Set flags - SetRFLAG(ZFResult); - SetRFLAG(Src, 0, true); -} - -void OpDispatchBuilder::CalculateFlags_LZCNT(uint8_t SrcSize, OrderedNode *Result) { +void OpDispatchBuilder::CalculateFlags_ZCNT(uint8_t SrcSize, OrderedNode *Result) { // OF, SF, AF, PF all undefined // Test ZF of result, SF is undefined so this is ok. SetNZ_ZeroCV(SrcSize, Result); From d5eb99fac8f29d360f0b611289db4773218b3d10 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 22 Jan 2024 13:00:07 -0400 Subject: [PATCH 09/16] OpcodeDispatcher: optimize popcount flags Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index e08771f06..2f3de68be 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1047,22 +1047,14 @@ void OpDispatchBuilder::CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Result (1UL << X86State::RFLAG_AF_RAW_LOC)); } -void OpDispatchBuilder::CalculateFlags_POPCOUNT(OrderedNode *Src) { - // Set ZF - auto Zero = _Constant(0); - auto ZFResult = _Select(FEXCore::IR::COND_EQ, - Src, Zero, - _Constant(1), Zero); +void OpDispatchBuilder::CalculateFlags_POPCOUNT(OrderedNode *Result) { + // We need to set ZF while clearing the rest of NZCV. The result of a popcount + // is in the range [0, 63]. In particular, it is always positive. So a + // combined NZ test will correctly zero SF/CF/OF while setting ZF. + SetNZ_ZeroCV(OpSize::i32Bit, Result); - // Set flags - uint32_t FlagsMaskToZero = - FullNZCVMask | - (1U << X86State::RFLAG_AF_RAW_LOC) | - (1U << X86State::RFLAG_PF_RAW_LOC); - - ZeroMultipleFlags(FlagsMaskToZero); - - SetRFLAG(ZFResult); + ZeroMultipleFlags((1U << X86State::RFLAG_AF_RAW_LOC) | + (1U << X86State::RFLAG_PF_RAW_LOC)); } void OpDispatchBuilder::CalculateFlags_BZHI(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) { From c9461d99972b6b4af33ae2a621a39ef1a3ac04a1 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 22 Jan 2024 12:53:54 -0400 Subject: [PATCH 10/16] OpcodeDispatcher: optimize BEXTR flag setting use native test. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 2f3de68be..0d612d603 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -976,30 +976,12 @@ void OpDispatchBuilder::CalculateFlags_RotateLeftImmediate(uint8_t SrcSize, Orde } void OpDispatchBuilder::CalculateFlags_BEXTR(OrderedNode *Src) { - auto Zero = _Constant(0); - auto One = _Constant(1); + // ZF is set properly. CF and OF are defined as being set to zero. SF, PF, and + // AF are undefined. + SetNZ_ZeroCV(GetOpSize(Src), Src); - // Handle flag setting. - // - // All that matters primarily for this instruction is - // that we only set the ZF flag properly. - // - // CF and OF are defined as being set to zero - // - // Every other flag is considered undefined after a - // BEXTR instruction, but we opt to reliably clear them. - // - ZeroMultipleFlags(FullNZCVMask); - - // PF/AF undefined _InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) | (1UL << X86State::RFLAG_AF_RAW_LOC)); - - // ZF - auto ZeroOp = _Select(IR::COND_EQ, - Src, Zero, - One, Zero); - SetRFLAG(ZeroOp); } void OpDispatchBuilder::CalculateFlags_BLSI(uint8_t SrcSize, OrderedNode *Result) { From f66085f4a7eb9a21143e822055f8e3f32ec03c19 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 22 Jan 2024 14:24:06 -0400 Subject: [PATCH 11/16] OpcodeDispatcher: optimize bextr's (1 << x) - 1 little algebraic trick I cribbed from llvm Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 8c25b811a..a023d759b 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -2138,12 +2138,12 @@ void OpDispatchBuilder::BEXTRBMIOp(OpcodeArgs) { Length, MaxSrcBitOp); // Now build up the mask - // (1 << SanitizedLength) - 1 - auto One = _Constant(SrcSize, 1); - auto Mask = _Sub(IR::SizeToOpSize(Size), _Lshl(IR::SizeToOpSize(Size), One, SanitizedLength), One); + // (1 << SanitizedLength) - 1 = ~(~0 << SanitizedLength) + auto AllOnes = _Constant(~0ull); + auto InvertedMask = _Lshl(IR::SizeToOpSize(Size), AllOnes, SanitizedLength); // Now put it all together and make the result. - auto Dest = _And(IR::SizeToOpSize(Size), SanitizedShifted, Mask); + auto Dest = _Andn(IR::SizeToOpSize(Size), SanitizedShifted, InvertedMask); // Finally store the result. StoreResult(GPRClass, Op, Dest, -1); From f3eee8f305931bf316218f8a01b4571346eeb818 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 22 Jan 2024 14:32:00 -0400 Subject: [PATCH 12/16] OpcodeDispatcher: optimize bextr's length sanitize reordering the operations saves an immediate move. Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index a023d759b..0af91899a 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -2133,17 +2133,17 @@ void OpDispatchBuilder::BEXTRBMIOp(OpcodeArgs) { // Now handle the length specifier. auto Length = _Bfe(OpSizeFromSrc(Op), 8, 8, Src2); - auto SanitizedLength = _Select(IR::COND_ULE, - Length, MaxSrcBitOp, - Length, MaxSrcBitOp); // Now build up the mask - // (1 << SanitizedLength) - 1 = ~(~0 << SanitizedLength) + // (1 << Length) - 1 = ~(~0 << Length) auto AllOnes = _Constant(~0ull); - auto InvertedMask = _Lshl(IR::SizeToOpSize(Size), AllOnes, SanitizedLength); + auto InvertedMask = _Lshl(IR::SizeToOpSize(Size), AllOnes, Length); // Now put it all together and make the result. - auto Dest = _Andn(IR::SizeToOpSize(Size), SanitizedShifted, InvertedMask); + auto Masked = _Andn(IR::SizeToOpSize(Size), SanitizedShifted, InvertedMask); + + // Sanitize the length. If it is above the max, we don't do the masking. + auto Dest = _Select(IR::COND_ULE, Length, MaxSrcBitOp, Masked, SanitizedShifted); // Finally store the result. StoreResult(GPRClass, Op, Dest, -1); From d9f08d4bdffc5506ad34e6c7e0d5976067b42ba0 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 14:13:57 -0400 Subject: [PATCH 13/16] unittests: add BLSR flag unit test failng on main Signed-off-by: Alyssa Rosenzweig --- unittests/ASM/FEX_bugs/BLSR_flags.asm | 60 +++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 unittests/ASM/FEX_bugs/BLSR_flags.asm diff --git a/unittests/ASM/FEX_bugs/BLSR_flags.asm b/unittests/ASM/FEX_bugs/BLSR_flags.asm new file mode 100644 index 000000000..b0f200f88 --- /dev/null +++ b/unittests/ASM/FEX_bugs/BLSR_flags.asm @@ -0,0 +1,60 @@ +%ifdef CONFIG +{ + "RegData": { + "RDX": "0xcafe" + }, + "HostFeatures": ["BMI1"] +} +%endif + +; Source 0 sets CF and ZF +mov rax, 0 +blsr rax, rax + +js fexi_fexi_im_so_broken +jnz fexi_fexi_im_so_broken +jnc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Source 1 sets ZF +mov rax, 1 +blsr rax, rax + +js fexi_fexi_im_so_broken +jnz fexi_fexi_im_so_broken +jc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Source 3 sets nothing +mov rax, 3 +blsr rax, rax + +js fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Source all-1's sets SF +mov rax, 0xffffffffffffffff +blsr rax, rax + +jns fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Make sure we're correctly clearing the overflow flag +mov rbx, 5 +mov al, 0x7F +inc al +jno fexi_fexi_im_so_broken +blsr rax, rax +jo fexi_fexi_im_so_broken + +; Happy ending +mov rdx, 0xcafe +hlt + +fexi_fexi_im_so_broken: +mov rdx, 0xdead +hlt From fd1307eea3606915817547d070e38839d3bb15ef Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 14:47:31 -0400 Subject: [PATCH 14/16] unittests: add BLSI flag test passing on main, but kinda by accident? Signed-off-by: Alyssa Rosenzweig --- unittests/ASM/FEX_bugs/BLSI_flags.asm | 60 +++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 unittests/ASM/FEX_bugs/BLSI_flags.asm diff --git a/unittests/ASM/FEX_bugs/BLSI_flags.asm b/unittests/ASM/FEX_bugs/BLSI_flags.asm new file mode 100644 index 000000000..e9698d5d8 --- /dev/null +++ b/unittests/ASM/FEX_bugs/BLSI_flags.asm @@ -0,0 +1,60 @@ +%ifdef CONFIG +{ + "RegData": { + "RDX": "0xcafe" + }, + "HostFeatures": ["BMI1"] +} +%endif + +; Source 0 sets ZF +mov rax, 0 +blsi rax, rax + +js fexi_fexi_im_so_broken +jnz fexi_fexi_im_so_broken +jc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Source 1 sets CF +mov rax, 1 +blsi rax, rax + +js fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jnc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Source all-1's sets CF +mov rax, 0xffffffffffffffff +blsi rax, rax + +js fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jnc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Source 1<<63 sets CF and SF +mov rax, 0x8000000000000000 +blsi rax, rax + +jns fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jnc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Make sure we're correctly clearing the overflow flag +mov rbx, 5 +mov al, 0x7F +inc al +jno fexi_fexi_im_so_broken +blsi rax, rax +jo fexi_fexi_im_so_broken + +; Happy ending +mov rdx, 0xcafe +hlt + +fexi_fexi_im_so_broken: +mov rdx, 0xdead +hlt From 5a143c016c4d6588947b8f3fefb70739bdaeb286 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 23 Jan 2024 11:53:56 -0400 Subject: [PATCH 15/16] unittests: add ASM test for blsmsk flags failing on main Signed-off-by: Alyssa Rosenzweig --- unittests/ASM/FEX_bugs/BLSMSK_flags.asm | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 unittests/ASM/FEX_bugs/BLSMSK_flags.asm diff --git a/unittests/ASM/FEX_bugs/BLSMSK_flags.asm b/unittests/ASM/FEX_bugs/BLSMSK_flags.asm new file mode 100644 index 000000000..b9c397a49 --- /dev/null +++ b/unittests/ASM/FEX_bugs/BLSMSK_flags.asm @@ -0,0 +1,63 @@ +%ifdef CONFIG +{ + "RegData": { + "RDX": "0xcafe", + "RBX": "5" + }, + "HostFeatures": ["BMI1"] +} +%endif + +; Result in all-1's due to underflow so SF/CF set +mov rbx, 1 +mov rax, 0 +blsmsk rax, rax + +jns fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jnc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Result in 1, so all flags clear +mov rbx, 2 +mov rax, 11 +blsmsk rax, rax + +js fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Result in all-1's without carry, so SF set +mov rbx, 3 +mov rax, 0x8000000000000000 +blsmsk rax, rax + +jns fexi_fexi_im_so_broken +jz fexi_fexi_im_so_broken +jc fexi_fexi_im_so_broken +jo fexi_fexi_im_so_broken + +; Make sure we're correctly clearing the zero flag +mov rbx, 4 +mov rax, 0 +add rax, rax +jnz fexi_fexi_im_so_broken +blsmsk rax, rax +jz fexi_fexi_im_so_broken + +; Make sure we're correctly clearing the overflow flag +mov rbx, 5 +mov al, 0x7F +inc al +jno fexi_fexi_im_so_broken +blsmsk rax, rax +jo fexi_fexi_im_so_broken + +; Happy ending +mov rdx, 0xcafe +hlt + +fexi_fexi_im_so_broken: +mov rdx, 0xdead +hlt From e9a6bfc077dcea8193fd19b3f4ccce5c91a85873 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 30 Jan 2024 22:27:58 -0400 Subject: [PATCH 16/16] InstCountCI: Update Signed-off-by: Alyssa Rosenzweig --- .../FlagM/Secondary_REP.json | 81 ++++++---------- .../InstructionCountCI/FlagM/VEX_map2.json | 58 +++++------- .../FlagM/VEX_map_group.json | 60 +++++------- .../InstructionCountCI/Secondary_REP.json | 93 ++++++++----------- unittests/InstructionCountCI/VEX_map2.json | 58 +++++------- .../InstructionCountCI/VEX_map_group.json | 48 +++++----- 6 files changed, 158 insertions(+), 240 deletions(-) diff --git a/unittests/InstructionCountCI/FlagM/Secondary_REP.json b/unittests/InstructionCountCI/FlagM/Secondary_REP.json index 12a75b610..6710e8472 100644 --- a/unittests/InstructionCountCI/FlagM/Secondary_REP.json +++ b/unittests/InstructionCountCI/FlagM/Secondary_REP.json @@ -14,7 +14,7 @@ }, "Instructions": { "popcnt ax, bx": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 9, "Comment": "0xf3 0x0f 0xb8", "ExpectedArm64ASM": [ "uxth w20, w7", @@ -23,124 +23,97 @@ "addp v0.8b, v0.8b, v0.8b", "umov w20, v0.b[0]", "bfxil x4, x20, #0, #16", + "tst w20, w20", "mov w27, #0x0", - "mov w26, #0x1", - "cmp x20, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "mov w26, #0x1" ] }, "popcnt eax, ebx": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 7, "Comment": "0xf3 0x0f 0xb8", "ExpectedArm64ASM": [ "fmov s0, w7", "cnt v0.8b, v0.8b", "addv b0, v0.8b", "umov w4, v0.b[0]", + "tst w4, w4", "mov w27, #0x0", - "mov w26, #0x1", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "mov w26, #0x1" ] }, "popcnt rax, rbx": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 7, "Comment": "0xf3 0x0f 0xb8", "ExpectedArm64ASM": [ "fmov d0, x7", "cnt v0.8b, v0.8b", "addv b0, v0.8b", "umov w4, v0.b[0]", + "tst w4, w4", "mov w27, #0x0", - "mov w26, #0x1", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "mov w26, #0x1" ] }, "tzcnt ax, bx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 6, "Comment": "0xf3 0x0f 0xbc", "ExpectedArm64ASM": [ "rbit w20, w7", "orr w20, w20, #0x8000", "clz w20, w20", "bfxil x4, x20, #0, #16", - "cmp x20, #0x0 (0)", - "cset x21, eq", - "lsl x21, x21, #29", - "msr nzcv, x21", - "rmif x20, #62, #nZcv" + "cmn wzr, w20, lsl #16", + "rmif x20, #3, #nzCv" ] }, "tzcnt eax, ebx": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 4, "Comment": "0xf3 0x0f 0xbc", "ExpectedArm64ASM": [ "rbit w4, w7", "clz w4, w4", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "msr nzcv, x20", - "rmif x4, #62, #nZcv" + "tst w4, w4", + "rmif x4, #4, #nzCv" ] }, "tzcnt rax, rbx": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 4, "Comment": "0xf3 0x0f 0xbc", "ExpectedArm64ASM": [ "rbit x4, x7", "clz x4, x4", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "msr nzcv, x20", - "rmif x4, #62, #nZcv" + "tst x4, x4", + "rmif x4, #5, #nzCv" ] }, "lzcnt ax, bx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 6, "Comment": "0xf3 0x0f 0xbd", "ExpectedArm64ASM": [ "lsl w20, w7, #16", "orr w20, w20, #0x8000", "clz w20, w20", "bfxil x4, x20, #0, #16", - "cmp x7, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "msr nzcv, x20", - "rmif x7, #13, #nZcv" + "cmn wzr, w20, lsl #16", + "rmif x20, #3, #nzCv" ] }, "lzcnt eax, ebx": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 3, "Comment": "0xf3 0x0f 0xbd", "ExpectedArm64ASM": [ "clz w4, w7", - "cmp x7, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "msr nzcv, x20", - "rmif x7, #29, #nZcv" + "tst w4, w4", + "rmif x4, #4, #nzCv" ] }, "lzcnt rax, rbx": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 3, "Comment": "0xf3 0x0f 0xbd", "ExpectedArm64ASM": [ "clz x4, x7", - "cmp x7, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "msr nzcv, x20", - "rmif x7, #61, #nZcv" + "tst x4, x4", + "rmif x4, #5, #nzCv" ] } } diff --git a/unittests/InstructionCountCI/FlagM/VEX_map2.json b/unittests/InstructionCountCI/FlagM/VEX_map2.json index 28b791206..f83e40ecd 100644 --- a/unittests/InstructionCountCI/FlagM/VEX_map2.json +++ b/unittests/InstructionCountCI/FlagM/VEX_map2.json @@ -442,53 +442,43 @@ ] }, "bextr eax, ebx, ecx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 12, "Comment": [ "Map 2 0b00 0xf7 32-bit" ], "ExpectedArm64ASM": [ - "mov w20, #0x1f", - "uxtb w21, w5", - "lsr w22, w7, w21", - "mov w23, #0x0", + "uxtb w20, w5", + "lsr w21, w7, w20", + "mov w22, #0x0", + "cmp w20, #0x1f (31)", + "csel w20, w21, w22, ls", + "ubfx w21, w5, #8, #8", + "mov x22, #0xffffffffffffffff", + "lsl w22, w22, w21", + "bic w22, w20, w22", "cmp w21, #0x1f (31)", - "csel w21, w22, w23, ls", - "ubfx w22, w5, #8, #8", - "cmp w22, #0x1f (31)", - "csel w20, w22, w20, ls", - "mov w22, #0x1", - "lsl w20, w22, w20", - "sub w20, w20, #0x1 (1)", - "and w4, w21, w20", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "csel w4, w22, w20, ls", + "tst w4, w4" ] }, "bextr rax, rbx, rcx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 12, "Comment": [ "Map 2 0b00 0xf7 64-bit" ], "ExpectedArm64ASM": [ - "mov w20, #0x3f", - "uxtb x21, w5", - "lsr x22, x7, x21", - "mov w23, #0x0", + "uxtb x20, w5", + "lsr x21, x7, x20", + "mov w22, #0x0", + "cmp x20, #0x3f (63)", + "csel x20, x21, x22, ls", + "ubfx x21, x5, #8, #8", + "mov x22, #0xffffffffffffffff", + "lsl x22, x22, x21", + "bic x22, x20, x22", "cmp x21, #0x3f (63)", - "csel x21, x22, x23, ls", - "ubfx x22, x5, #8, #8", - "cmp x22, #0x3f (63)", - "csel x20, x22, x20, ls", - "mov w22, #0x1", - "lsl x20, x22, x20", - "sub x20, x20, #0x1 (1)", - "and x4, x21, x20", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "csel x4, x22, x20, ls", + "tst x4, x4" ] } } diff --git a/unittests/InstructionCountCI/FlagM/VEX_map_group.json b/unittests/InstructionCountCI/FlagM/VEX_map_group.json index cb482da17..277bfad73 100644 --- a/unittests/InstructionCountCI/FlagM/VEX_map_group.json +++ b/unittests/InstructionCountCI/FlagM/VEX_map_group.json @@ -10,73 +10,63 @@ }, "Instructions": { "blsr eax, ebx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 6, "Comment": [ "Map group 17 0b001 32-bit" ], "ExpectedArm64ASM": [ "sub w20, w7, #0x1 (1)", "and w4, w20, w7", - "tst w4, w4", - "mrs x20, nzcv", "cmp x7, #0x0 (0)", - "cset x21, ne", - "orr w20, w20, w21, lsl #29", - "msr nzcv, x20" + "cset x20, eq", + "tst w4, w4", + "rmif x20, #63, #nzCv" ] }, "blsr rax, rbx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 6, "Comment": [ "Map group 17 0b001 64-bit" ], "ExpectedArm64ASM": [ "sub x20, x7, #0x1 (1)", "and x4, x20, x7", - "tst x4, x4", - "mrs x20, nzcv", "cmp x7, #0x0 (0)", - "cset x21, ne", - "orr w20, w20, w21, lsl #29", - "msr nzcv, x20" + "cset x20, eq", + "tst x4, x4", + "rmif x20, #63, #nzCv" ] }, "blsmsk eax, ebx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 6, "Comment": [ "Map group 17 0b010 32-bit" ], "ExpectedArm64ASM": [ "sub w20, w7, #0x1 (1)", "eor w4, w20, w7", - "mov w20, #0x50000000", - "mrs x21, nzcv", - "bic x20, x21, x20", "cmp x7, #0x0 (0)", - "cset x21, ne", - "msr nzcv, x20", - "rmif x21, #63, #nzCv" + "cset x20, eq", + "tst w4, w4", + "rmif x20, #63, #nzCv" ] }, "blsmsk rax, rbx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 6, "Comment": [ "Map group 17 0b010 64-bit" ], "ExpectedArm64ASM": [ "sub x20, x7, #0x1 (1)", "eor x4, x20, x7", - "mov w20, #0x50000000", - "mrs x21, nzcv", - "bic x20, x21, x20", "cmp x7, #0x0 (0)", - "cset x21, ne", - "msr nzcv, x20", - "rmif x21, #63, #nzCv" + "cset x20, eq", + "tst x4, x4", + "rmif x20, #63, #nzCv" ] }, "blsi eax, ebx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 5, "Comment": [ "Map group 17 0b011 32-bit" ], @@ -84,15 +74,12 @@ "neg w20, w7", "and w4, w7, w20", "tst w4, w4", - "mrs x20, nzcv", - "cmp x4, #0x0 (0)", - "cset x21, ne", - "orr w20, w20, w21, lsl #29", - "msr nzcv, x20" + "cset w20, ne", + "rmif x20, #63, #nzCv" ] }, "blsi rax, rbx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 5, "Comment": [ "Map group 17 0b011 64-bit" ], @@ -100,11 +87,8 @@ "neg x20, x7", "and x4, x7, x20", "tst x4, x4", - "mrs x20, nzcv", - "cmp x4, #0x0 (0)", - "cset x21, ne", - "orr w20, w20, w21, lsl #29", - "msr nzcv, x20" + "cset w20, ne", + "rmif x20, #63, #nzCv" ] } } diff --git a/unittests/InstructionCountCI/Secondary_REP.json b/unittests/InstructionCountCI/Secondary_REP.json index 4dacfc523..6a223b739 100644 --- a/unittests/InstructionCountCI/Secondary_REP.json +++ b/unittests/InstructionCountCI/Secondary_REP.json @@ -399,7 +399,7 @@ ] }, "popcnt ax, bx": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 9, "Comment": "0xf3 0x0f 0xb8", "ExpectedArm64ASM": [ "uxth w20, w7", @@ -408,129 +408,114 @@ "addp v0.8b, v0.8b, v0.8b", "umov w20, v0.b[0]", "bfxil x4, x20, #0, #16", + "tst w20, w20", "mov w27, #0x0", - "mov w26, #0x1", - "cmp x20, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "mov w26, #0x1" ] }, "popcnt eax, ebx": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 7, "Comment": "0xf3 0x0f 0xb8", "ExpectedArm64ASM": [ "fmov s0, w7", "cnt v0.8b, v0.8b", "addv b0, v0.8b", "umov w4, v0.b[0]", + "tst w4, w4", "mov w27, #0x0", - "mov w26, #0x1", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "mov w26, #0x1" ] }, "popcnt rax, rbx": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 7, "Comment": "0xf3 0x0f 0xb8", "ExpectedArm64ASM": [ "fmov d0, x7", "cnt v0.8b, v0.8b", "addv b0, v0.8b", "umov w4, v0.b[0]", + "tst w4, w4", "mov w27, #0x0", - "mov w26, #0x1", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "mov w26, #0x1" ] }, "tzcnt ax, bx": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 9, "Comment": "0xf3 0x0f 0xbc", "ExpectedArm64ASM": [ "rbit w20, w7", "orr w20, w20, #0x8000", "clz w20, w20", "bfxil x4, x20, #0, #16", - "cmp x20, #0x0 (0)", - "cset x21, eq", - "lsl x21, x21, #29", - "ubfx x20, x20, #0, #1", - "orr w20, w21, w20, lsl #30", + "cmn wzr, w20, lsl #16", + "mrs x21, nzcv", + "ubfx x20, x20, #4, #1", + "orr w20, w21, w20, lsl #29", "msr nzcv, x20" ] }, "tzcnt eax, ebx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 7, "Comment": "0xf3 0x0f 0xbc", "ExpectedArm64ASM": [ "rbit w4, w7", "clz w4, w4", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "ubfx x21, x4, #0, #1", - "orr w20, w20, w21, lsl #30", + "tst w4, w4", + "mrs x20, nzcv", + "ubfx x21, x4, #5, #1", + "orr w20, w20, w21, lsl #29", "msr nzcv, x20" ] }, "tzcnt rax, rbx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 7, "Comment": "0xf3 0x0f 0xbc", "ExpectedArm64ASM": [ "rbit x4, x7", "clz x4, x4", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "ubfx x21, x4, #0, #1", - "orr w20, w20, w21, lsl #30", + "tst x4, x4", + "mrs x20, nzcv", + "ubfx x21, x4, #6, #1", + "orr w20, w20, w21, lsl #29", "msr nzcv, x20" ] }, "lzcnt ax, bx": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 9, "Comment": "0xf3 0x0f 0xbd", "ExpectedArm64ASM": [ "lsl w20, w7, #16", "orr w20, w20, #0x8000", "clz w20, w20", "bfxil x4, x20, #0, #16", - "cmp x7, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "ubfx x21, x7, #15, #1", - "orr w20, w20, w21, lsl #30", + "cmn wzr, w20, lsl #16", + "mrs x21, nzcv", + "ubfx x20, x20, #4, #1", + "orr w20, w21, w20, lsl #29", "msr nzcv, x20" ] }, "lzcnt eax, ebx": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Comment": "0xf3 0x0f 0xbd", "ExpectedArm64ASM": [ "clz w4, w7", - "cmp x7, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "ubfx x21, x7, #31, #1", - "orr w20, w20, w21, lsl #30", + "tst w4, w4", + "mrs x20, nzcv", + "ubfx x21, x4, #5, #1", + "orr w20, w20, w21, lsl #29", "msr nzcv, x20" ] }, "lzcnt rax, rbx": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Comment": "0xf3 0x0f 0xbd", "ExpectedArm64ASM": [ "clz x4, x7", - "cmp x7, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #29", - "lsr x21, x7, #63", - "orr w20, w20, w21, lsl #30", + "tst x4, x4", + "mrs x20, nzcv", + "ubfx x21, x4, #6, #1", + "orr w20, w20, w21, lsl #29", "msr nzcv, x20" ] }, diff --git a/unittests/InstructionCountCI/VEX_map2.json b/unittests/InstructionCountCI/VEX_map2.json index bdde71dfd..5bf2590f7 100644 --- a/unittests/InstructionCountCI/VEX_map2.json +++ b/unittests/InstructionCountCI/VEX_map2.json @@ -3381,53 +3381,43 @@ ] }, "bextr eax, ebx, ecx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 12, "Comment": [ "Map 2 0b00 0xf7 32-bit" ], "ExpectedArm64ASM": [ - "mov w20, #0x1f", - "uxtb w21, w5", - "lsr w22, w7, w21", - "mov w23, #0x0", + "uxtb w20, w5", + "lsr w21, w7, w20", + "mov w22, #0x0", + "cmp w20, #0x1f (31)", + "csel w20, w21, w22, ls", + "ubfx w21, w5, #8, #8", + "mov x22, #0xffffffffffffffff", + "lsl w22, w22, w21", + "bic w22, w20, w22", "cmp w21, #0x1f (31)", - "csel w21, w22, w23, ls", - "ubfx w22, w5, #8, #8", - "cmp w22, #0x1f (31)", - "csel w20, w22, w20, ls", - "mov w22, #0x1", - "lsl w20, w22, w20", - "sub w20, w20, #0x1 (1)", - "and w4, w21, w20", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "csel w4, w22, w20, ls", + "tst w4, w4" ] }, "bextr rax, rbx, rcx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 12, "Comment": [ "Map 2 0b00 0xf7 64-bit" ], "ExpectedArm64ASM": [ - "mov w20, #0x3f", - "uxtb x21, w5", - "lsr x22, x7, x21", - "mov w23, #0x0", + "uxtb x20, w5", + "lsr x21, x7, x20", + "mov w22, #0x0", + "cmp x20, #0x3f (63)", + "csel x20, x21, x22, ls", + "ubfx x21, x5, #8, #8", + "mov x22, #0xffffffffffffffff", + "lsl x22, x22, x21", + "bic x22, x20, x22", "cmp x21, #0x3f (63)", - "csel x21, x22, x23, ls", - "ubfx x22, x5, #8, #8", - "cmp x22, #0x3f (63)", - "csel x20, x22, x20, ls", - "mov w22, #0x1", - "lsl x20, x22, x20", - "sub x20, x20, #0x1 (1)", - "and x4, x21, x20", - "cmp x4, #0x0 (0)", - "cset x20, eq", - "lsl x20, x20, #30", - "msr nzcv, x20" + "csel x4, x22, x20, ls", + "tst x4, x4" ] }, "shlx eax, ebx, ecx": { diff --git a/unittests/InstructionCountCI/VEX_map_group.json b/unittests/InstructionCountCI/VEX_map_group.json index 19187a9fe..6ed4366dd 100644 --- a/unittests/InstructionCountCI/VEX_map_group.json +++ b/unittests/InstructionCountCI/VEX_map_group.json @@ -616,11 +616,11 @@ "ExpectedArm64ASM": [ "sub w20, w7, #0x1 (1)", "and w4, w20, w7", - "tst w4, w4", - "mrs x20, nzcv", "cmp x7, #0x0 (0)", - "cset x21, ne", - "orr w20, w20, w21, lsl #29", + "cset x20, eq", + "tst w4, w4", + "mrs x21, nzcv", + "orr w20, w21, w20, lsl #29", "msr nzcv, x20" ] }, @@ -632,50 +632,48 @@ "ExpectedArm64ASM": [ "sub x20, x7, #0x1 (1)", "and x4, x20, x7", - "tst x4, x4", - "mrs x20, nzcv", "cmp x7, #0x0 (0)", - "cset x21, ne", - "orr w20, w20, w21, lsl #29", + "cset x20, eq", + "tst x4, x4", + "mrs x21, nzcv", + "orr w20, w21, w20, lsl #29", "msr nzcv, x20" ] }, "blsmsk eax, ebx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 8, "Comment": [ "Map group 17 0b010 32-bit" ], "ExpectedArm64ASM": [ "sub w20, w7, #0x1 (1)", "eor w4, w20, w7", - "mov w20, #0x50000000", - "mrs x21, nzcv", - "bic x20, x21, x20", "cmp x7, #0x0 (0)", - "cset x21, ne", - "bfi w20, w21, #29, #1", + "cset x20, eq", + "tst w4, w4", + "mrs x21, nzcv", + "orr w20, w21, w20, lsl #29", "msr nzcv, x20" ] }, "blsmsk rax, rbx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 8, "Comment": [ "Map group 17 0b010 64-bit" ], "ExpectedArm64ASM": [ "sub x20, x7, #0x1 (1)", "eor x4, x20, x7", - "mov w20, #0x50000000", - "mrs x21, nzcv", - "bic x20, x21, x20", "cmp x7, #0x0 (0)", - "cset x21, ne", - "bfi w20, w21, #29, #1", + "cset x20, eq", + "tst x4, x4", + "mrs x21, nzcv", + "orr w20, w21, w20, lsl #29", "msr nzcv, x20" ] }, "blsi eax, ebx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 7, "Comment": [ "Map group 17 0b011 32-bit" ], @@ -684,14 +682,13 @@ "and w4, w7, w20", "tst w4, w4", "mrs x20, nzcv", - "cmp x4, #0x0 (0)", - "cset x21, ne", + "cset w21, ne", "orr w20, w20, w21, lsl #29", "msr nzcv, x20" ] }, "blsi rax, rbx": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 7, "Comment": [ "Map group 17 0b011 64-bit" ], @@ -700,8 +697,7 @@ "and x4, x7, x20", "tst x4, x4", "mrs x20, nzcv", - "cmp x4, #0x0 (0)", - "cset x21, ne", + "cset w21, ne", "orr w20, w20, w21, lsl #29", "msr nzcv, x20" ]