From 130dcb17045654fa89188aca911619fbfa9b31f5 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 17:54:18 -0800 Subject: [PATCH 01/12] HarnessHelper: Ensure placement of greg offsets --- Source/Tests/HarnessHelpers.h | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/Source/Tests/HarnessHelpers.h b/Source/Tests/HarnessHelpers.h index 2f035da1d..21b4dc502 100644 --- a/Source/Tests/HarnessHelpers.h +++ b/Source/Tests/HarnessHelpers.h @@ -201,22 +201,22 @@ namespace FEX::HarnessHelper { if (BaseConfig.OptionRegDataCount > 0) { static constexpr std::array OffsetArrayAVX = {{ offsetof(FEXCore::Core::CPUState, rip), - offsetof(FEXCore::Core::CPUState, gregs[0]), - offsetof(FEXCore::Core::CPUState, gregs[1]), - offsetof(FEXCore::Core::CPUState, gregs[2]), - offsetof(FEXCore::Core::CPUState, gregs[3]), - offsetof(FEXCore::Core::CPUState, gregs[4]), - offsetof(FEXCore::Core::CPUState, gregs[5]), - offsetof(FEXCore::Core::CPUState, gregs[6]), - offsetof(FEXCore::Core::CPUState, gregs[7]), - offsetof(FEXCore::Core::CPUState, gregs[8]), - offsetof(FEXCore::Core::CPUState, gregs[9]), - offsetof(FEXCore::Core::CPUState, gregs[10]), - offsetof(FEXCore::Core::CPUState, gregs[11]), - offsetof(FEXCore::Core::CPUState, gregs[12]), - offsetof(FEXCore::Core::CPUState, gregs[13]), - offsetof(FEXCore::Core::CPUState, gregs[14]), - offsetof(FEXCore::Core::CPUState, gregs[15]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RAX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RBX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RBP]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R8]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R9]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R10]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R11]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R12]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R13]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R14]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R15]), offsetof(FEXCore::Core::CPUState, xmm.avx.data[0][0]), offsetof(FEXCore::Core::CPUState, xmm.avx.data[1][0]), offsetof(FEXCore::Core::CPUState, xmm.avx.data[2][0]), @@ -248,22 +248,22 @@ namespace FEX::HarnessHelper { }}; static constexpr std::array OffsetArraySSE = {{ offsetof(FEXCore::Core::CPUState, rip), - offsetof(FEXCore::Core::CPUState, gregs[0]), - offsetof(FEXCore::Core::CPUState, gregs[1]), - offsetof(FEXCore::Core::CPUState, gregs[2]), - offsetof(FEXCore::Core::CPUState, gregs[3]), - offsetof(FEXCore::Core::CPUState, gregs[4]), - offsetof(FEXCore::Core::CPUState, gregs[5]), - offsetof(FEXCore::Core::CPUState, gregs[6]), - offsetof(FEXCore::Core::CPUState, gregs[7]), - offsetof(FEXCore::Core::CPUState, gregs[8]), - offsetof(FEXCore::Core::CPUState, gregs[9]), - offsetof(FEXCore::Core::CPUState, gregs[10]), - offsetof(FEXCore::Core::CPUState, gregs[11]), - offsetof(FEXCore::Core::CPUState, gregs[12]), - offsetof(FEXCore::Core::CPUState, gregs[13]), - offsetof(FEXCore::Core::CPUState, gregs[14]), - offsetof(FEXCore::Core::CPUState, gregs[15]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RAX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RBX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDX]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RBP]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R8]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R9]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R10]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R11]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R12]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R13]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R14]), + offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_R15]), offsetof(FEXCore::Core::CPUState, xmm.sse.data[0][0]), offsetof(FEXCore::Core::CPUState, xmm.sse.data[1][0]), offsetof(FEXCore::Core::CPUState, xmm.sse.data[2][0]), From a5cc2536cb0e61ceac2b1af543abe43383fd5fa1 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 17:54:56 -0800 Subject: [PATCH 02/12] X86Enums: Sort GPRs by their encoding order. --- External/FEXCore/include/FEXCore/Core/X86Enums.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/External/FEXCore/include/FEXCore/Core/X86Enums.h b/External/FEXCore/include/FEXCore/Core/X86Enums.h index 545fe654d..bfbe4821c 100644 --- a/External/FEXCore/include/FEXCore/Core/X86Enums.h +++ b/External/FEXCore/include/FEXCore/Core/X86Enums.h @@ -8,13 +8,13 @@ namespace FEXCore::X86State { * @{ */ enum X86Reg : uint32_t { REG_RAX = 0, - REG_RBX = 1, - REG_RCX = 2, - REG_RDX = 3, - REG_RSI = 4, - REG_RDI = 5, - REG_RBP = 6, - REG_RSP = 7, + REG_RCX = 1, + REG_RDX = 2, + REG_RBX = 3, + REG_RSP = 4, + REG_RBP = 5, + REG_RSI = 6, + REG_RDI = 7, REG_R8 = 8, REG_R9 = 9, REG_R10 = 10, From 47bd119c9c258b0ffc981f0e092dd59b108eec97 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:24:20 -0800 Subject: [PATCH 03/12] OpDispatcher: Fix MOVSeg from previous reordering --- .../Interface/Core/OpcodeDispatcher.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index de77e1316..70338bb8b 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1613,17 +1613,17 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { OrderedNode *Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], 2, Op->Flags, -1); switch (Op->Dest.Data.GPR.GPR) { - case 0: // ES + case FEXCore::X86State::REG_RAX: // ES case FEXCore::X86State::REG_R8: // ES _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, es_idx)); UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX); break; - case 1: // DS + case FEXCore::X86State::REG_RBX: // DS case FEXCore::X86State::REG_R11: // DS _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, ds_idx)); UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); break; - case 2: // CS + case FEXCore::X86State::REG_RCX: // CS case FEXCore::X86State::REG_R9: // CS // CPL3 can't write to this _Break(FEXCore::IR::BreakDefinition { @@ -1633,12 +1633,12 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { .si_code = 0, }); break; - case 3: // SS + case FEXCore::X86State::REG_RDX: // SS case FEXCore::X86State::REG_R10: // SS _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, ss_idx)); UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_SS_PREFIX); break; - case 6: // GS + case FEXCore::X86State::REG_RBP: // GS case FEXCore::X86State::REG_R13: // GS if (!CTX->Config.Is64BitMode) { _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, gs_idx)); @@ -1648,7 +1648,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { DecodeFailure = true; } break; - case 7: // FS + case FEXCore::X86State::REG_RSP: // FS case FEXCore::X86State::REG_R12: // FS if (!CTX->Config.Is64BitMode) { _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, fs_idx)); @@ -1668,23 +1668,23 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { OrderedNode *Segment{}; switch (Op->Src[0].Data.GPR.GPR) { - case 0: // ES + case FEXCore::X86State::REG_RAX: // ES case FEXCore::X86State::REG_R8: // ES Segment = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, es_idx)); break; - case 1: // DS + case FEXCore::X86State::REG_RBX: // DS case FEXCore::X86State::REG_R11: // DS Segment = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, ds_idx)); break; - case 2: // CS + case FEXCore::X86State::REG_RCX: // CS case FEXCore::X86State::REG_R9: // CS Segment = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, cs_idx)); break; - case 3: // SS + case FEXCore::X86State::REG_RDX: // SS case FEXCore::X86State::REG_R10: // SS Segment = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, ss_idx)); break; - case 6: // GS + case FEXCore::X86State::REG_RBP: // GS case FEXCore::X86State::REG_R13: // GS if (CTX->Config.Is64BitMode) { Segment = _Constant(0); @@ -1693,7 +1693,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { Segment = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, gs_idx)); } break; - case 7: // FS + case FEXCore::X86State::REG_RSP: // FS case FEXCore::X86State::REG_R12: // FS if (CTX->Config.Is64BitMode) { Segment = _Constant(0); From 2866dda73f3a1b45e7da67aae4343c469968c55b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:24:36 -0800 Subject: [PATCH 04/12] Frontend: Optimize MapModRMToReg and MapVEXToReg --- .../Source/Interface/Core/Frontend.cpp | 126 ++---------------- 1 file changed, 14 insertions(+), 112 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index e436b0619..ad2a911b8 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -32,26 +32,6 @@ using namespace FEXCore::X86Tables; static uint32_t MapModRMToReg(uint8_t REX, uint8_t bits, bool HighBits, bool HasREX, bool HasXMM, bool HasMM, uint8_t InvalidOffset = 16) { using GPRArray = std::array; - static constexpr GPRArray GPRIndexes = { - // Classical ordering? - FEXCore::X86State::REG_RAX, - FEXCore::X86State::REG_RCX, - FEXCore::X86State::REG_RDX, - FEXCore::X86State::REG_RBX, - FEXCore::X86State::REG_RSP, - FEXCore::X86State::REG_RBP, - FEXCore::X86State::REG_RSI, - FEXCore::X86State::REG_RDI, - FEXCore::X86State::REG_R8, - FEXCore::X86State::REG_R9, - FEXCore::X86State::REG_R10, - FEXCore::X86State::REG_R11, - FEXCore::X86State::REG_R12, - FEXCore::X86State::REG_R13, - FEXCore::X86State::REG_R14, - FEXCore::X86State::REG_R15, - }; - static constexpr GPRArray GPR8BitHighIndexes = { // Classical ordering? FEXCore::X86State::REG_RAX, @@ -72,108 +52,30 @@ static uint32_t MapModRMToReg(uint8_t REX, uint8_t bits, bool HighBits, bool Has FEXCore::X86State::REG_R15, }; - static constexpr GPRArray XMMIndexes = { - FEXCore::X86State::REG_XMM_0, - FEXCore::X86State::REG_XMM_1, - FEXCore::X86State::REG_XMM_2, - FEXCore::X86State::REG_XMM_3, - FEXCore::X86State::REG_XMM_4, - FEXCore::X86State::REG_XMM_5, - FEXCore::X86State::REG_XMM_6, - FEXCore::X86State::REG_XMM_7, - FEXCore::X86State::REG_XMM_8, - FEXCore::X86State::REG_XMM_9, - FEXCore::X86State::REG_XMM_10, - FEXCore::X86State::REG_XMM_11, - FEXCore::X86State::REG_XMM_12, - FEXCore::X86State::REG_XMM_13, - FEXCore::X86State::REG_XMM_14, - FEXCore::X86State::REG_XMM_15, - }; - - static constexpr GPRArray MMIndexes = { - FEXCore::X86State::REG_MM_0, - FEXCore::X86State::REG_MM_1, - FEXCore::X86State::REG_MM_2, - FEXCore::X86State::REG_MM_3, - FEXCore::X86State::REG_MM_4, - FEXCore::X86State::REG_MM_5, - FEXCore::X86State::REG_MM_6, - FEXCore::X86State::REG_MM_7, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID, - FEXCore::X86State::REG_INVALID - }; - - const GPRArray *GPRs = &GPRIndexes; - if (HasXMM) { - GPRs = &XMMIndexes; - } - else if (HasMM) { - GPRs = &MMIndexes; - } - else if (HighBits && !HasREX) { - GPRs = &GPR8BitHighIndexes; - } - uint8_t Offset = (REX << 3) | bits; if (Offset == InvalidOffset) { return FEXCore::X86State::REG_INVALID; } - return (*GPRs)[(REX << 3) | bits]; + + if (HasXMM) { + return FEXCore::X86State::REG_XMM_0 + Offset; + } + else if (HasMM) { + return FEXCore::X86State::REG_MM_0 + Offset; + } + else if (!(HighBits && !HasREX)) { + return FEXCore::X86State::REG_RAX + Offset; + } + + return GPR8BitHighIndexes[Offset]; } static uint32_t MapVEXToReg(uint8_t vvvv, bool HasXMM) { - using GPRArray = std::array; - - static constexpr GPRArray GPRIndexes = { - FEXCore::X86State::REG_RAX, - FEXCore::X86State::REG_RCX, - FEXCore::X86State::REG_RDX, - FEXCore::X86State::REG_RBX, - FEXCore::X86State::REG_RSP, - FEXCore::X86State::REG_RBP, - FEXCore::X86State::REG_RSI, - FEXCore::X86State::REG_RDI, - FEXCore::X86State::REG_R8, - FEXCore::X86State::REG_R9, - FEXCore::X86State::REG_R10, - FEXCore::X86State::REG_R11, - FEXCore::X86State::REG_R12, - FEXCore::X86State::REG_R13, - FEXCore::X86State::REG_R14, - FEXCore::X86State::REG_R15, - }; - - static constexpr GPRArray XMMIndexes = { - FEXCore::X86State::REG_XMM_0, - FEXCore::X86State::REG_XMM_1, - FEXCore::X86State::REG_XMM_2, - FEXCore::X86State::REG_XMM_3, - FEXCore::X86State::REG_XMM_4, - FEXCore::X86State::REG_XMM_5, - FEXCore::X86State::REG_XMM_6, - FEXCore::X86State::REG_XMM_7, - FEXCore::X86State::REG_XMM_8, - FEXCore::X86State::REG_XMM_9, - FEXCore::X86State::REG_XMM_10, - FEXCore::X86State::REG_XMM_11, - FEXCore::X86State::REG_XMM_12, - FEXCore::X86State::REG_XMM_13, - FEXCore::X86State::REG_XMM_14, - FEXCore::X86State::REG_XMM_15, - }; - if (HasXMM) { - return XMMIndexes[vvvv]; + return FEXCore::X86State::REG_XMM_0 + vvvv; } else { - return GPRIndexes[vvvv]; + return FEXCore::X86State::REG_RAX + vvvv; } } From c98816b35022da4f391d745b7091866ed97a5585 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:26:14 -0800 Subject: [PATCH 05/12] OpDispatcher: Make ReadByte check only happen with assertions enabled. --- External/FEXCore/Source/Interface/Core/Frontend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index ad2a911b8..469c004ef 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -108,7 +108,7 @@ uint64_t Decoder::ReadData(uint8_t Size) { uint64_t Res = 0; std::memcpy(&Res, &InstStream[InstructionSize], Size); -#ifndef NDEBUG +#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED for(size_t i = 0; i < Size; ++i) { ReadByte(); } From c61ce1fe1194289ce11356112a00d3b3f598db8e Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:26:51 -0800 Subject: [PATCH 06/12] Frontend: Remove unnecessary checks --- External/FEXCore/Source/Interface/Core/Frontend.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index 469c004ef..95d3aa17e 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -286,12 +286,6 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, DecodeInst->OP = Op; DecodeInst->TableInfo = Info; - // XXX: Once we support 32bit x86 then this will be necessary to support - if (Info->Type == FEXCore::X86Tables::TYPE_LEGACY_PREFIX) { - LogMan::Msg::DFmt("Legacy Prefix"); - return false; - } - if (Info->Type == FEXCore::X86Tables::TYPE_UNKNOWN) { LogMan::Msg::DFmt("Unknown instruction: {} 0x{:04x} 0x{:x}", Info->Name ?: "UND", Op, DecodeInst->PC); return false; @@ -586,12 +580,6 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16 DecodeInst->OP = Op; DecodeInst->TableInfo = Info; - // XXX: Once we support 32bit x86 then this will be necessary to support - if (Info->Type == FEXCore::X86Tables::TYPE_LEGACY_PREFIX) { - LogMan::Msg::DFmt("Legacy Prefix"); - return false; - } - if (Info->Type == FEXCore::X86Tables::TYPE_UNKNOWN) { LogMan::Msg::DFmt("Unknown instruction: {} 0x{:04x} 0x{:x}", Info->Name ?: "UND", Op, DecodeInst->PC); return false; From a065849e39f5526ef1b4809078649eeff831a317 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:27:27 -0800 Subject: [PATCH 07/12] Frontend: Only add contained code pages at the end --- External/FEXCore/Source/Interface/Core/Frontend.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index 95d3aa17e..c494e0569 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -1130,19 +1130,14 @@ void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC, auto OpMinPage = OpMinAddress & FHU::FEX_PAGE_MASK; auto OpMaxPage = OpMaxAddress & FHU::FEX_PAGE_MASK; - if (OpMinPage != CurrentCodePage) { CurrentCodePage = OpMinPage; - if (CodePages.insert(CurrentCodePage).second) { - AddContainedCodePage(PC, CurrentCodePage, FHU::FEX_PAGE_SIZE); - } + CodePages.insert(CurrentCodePage); } if (OpMaxPage != CurrentCodePage) { CurrentCodePage = OpMaxPage; - if (CodePages.insert(CurrentCodePage).second) { - AddContainedCodePage(PC, CurrentCodePage, FHU::FEX_PAGE_SIZE); - } + CodePages.insert(CurrentCodePage); } bool ErrorDuringDecoding = !DecodeInstruction(RIPToDecode + PCOffset); @@ -1204,6 +1199,9 @@ void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC, CurrentBlockDecoding.DecodedInstructions = &DecodedBuffer[BlockStartOffset]; } + for (auto CodePage : CodePages) { + AddContainedCodePage(PC, CodePage, FHU::FEX_PAGE_SIZE); + } // sort for better branching std::sort(Blocks.begin(), Blocks.end(), [](const FEXCore::Frontend::Decoder::DecodedBlocks& a, const FEXCore::Frontend::Decoder::DecodedBlocks& b) { From ed0d46e51aece6026dd1b52c35a36dc5ee15b8db Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:28:48 -0800 Subject: [PATCH 08/12] Frontend: Optimize NormalOp to most likely pick a NormalOp. It's the most common. --- External/FEXCore/Source/Interface/Core/Frontend.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index c494e0569..07cb1f859 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -593,7 +593,11 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16 LOGMAN_THROW_AA_FMT(Info->Type != FEXCore::X86Tables::TYPE_REX_PREFIX, "REX PREFIX should have been decoded before this!"); - if (Info->Type >= FEXCore::X86Tables::TYPE_GROUP_1 && + // A normal instruction is the most likely. + if (Info->Type == FEXCore::X86Tables::TYPE_INST) [[likely]] { + return NormalOp(Info, Op); + } + else if (Info->Type >= FEXCore::X86Tables::TYPE_GROUP_1 && Info->Type <= FEXCore::X86Tables::TYPE_GROUP_11) { uint8_t ModRMByte = ReadByte(); DecodeInst->ModRM = ModRMByte; @@ -741,7 +745,8 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16 return NormalOp(&EVEXTableOps[EVEXOp], EVEXOp); } - return NormalOp(Info, Op); + LOGMAN_MSG_A_FMT("Invalid instruction decoding type"); + FEX_UNREACHABLE; } bool Decoder::DecodeInstruction(uint64_t PC) { From 30dc92cdfd27a7e313491a80349a40132afed311 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:29:37 -0800 Subject: [PATCH 09/12] Frontend: Set Is8Bit{Dest,Src} immediately rather than query flags after the fact. --- .../FEXCore/Source/Interface/Core/Frontend.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index 07cb1f859..5bf1afc53 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -325,6 +325,14 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, const bool Has16BitAddressing = !CTX->Config.Is64BitMode && DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE; + // This is used for ModRM register modification + // For both modrm.reg and modrm.rm(when mod == 0b11) when value is >= 0b100 + // then it changes from expected registers to the high 8bits of the lower registers + // Bit annoying to support + // In the case of no modrm (REX in byte situation) then it is unaffected + bool Is8BitSrc{}; + bool Is8BitDest{}; + // If we require ModRM and haven't decoded it yet, do it now // Some instructions have to read modrm upfront, others do it later if (HasMODRM && !DecodeInst->DecodedModRM) { @@ -341,6 +349,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, if (DstSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_8BIT) { DecodeInst->Flags |= DecodeFlags::GenSizeDstSize(DecodeFlags::SIZE_8BIT); DestSize = 1; + Is8BitDest = true; } else if (DstSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_16BIT) { DecodeInst->Flags |= DecodeFlags::GenSizeDstSize(DecodeFlags::SIZE_16BIT); @@ -383,6 +392,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, // Decode sources if (SrcSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_8BIT) { DecodeInst->Flags |= DecodeFlags::GenSizeSrcSize(DecodeFlags::SIZE_8BIT); + Is8BitSrc = true; } else if (SrcSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_16BIT) { DecodeInst->Flags |= DecodeFlags::GenSizeSrcSize(DecodeFlags::SIZE_16BIT); @@ -416,14 +426,6 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, } } - // This is used for ModRM register modification - // For both modrm.reg and modrm.rm(when mod == 0b11) when value is >= 0b100 - // then it changes from expected registers to the high 8bits of the lower registers - // Bit annoying to support - // In the case of no modrm (REX in byte situation) then it is unaffected - const bool Is8BitSrc = (DecodeFlags::GetSizeSrcFlags(DecodeInst->Flags) == DecodeFlags::SIZE_8BIT); - const bool Is8BitDest = (DecodeFlags::GetSizeDstFlags(DecodeInst->Flags) == DecodeFlags::SIZE_8BIT); - auto *CurrentDest = &DecodeInst->Dest; if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_DST_RAX) || From b9fedfff7c731f99fb727b3180f45e5e53924dc4 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:31:24 -0800 Subject: [PATCH 10/12] Frontend: Optimize that Dst RAX/RCX and REX in byte is mutually exclusive. --- External/FEXCore/Source/Interface/Core/Frontend.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index 5bf1afc53..b22319ff5 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -436,8 +436,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, CurrentDest->Data.GPR.GPR = HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_DST_RAX) ? FEXCore::X86State::REG_RAX : FEXCore::X86State::REG_RDX; CurrentDest = &DecodeInst->Src[0]; } - - if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_REX_IN_BYTE)) { + else if (HAS_NON_XMM_SUBFLAG(Info->Flags, FEXCore::X86Tables::InstFlags::FLAGS_SF_REX_IN_BYTE)) { LOGMAN_THROW_AA_FMT(!HasMODRM, "This instruction shouldn't have ModRM!"); // If the REX is in the byte that means the lower nibble of the OP contains the destination GPR From 7696641b4ccc808c7a1f203184266747a825875b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 18:32:15 -0800 Subject: [PATCH 11/12] Frontend: Add some switch statement hints for most command paths. --- .../Source/Interface/Core/Frontend.cpp | 177 +++++++++--------- 1 file changed, 89 insertions(+), 88 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index b22319ff5..c74fec855 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -766,105 +766,106 @@ bool Decoder::DecodeInstruction(uint64_t PC) { case 0x0F: {// Escape Op uint8_t EscapeOp = ReadByte(); switch (EscapeOp) { - case 0x0F: [[unlikely]] { // 3DNow! - // 3DNow! Instruction Encoding: 0F 0F [ModRM] [SIB] [Displacement] [Opcode] - // Decode ModRM - uint8_t ModRMByte = ReadByte(); - DecodeInst->ModRM = ModRMByte; - DecodeInst->DecodedModRM = true; + case 0x0F: [[unlikely]] { // 3DNow! + // 3DNow! Instruction Encoding: 0F 0F [ModRM] [SIB] [Displacement] [Opcode] + // Decode ModRM + uint8_t ModRMByte = ReadByte(); + DecodeInst->ModRM = ModRMByte; + DecodeInst->DecodedModRM = true; - FEXCore::X86Tables::ModRMDecoded ModRM; - ModRM.Hex = DecodeInst->ModRM; + FEXCore::X86Tables::ModRMDecoded ModRM; + ModRM.Hex = DecodeInst->ModRM; - const bool Has16BitAddressing = !CTX->Config.Is64BitMode && - DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE; + const bool Has16BitAddressing = !CTX->Config.Is64BitMode && + DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE; - // All 3DNow! instructions have the second argument as the rm handler - // We need to decode it upfront to get the displacement out of the way - if (ModRM.mod != 0b11) { - auto Disp = DecodeModRMs_Disp[Has16BitAddressing]; - (this->*Disp)(&DecodeInst->Src[0], ModRM); + // All 3DNow! instructions have the second argument as the rm handler + // We need to decode it upfront to get the displacement out of the way + if (ModRM.mod != 0b11) { + auto Disp = DecodeModRMs_Disp[Has16BitAddressing]; + (this->*Disp)(&DecodeInst->Src[0], ModRM); + } + + // Take a peek at the op just past the displacement + uint8_t LocalOp = ReadByte(); + return NormalOpHeader(&FEXCore::X86Tables::DDDNowOps[LocalOp], LocalOp); + break; } + case 0x38: { // F38 Table! + constexpr uint16_t PF_38_NONE = 0; + constexpr uint16_t PF_38_66 = (1U << 0); + constexpr uint16_t PF_38_F2 = (1U << 1); + constexpr uint16_t PF_38_F3 = (1U << 2); - // Take a peek at the op just past the displacement - uint8_t LocalOp = ReadByte(); - return NormalOpHeader(&FEXCore::X86Tables::DDDNowOps[LocalOp], LocalOp); - break; - } - case 0x38: { // F38 Table! - constexpr uint16_t PF_38_NONE = 0; - constexpr uint16_t PF_38_66 = (1U << 0); - constexpr uint16_t PF_38_F2 = (1U << 1); - constexpr uint16_t PF_38_F3 = (1U << 2); + uint16_t Prefix = PF_38_NONE; + if (DecodeInst->Flags & DecodeFlags::FLAG_OPERAND_SIZE) { + Prefix |= PF_38_66; + } + if (DecodeInst->Flags & DecodeFlags::FLAG_REPNE_PREFIX) { + Prefix |= PF_38_F2; + } + if (DecodeInst->Flags & DecodeFlags::FLAG_REP_PREFIX) { + Prefix |= PF_38_F3; + } - uint16_t Prefix = PF_38_NONE; - if (DecodeInst->Flags & DecodeFlags::FLAG_OPERAND_SIZE) { - Prefix |= PF_38_66; - } - if (DecodeInst->Flags & DecodeFlags::FLAG_REPNE_PREFIX) { - Prefix |= PF_38_F2; - } - if (DecodeInst->Flags & DecodeFlags::FLAG_REP_PREFIX) { - Prefix |= PF_38_F3; + uint16_t LocalOp = (Prefix << 8) | ReadByte(); + return NormalOpHeader(&FEXCore::X86Tables::H0F38TableOps[LocalOp], LocalOp); + break; } + case 0x3A: { // F3A Table! + constexpr uint16_t PF_3A_NONE = 0; + constexpr uint16_t PF_3A_66 = (1 << 0); + constexpr uint16_t PF_3A_REX = (1 << 1); - uint16_t LocalOp = (Prefix << 8) | ReadByte(); - return NormalOpHeader(&FEXCore::X86Tables::H0F38TableOps[LocalOp], LocalOp); - break; - } - case 0x3A: { // F3A Table! - constexpr uint16_t PF_3A_NONE = 0; - constexpr uint16_t PF_3A_66 = (1 << 0); - constexpr uint16_t PF_3A_REX = (1 << 1); + uint16_t Prefix = PF_3A_NONE; + if (DecodeInst->LastEscapePrefix == 0x66) // Operand Size + Prefix = PF_3A_66; - uint16_t Prefix = PF_3A_NONE; - if (DecodeInst->LastEscapePrefix == 0x66) // Operand Size - Prefix = PF_3A_66; + if (DecodeInst->Flags & DecodeFlags::FLAG_REX_WIDENING) + Prefix |= PF_3A_REX; - if (DecodeInst->Flags & DecodeFlags::FLAG_REX_WIDENING) - Prefix |= PF_3A_REX; + uint16_t LocalOp = (Prefix << 8) | ReadByte(); + return NormalOpHeader(&FEXCore::X86Tables::H0F3ATableOps[LocalOp], LocalOp); + break; + } + default: [[likely]] { // Two byte table! + // x86-64 abuses three legacy prefixes to extend the table encodings + // 0x66 - Operand Size prefix + // 0xF2 - REPNE prefix + // 0xF3 - REP prefix + // If any of these three prefixes are used then it falls down the subtable + // Additionally: If you hit repeat of differnt prefixes then only the LAST one before this one works for subtable selection - uint16_t LocalOp = (Prefix << 8) | ReadByte(); - return NormalOpHeader(&FEXCore::X86Tables::H0F3ATableOps[LocalOp], LocalOp); - break; - } - default: // Two byte table! - // x86-64 abuses three legacy prefixes to extend the table encodings - // 0x66 - Operand Size prefix - // 0xF2 - REPNE prefix - // 0xF3 - REP prefix - // If any of these three prefixes are used then it falls down the subtable - // Additionally: If you hit repeat of differnt prefixes then only the LAST one before this one works for subtable selection + bool NoOverlay = (FEXCore::X86Tables::SecondBaseOps[EscapeOp].Flags & InstFlags::FLAGS_NO_OVERLAY) != 0; + bool NoOverlay66 = (FEXCore::X86Tables::SecondBaseOps[EscapeOp].Flags & InstFlags::FLAGS_NO_OVERLAY66) != 0; - bool NoOverlay = (FEXCore::X86Tables::SecondBaseOps[EscapeOp].Flags & InstFlags::FLAGS_NO_OVERLAY) != 0; - bool NoOverlay66 = (FEXCore::X86Tables::SecondBaseOps[EscapeOp].Flags & InstFlags::FLAGS_NO_OVERLAY66) != 0; - - if (NoOverlay) { // This section of the table ignores prefix extention - return NormalOpHeader(&FEXCore::X86Tables::SecondBaseOps[EscapeOp], EscapeOp); + if (NoOverlay) { // This section of the table ignores prefix extention + return NormalOpHeader(&FEXCore::X86Tables::SecondBaseOps[EscapeOp], EscapeOp); + } + else if (DecodeInst->LastEscapePrefix == 0xF3) { // REP + // Remove prefix so it doesn't effect calculations. + // This is only an escape prefix rather tan modifier now + DecodeInst->Flags &= ~DecodeFlags::FLAG_REP_PREFIX; + return NormalOpHeader(&FEXCore::X86Tables::RepModOps[EscapeOp], EscapeOp); + } + else if (DecodeInst->LastEscapePrefix == 0xF2) { // REPNE + // Remove prefix so it doesn't effect calculations. + // This is only an escape prefix rather tan modifier now + DecodeInst->Flags &= ~DecodeFlags::FLAG_REPNE_PREFIX; + return NormalOpHeader(&FEXCore::X86Tables::RepNEModOps[EscapeOp], EscapeOp); + } + else if (DecodeInst->LastEscapePrefix == 0x66 && !NoOverlay66) { // Operand Size + // Remove prefix so it doesn't effect calculations. + // This is only an escape prefix rather tan modifier now + DecodeInst->Flags &= ~DecodeFlags::FLAG_OPERAND_SIZE; + DecodeFlags::PopOpAddrIf(&DecodeInst->Flags, DecodeFlags::FLAG_OPERAND_SIZE_LAST); + return NormalOpHeader(&FEXCore::X86Tables::OpSizeModOps[EscapeOp], EscapeOp); + } + else { + return NormalOpHeader(&FEXCore::X86Tables::SecondBaseOps[EscapeOp], EscapeOp); + } + break; } - else if (DecodeInst->LastEscapePrefix == 0xF3) { // REP - // Remove prefix so it doesn't effect calculations. - // This is only an escape prefix rather tan modifier now - DecodeInst->Flags &= ~DecodeFlags::FLAG_REP_PREFIX; - return NormalOpHeader(&FEXCore::X86Tables::RepModOps[EscapeOp], EscapeOp); - } - else if (DecodeInst->LastEscapePrefix == 0xF2) { // REPNE - // Remove prefix so it doesn't effect calculations. - // This is only an escape prefix rather tan modifier now - DecodeInst->Flags &= ~DecodeFlags::FLAG_REPNE_PREFIX; - return NormalOpHeader(&FEXCore::X86Tables::RepNEModOps[EscapeOp], EscapeOp); - } - else if (DecodeInst->LastEscapePrefix == 0x66 && !NoOverlay66) { // Operand Size - // Remove prefix so it doesn't effect calculations. - // This is only an escape prefix rather tan modifier now - DecodeInst->Flags &= ~DecodeFlags::FLAG_OPERAND_SIZE; - DecodeFlags::PopOpAddrIf(&DecodeInst->Flags, DecodeFlags::FLAG_OPERAND_SIZE_LAST); - return NormalOpHeader(&FEXCore::X86Tables::OpSizeModOps[EscapeOp], EscapeOp); - } - else { - return NormalOpHeader(&FEXCore::X86Tables::SecondBaseOps[EscapeOp], EscapeOp); - } - break; } break; } @@ -917,7 +918,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) { case 0x65: // GS prefix DecodeInst->Flags |= DecodeFlags::FLAG_GS_PREFIX; break; - default: { // Default base table + default: [[likely]] { // Default base table auto Info = &FEXCore::X86Tables::BaseOps[Op]; if (Info->Type == FEXCore::X86Tables::TYPE_REX_PREFIX) { @@ -1148,7 +1149,7 @@ void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC, bool ErrorDuringDecoding = !DecodeInstruction(RIPToDecode + PCOffset); - if (ErrorDuringDecoding) { + if (ErrorDuringDecoding) [[unlikely]] { LogMan::Msg::DFmt("Couldn't Decode something at 0x{:x}, Started at 0x{:x}", RIPToDecode + PCOffset, PC); // Put an invalid instruction in the stream so the core can raise SIGILL if hit CurrentBlockDecoding.HasInvalidInstruction = true; From b57a8ac08661c9f5f57d0c8f27d4a92ec6dcd087 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Jan 2023 19:35:12 -0800 Subject: [PATCH 12/12] IR: Update tests for new GPR offsets --- unittests/IR/Basic/Sbfe.ir | 8 ++++---- unittests/IR/Correctness/AddTruncate.ir | 6 +++--- unittests/IR/Correctness/LeftShiftTruncate.ir | 6 +++--- unittests/IR/Correctness/SubTruncate.ir | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/unittests/IR/Basic/Sbfe.ir b/unittests/IR/Basic/Sbfe.ir index b19dc199a..33089fd08 100644 --- a/unittests/IR/Basic/Sbfe.ir +++ b/unittests/IR/Basic/Sbfe.ir @@ -26,17 +26,17 @@ %Res1 i64 = Sbfe #0x8, #0x0, %Val (%Store1 i64) StoreRegister %Res1 i64, #0, #8, GPR, GPRFixed, #8 %Res2 i64 = Sbfe #0x10, #0x0, %Val - (%Store2 i64) StoreRegister %Res2 i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store2 i64) StoreRegister %Res2 i64, #0, #0x20, GPR, GPRFixed, #8 %Res3 i64 = Sbfe #0x20, #0x0, %Val - (%Store3 i64) StoreRegister %Res3 i64, #0, #0x18, GPR, GPRFixed, #8 + (%Store3 i64) StoreRegister %Res3 i64, #0, #0x10, GPR, GPRFixed, #8 %Addr2 i64 = Constant #0x1000008 ; Test non special width %Val2 i64 = LoadMem GPR, #8, %Addr2 i64, %Invalid, #8, SXTX, #1 %Res4 i64 = Sbfe #0x6, #0x0, %Val2 - (%Store4 i64) StoreRegister %Res4 i64, #0, #0x20, GPR, GPRFixed, #8 + (%Store4 i64) StoreRegister %Res4 i64, #0, #0x18, GPR, GPRFixed, #8 ; Test with + shift %Res5 i64 = Sbfe #0x4, #0x2, %Val2 - (%Store5 i64) StoreRegister %Res5 i64, #0, #0x28, GPR, GPRFixed, #8 + (%Store5 i64) StoreRegister %Res5 i64, #0, #0x38, GPR, GPRFixed, #8 (%brk i0) Break {0.11.0.128} (%end i0) EndBlock %ssa2 diff --git a/unittests/IR/Correctness/AddTruncate.ir b/unittests/IR/Correctness/AddTruncate.ir index 9b0cfa56d..0dbceb44e 100644 --- a/unittests/IR/Correctness/AddTruncate.ir +++ b/unittests/IR/Correctness/AddTruncate.ir @@ -27,13 +27,13 @@ %ResultB i64 = Add %MemValueA, %MemValueB (%Store i64) StoreRegister %ResultA i64, #0, #0x8, GPR, GPRFixed, #8 - (%Store i64) StoreRegister %ResultB i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultB i64, #0, #0x20, GPR, GPRFixed, #8 ; Constant optimisable version %ValueC i64 = Constant #0xaaaaaaaaaaaaaaa8 %ValueD i64 = Constant #0x5555555555555551 %ResultC i32 = Add %ValueC, %ValueD %ResultD i64 = Add %ValueC, %ValueD - (%Store i64) StoreRegister %ResultC i64, #0, #0x18, GPR, GPRFixed, #8 - (%Store i64) StoreRegister %ResultD i64, #0, #0x20, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultC i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultD i64, #0, #0x18, GPR, GPRFixed, #8 (%ssa7 i0) Break {0.11.0.128} (%ssa12 i0) EndBlock %ssa2 diff --git a/unittests/IR/Correctness/LeftShiftTruncate.ir b/unittests/IR/Correctness/LeftShiftTruncate.ir index 2c7e0ad6b..334d3ddf9 100644 --- a/unittests/IR/Correctness/LeftShiftTruncate.ir +++ b/unittests/IR/Correctness/LeftShiftTruncate.ir @@ -25,12 +25,12 @@ %ResultA i32 = Lshl %MemValueA, %Shift %ResultB i64 = Lshl %MemValueA, %Shift (%Store i64) StoreRegister %ResultA i64, #0, #0x8, GPR, GPRFixed, #8 - (%Store i64) StoreRegister %ResultB i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultB i64, #0, #0x20, GPR, GPRFixed, #8 ; Constant optimisable version %ValueB i64 = Constant #0x87654321 %ResultC i32 = Lshl %ValueB, %Shift %ResultD i64 = Lshl %ValueB, %Shift - (%Store i64) StoreRegister %ResultC i64, #0, #0x18, GPR, GPRFixed, #8 - (%Store i64) StoreRegister %ResultD i64, #0, #0x20, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultC i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultD i64, #0, #0x18, GPR, GPRFixed, #8 (%ssa7 i0) Break {0.11.0.128} (%ssa12 i0) EndBlock %ssa2 diff --git a/unittests/IR/Correctness/SubTruncate.ir b/unittests/IR/Correctness/SubTruncate.ir index 0afebda94..54c7d6c1f 100644 --- a/unittests/IR/Correctness/SubTruncate.ir +++ b/unittests/IR/Correctness/SubTruncate.ir @@ -26,13 +26,13 @@ %ResultA i32 = Sub %MemValueA, %MemValueB %ResultB i64 = Sub %MemValueA, %MemValueB (%Store i64) StoreRegister %ResultA i64, #0, #0x8, GPR, GPRFixed, #8 - (%Store i64) StoreRegister %ResultB i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultB i64, #0, #0x20, GPR, GPRFixed, #8 ; Constant optimisable version %ValueC i64 = Constant #0xaaaaaaaaaaaaaaa8 %ValueD i64 = Constant #0x5555555555555551 %ResultC i32 = Sub %ValueC, %ValueD %ResultD i64 = Sub %ValueC, %ValueD - (%Store i64) StoreRegister %ResultC i64, #0, #0x18, GPR, GPRFixed, #8 - (%Store i64) StoreRegister %ResultD i64, #0, #0x20, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultC i64, #0, #0x10, GPR, GPRFixed, #8 + (%Store i64) StoreRegister %ResultD i64, #0, #0x18, GPR, GPRFixed, #8 (%ssa7 i0) Break {0.11.0.128} (%ssa12 i0) EndBlock %ssa2