diff --git a/FEXCore/Source/Interface/Core/Frontend.cpp b/FEXCore/Source/Interface/Core/Frontend.cpp index ac58961b6..8431258f2 100644 --- a/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/FEXCore/Source/Interface/Core/Frontend.cpp @@ -625,13 +625,6 @@ Decoder::DecodedBlockStatus Decoder::NormalOp(const FEXCore::X86Tables::X86InstI ++CurrentSrc; } - if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_SRC_RCX)) { - DecodeInst->Src[CurrentSrc].Type = DecodedOperand::OpType::GPR; - DecodeInst->Src[CurrentSrc].Data.GPR.HighBits = false; - DecodeInst->Src[CurrentSrc].Data.GPR.GPR = FEXCore::X86State::REG_RCX; - ++CurrentSrc; - } - if (VEXOperand == FEXCore::X86Tables::InstFlags::FLAGS_VEX_DST) { CurrentDest->Type = DecodedOperand::OpType::GPR; CurrentDest->Data.GPR.HighBits = false; diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 370bb9c03..88598786a 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -774,11 +774,11 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { OpSize = OpSize::i32Bit; } - uint64_t Target = Op->PC + Op->InstSize + Op->Src[1].Literal(); + uint64_t Target = Op->PC + Op->InstSize + Op->Src[0].Literal(); - Ref CondReg = LoadSourceGPR_WithOpSize(Op, Op->Src[0], SrcSize, Op->Flags); + Ref CondReg = LoadGPRRegister(X86State::REG_RCX, SrcSize); CondReg = Sub(OpSize, CondReg, 1); - StoreResultGPR(Op, Op->Src[0], CondReg); + StoreGPRRegister(X86State::REG_RCX, CondReg, SrcSize); // If LOOPE then jumps to target if RCX != 0 && ZF == 1 // If LOOPNE then jumps to target if RCX != 0 && ZF == 0 @@ -807,7 +807,7 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { StartNewBlock(); // Store the new RIP - ExitRelocatedPC(Op, Op->Src[1].Literal()); + ExitRelocatedPC(Op, Op->Src[0].Literal()); } // Failure to take branch @@ -1394,7 +1394,7 @@ void OpDispatchBuilder::XGetBVOp(OpcodeArgs) { void OpDispatchBuilder::SHLOp(OpcodeArgs) { const auto Size = OpSizeFromSrc(Op); auto Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); - auto Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); Ref Result = _Lshl(Size == OpSize::i64Bit ? OpSize::i64Bit : OpSize::i32Bit, Dest, Src); HandleShift(Op, Result, Dest, ShiftType::LSL, Src); @@ -1416,7 +1416,7 @@ void OpDispatchBuilder::SHLImmediateOp(OpcodeArgs, bool SHL1Bit) { void OpDispatchBuilder::SHROp(OpcodeArgs) { const auto Size = OpSizeFromSrc(Op); auto Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = Size >= OpSize::i32Bit}); - auto Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); auto ALUOp = _Lshr(std::max(OpSize::i32Bit, Size), Dest, Src); HandleShift(Op, ALUOp, Dest, ShiftType::LSR, Src); @@ -1445,7 +1445,7 @@ void OpDispatchBuilder::SHLDOp(OpcodeArgs) { Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags); // Allow garbage on the shift, we're masking it anyway. - Ref Shift = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + Ref Shift = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); // x86 masks the shift by 0x3F or 0x1F depending on size of op. if (Size == 64) { @@ -1516,7 +1516,7 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) { Ref Src = LoadSourceGPR(Op, Op->Src[0], Op->Flags); Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags); - Ref Shift = LoadGPRRegister(X86State::REG_RCX); + Ref Shift = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); const auto Size = GetDstBitSize(Op); @@ -1594,7 +1594,7 @@ void OpDispatchBuilder::ASHROp(OpcodeArgs, bool Immediate, bool SHR1Bit) { CalculateDeferredFlags(); StoreResultGPR(Op, Result); } else { - auto Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); Ref Result = _Ashr(OpSize, Dest, Src); HandleShift(Op, Result, Dest, ShiftType::ASR, Src); @@ -1618,7 +1618,7 @@ void OpDispatchBuilder::RotateOp(OpcodeArgs, bool Left, bool IsImmediate, bool I UnmaskedConst = GetConstantShift(Op, Is1Bit); UnmaskedSrc = ARef(UnmaskedConst); } else { - UnmaskedSrc = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); + UnmaskedSrc = ARef(LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true)); } auto Src = UnmaskedSrc.And(Mask); @@ -2008,11 +2008,11 @@ void OpDispatchBuilder::RCROp8x1Bit(OpcodeArgs) { SetRFLAG(_XorShift(OpSize::i32Bit, Res, Res, ShiftType::LSR, 1), SizeBit - 2, true); } -void OpDispatchBuilder::RCROp(OpcodeArgs) { +void OpDispatchBuilder::RCROp(OpcodeArgs, bool UseRCX) { const auto Size = GetSrcBitSize(Op); if (Size == 8 || Size == 16) { - RCRSmallerOp(Op); + RCRSmallerOp(Op, UseRCX); return; } @@ -2022,49 +2022,54 @@ void OpDispatchBuilder::RCROp(OpcodeArgs) { CalculateDeferredFlags(); const auto OpSize = OpSizeFromSrc(Op); - Ref Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); - uint64_t Const; - if (IsValueConstant(WrapNode(Src), &Const)) { - Const &= Mask; - if (!Const) { - ZeroShiftResult(Op); + if (!UseRCX) { + Ref Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + uint64_t Const; + if (IsValueConstant(WrapNode(Src), &Const)) { + Const &= Mask; + if (!Const) { + ZeroShiftResult(Op); + return; + } + + Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); + + // Res = Src >> Shift + Ref Res = _Lshr(OpSize, Dest, Src); + auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC); + + // Constant folded version of the above, with fused shifts. + if (Const > 1) { + Res = _Orlshl(OpSize, Res, Dest, Size + 1 - Const); + } + + // Our new CF will be bit (Shift - 1) of the source. + SetCFDirect(Dest, Const - 1, true); + + // Since shift != 0 we can inject the CF + Res = _Orlshl(OpSize, Res, CF, Size - Const); + + // OF is the top two MSBs XOR'd together + // Only when Shift == 1, it is undefined otherwise + if (Const == 1) { + auto Xor = _XorShift(OpSize, Res, Res, ShiftType::LSR, 1); + SetRFLAG(Xor, Size - 2, true); + } + + StoreResultGPR(Op, Res); return; } - - Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); - - // Res = Src >> Shift - Ref Res = _Lshr(OpSize, Dest, Src); - auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC); - - // Constant folded version of the above, with fused shifts. - if (Const > 1) { - Res = _Orlshl(OpSize, Res, Dest, Size + 1 - Const); - } - - // Our new CF will be bit (Shift - 1) of the source. - SetCFDirect(Dest, Const - 1, true); - - // Since shift != 0 we can inject the CF - Res = _Orlshl(OpSize, Res, CF, Size - Const); - - // OF is the top two MSBs XOR'd together - // Only when Shift == 1, it is undefined otherwise - if (Const == 1) { - auto Xor = _XorShift(OpSize, Res, Res, ShiftType::LSR, 1); - SetRFLAG(Xor, Size - 2, true); - } - - StoreResultGPR(Op, Res); - return; } + // x86 masks the shift by 0x3F or 0x1F depending on size of op + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); Ref SrcMasked = _And(OpSize, Src, _InlineConstant(Mask)); + Calculate_ShiftVariable( Op, SrcMasked, [this, Op, Size, OpSize]() { // Rematerialize loads to avoid crossblock liveness - Ref Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); // Res = Src >> Shift @@ -2100,21 +2105,29 @@ void OpDispatchBuilder::RCROp(OpcodeArgs) { OpSizeFromSrc(Op) == OpSize::i32Bit ? std::make_optional(&OpDispatchBuilder::ZeroShiftResult) : std::nullopt); } -void OpDispatchBuilder::RCRSmallerOp(OpcodeArgs) { +void OpDispatchBuilder::RCRSmallerOp(OpcodeArgs, bool UseRCX) { CalculateDeferredFlags(); const auto Size = GetSrcBitSize(Op); // x86 masks the shift by 0x3F or 0x1F depending on size of op - auto Src = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); - Src = Src.And(0x1F); + auto GetShift = [this, Op, UseRCX]() { + if (UseRCX) { + auto Src = ARef(LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true)); + return Src.And(0x1F); + } else { + auto Src = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); + return Src.And(0x1F); + } + }; + + auto Src = GetShift(); // CF only changes if we actually shifted. OF undefined if we didn't shift. // The result is unchanged if we didn't shift. So branch over the whole thing. - Calculate_ShiftVariable(Op, Src.Ref(), [this, Op, Size]() { + Calculate_ShiftVariable(Op, Src.Ref(), [this, Op, Size, GetShift]() { // Rematerialized to avoid crossblock liveness - auto Src = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); - Src = Src.And(0x1F); + auto Src = GetShift(); auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC); @@ -2224,11 +2237,11 @@ void OpDispatchBuilder::RCLOp1Bit(OpcodeArgs) { StoreResultGPR(Op, Res); } -void OpDispatchBuilder::RCLOp(OpcodeArgs) { +void OpDispatchBuilder::RCLOp(OpcodeArgs, bool UseRCX) { const auto Size = GetSrcBitSize(Op); if (Size == 8 || Size == 16) { - RCLSmallerOp(Op); + RCLSmallerOp(Op, UseRCX); return; } @@ -2237,50 +2250,55 @@ void OpDispatchBuilder::RCLOp(OpcodeArgs) { // Calculate flags early. CalculateDeferredFlags(); - Ref Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); const auto OpSize = OpSizeFromSrc(Op); - uint64_t Const; - if (IsValueConstant(WrapNode(Src), &Const)) { - Const &= Mask; - if (!Const) { - ZeroShiftResult(Op); + if (!UseRCX) { + Ref Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + uint64_t Const; + if (IsValueConstant(WrapNode(Src), &Const)) { + Const &= Mask; + if (!Const) { + ZeroShiftResult(Op); + return; + } + + // Res = Src << Shift + Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); + Ref Res = _Lshl(OpSize, Dest, Src); + auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC); + + // Res |= (Src << (Size - Shift + 1)); + if (Const > 1) { + Res = _Orlshr(OpSize, Res, Dest, Size + 1 - Const); + } + + // Our new CF will be bit (Shift - 1) of the source + SetCFDirect(Dest, Size - Const, true); + + // Since Shift != 0 we can inject the CF + Res = _Orlshl(OpSize, Res, CF, Const - 1); + + // OF is the top two MSBs XOR'd together + // Only when Shift == 1, it is undefined otherwise + if (Const == 1) { + auto NewOF = _Xor(OpSize, Res, Dest); + SetRFLAG(NewOF, Size - 1, true); + } + + StoreResultGPR(Op, Res); return; } - - // Res = Src << Shift - Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); - Ref Res = _Lshl(OpSize, Dest, Src); - auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC); - - // Res |= (Src << (Size - Shift + 1)); - if (Const > 1) { - Res = _Orlshr(OpSize, Res, Dest, Size + 1 - Const); - } - - // Our new CF will be bit (Shift - 1) of the source - SetCFDirect(Dest, Size - Const, true); - - // Since Shift != 0 we can inject the CF - Res = _Orlshl(OpSize, Res, CF, Const - 1); - - // OF is the top two MSBs XOR'd together - // Only when Shift == 1, it is undefined otherwise - if (Const == 1) { - auto NewOF = _Xor(OpSize, Res, Dest); - SetRFLAG(NewOF, Size - 1, true); - } - - StoreResultGPR(Op, Res); - return; } + // x86 masks the shift by 0x3F or 0x1F depending on size of op + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); Ref SrcMasked = _And(OpSize, Src, _InlineConstant(Mask)); + Calculate_ShiftVariable( Op, SrcMasked, [this, Op, Size, OpSize]() { // Rematerialized to avoid crossblock liveness - Ref Src = LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); + auto Src = LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true); // Res = Src << Shift Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); @@ -2315,21 +2333,29 @@ void OpDispatchBuilder::RCLOp(OpcodeArgs) { OpSizeFromSrc(Op) == OpSize::i32Bit ? std::make_optional(&OpDispatchBuilder::ZeroShiftResult) : std::nullopt); } -void OpDispatchBuilder::RCLSmallerOp(OpcodeArgs) { +void OpDispatchBuilder::RCLSmallerOp(OpcodeArgs, bool UseRCX) { CalculateDeferredFlags(); const auto Size = GetSrcBitSize(Op); // x86 masks the shift by 0x3F or 0x1F depending on size of op - auto Src = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); - Src = Src.And(0x1F); + auto GetShift = [this, Op, UseRCX]() { + if (UseRCX) { + auto Src = ARef(LoadGPRRegister(X86State::REG_RCX, OpSize::iInvalid, 0, true)); + return Src.And(0x1F); + } else { + auto Src = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); + return Src.And(0x1F); + } + }; + + auto Src = GetShift(); // CF only changes if we actually shifted. OF undefined if we didn't shift. // The result is unchanged if we didn't shift. So branch over the whole thing. - Calculate_ShiftVariable(Op, Src.Ref(), [this, Op, Size]() { + Calculate_ShiftVariable(Op, Src.Ref(), [this, Op, Size, GetShift]() { // Rematerialized to avoid crossblock liveness - auto Src = ARef(LoadSourceGPR(Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true})); - Src = Src.And(0x1F); + auto Src = GetShift(); Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags); auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 7639e5937..857eb3e72 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -428,11 +428,11 @@ public: void RotateOp(OpcodeArgs, bool Left, bool IsImmediate, bool Is1Bit); void RCROp1Bit(OpcodeArgs); void RCROp8x1Bit(OpcodeArgs); - void RCROp(OpcodeArgs); - void RCRSmallerOp(OpcodeArgs); + void RCROp(OpcodeArgs, bool UseRCX); + void RCRSmallerOp(OpcodeArgs, bool UseRCX); void RCLOp1Bit(OpcodeArgs); - void RCLOp(OpcodeArgs); - void RCLSmallerOp(OpcodeArgs); + void RCLOp(OpcodeArgs, bool UseRCX); + void RCLSmallerOp(OpcodeArgs, bool UseRCX); void BTOp(OpcodeArgs, uint32_t SrcIndex, enum BTAction Action); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/PrimaryGroupTables.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher/PrimaryGroupTables.h index 9dcde9d96..7fccb784e 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/PrimaryGroupTables.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/PrimaryGroupTables.h @@ -37,8 +37,8 @@ constexpr DispatchTableEntry OpDispatch_PrimaryGroupTables[] = { // GROUP 2 {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 0), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RotateOp, true, true, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 1), 1, &OpDispatchBuilder::Bind<&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), 2), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCLOp, false>}, + {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 3), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCROp, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 4), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::SHLImmediateOp, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 5), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::SHRImmediateOp, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC0), 6), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::SHLImmediateOp, false>}, // SAL @@ -46,8 +46,8 @@ constexpr DispatchTableEntry OpDispatch_PrimaryGroupTables[] = { {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 0), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RotateOp, true, true, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 1), 1, &OpDispatchBuilder::Bind<&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), 2), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCLOp, false>}, + {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 3), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCROp, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 4), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::SHLImmediateOp, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 5), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::SHRImmediateOp, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xC1), 6), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::SHLImmediateOp, false>}, // SAL @@ -73,8 +73,8 @@ constexpr DispatchTableEntry OpDispatch_PrimaryGroupTables[] = { {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 0), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RotateOp, true, false, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 1), 1, &OpDispatchBuilder::Bind<&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), 2), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCLSmallerOp, true>}, + {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD2), 3), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCRSmallerOp, true>}, {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 @@ -82,8 +82,8 @@ constexpr DispatchTableEntry OpDispatch_PrimaryGroupTables[] = { {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 0), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RotateOp, true, false, false>}, {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 1), 1, &OpDispatchBuilder::Bind<&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), 2), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCLOp, true>}, + {OPD(FEXCore::X86Tables::TYPE_GROUP_2, OpToIndex(0xD3), 3), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::RCROp, true>}, {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 diff --git a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp index 1fd0ce05b..8cb14e29f 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp @@ -371,9 +371,9 @@ const std::array BaseOps = []() consteval { {0xD6, 1, X86InstInfo{"", TYPE_ARCH_DISPATCHER, FLAGS_NONE, 0, { .Indirect = Primary_ArchSelect_LUT[ENTRY_D6] }}}, {0xD7, 1, X86InstInfo{"XLAT", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS, 0}}, - {0xE0, 1, X86InstInfo{"LOOPNE", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT | FLAGS_SF_SRC_RCX, 1}}, - {0xE1, 1, X86InstInfo{"LOOPE", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT | FLAGS_SF_SRC_RCX, 1}}, - {0xE2, 1, X86InstInfo{"LOOP", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT | FLAGS_SF_SRC_RCX, 1}}, + {0xE0, 1, X86InstInfo{"LOOPNE", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT, 1}}, + {0xE1, 1, X86InstInfo{"LOOPE", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT, 1}}, + {0xE2, 1, X86InstInfo{"LOOP", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT, 1}}, {0xE3, 1, X86InstInfo{"JrCXZ", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_SRC_SEXT , 1}}, // Should just throw GP diff --git a/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp index 13c0f4988..7b3ac484a 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp @@ -140,23 +140,23 @@ constexpr std::array PrimaryInstGroupOps {OPD(TYPE_GROUP_2, OpToIndex(0xD1), 6), 1, X86InstInfo{"SHL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, {OPD(TYPE_GROUP_2, OpToIndex(0xD1), 7), 1, X86InstInfo{"SAR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 0), 1, X86InstInfo{"ROL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 1), 1, X86InstInfo{"ROR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 2), 1, X86InstInfo{"RCL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 3), 1, X86InstInfo{"RCR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 4), 1, X86InstInfo{"SHL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 5), 1, X86InstInfo{"SHR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 6), 1, X86InstInfo{"SHL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 7), 1, X86InstInfo{"SAR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 0), 1, X86InstInfo{"ROL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 1), 1, X86InstInfo{"ROR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 2), 1, X86InstInfo{"RCL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 3), 1, X86InstInfo{"RCR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 4), 1, X86InstInfo{"SHL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 5), 1, X86InstInfo{"SHR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 6), 1, X86InstInfo{"SHL", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD2), 7), 1, X86InstInfo{"SAR", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 0), 1, X86InstInfo{"ROL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 1), 1, X86InstInfo{"ROR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 2), 1, X86InstInfo{"RCL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 3), 1, X86InstInfo{"RCR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 4), 1, X86InstInfo{"SHL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 5), 1, X86InstInfo{"SHR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 6), 1, X86InstInfo{"SHL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, - {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 7), 1, X86InstInfo{"SAR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 0), 1, X86InstInfo{"ROL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 1), 1, X86InstInfo{"ROR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 2), 1, X86InstInfo{"RCL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 3), 1, X86InstInfo{"RCR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 4), 1, X86InstInfo{"SHL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 5), 1, X86InstInfo{"SHR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 6), 1, X86InstInfo{"SHL", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, + {OPD(TYPE_GROUP_2, OpToIndex(0xD3), 7), 1, X86InstInfo{"SAR", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0}}, // GROUP 3 {OPD(TYPE_GROUP_3, OpToIndex(0xF6), 0), 1, X86InstInfo{"TEST", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 1}}, diff --git a/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp index a3c71f941..a08c243c2 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp @@ -207,14 +207,14 @@ constexpr std::array SecondBaseOps = []() co {0xA2, 1, X86InstInfo{"CPUID", TYPE_INST, FLAGS_NO_OVERLAY, 0}}, {0xA3, 1, X86InstInfo{"BT", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY | FLAGS_SUPPORTS_LOCK, 0}}, {0xA4, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 1}}, - {0xA5, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX | FLAGS_NO_OVERLAY, 0}}, + {0xA5, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0}}, {0xA6, 2, X86InstInfo{"", TYPE_INVALID, FLAGS_NO_OVERLAY, 0}}, {0xA8, 1, X86InstInfo{"", TYPE_ARCH_DISPATCHER, FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .Indirect = Secondary_ArchSelect_LUT[ENTRY_A8] }}}, {0xA9, 1, X86InstInfo{"", TYPE_ARCH_DISPATCHER, FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .Indirect = Secondary_ArchSelect_LUT[ENTRY_A9] }}}, {0xAA, 1, X86InstInfo{"RSM", TYPE_PRIV, FLAGS_NO_OVERLAY, 0}}, {0xAB, 1, X86InstInfo{"BTS", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY | FLAGS_SUPPORTS_LOCK, 0}}, {0xAC, 1, X86InstInfo{"SHRD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 1}}, - {0xAD, 1, X86InstInfo{"SHRD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_SRC_RCX | FLAGS_NO_OVERLAY, 0}}, + {0xAD, 1, X86InstInfo{"SHRD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0}}, {0xAE, 1, X86InstInfo{"", TYPE_GROUP_15, FLAGS_NO_OVERLAY, 0}}, {0xAF, 1, X86InstInfo{"IMUL", TYPE_INST, FLAGS_MODRM | FLAGS_NO_OVERLAY, 0}}, diff --git a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h index f5981529d..915a0bf29 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h +++ b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h @@ -356,8 +356,7 @@ namespace InstFlags { // Non-XMM subflags constexpr InstFlagType FLAGS_SF_DST_RAX = (1ULL << 11); - // subflag [13:12] unused - constexpr InstFlagType FLAGS_SF_SRC_RCX = (1ULL << 14); + // subflag [14:12] unused constexpr InstFlagType FLAGS_SF_REX_IN_BYTE = (1ULL << 15); // XMM subflags