diff --git a/FEXCore/Source/Interface/Core/Frontend.cpp b/FEXCore/Source/Interface/Core/Frontend.cpp index 710c37937..a829803b8 100644 --- a/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/FEXCore/Source/Interface/Core/Frontend.cpp @@ -501,8 +501,7 @@ Decoder::DecodedBlockStatus Decoder::NormalOp(const FEXCore::X86Tables::X86InstI auto* CurrentDest = &DecodeInst->Dest; - if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_DST_RAX) || - HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_DST_RDX)) { + if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_DST_RAX)) { // Some instructions hardcode their destination as RAX 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 dbb02496c..c27e6cdbe 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1083,8 +1083,7 @@ void OpDispatchBuilder::CQOOp(OpcodeArgs) { Ref Src = LoadSourceGPR(Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); auto Size = OpSizeFromSrc(Op); Ref Upper = _Sbfe(std::max(OpSize::i32Bit, Size), 1, GetSrcBitSize(Op) - 1, Src); - - StoreResultGPR(Op, Upper); + StoreGPRResultWithZExtSemantics(X86State::REG_RDX, Upper, OpSizeFromDst(Op)); } void OpDispatchBuilder::XCHGOp(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 6d4ef0262..f31d4daea 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1510,6 +1510,20 @@ private: void StoreGPRRegister(uint32_t GPR, const Ref Src, IR::OpSize Size = OpSize::iInvalid, uint8_t Offset = 0); void StoreXMMRegister(uint32_t XMM, const Ref Src); + // Matches semantics around GPR storing that matches `StoreResult_WithOpSize` behaviour. + void StoreGPRResultWithZExtSemantics(uint32_t GPR, Ref Src, IR::OpSize OpSize) { + const auto GPRSize = GetGPROpSize(); + + if (GPRSize == OpSize::i64Bit && OpSize == OpSize::i32Bit) { + // If the Source IR op is 64 bits, we need to zext the upper bits + // For all other sizes, the upper bits are guaranteed to already be zero + Src = GetOpSize(Src) == OpSize::i64Bit ? ARef(Src).Bfe(0, 32).Ref() : Src; + StoreGPRRegister(X86State::REG_RDX, Src, GPRSize); + } else { + StoreGPRRegister(X86State::REG_RDX, Src, std::min(GPRSize, OpSize)); + } + } + Ref _GetRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset, bool Inline) { const auto GPRSize = GetGPROpSize(); const auto Offs = Op->PC + Op->InstSize + Offset - Entry; diff --git a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp index f0d4a1d67..8401547d4 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp @@ -323,7 +323,7 @@ const std::array BaseOps = []() consteval { {0x8F, 1, X86InstInfo{"POP", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_MOD_ZERO_REG | FLAGS_DEBUG_MEM_ACCESS, 0}}, {0x90, 8, X86InstInfo{"XCHG", TYPE_INST, FLAGS_SF_REX_IN_BYTE | FLAGS_SF_SRC_RAX, 0}}, {0x98, 1, X86InstInfo{"CDQE", TYPE_INST, FLAGS_SF_DST_RAX | FLAGS_SF_SRC_RAX, 0}}, - {0x99, 1, X86InstInfo{"CQO", TYPE_INST, FLAGS_SF_DST_RDX | FLAGS_SF_SRC_RAX, 0}}, + {0x99, 1, X86InstInfo{"CQO", TYPE_INST, FLAGS_SF_SRC_RAX, 0}}, // These three are all X87 instructions {0x9B, 1, X86InstInfo{"FWAIT", TYPE_INST, FLAGS_NONE, 0}}, diff --git a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h index 97cf38908..436141536 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h +++ b/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h @@ -356,7 +356,7 @@ namespace InstFlags { // Non-XMM subflags constexpr InstFlagType FLAGS_SF_DST_RAX = (1ULL << 11); - constexpr InstFlagType FLAGS_SF_DST_RDX = (1ULL << 12); + // subflag [12] unused constexpr InstFlagType FLAGS_SF_SRC_RAX = (1ULL << 13); constexpr InstFlagType FLAGS_SF_SRC_RCX = (1ULL << 14); constexpr InstFlagType FLAGS_SF_REX_IN_BYTE = (1ULL << 15);