Merge pull request #3385 from alyssarosenzweig/opt/bmi

Optimize bit manipulation instructions
This commit is contained in:
Mai authored and GitHub committed 2024-01-31 14:07:23 -05:00
commit f4086b25e6
12 files changed
+408 -373

No files matched your search

@@ -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
auto One = _Constant(SrcSize, 1);
auto Mask = _Sub(IR::SizeToOpSize(Size), _Lshl(IR::SizeToOpSize(Size), One, SanitizedLength), One);
// (1 << Length) - 1 = ~(~0 << Length)
auto AllOnes = _Constant(~0ull);
auto InvertedMask = _Lshl(IR::SizeToOpSize(Size), AllOnes, Length);
// Now put it all together and make the result.
auto Dest = _And(IR::SizeToOpSize(Size), SanitizedShifted, Mask);
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);
@@ -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) {
@@ -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, Src);
GenerateFlags_ZCNT(Op, Res);
}
void OpDispatchBuilder::MOVBEOp(OpcodeArgs) {
@@ -102,8 +102,7 @@ public:
TYPE_BLSR,
TYPE_POPCOUNT,
TYPE_BZHI,
TYPE_TZCNT,
TYPE_LZCNT,
TYPE_ZCNT,
TYPE_RDRAND,
};
@@ -1604,11 +1603,11 @@ private:
OrderedNode *Res{};
union {
// UMUL, BEXTR, BLSI, BLSMSK, POPCOUNT, TZCNT, LZCNT, RDRAND
// UMUL, BEXTR, BLSI, POPCOUNT, ZCNT, RDRAND
struct {
} NoSource;
// MUL, BLSR, BZHI
// MUL, BLSR, BLSMSKB, BZHI
struct {
OrderedNode *Src1;
} OneSource;
@@ -1740,12 +1739,11 @@ 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);
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);
/** @} */
@@ -2064,11 +2062,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,
},
},
};
}
@@ -2106,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,
};
@@ -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(
@@ -461,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;
@@ -976,112 +976,67 @@ 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<X86State::RFLAG_ZF_RAW_LOC>(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<X86State::RFLAG_CF_RAW_LOC>(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<X86State::RFLAG_CF_RAW_LOC>(CFOp);
}
}
void OpDispatchBuilder::CalculateFlags_BLSMSK(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);
void OpDispatchBuilder::CalculateFlags_BLSMSK(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) {
// PF/AF undefined
_InvalidateFlags((1UL << X86State::RFLAG_PF_RAW_LOC) |
(1UL << X86State::RFLAG_AF_RAW_LOC));
auto CFOp = _Select(IR::COND_NEQ, Src, Zero, One, Zero);
// CF set according to the Src
auto Zero = _Constant(0);
auto One = _Constant(1);
auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero);
// 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<X86State::RFLAG_CF_RAW_LOC>(CFOp);
}
void OpDispatchBuilder::CalculateFlags_BLSR(uint8_t SrcSize, OrderedNode *Result, OrderedNode *Src) {
// Now for flags.
auto Zero = _Constant(0);
auto One = _Constant(1);
auto CFOp = _Select(IR::COND_EQ, Src, Zero, One, Zero);
SetNZ_ZeroCV(SrcSize, Result);
SetRFLAG<X86State::RFLAG_CF_RAW_LOC>(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<X86State::RFLAG_CF_RAW_LOC>(CFOp);
}
}
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<FEXCore::X86State::RFLAG_ZF_RAW_LOC>(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) {
@@ -1093,32 +1048,16 @@ void OpDispatchBuilder::CalculateFlags_BZHI(uint8_t SrcSize, OrderedNode *Result
SetRFLAG<X86State::RFLAG_CF_RAW_LOC>(Src);
}
void OpDispatchBuilder::CalculateFlags_TZCNT(OrderedNode *Src) {
void OpDispatchBuilder::CalculateFlags_ZCNT(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<FEXCore::X86State::RFLAG_CF_RAW_LOC>(ZFResult);
SetRFLAG<FEXCore::X86State::RFLAG_ZF_RAW_LOC>(Src, 0, true);
}
void OpDispatchBuilder::CalculateFlags_LZCNT(uint8_t SrcSize, 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<FEXCore::X86State::RFLAG_CF_RAW_LOC>(ZFResult);
SetRFLAG<FEXCore::X86State::RFLAG_ZF_RAW_LOC>(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<FEXCore::X86State::RFLAG_CF_RAW_LOC>(Result, CarryBit);
}
void OpDispatchBuilder::CalculateFlags_RDRAND(OrderedNode *Src) {
+60
View File
@@ -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
+63
View File
@@ -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
+60
View File
@@ -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
@@ -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"
]
}
}
@@ -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"
]
}
}
@@ -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"
]
}
}
+39 -54
View File
@@ -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"
]
},
+24 -34
View File
@@ -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": {
+22 -26
View File
@@ -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"
]