Merge pull request #3553 from alyssarosenzweig/ra/shifts-rework-easy

OpcodeDispatcher: clean up shifts
This commit is contained in:
Alyssa Rosenzweig 2024-04-05 11:36:33 -04:00 committed by GitHub
commit c43af8e975
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 175 deletions

View File

@ -1546,6 +1546,19 @@ void OpDispatchBuilder::CPUIDOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RCX, _Bfe(OpSize::i64Bit, 32, 0, Result_Upper));
}
uint32_t OpDispatchBuilder::LoadConstantShift(X86Tables::DecodedOp Op, bool Is1Bit) {
if (Is1Bit) {
return 1;
} else {
// x86 masks the shift by 0x3F or 0x1F depending on size of op
const uint32_t Size = GetSrcBitSize(Op);
uint64_t Mask = Size == 64 ? 0x3F : 0x1F;
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
return Op->Src[1].Data.Literal.Value & Mask;
}
}
void OpDispatchBuilder::XGetBVOp(OpcodeArgs) {
OrderedNode *Function = LoadGPRRegister(X86State::REG_RCX);
@ -1558,49 +1571,24 @@ void OpDispatchBuilder::XGetBVOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RDX, Result_Upper);
}
template<bool SHL1Bit>
void OpDispatchBuilder::SHLOp(OpcodeArgs) {
OrderedNode *Src{};
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
if constexpr (SHL1Bit) {
Src = _Constant(1);
}
else {
Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags);
}
const auto Size = GetSrcBitSize(Op);
auto Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
auto Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags);
OrderedNode *Result = _Lshl(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Dest, Src);
StoreResult(GPRClass, Op, Result, -1);
if (Size < 32) {
Result = _Bfe(OpSize::i32Bit, Size, 0, Result);
}
if constexpr (SHL1Bit) {
GenerateFlags_ShiftLeftImmediate(Op, Result, Dest, 1);
}
else {
GenerateFlags_ShiftLeft(Op, Result, Dest, Src);
}
GenerateFlags_ShiftLeft(Op, Result, Dest, Src);
}
template<bool SHL1Bit>
void OpDispatchBuilder::SHLImmediateOp(OpcodeArgs) {
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
uint64_t Shift = Op->Src[1].Data.Literal.Value;
uint64_t Shift = LoadConstantShift(Op, SHL1Bit);
const auto Size = GetSrcBitSize(Op);
// x86 masks the shift by 0x3F or 0x1F depending on size of op
if (Size == 64) {
Shift &= 0x3F;
} else {
Shift &= 0x1F;
}
OrderedNode *Src = _Constant(Size, Shift);
OrderedNode *Result = _Lshl(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Dest, Src);
@ -1609,44 +1597,23 @@ void OpDispatchBuilder::SHLImmediateOp(OpcodeArgs) {
GenerateFlags_ShiftLeftImmediate(Op, Result, Dest, Shift);
}
template<bool SHR1Bit>
void OpDispatchBuilder::SHROp(OpcodeArgs) {
OrderedNode *Src;
auto Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
if constexpr (SHR1Bit) {
Src = _Constant(1);
}
else {
Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags);
}
auto Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags);
auto ALUOp = _Lshr(IR::SizeToOpSize(std::max<uint8_t>(4, GetSrcSize(Op))), Dest, Src);
StoreResult(GPRClass, Op, ALUOp, -1);
if constexpr (SHR1Bit) {
GenerateFlags_ShiftRightImmediate(Op, ALUOp, Dest, 1);
}
else {
GenerateFlags_ShiftRight(Op, ALUOp, Dest, Src);
}
GenerateFlags_ShiftRight(Op, ALUOp, Dest, Src);
}
template<bool SHR1Bit>
void OpDispatchBuilder::SHRImmediateOp(OpcodeArgs) {
auto Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
uint64_t Shift = Op->Src[1].Data.Literal.Value;
uint64_t Shift = LoadConstantShift(Op, SHR1Bit);
const auto Size = GetSrcBitSize(Op);
// x86 masks the shift by 0x3F or 0x1F depending on size of op
if (Size == 64) {
Shift &= 0x3F;
} else {
Shift &= 0x1F;
}
OrderedNode *Src = _Constant(Size, Shift);
auto ALUOp = _Lshr(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Dest, Src);
@ -1666,13 +1633,7 @@ void OpDispatchBuilder::SHLDOp(OpcodeArgs) {
const auto Size = GetSrcBitSize(Op);
// x86 masks the shift by 0x3F or 0x1F depending on size of op. Arm will mask
// by 0x3F when we do 64-bit shifts so we don't need to mask in that case,
// since the modulo is preserved even after presubtracting Size=64 for
// ShiftRight.
//
// TODO: Implement this optimization, it requires turning the shift=0 cases
// into (shift&0xc0) bit tests which is a bit complicated for now.
// x86 masks the shift by 0x3F or 0x1F depending on size of op.
if (Size == 64) {
Shift = _And(OpSize::i64Bit, Shift, _Constant(0x3F));
} else {
@ -1712,18 +1673,9 @@ void OpDispatchBuilder::SHLDImmediateOp(OpcodeArgs) {
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
uint64_t Shift = Op->Src[1].Data.Literal.Value;
uint64_t Shift = LoadConstantShift(Op, false);
const auto Size = GetSrcBitSize(Op);
// x86 masks the shift by 0x3F or 0x1F depending on size of op
if (Size == 64) {
Shift &= 0x3F;
} else {
Shift &= 0x1F;
}
if (Shift != 0) {
OrderedNode *Res{};
if (Size < 32) {
@ -1784,9 +1736,6 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) {
StoreResult(GPRClass, Op, Res, -1);
if (Size != 64) {
Res = _Bfe(OpSize::i64Bit, Size, 0, Res);
}
GenerateFlags_ShiftRight(Op, Res, Dest, Shift);
}
@ -1794,20 +1743,10 @@ void OpDispatchBuilder::SHRDImmediateOp(OpcodeArgs) {
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
uint64_t Shift = Op->Src[1].Data.Literal.Value;
uint64_t Shift = LoadConstantShift(Op, false);
const auto Size = GetSrcBitSize(Op);
// x86 masks the shift by 0x3F or 0x1F depending on size of op
if (Size == 64) {
Shift &= 0x3F;
} else {
Shift &= 0x1F;
}
if (Shift != 0) {
OrderedNode *Res{};
if (Size < 32) {
OrderedNode *ShiftRight = _Constant(Shift);
@ -1832,19 +1771,11 @@ void OpDispatchBuilder::SHRDImmediateOp(OpcodeArgs) {
}
}
template<bool SHR1Bit>
void OpDispatchBuilder::ASHROp(OpcodeArgs) {
OrderedNode *Src;
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
auto Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
auto Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags);
const auto Size = GetSrcBitSize(Op);
if constexpr (SHR1Bit) {
Src = _Constant(Size, 1);
} else {
Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags);
}
if (Size < 32) {
Dest = _Sbfe(OpSize::i64Bit, Size, 0, Dest);
}
@ -1852,28 +1783,16 @@ void OpDispatchBuilder::ASHROp(OpcodeArgs) {
OrderedNode *Result = _Ashr(IR::SizeToOpSize(std::max<uint8_t>(4, GetSrcSize(Op))), Dest, Src);
StoreResult(GPRClass, Op, Result, -1);
if constexpr (SHR1Bit) {
GenerateFlags_SignShiftRightImmediate(Op, Result, Dest, 1);
} else {
GenerateFlags_SignShiftRight(Op, Result, Dest, Src);
}
GenerateFlags_SignShiftRight(Op, Result, Dest, Src);
}
template<bool SHR1Bit>
void OpDispatchBuilder::ASHRImmediateOp(OpcodeArgs) {
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
uint64_t Shift = Op->Src[1].Data.Literal.Value;
uint64_t Shift = LoadConstantShift(Op, SHR1Bit);
const auto Size = GetSrcBitSize(Op);
// x86 masks the shift by 0x3F or 0x1F depending on size of op
if (Size == 64) {
Shift &= 0x3F;
} else {
Shift &= 0x1F;
}
if (Size < 32) {
Dest = _Sbfe(OpSize::i64Bit, Size, 0, Dest);
}
@ -1891,16 +1810,13 @@ void OpDispatchBuilder::RotateOp(OpcodeArgs) {
CalculateDeferredFlags();
auto LoadShift = [this, Op](bool MustMask) -> OrderedNode * {
// x86 masks the shift by 0x3F or 0x1F depending on size of op
const uint32_t Size = GetSrcBitSize(Op);
uint64_t Mask = Size == 64 ? 0x3F : 0x1F;
if (Is1Bit) {
return _Constant(1);
} else if (IsImmediate) {
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
return _Constant(Op->Src[1].Data.Literal.Value & Mask);
if (Is1Bit || IsImmediate) {
return _Constant(LoadConstantShift(Op, Is1Bit));
} else {
// x86 masks the shift by 0x3F or 0x1F depending on size of op
const uint32_t Size = GetSrcBitSize(Op);
uint64_t Mask = Size == 64 ? 0x3F : 0x1F;
auto Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true});
return MustMask ? _And(OpSize::i64Bit, Src, _Constant(Mask)) : Src;
}
@ -6080,55 +5996,55 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 1), 1, &OpDispatchBuilder::RotateOp<false, true, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 2), 1, &OpDispatchBuilder::RCLOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 3), 1, &OpDispatchBuilder::RCROp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 4), 1, &OpDispatchBuilder::SHLImmediateOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 5), 1, &OpDispatchBuilder::SHRImmediateOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 6), 1, &OpDispatchBuilder::SHLImmediateOp}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 7), 1, &OpDispatchBuilder::ASHRImmediateOp}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 4), 1, &OpDispatchBuilder::SHLImmediateOp<false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 5), 1, &OpDispatchBuilder::SHRImmediateOp<false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 6), 1, &OpDispatchBuilder::SHLImmediateOp<false>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 7), 1, &OpDispatchBuilder::ASHRImmediateOp<false>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 0), 1, &OpDispatchBuilder::RotateOp<true, true, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 1), 1, &OpDispatchBuilder::RotateOp<false, true, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 2), 1, &OpDispatchBuilder::RCLOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 3), 1, &OpDispatchBuilder::RCROp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 4), 1, &OpDispatchBuilder::SHLImmediateOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 5), 1, &OpDispatchBuilder::SHRImmediateOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 6), 1, &OpDispatchBuilder::SHLImmediateOp}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 7), 1, &OpDispatchBuilder::ASHRImmediateOp}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 4), 1, &OpDispatchBuilder::SHLImmediateOp<false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 5), 1, &OpDispatchBuilder::SHRImmediateOp<false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 6), 1, &OpDispatchBuilder::SHLImmediateOp<false>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 7), 1, &OpDispatchBuilder::ASHRImmediateOp<false>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 0), 1, &OpDispatchBuilder::RotateOp<true, true, true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 1), 1, &OpDispatchBuilder::RotateOp<false, true, true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 2), 1, &OpDispatchBuilder::RCLOp1Bit},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 3), 1, &OpDispatchBuilder::RCROp8x1Bit},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 4), 1, &OpDispatchBuilder::SHLOp<true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 5), 1, &OpDispatchBuilder::SHROp<true>}, // 1Bit SHR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 6), 1, &OpDispatchBuilder::SHLOp<true>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 7), 1, &OpDispatchBuilder::ASHROp<true>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 4), 1, &OpDispatchBuilder::SHLImmediateOp<true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 5), 1, &OpDispatchBuilder::SHRImmediateOp<true>}, // 1Bit SHR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 6), 1, &OpDispatchBuilder::SHLImmediateOp<true>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD0), 7), 1, &OpDispatchBuilder::ASHRImmediateOp<true>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 0), 1, &OpDispatchBuilder::RotateOp<true, true, true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 1), 1, &OpDispatchBuilder::RotateOp<false, true, true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 2), 1, &OpDispatchBuilder::RCLOp1Bit},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 3), 1, &OpDispatchBuilder::RCROp1Bit},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 4), 1, &OpDispatchBuilder::SHLOp<true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 5), 1, &OpDispatchBuilder::SHROp<true>}, // 1Bit SHR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 6), 1, &OpDispatchBuilder::SHLOp<true>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 7), 1, &OpDispatchBuilder::ASHROp<true>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 4), 1, &OpDispatchBuilder::SHLImmediateOp<true>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 5), 1, &OpDispatchBuilder::SHRImmediateOp<true>}, // 1Bit SHR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 6), 1, &OpDispatchBuilder::SHLImmediateOp<true>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD1), 7), 1, &OpDispatchBuilder::ASHRImmediateOp<true>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 0), 1, &OpDispatchBuilder::RotateOp<true, false, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 1), 1, &OpDispatchBuilder::RotateOp<false, false, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 2), 1, &OpDispatchBuilder::RCLSmallerOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 3), 1, &OpDispatchBuilder::RCRSmallerOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 4), 1, &OpDispatchBuilder::SHLOp<false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 5), 1, &OpDispatchBuilder::SHROp<false>}, // SHR by CL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 6), 1, &OpDispatchBuilder::SHLOp<false>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 7), 1, &OpDispatchBuilder::ASHROp<false>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 4), 1, &OpDispatchBuilder::SHLOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 5), 1, &OpDispatchBuilder::SHROp}, // SHR by CL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 6), 1, &OpDispatchBuilder::SHLOp}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 7), 1, &OpDispatchBuilder::ASHROp}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 0), 1, &OpDispatchBuilder::RotateOp<true, false, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 1), 1, &OpDispatchBuilder::RotateOp<false, false, false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 2), 1, &OpDispatchBuilder::RCLOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 3), 1, &OpDispatchBuilder::RCROp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 4), 1, &OpDispatchBuilder::SHLOp<false>},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 5), 1, &OpDispatchBuilder::SHROp<false>}, // SHR by CL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 6), 1, &OpDispatchBuilder::SHLOp<false>}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 7), 1, &OpDispatchBuilder::ASHROp<false>}, // SAR
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 4), 1, &OpDispatchBuilder::SHLOp},
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 5), 1, &OpDispatchBuilder::SHROp}, // SHR by CL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 6), 1, &OpDispatchBuilder::SHLOp}, // SAL
{OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 7), 1, &OpDispatchBuilder::ASHROp}, // SAR
// GROUP 3
{OPD(FEXCore::X86Tables::TYPE_GROUP_3, OpToIndex(0xF6), 0), 1, &OpDispatchBuilder::TESTOp<1>},

View File

@ -329,18 +329,19 @@ public:
void CMOVOp(OpcodeArgs);
void CPUIDOp(OpcodeArgs);
void XGetBVOp(OpcodeArgs);
template<bool SHL1Bit>
uint32_t LoadConstantShift(X86Tables::DecodedOp Op, bool Is1Bit);
void SHLOp(OpcodeArgs);
template<bool SHL1Bit>
void SHLImmediateOp(OpcodeArgs);
template<bool SHR1Bit>
void SHROp(OpcodeArgs);
template<bool SHR1Bit>
void SHRImmediateOp(OpcodeArgs);
void SHLDOp(OpcodeArgs);
void SHLDImmediateOp(OpcodeArgs);
void SHRDOp(OpcodeArgs);
void SHRDImmediateOp(OpcodeArgs);
template<bool SHR1Bit>
void ASHROp(OpcodeArgs);
template<bool SHR1Bit>
void ASHRImmediateOp(OpcodeArgs);
template<bool Left, bool IsImmediate, bool Is1Bit>
void RotateOp(OpcodeArgs);

View File

@ -1295,13 +1295,12 @@
]
},
"shl al, 1": {
"ExpectedInstructionCount": 8,
"ExpectedInstructionCount": 7,
"Comment": "GROUP2 0xd0 /4",
"ExpectedArm64ASM": [
"uxtb w20, w4",
"lsl w21, w20, #1",
"bfxil x4, x21, #0, #8",
"uxtb w26, w21",
"lsl w26, w20, #1",
"bfxil x4, x26, #0, #8",
"cmn wzr, w26, lsl #24",
"rmif x20, #6, #nzCv",
"eor w20, w26, w20",
@ -1326,7 +1325,7 @@
"ExpectedArm64ASM": [
"uxtb w20, w4",
"sxtb x20, w20",
"asr w26, w20, #1",
"asr x26, x20, #1",
"bfxil x4, x26, #0, #8",
"cmn wzr, w26, lsl #24",
"rmif x20, #63, #nzCv"
@ -1471,13 +1470,12 @@
]
},
"shl ax, 1": {
"ExpectedInstructionCount": 8,
"ExpectedInstructionCount": 7,
"Comment": "GROUP2 0xd1 /4",
"ExpectedArm64ASM": [
"uxth w20, w4",
"lsl w21, w20, #1",
"bfxil x4, x21, #0, #16",
"uxth w26, w21",
"lsl w26, w20, #1",
"bfxil x4, x26, #0, #16",
"cmn wzr, w26, lsl #16",
"rmif x20, #14, #nzCv",
"eor w20, w26, w20",
@ -1552,7 +1550,7 @@
"ExpectedArm64ASM": [
"uxth w20, w4",
"sxth x20, w20",
"asr w26, w20, #1",
"asr x26, x20, #1",
"bfxil x4, x26, #0, #16",
"cmn wzr, w26, lsl #16",
"rmif x20, #63, #nzCv"
@ -1671,14 +1669,13 @@
]
},
"shl al, cl": {
"ExpectedInstructionCount": 14,
"ExpectedInstructionCount": 13,
"Comment": "GROUP2 0xd2 /4",
"ExpectedArm64ASM": [
"uxtb w20, w4",
"uxtb w21, w5",
"lsl w22, w20, w21",
"bfxil x4, x22, #0, #8",
"uxtb w22, w22",
"cbz x21, #+0x24",
"cmn wzr, w22, lsl #24",
"mov w23, #0x8",
@ -1939,14 +1936,13 @@
]
},
"shl ax, cl": {
"ExpectedInstructionCount": 14,
"ExpectedInstructionCount": 13,
"Comment": "GROUP2 0xd3 /4",
"ExpectedArm64ASM": [
"uxth w20, w4",
"uxth w21, w5",
"lsl w22, w20, w21",
"bfxil x4, x22, #0, #16",
"uxth w22, w22",
"cbz x21, #+0x24",
"cmn wzr, w22, lsl #16",
"mov w23, #0x10",

View File

@ -1504,13 +1504,12 @@
]
},
"shl al, 1": {
"ExpectedInstructionCount": 12,
"ExpectedInstructionCount": 11,
"Comment": "GROUP2 0xd0 /4",
"ExpectedArm64ASM": [
"uxtb w20, w4",
"lsl w21, w20, #1",
"bfxil x4, x21, #0, #8",
"uxtb w26, w21",
"lsl w26, w20, #1",
"bfxil x4, x26, #0, #8",
"cmn wzr, w26, lsl #24",
"ubfx x21, x20, #7, #1",
"mrs x22, nzcv",
@ -1543,7 +1542,7 @@
"ExpectedArm64ASM": [
"uxtb w20, w4",
"sxtb x20, w20",
"asr w26, w20, #1",
"asr x26, x20, #1",
"bfxil x4, x26, #0, #8",
"cmn wzr, w26, lsl #24",
"ubfx x20, x20, #0, #1",
@ -1769,13 +1768,12 @@
]
},
"shl ax, 1": {
"ExpectedInstructionCount": 12,
"ExpectedInstructionCount": 11,
"Comment": "GROUP2 0xd1 /4",
"ExpectedArm64ASM": [
"uxth w20, w4",
"lsl w21, w20, #1",
"bfxil x4, x21, #0, #16",
"uxth w26, w21",
"lsl w26, w20, #1",
"bfxil x4, x26, #0, #16",
"cmn wzr, w26, lsl #16",
"ubfx x21, x20, #15, #1",
"mrs x22, nzcv",
@ -1874,7 +1872,7 @@
"ExpectedArm64ASM": [
"uxth w20, w4",
"sxth x20, w20",
"asr w26, w20, #1",
"asr x26, x20, #1",
"bfxil x4, x26, #0, #16",
"cmn wzr, w26, lsl #16",
"ubfx x20, x20, #0, #1",
@ -2026,14 +2024,13 @@
]
},
"shl al, cl": {
"ExpectedInstructionCount": 18,
"ExpectedInstructionCount": 17,
"Comment": "GROUP2 0xd2 /4",
"ExpectedArm64ASM": [
"uxtb w20, w4",
"uxtb w21, w5",
"lsl w22, w20, w21",
"bfxil x4, x22, #0, #8",
"uxtb w22, w22",
"cbz x21, #+0x34",
"cmn wzr, w22, lsl #24",
"mov w23, #0x8",
@ -2381,14 +2378,13 @@
]
},
"shl ax, cl": {
"ExpectedInstructionCount": 18,
"ExpectedInstructionCount": 17,
"Comment": "GROUP2 0xd3 /4",
"ExpectedArm64ASM": [
"uxth w20, w4",
"uxth w21, w5",
"lsl w22, w20, w21",
"bfxil x4, x22, #0, #16",
"uxth w22, w22",
"cbz x21, #+0x34",
"cmn wzr, w22, lsl #16",
"mov w23, #0x10",