Skip to content

Commit

Permalink
Merge pull request #3553 from alyssarosenzweig/ra/shifts-rework-easy
Browse files Browse the repository at this point in the history
OpcodeDispatcher: clean up shifts
  • Loading branch information
alyssarosenzweig authored Apr 5, 2024
2 parents 202a60b + a787daa commit c43af8e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 175 deletions.
204 changes: 60 additions & 144 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -1784,30 +1736,17 @@ 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);
}

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);
Expand All @@ -1832,48 +1771,28 @@ 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);
}

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);
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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>},
Expand Down
7 changes: 4 additions & 3 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,18 +329,19 @@ friend class FEXCore::IR::PassManager;
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);
Expand Down
Loading

0 comments on commit c43af8e

Please sign in to comment.