From ec5f3a6854da52f4fc69a9eedec108d45ec88247 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 19 Feb 2020 17:57:28 -0800 Subject: [PATCH] Fixes LEA instruction LEA changes behaviour based on the ordering of the prefixes on the instruction eg: 66 48 8d 3d ffffffff: lea rdi, [rip - 1] 48 66 8d 3d ffffffff: lea di, [rip - 1] So we need to know the order of a few of the prefixes. In the future this should probably be switched to a three deep stack to have the ordering but for now this'll do --- Source/Interface/Core/Frontend.cpp | 5 ++++- Source/Interface/Core/OpcodeDispatcher.cpp | 6 +++--- include/FEXCore/Debug/X86Tables.h | 8 ++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Source/Interface/Core/Frontend.cpp b/Source/Interface/Core/Frontend.cpp index ef73889db..367930938 100644 --- a/Source/Interface/Core/Frontend.cpp +++ b/Source/Interface/Core/Frontend.cpp @@ -743,6 +743,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) { case 0x66: // Operand Size prefix DecodeInst->Flags |= DecodeFlags::FLAG_OPERAND_SIZE; DecodeInst->LastEscapePrefix = Op; + DecodeInst->Flags = (DecodeInst->Flags & ~DecodeFlags::FLAG_OPADDR_MASK) | DecodeFlags::FLAG_OPERAND_SIZE_LAST; break; case 0x67: // Address Size override prefix DecodeInst->Flags |= DecodeFlags::FLAG_ADDRESS_SIZE; @@ -773,8 +774,10 @@ bool Decoder::DecodeInstruction(uint64_t PC) { DecodeInst->Flags |= DecodeFlags::FLAG_REX_PREFIX; // Widening displacement - if (Op & 0b1000) + if (Op & 0b1000) { DecodeInst->Flags |= DecodeFlags::FLAG_REX_WIDENING; + DecodeInst->Flags = (DecodeInst->Flags & ~DecodeFlags::FLAG_OPADDR_MASK) | DecodeFlags::FLAG_WIDENING_SIZE_LAST; + } // XGPR_B bit set if (Op & 0b0001) diff --git a/Source/Interface/Core/OpcodeDispatcher.cpp b/Source/Interface/Core/OpcodeDispatcher.cpp index ea10c45f9..3038e8350 100644 --- a/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/Source/Interface/Core/OpcodeDispatcher.cpp @@ -66,9 +66,9 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) { } void OpDispatchBuilder::LEAOp(OpcodeArgs) { - uint32_t DstSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_OPERAND_SIZE) ? 16 : - (Op->Flags & X86Tables::DecodeFlags::FLAG_REX_WIDENING) ? 64 : 32; - uint32_t SrcSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? 32 : 64; + uint32_t DstSize = X86Tables::DecodeFlags::GetOpAddr(Op->Flags) == X86Tables::DecodeFlags::FLAG_OPERAND_SIZE_LAST ? 2 : + X86Tables::DecodeFlags::GetOpAddr(Op->Flags) == X86Tables::DecodeFlags::FLAG_WIDENING_SIZE_LAST ? 8 : 4; + uint32_t SrcSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? 4 : 8; OrderedNode *Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], SrcSize, Op->Flags, -1, false); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, DstSize, -1); diff --git a/include/FEXCore/Debug/X86Tables.h b/include/FEXCore/Debug/X86Tables.h index d22e8b8f9..023fc726a 100644 --- a/include/FEXCore/Debug/X86Tables.h +++ b/include/FEXCore/Debug/X86Tables.h @@ -42,11 +42,19 @@ constexpr uint32_t SIZE_64BIT = 0b100; constexpr uint32_t SIZE_128BIT = 0b101; constexpr uint32_t SIZE_256BIT = 0b110; +constexpr uint32_t FLAG_OPADDR_OFF = (FLAG_SIZE_SRC_OFF + 3); +constexpr uint32_t FLAG_OPADDR_MASK = (0b11 << FLAG_OPADDR_OFF); + +constexpr uint32_t FLAG_OPERAND_SIZE_LAST = (0b01 << FLAG_OPADDR_OFF); +constexpr uint32_t FLAG_WIDENING_SIZE_LAST = (0b10 << FLAG_OPADDR_OFF); + inline uint32_t GetSizeDstFlags(uint32_t Flags) { return (Flags >> FLAG_SIZE_DST_OFF) & SIZE_MASK; } inline uint32_t GetSizeSrcFlags(uint32_t Flags) { return (Flags >> FLAG_SIZE_SRC_OFF) & SIZE_MASK; } inline uint32_t GenSizeDstSize(uint32_t Size) { return Size << FLAG_SIZE_DST_OFF; } inline uint32_t GenSizeSrcSize(uint32_t Size) { return Size << FLAG_SIZE_SRC_OFF; } + +inline uint32_t GetOpAddr(uint32_t Flags) { return Flags & FLAG_OPADDR_MASK; } } union DecodedOperand {