From f7586f4459656d99a59b43c8142366662ec5468f Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 11 Mar 2024 18:35:32 -0400 Subject: [PATCH 1/8] CoreState: use x86 enums for readability Signed-off-by: Alyssa Rosenzweig --- FEXCore/include/FEXCore/Core/CoreState.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FEXCore/include/FEXCore/Core/CoreState.h b/FEXCore/include/FEXCore/Core/CoreState.h index 5d7ab16d4..ae751a0d5 100644 --- a/FEXCore/include/FEXCore/Core/CoreState.h +++ b/FEXCore/include/FEXCore/Core/CoreState.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT #pragma once +#include "FEXCore/Core/X86Enums.h" #include "FEXCore/IR/IR.h" #include #include @@ -147,8 +148,8 @@ namespace FEXCore::Core { } #endif - flags[1] = 1; ///< Reserved - Always 1. - flags[9] = 1; ///< Interrupt flag - Always 1. + flags[X86State::RFLAG_RESERVED_LOC] = 1; ///< Reserved - Always 1. + flags[X86State::RFLAG_IF_LOC] = 1; ///< Interrupt flag - Always 1. } }; static_assert(std::is_trivially_copyable_v, "Needs to be trivial"); From a76321c6c172259b38e95970ac369cf49b8b67c7 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 27 Feb 2024 12:18:58 -0400 Subject: [PATCH 2/8] OpcodeDispatcher: add DF retrieval helpers Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 076e44b27..7afc94dfd 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1458,6 +1458,18 @@ private: } } + // Returns (DF ? -Size : Size) + OrderedNode *LoadDir(const unsigned Size) { + auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); + auto SizeConst = _Constant(Size); + return _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + } + + // Returns DF ? (X - Size) : (X + Size) + OrderedNode *OffsetByDir(OrderedNode *X, const unsigned Size) { + return _Add(OpSize::i64Bit, X, LoadDir(Size)); + } + // Set SSE comparison flags based on the result set by Arm FCMP. This converts // NZCV from the Arm representation to an eXternal representation that's // totally not a euphemism for x86 or anything, nuh-uh. From aee00f524cd05ca6f18275d94c350a94d5b1abd9 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 27 Feb 2024 12:19:11 -0400 Subject: [PATCH 3/8] OpcodeDispatcher: use DF retrieval helpers Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher.cpp | 49 ++++--------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 19c91a05f..61668099d 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -3636,16 +3636,9 @@ void OpDispatchBuilder::STOSOp(OpcodeArgs) { // Store to memory where RDI points _StoreMemAutoTSO(GPRClass, Size, Dest, Src, Size); - // Calculate direction. - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); - // Offset the pointer OrderedNode *TailDest = LoadGPRRegister(X86State::REG_RDI); - TailDest = _Add(OpSize::i64Bit, TailDest, PtrDir); - - StoreGPRRegister(X86State::REG_RDI, TailDest); + StoreGPRRegister(X86State::REG_RDI, OffsetByDir(TailDest, Size)); } else { // FEX doesn't support partial faulting REP instructions. @@ -3676,9 +3669,6 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { // RA now can handle these to be here, to avoid DF accesses const auto Size = GetSrcSize(Op); - // Calculate direction. - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - if (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) { auto SrcAddr = LoadGPRRegister(X86State::REG_RSI); auto DstAddr = LoadGPRRegister(X86State::REG_RDI); @@ -3687,6 +3677,7 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { auto DstSegment = GetSegment(0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); auto SrcSegment = GetSegment(Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); + auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto Result = _MemCpy(CTX->IsAtomicTSOEnabled(), Size, DstSegment ?: InvalidNode, SrcSegment ?: InvalidNode, @@ -3700,9 +3691,6 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { StoreGPRRegister(X86State::REG_RSI, Result_Src); } else { - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); - OrderedNode *RSI = LoadGPRRegister(X86State::REG_RSI); OrderedNode *RDI = LoadGPRRegister(X86State::REG_RDI); RDI= AppendSegmentOffset(RDI, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); @@ -3713,6 +3701,7 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { // Store to memory where RDI points _StoreMemAutoTSO(GPRClass, Size, RDI, Src, Size); + auto PtrDir = LoadDir(Size); RSI = _Add(OpSize::i64Bit, RSI, PtrDir); RDI = _Add(OpSize::i64Bit, RDI, PtrDir); @@ -3745,9 +3734,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { GenerateFlags_SUB(Op, Src2, Src1); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = LoadDir(Size); // Offset the pointer Dest_RDI = _Add(OpSize::i64Bit, Dest_RDI, PtrDir); @@ -3764,9 +3751,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { bool REPE = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX; // read DF once - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = LoadDir(Size); auto JumpStart = Jump(); // Make sure to start a new block after ending this one @@ -3856,15 +3841,9 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { StoreResult(GPRClass, Op, Src, -1); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); - // Offset the pointer OrderedNode *TailDest_RSI = LoadGPRRegister(X86State::REG_RSI); - - TailDest_RSI = _Add(OpSize::i64Bit, TailDest_RSI, PtrDir); - StoreGPRRegister(X86State::REG_RSI, TailDest_RSI); + StoreGPRRegister(X86State::REG_RSI, OffsetByDir(TailDest_RSI, Size)); } else { // Calculate flags early. because end of block @@ -3877,9 +3856,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { // May or may not matter // Read DF once - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = LoadDir(Size); auto JumpStart = Jump(); // Make sure to start a new block after ending this one @@ -3953,15 +3930,9 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { GenerateFlags_SUB(Op, Src1, Src2); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); - // Offset the pointer OrderedNode *TailDest_RDI = LoadGPRRegister(X86State::REG_RDI); - - TailDest_RDI = _Add(OpSize::i64Bit, TailDest_RDI, PtrDir); - StoreGPRRegister(X86State::REG_RDI, TailDest_RDI); + StoreGPRRegister(X86State::REG_RDI, OffsetByDir(TailDest_RDI, Size)); } else { // Calculate flags early. because end of block @@ -3970,9 +3941,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { bool REPE = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX; // read DF once - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = LoadDir(Size); auto JumpStart = Jump(); // Make sure to start a new block after ending this one From e3ee65e4917c293c057168ed7fd0b29855beb39d Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 27 Feb 2024 13:17:15 -0400 Subject: [PATCH 4/8] OpcodeDispatcher: use transformed DF for memset/memcpy Use the 1/-1 representation instead of 0/1. This will be better by the end of the series. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/JIT/Arm64/MemoryOps.cpp | 16 ++++++++-------- .../Source/Interface/Core/OpcodeDispatcher.cpp | 7 +++---- FEXCore/Source/Interface/IR/Passes/ConstProp.cpp | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp index 40472ac20..6a2fe7118 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp @@ -1708,7 +1708,7 @@ DEF_OP(MemSet) { DirectionReg = GetReg(Op->Direction.ID()); } - // If Direction == 0 then: + // If Direction > 0 then: // MemReg is incremented (by size) // else: // MemReg is decremented (by size) @@ -1729,7 +1729,7 @@ DEF_OP(MemSet) { if (!DirectionIsInline) { // Backward or forwards implementation depends on flag - cbnz(ARMEmitter::Size::i64Bit, DirectionReg, &BackwardImpl); + tbnz(DirectionReg, 1, &BackwardImpl); } auto MemStore = [this](auto Value, uint32_t OpSize, int32_t Size) { @@ -1847,8 +1847,8 @@ DEF_OP(MemSet) { }; if (DirectionIsInline) { - // If the direction constant is set then the direction is negative. - EmitMemset(DirectionConstant ? -1 : 1); + LOGMAN_THROW_AA_FMT(DirectionConstant == 1 || DirectionConstant == -1, "unexpected direction"); + EmitMemset(DirectionConstant); } else { // Emit forward direction memset then backward direction memset. @@ -1886,7 +1886,7 @@ DEF_OP(MemCpy) { } auto Dst = GetRegPair(Node); - // If Direction == 0 then: + // If Direction > 0 then: // MemRegDest is incremented (by size) // MemRegSrc is incremented (by size) // else: @@ -1922,7 +1922,7 @@ DEF_OP(MemCpy) { if (!DirectionIsInline) { // Backward or forwards implementation depends on flag - cbnz(ARMEmitter::Size::i64Bit, DirectionReg, &BackwardImpl); + tbnz(DirectionReg, 1, &BackwardImpl); } auto MemCpy = [this](uint32_t OpSize, int32_t Size) { @@ -2121,8 +2121,8 @@ DEF_OP(MemCpy) { }; if (DirectionIsInline) { - // If the direction constant is set then the direction is negative. - EmitMemcpy(DirectionConstant ? -1 : 1); + LOGMAN_THROW_AA_FMT(DirectionConstant == 1 || DirectionConstant == -1, "unexpected direction"); + EmitMemcpy(DirectionConstant); } else { // Emit forward direction memset then backward direction memset. diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 61668099d..48cb08966 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -3651,9 +3651,8 @@ void OpDispatchBuilder::STOSOp(OpcodeArgs) { auto Segment = GetSegment(0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); OrderedNode *Counter = LoadGPRRegister(X86State::REG_RCX); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto Result = _MemSet(CTX->IsAtomicTSOEnabled(), Size, Segment ?: InvalidNode, Dest, Src, Counter, DF); + auto Result = _MemSet(CTX->IsAtomicTSOEnabled(), Size, Segment ?: InvalidNode, Dest, Src, Counter, LoadDir(1)); StoreGPRRegister(X86State::REG_RCX, _Constant(0)); StoreGPRRegister(X86State::REG_RDI, Result); } @@ -3677,11 +3676,11 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { auto DstSegment = GetSegment(0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); auto SrcSegment = GetSegment(Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto Result = _MemCpy(CTX->IsAtomicTSOEnabled(), Size, DstSegment ?: InvalidNode, SrcSegment ?: InvalidNode, - DstAddr, SrcAddr, Counter, DF); + DstAddr, SrcAddr, Counter, + LoadDir(1)); OrderedNode *Result_Dst = _ExtractElementPair(OpSize::i64Bit, Result, 0); OrderedNode *Result_Src = _ExtractElementPair(OpSize::i64Bit, Result, 1); diff --git a/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp b/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp index b27d70210..2a2706091 100644 --- a/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp +++ b/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp @@ -1330,7 +1330,7 @@ bool ConstProp::ConstantInlining(IREmitter *IREmit, const IRListView& CurrentIR) if (IREmit->IsValueConstant(Op->Direction, &Constant)) { IREmit->SetWriteCursor(CurrentIR.GetNode(Op->Direction)); - IREmit->ReplaceNodeArgument(CodeNode, Op->Direction_Index, CreateInlineConstant(IREmit, Constant & 1)); + IREmit->ReplaceNodeArgument(CodeNode, Op->Direction_Index, CreateInlineConstant(IREmit, Constant)); Changed = true; } @@ -1344,7 +1344,7 @@ bool ConstProp::ConstantInlining(IREmitter *IREmit, const IRListView& CurrentIR) if (IREmit->IsValueConstant(Op->Direction, &Constant)) { IREmit->SetWriteCursor(CurrentIR.GetNode(Op->Direction)); - IREmit->ReplaceNodeArgument(CodeNode, Op->Direction_Index, CreateInlineConstant(IREmit, Constant & 1)); + IREmit->ReplaceNodeArgument(CodeNode, Op->Direction_Index, CreateInlineConstant(IREmit, Constant)); Changed = true; } From c99cbe6d0ae7889ddd196cde36762aa66f24c0d5 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 27 Feb 2024 10:16:15 -0400 Subject: [PATCH 5/8] JIT: switch DF representation Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/Core.cpp | 10 +++++ .../Interface/Core/JIT/Arm64/MemoryOps.cpp | 8 ++++ .../Interface/Core/OpcodeDispatcher.cpp | 4 +- .../Source/Interface/Core/OpcodeDispatcher.h | 18 ++++++-- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 2 +- FEXCore/Source/Interface/IR/IR.json | 7 +++ .../IR/Passes/DeadContextStoreElimination.cpp | 45 ++++++++++++------- .../IR/Passes/DeadStoreElimination.cpp | 5 +++ FEXCore/include/FEXCore/Core/CoreState.h | 5 +++ FEXCore/include/FEXCore/Core/X86Enums.h | 2 +- 10 files changed, 83 insertions(+), 23 deletions(-) diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 88076f980..974d37ab6 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -167,6 +167,7 @@ namespace FEXCore::Context { case X86State::RFLAG_ZF_RAW_LOC: case X86State::RFLAG_SF_RAW_LOC: case X86State::RFLAG_OF_RAW_LOC: + case X86State::RFLAG_DF_RAW_LOC: // Intentionally do nothing. // These contain multiple bits which can corrupt other members when compacted. break; @@ -215,6 +216,11 @@ namespace FEXCore::Context { uint32_t AF = ((Frame->State.af_raw ^ PFByte) & (1 << 4)) ? 1 : 0; EFLAGS |= AF << X86State::RFLAG_AF_RAW_LOC; + // DF is pretransformed, undo the transform from 1/-1 back to 0/1 + uint8_t DFByte = Frame->State.flags[X86State::RFLAG_DF_RAW_LOC]; + if (DFByte & 0x80) + EFLAGS |= 1 << X86State::RFLAG_DF_RAW_LOC; + return EFLAGS; } @@ -238,6 +244,10 @@ namespace FEXCore::Context { // PF is inverted in our internal representation. Frame->State.pf_raw = (EFLAGS & (1U << i)) ? 0 : 1; break; + case X86State::RFLAG_DF_RAW_LOC: + // DF is encoded as 1/-1 + Frame->State.flags[i] = (EFLAGS & (1U << i)) ? 0xff : 1; + break; default: Frame->State.flags[i] = (EFLAGS & (1U << i)) ? 1 : 0; break; diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp index 6a2fe7118..b926c6e20 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp @@ -888,6 +888,14 @@ DEF_OP(StoreNZCV) { msr(ARMEmitter::SystemRegister::NZCV, GetReg(Op->Value.ID())); } +DEF_OP(LoadDF) { + auto Dst = GetReg(Node); + auto Flag = X86State::RFLAG_DF_RAW_LOC; + + // DF needs sign extension to turn 0x1/0xFF into 1/-1 + ldrsb(Dst.X(), STATE, offsetof(FEXCore::Core::CPUState, flags[Flag])); +} + DEF_OP(LoadFlag) { auto Op = IROp->C(); auto Dst = GetReg(Node); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 48cb08966..81ce39e14 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1379,10 +1379,10 @@ void OpDispatchBuilder::FLAGControlOp(OpcodeArgs) { SetRFLAG(_Constant(1), FEXCore::X86State::RFLAG_CF_RAW_LOC); break; case 0xFC: // CLD - SetRFLAG(_Constant(0), FEXCore::X86State::RFLAG_DF_LOC); + SetRFLAG(_Constant(0), FEXCore::X86State::RFLAG_DF_RAW_LOC); break; case 0xFD: // STD - SetRFLAG(_Constant(1), FEXCore::X86State::RFLAG_DF_LOC); + SetRFLAG(_Constant(1), FEXCore::X86State::RFLAG_DF_RAW_LOC); break; } } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 7afc94dfd..ce3e16a5f 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1401,6 +1401,11 @@ private: if (ValueOffset || MustMask) Value = _Bfe(OpSize::i32Bit, 1, ValueOffset, Value); + // For DF, we need to transform 0/1 into 1/-1 + if (BitOffset == FEXCore::X86State::RFLAG_DF_RAW_LOC) { + Value = _SubShift(OpSize::i64Bit, _Constant(1), Value, ShiftType::LSL, 1); + } + _StoreFlag(Value, BitOffset); } } @@ -1453,6 +1458,9 @@ private: return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize()); } else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) { return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize()); + } else if (BitOffset == FEXCore::X86State::RFLAG_DF_RAW_LOC) { + // Recover the sign bit, it is the logical DF value + return _Lshr(OpSize::i64Bit, _LoadDF(), _Constant(63)); } else { return _LoadFlag(BitOffset); } @@ -1460,9 +1468,13 @@ private: // Returns (DF ? -Size : Size) OrderedNode *LoadDir(const unsigned Size) { - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto SizeConst = _Constant(Size); - return _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto Dir = _LoadDF(); + auto Shift = FEXCore::ilog2(Size); + + if (Shift) + return _Lshl(IR::SizeToOpSize(CTX->GetGPRSize()), Dir, _Constant(Shift)); + else + return Dir; } // Returns DF ? (X - Size) : (X + Size) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index b6590b7f3..67e51966d 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -27,7 +27,7 @@ constexpr std::array FlagOffsets = { FEXCore::X86State::RFLAG_SF_RAW_LOC, FEXCore::X86State::RFLAG_TF_LOC, FEXCore::X86State::RFLAG_IF_LOC, - FEXCore::X86State::RFLAG_DF_LOC, + FEXCore::X86State::RFLAG_DF_RAW_LOC, FEXCore::X86State::RFLAG_OF_RAW_LOC, FEXCore::X86State::RFLAG_IOPL_LOC, FEXCore::X86State::RFLAG_NT_LOC, diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index 9e29955d1..d1705a5aa 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -456,6 +456,13 @@ "DestSize": "4" }, + "GPR = LoadDF": { + "Desc": ["Loads the decimal flag from the context object in -1/1", + "representation for easy consumption" + ], + "DestSize": "8" + }, + "GPR = LoadFlag u32:$Flag": { "Desc": ["Loads an x86-64 flag from the context object", "Specialized to allow flexible implementation of flag handling" diff --git a/FEXCore/Source/Interface/IR/Passes/DeadContextStoreElimination.cpp b/FEXCore/Source/Interface/IR/Passes/DeadContextStoreElimination.cpp index f8a33e653..8219e1178 100644 --- a/FEXCore/Source/Interface/IR/Passes/DeadContextStoreElimination.cpp +++ b/FEXCore/Source/Interface/IR/Passes/DeadContextStoreElimination.cpp @@ -11,6 +11,7 @@ $end_info$ #include "Interface/IR/PassManager.h" #include +#include #include #include #include @@ -483,6 +484,8 @@ private: ContextMemberInfo *RecordAccess(ContextMemberInfo *Info, FEXCore::IR::RegisterClassType RegClass, uint32_t Offset, uint8_t Size, LastAccessType AccessType, FEXCore::IR::OrderedNode *Node, FEXCore::IR::OrderedNode *StoreNode = nullptr); ContextMemberInfo *RecordAccess(ContextInfo *ClassifiedInfo, FEXCore::IR::RegisterClassType RegClass, uint32_t Offset, uint8_t Size, LastAccessType AccessType, FEXCore::IR::OrderedNode *Node, FEXCore::IR::OrderedNode *StoreNode = nullptr); + bool HandleLoadFlag(FEXCore::IR::IREmitter *IREmit, ContextInfo *LocalInfo, FEXCore::IR::OrderedNode *CodeNode, unsigned Flag); + // Classify context loads and stores. bool ClassifyContextLoad(FEXCore::IR::IREmitter *IREmit, ContextInfo *LocalInfo, FEXCore::IR::RegisterClassType Class, uint32_t Offset, uint8_t Size, FEXCore::IR::OrderedNode *CodeNode, FEXCore::IR::NodeIterator BlockEnd); bool ClassifyContextStore(FEXCore::IR::IREmitter *IREmit, ContextInfo *LocalInfo, FEXCore::IR::RegisterClassType Class, uint32_t Offset, uint8_t Size, FEXCore::IR::OrderedNode *CodeNode, FEXCore::IR::OrderedNode *ValueNode); @@ -551,6 +554,28 @@ bool RCLSE::ClassifyContextStore(FEXCore::IR::IREmitter *IREmit, ContextInfo *Lo return false; } +bool RCLSE::HandleLoadFlag(FEXCore::IR::IREmitter *IREmit, ContextInfo *LocalInfo, FEXCore::IR::OrderedNode *CodeNode, unsigned Flag) { + const auto FlagOffset = offsetof(FEXCore::Core::CPUState, flags[Flag]); + auto Info = FindMemberInfo(LocalInfo, FlagOffset, 1); + LastAccessType LastAccess = Info->Accessed; + auto LastValueNode = Info->ValueNode; + + if (IsWriteAccess(LastAccess)) { // 1 byte so always a full write + // If the last store matches this load value then we can replace the loaded value with the previous valid one + IREmit->SetWriteCursor(CodeNode); + IREmit->ReplaceAllUsesWith(CodeNode, LastValueNode); + RecordAccess(Info, FEXCore::IR::GPRClass, FlagOffset, 1, LastAccessType::READ, LastValueNode); + return true; + } + else if (IsReadAccess(LastAccess)) { + IREmit->ReplaceAllUsesWith(CodeNode, LastValueNode); + RecordAccess(Info, FEXCore::IR::GPRClass, FlagOffset, 1, LastAccessType::READ, LastValueNode); + return true; + } + + return false; +} + /** * @brief This pass removes redundant pairs of storecontext and loadcontext ops * @@ -660,23 +685,11 @@ bool RCLSE::RedundantStoreLoadElimination(FEXCore::IR::IREmitter *IREmit) { } else if (IROp->Op == OP_LOADFLAG) { const auto Op = IROp->CW(); - const auto FlagOffset = offsetof(FEXCore::Core::CPUState, flags[0]) + Op->Flag; - auto Info = FindMemberInfo(&LocalInfo, FlagOffset, 1); - LastAccessType LastAccess = Info->Accessed; - OrderedNode *LastValueNode = Info->ValueNode; - if (IsWriteAccess(LastAccess)) { // 1 byte so always a full write - // If the last store matches this load value then we can replace the loaded value with the previous valid one - IREmit->SetWriteCursor(CodeNode); - IREmit->ReplaceAllUsesWith(CodeNode, LastValueNode); - RecordAccess(Info, FEXCore::IR::GPRClass, FlagOffset, 1, LastAccessType::READ, LastValueNode); - Changed = true; - } - else if (IsReadAccess(LastAccess)) { - IREmit->ReplaceAllUsesWith(CodeNode, LastValueNode); - RecordAccess(Info, FEXCore::IR::GPRClass, FlagOffset, 1, LastAccessType::READ, LastValueNode); - Changed = true; - } + Changed |= HandleLoadFlag(IREmit, &LocalInfo, CodeNode, Op->Flag); + } + else if (IROp->Op == OP_LOADDF) { + Changed |= HandleLoadFlag(IREmit, &LocalInfo, CodeNode, X86State::RFLAG_DF_RAW_LOC); } else if (IROp->Op == OP_SYSCALL || IROp->Op == OP_INLINESYSCALL) { diff --git a/FEXCore/Source/Interface/IR/Passes/DeadStoreElimination.cpp b/FEXCore/Source/Interface/IR/Passes/DeadStoreElimination.cpp index beee2b5bc..9bd5c6232 100644 --- a/FEXCore/Source/Interface/IR/Passes/DeadStoreElimination.cpp +++ b/FEXCore/Source/Interface/IR/Passes/DeadStoreElimination.cpp @@ -10,6 +10,7 @@ $end_info$ #include "Interface/IR/PassManager.h" #include +#include #include #include #include @@ -211,6 +212,10 @@ bool DeadStoreElimination::Run(IREmitter *IREmit) { auto& BlockInfo = InfoMap[BlockNode]; BlockInfo.flag.reads |= 1UL << Op->Flag; + } else if (IROp->Op == OP_LOADDF) { + auto& BlockInfo = InfoMap[BlockNode]; + + BlockInfo.flag.reads |= 1UL << X86State::RFLAG_DF_RAW_LOC; } else if (IROp->Op == OP_STOREREGISTER) { auto Op = IROp->C(); diff --git a/FEXCore/include/FEXCore/Core/CoreState.h b/FEXCore/include/FEXCore/Core/CoreState.h index ae751a0d5..a11d677a4 100644 --- a/FEXCore/include/FEXCore/Core/CoreState.h +++ b/FEXCore/include/FEXCore/Core/CoreState.h @@ -150,6 +150,11 @@ namespace FEXCore::Core { flags[X86State::RFLAG_RESERVED_LOC] = 1; ///< Reserved - Always 1. flags[X86State::RFLAG_IF_LOC] = 1; ///< Interrupt flag - Always 1. + + // DF needs to be initialized to 0 to comply with the Linux ABI. However, + // we encode DF as 1/-1 within the JIT, so we have to write 0x1 here to + // zero DF. + flags[X86State::RFLAG_DF_RAW_LOC] = 0x1; } }; static_assert(std::is_trivially_copyable_v, "Needs to be trivial"); diff --git a/FEXCore/include/FEXCore/Core/X86Enums.h b/FEXCore/include/FEXCore/Core/X86Enums.h index 053325f16..12460b6db 100644 --- a/FEXCore/include/FEXCore/Core/X86Enums.h +++ b/FEXCore/include/FEXCore/Core/X86Enums.h @@ -64,7 +64,7 @@ enum X86RegLocation : uint32_t { RFLAG_SF_RAW_LOC = 7, // Not used directly, needs to be reconstructed using `ReconstructCompactedEFLAGS` RFLAG_TF_LOC = 8, RFLAG_IF_LOC = 9, - RFLAG_DF_LOC = 10, + RFLAG_DF_RAW_LOC = 10, // Contains multiple bits, needs to be reconstructed using `ReconstructCompactedEFLAGS` RFLAG_OF_RAW_LOC = 11, // Not used directly, needs to be reconstructed using `ReconstructCompactedEFLAGS` RFLAG_IOPL_LOC = 12, RFLAG_NT_LOC = 14, From 03c6abdad4ac9955d3fd31dfed19461946a8eed0 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 27 Feb 2024 13:39:36 -0400 Subject: [PATCH 6/8] OpcodeDispatcher: optimize DF add fuse the shift the right way Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index ce3e16a5f..c6be701f6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1479,7 +1479,9 @@ private: // Returns DF ? (X - Size) : (X + Size) OrderedNode *OffsetByDir(OrderedNode *X, const unsigned Size) { - return _Add(OpSize::i64Bit, X, LoadDir(Size)); + auto Shift = FEXCore::ilog2(Size); + + return _AddShift(OpSize::i64Bit, X, _LoadDF(), ShiftType::LSL, Shift); } // Set SSE comparison flags based on the result set by Arm FCMP. This converts From 7629007cfa36d5106af532281e8d1b886e59ea59 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 11 Mar 2024 18:47:27 -0400 Subject: [PATCH 7/8] OpcodeDispatcher: allow upper garbage on STOS Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 81ce39e14..43603bdab 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -3627,7 +3627,8 @@ void OpDispatchBuilder::STOSOp(OpcodeArgs) { const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) != 0; if (!Repeat) { - OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); + // Src is used only for a store of the same size so allow garbage + OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); OrderedNode *Dest = LoadGPRRegister(X86State::REG_RDI); // Only ES prefix From 063b81da1d32ce1816a90ff4a2ec15a69fc9dff4 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 11 Mar 2024 18:45:56 -0400 Subject: [PATCH 8/8] InstCountCI: Update Signed-off-by: Alyssa Rosenzweig --- .../InstructionCountCI/FEXOpt/MultiInst.json | 72 ++-- .../InstructionCountCI/FlagM/Primary.json | 179 ++++----- unittests/InstructionCountCI/Primary.json | 354 ++++++++---------- 3 files changed, 263 insertions(+), 342 deletions(-) diff --git a/unittests/InstructionCountCI/FEXOpt/MultiInst.json b/unittests/InstructionCountCI/FEXOpt/MultiInst.json index d9da698cd..b600f7110 100644 --- a/unittests/InstructionCountCI/FEXOpt/MultiInst.json +++ b/unittests/InstructionCountCI/FEXOpt/MultiInst.json @@ -68,7 +68,7 @@ "movsb" ], "ExpectedArm64ASM": [ - "mov w20, #0x0", + "mov w20, #0x1", "strb w20, [x28, #714]", "ldrb w20, [x10]", "strb w20, [x11]", @@ -87,7 +87,7 @@ "movsw" ], "ExpectedArm64ASM": [ - "mov w20, #0x0", + "mov w20, #0x1", "strb w20, [x28, #714]", "ldrh w20, [x10]", "strh w20, [x11]", @@ -106,7 +106,7 @@ "movsd" ], "ExpectedArm64ASM": [ - "mov w20, #0x0", + "mov w20, #0x1", "strb w20, [x28, #714]", "ldr w20, [x10]", "str w20, [x11]", @@ -125,7 +125,7 @@ "movsq" ], "ExpectedArm64ASM": [ - "mov w20, #0x0", + "mov w20, #0x1", "strb w20, [x28, #714]", "ldr x20, [x10]", "str x20, [x11]", @@ -144,7 +144,7 @@ "movsb" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "ldrb w20, [x10]", "strb w20, [x11]", @@ -163,7 +163,7 @@ "movsw" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "ldrh w20, [x10]", "strh w20, [x11]", @@ -182,7 +182,7 @@ "movsd" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "ldr w20, [x10]", "str w20, [x11]", @@ -201,7 +201,7 @@ "movsq" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "ldr x20, [x10]", "str x20, [x11]", @@ -210,7 +210,7 @@ ] }, "positive rep movsb": { - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 19, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -221,7 +221,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", @@ -241,7 +242,7 @@ ] }, "positive rep movsw": { - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 19, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -252,7 +253,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", @@ -272,7 +274,7 @@ ] }, "positive rep movsd": { - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 19, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -283,7 +285,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", @@ -303,7 +306,7 @@ ] }, "positive rep movsq": { - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 19, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -314,7 +317,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", @@ -344,7 +348,7 @@ "rep movsb" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "mov x0, x5", "mov x1, x11", @@ -375,7 +379,7 @@ "rep movsw" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "mov x0, x5", "mov x1, x11", @@ -406,7 +410,7 @@ "rep movsd" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "mov x0, x5", "mov x1, x11", @@ -437,7 +441,7 @@ "rep movsq" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "mov x0, x5", "mov x1, x11", @@ -458,7 +462,7 @@ ] }, "positive rep stosb": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 12, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -469,7 +473,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "uxtb w21, w4", "mov x0, x5", "mov x1, x11", @@ -482,7 +487,7 @@ ] }, "positive rep stosw": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 12, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -493,7 +498,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "uxth w21, w4", "mov x0, x5", "mov x1, x11", @@ -506,7 +512,7 @@ ] }, "positive rep stosd": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 12, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -517,7 +523,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "mov w21, w4", "mov x0, x5", "mov x1, x11", @@ -530,7 +537,7 @@ ] }, "positive rep stosq": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 11, "Comment": [ "When direction flag is a compile time constant we can optimize", "loads and stores can turn in to post-increment when known" @@ -541,7 +548,8 @@ ], "ExpectedArm64ASM": [ "mov w20, #0x0", - "strb w20, [x28, #714]", + "mov w21, #0x1", + "strb w21, [x28, #714]", "mov x0, x5", "mov x1, x11", "cbz x0, #+0x10", @@ -563,7 +571,7 @@ "rep stosb" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "uxtb w20, w4", "mov x0, x5", @@ -587,7 +595,7 @@ "rep stosw" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "uxth w20, w4", "mov x0, x5", @@ -611,7 +619,7 @@ "rep stosd" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "mov w20, w4", "mov x0, x5", @@ -635,7 +643,7 @@ "rep stosq" ], "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]", "mov x0, x5", "mov x1, x11", diff --git a/unittests/InstructionCountCI/FlagM/Primary.json b/unittests/InstructionCountCI/FlagM/Primary.json index 7eaf98fc3..743376c77 100644 --- a/unittests/InstructionCountCI/FlagM/Primary.json +++ b/unittests/InstructionCountCI/FlagM/Primary.json @@ -1714,7 +1714,7 @@ ] }, "pushf": { - "ExpectedInstructionCount": 38, + "ExpectedInstructionCount": 39, "Comment": "0x9c", "ExpectedArm64ASM": [ "cset w20, hs", @@ -1725,7 +1725,8 @@ "orr x20, x20, x21, lsl #8", "ldrb w21, [x28, #713]", "orr x20, x20, x21, lsl #9", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", + "lsr x21, x21, #63", "orr x20, x20, x21, lsl #10", "cset w21, vs", "orr x20, x20, x21, lsl #11", @@ -1758,7 +1759,7 @@ ] }, "pushfq": { - "ExpectedInstructionCount": 38, + "ExpectedInstructionCount": 39, "Comment": "0x9c", "ExpectedArm64ASM": [ "cset w20, hs", @@ -1769,7 +1770,8 @@ "orr x20, x20, x21, lsl #8", "ldrb w21, [x28, #713]", "orr x20, x20, x21, lsl #9", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", + "lsr x21, x21, #63", "orr x20, x20, x21, lsl #10", "cset w21, vs", "orr x20, x20, x21, lsl #11", @@ -1802,7 +1804,7 @@ ] }, "popf": { - "ExpectedInstructionCount": 32, + "ExpectedInstructionCount": 34, "Comment": "0x9d", "ExpectedArm64ASM": [ "ldr x20, [x8]", @@ -1811,6 +1813,7 @@ "orr x27, x20, x21", "rmif x27, #63, #nzCv", "ubfx w20, w27, #2, #1", + "mov w21, #0x1", "eor w26, w20, #0x1", "rmif x27, #4, #nZcv", "rmif x27, #4, #Nzcv", @@ -1819,6 +1822,7 @@ "ubfx w20, w27, #9, #1", "strb w20, [x28, #713]", "ubfx w20, w27, #10, #1", + "sub x20, x21, x20, lsl #1", "strb w20, [x28, #714]", "rmif x27, #11, #nzcV", "ubfx w20, w27, #12, #1", @@ -1875,16 +1879,14 @@ ] }, "cmpsb": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 10, "Comment": [ "0xa6" ], "ExpectedArm64ASM": [ "ldrb w20, [x11]", "ldrb w21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x1", - "sub x22, x23, x22, lsl #1", + "ldrsb x22, [x28, #714]", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -1895,16 +1897,15 @@ ] }, "cmpsw": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 11, "Comment": [ "0xa7" ], "ExpectedArm64ASM": [ "ldrh w20, [x11]", "ldrh w21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x2", - "sub x22, x23, x22, lsl #2", + "ldrsb x22, [x28, #714]", + "lsl x22, x22, #1", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -1915,16 +1916,15 @@ ] }, "cmpsd": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 9, "Comment": [ "0xa7" ], "ExpectedArm64ASM": [ "ldr w20, [x11]", "ldr w21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x4", - "sub x22, x23, x22, lsl #3", + "ldrsb x22, [x28, #714]", + "lsl x22, x22, #2", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -1933,16 +1933,15 @@ ] }, "cmpsq": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 9, "Comment": [ "0xa7" ], "ExpectedArm64ASM": [ "ldr x20, [x11]", "ldr x21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x8", - "sub x22, x23, x22, lsl #4", + "ldrsb x22, [x28, #714]", + "lsl x22, x22, #3", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -1951,12 +1950,10 @@ ] }, "repz cmpsb": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 13, "Comment": "0xa6", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x30", "ldrb w21, [x11]", "ldrb w22, [x10]", @@ -1972,12 +1969,11 @@ ] }, "repz cmpsw": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x30", "ldrh w21, [x11]", "ldrh w22, [x10]", @@ -1993,12 +1989,11 @@ ] }, "repz cmpsd": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x28", "ldr w21, [x11]", "ldr w22, [x10]", @@ -2012,12 +2007,11 @@ ] }, "repz cmpsq": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x28", "ldr x21, [x11]", "ldr x22, [x10]", @@ -2031,12 +2025,10 @@ ] }, "repnz cmpsb": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 13, "Comment": "0xa6", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x30", "ldrb w21, [x11]", "ldrb w22, [x10]", @@ -2052,12 +2044,11 @@ ] }, "repnz cmpsw": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x30", "ldrh w21, [x11]", "ldrh w22, [x10]", @@ -2073,12 +2064,11 @@ ] }, "repnz cmpsd": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x28", "ldr w21, [x11]", "ldr w22, [x10]", @@ -2092,12 +2082,11 @@ ] }, "repnz cmpsq": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x28", "ldr x21, [x11]", "ldr x22, [x10]", @@ -2171,13 +2160,11 @@ ] }, "scasb": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 8, "Comment": "0xae", "ExpectedArm64ASM": [ "ldrb w20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x1", - "sub x21, x22, x21, lsl #1", + "ldrsb x21, [x28, #714]", "add x11, x11, x21", "eor w27, w4, w20", "lsl w0, w4, #24", @@ -2187,14 +2174,12 @@ ] }, "scasw": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 8, "Comment": "0xaf", "ExpectedArm64ASM": [ "ldrh w20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x2", - "sub x21, x22, x21, lsl #2", - "add x11, x11, x21", + "ldrsb x21, [x28, #714]", + "add x11, x11, x21, lsl #1", "eor w27, w4, w20", "lsl w0, w4, #16", "cmp w0, w20, lsl #16", @@ -2203,40 +2188,34 @@ ] }, "scasd": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 6, "Comment": "0xaf", "ExpectedArm64ASM": [ "ldr w20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x4", - "sub x21, x22, x21, lsl #3", - "add x11, x11, x21", + "ldrsb x21, [x28, #714]", + "add x11, x11, x21, lsl #2", "eor w27, w4, w20", "subs w26, w4, w20", "cfinv" ] }, "scasq": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 6, "Comment": "0xaf", "ExpectedArm64ASM": [ "ldr x20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x8", - "sub x21, x22, x21, lsl #4", - "add x11, x11, x21", + "ldrsb x21, [x28, #714]", + "add x11, x11, x21, lsl #3", "eor w27, w4, w20", "subs x26, x4, x20", "cfinv" ] }, "repz scasb": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 11, "Comment": "0xae", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x28", "ldrb w21, [x11]", "eor w27, w4, w21", @@ -2250,12 +2229,11 @@ ] }, "repz scasw": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x28", "ldrh w21, [x11]", "eor w27, w4, w21", @@ -2269,12 +2247,11 @@ ] }, "repz scasd": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 10, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x20", "ldr w21, [x11]", "eor w27, w4, w21", @@ -2286,12 +2263,11 @@ ] }, "repz scasq": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 10, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x20", "ldr x21, [x11]", "eor w27, w4, w21", @@ -2303,12 +2279,10 @@ ] }, "repnz scasb": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 11, "Comment": "0xae", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x28", "ldrb w21, [x11]", "eor w27, w4, w21", @@ -2322,12 +2296,11 @@ ] }, "repnz scasw": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x28", "ldrh w21, [x11]", "eor w27, w4, w21", @@ -2341,12 +2314,11 @@ ] }, "repnz scasd": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 10, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x20", "ldr w21, [x11]", "eor w27, w4, w21", @@ -2358,12 +2330,11 @@ ] }, "repnz scasq": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 10, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x20", "ldr x21, [x11]", "eor w27, w4, w21", diff --git a/unittests/InstructionCountCI/Primary.json b/unittests/InstructionCountCI/Primary.json index a7f8fad12..143ae2af8 100644 --- a/unittests/InstructionCountCI/Primary.json +++ b/unittests/InstructionCountCI/Primary.json @@ -2575,7 +2575,7 @@ "ExpectedArm64ASM": [] }, "pushf": { - "ExpectedInstructionCount": 38, + "ExpectedInstructionCount": 39, "Comment": "0x9c", "ExpectedArm64ASM": [ "cset w20, hs", @@ -2586,7 +2586,8 @@ "orr x20, x20, x21, lsl #8", "ldrb w21, [x28, #713]", "orr x20, x20, x21, lsl #9", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", + "lsr x21, x21, #63", "orr x20, x20, x21, lsl #10", "cset w21, vs", "orr x20, x20, x21, lsl #11", @@ -2619,7 +2620,7 @@ ] }, "pushfq": { - "ExpectedInstructionCount": 38, + "ExpectedInstructionCount": 39, "Comment": "0x9c", "ExpectedArm64ASM": [ "cset w20, hs", @@ -2630,7 +2631,8 @@ "orr x20, x20, x21, lsl #8", "ldrb w21, [x28, #713]", "orr x20, x20, x21, lsl #9", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", + "lsr x21, x21, #63", "orr x20, x20, x21, lsl #10", "cset w21, vs", "orr x20, x20, x21, lsl #11", @@ -2663,7 +2665,7 @@ ] }, "popf": { - "ExpectedInstructionCount": 37, + "ExpectedInstructionCount": 39, "Comment": "0x9d", "ExpectedArm64ASM": [ "ldr x20, [x8]", @@ -2673,6 +2675,7 @@ "ubfx x20, x27, #0, #1", "lsl x20, x20, #29", "ubfx w21, w27, #2, #1", + "mov w22, #0x1", "eor w26, w21, #0x1", "ubfx x21, x27, #6, #1", "orr w20, w20, w21, lsl #30", @@ -2683,6 +2686,7 @@ "ubfx w21, w27, #9, #1", "strb w21, [x28, #713]", "ubfx w21, w27, #10, #1", + "sub x21, x22, x21, lsl #1", "strb w21, [x28, #714]", "ubfx x21, x27, #11, #1", "orr w20, w20, w21, lsl #28", @@ -2801,61 +2805,56 @@ ] }, "movsb": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 5, "Comment": [ "0xa4" ], "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", - "ldrb w21, [x10]", - "strb w21, [x11]", + "ldrb w20, [x10]", + "strb w20, [x11]", + "ldrsb x20, [x28, #714]", "add x10, x10, x20", "add x11, x11, x20" ] }, "movsw": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Comment": [ "0xa5" ], "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", - "ldrh w21, [x10]", - "strh w21, [x11]", + "ldrh w20, [x10]", + "strh w20, [x11]", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "add x10, x10, x20", "add x11, x11, x20" ] }, "movsd": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Comment": [ "0xa5" ], "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", - "ldr w21, [x10]", - "str w21, [x11]", + "ldr w20, [x10]", + "str w20, [x11]", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "add x10, x10, x20", "add x11, x11, x20" ] }, "movsq": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Comment": [ "0xa5" ], "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", - "ldr x21, [x10]", - "str x21, [x11]", + "ldr x20, [x10]", + "str x20, [x11]", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "add x10, x10, x20", "add x11, x11, x20" ] @@ -2864,11 +2863,11 @@ "ExpectedInstructionCount": 29, "Comment": "0xa4", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", + "ldrsb x20, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", - "cbnz x20, #+0x30", + "tbnz w20, #1, #+0x30", "cbz x0, #+0x14", "ldrb w3, [x2], #1", "strb w3, [x1], #1", @@ -2899,11 +2898,11 @@ "ExpectedInstructionCount": 29, "Comment": "0xa5", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", + "ldrsb x20, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", - "cbnz x20, #+0x30", + "tbnz w20, #1, #+0x30", "cbz x0, #+0x14", "ldrh w3, [x2], #2", "strh w3, [x1], #2", @@ -2934,11 +2933,11 @@ "ExpectedInstructionCount": 29, "Comment": "0xa5", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", + "ldrsb x20, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", - "cbnz x20, #+0x30", + "tbnz w20, #1, #+0x30", "cbz x0, #+0x14", "ldr w3, [x2], #4", "str w3, [x1], #4", @@ -2969,11 +2968,11 @@ "ExpectedInstructionCount": 29, "Comment": "0xa5", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", + "ldrsb x20, [x28, #714]", "mov x0, x5", "mov x1, x11", "mov x2, x10", - "cbnz x20, #+0x30", + "tbnz w20, #1, #+0x30", "cbz x0, #+0x14", "ldr x3, [x2], #8", "str x3, [x1], #8", @@ -3001,16 +3000,14 @@ ] }, "cmpsb": { - "ExpectedInstructionCount": 14, + "ExpectedInstructionCount": 12, "Comment": [ "0xa6" ], "ExpectedArm64ASM": [ "ldrb w20, [x11]", "ldrb w21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x1", - "sub x22, x23, x22, lsl #1", + "ldrsb x22, [x28, #714]", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -3023,16 +3020,15 @@ ] }, "cmpsw": { - "ExpectedInstructionCount": 14, + "ExpectedInstructionCount": 13, "Comment": [ "0xa7" ], "ExpectedArm64ASM": [ "ldrh w20, [x11]", "ldrh w21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x2", - "sub x22, x23, x22, lsl #2", + "ldrsb x22, [x28, #714]", + "lsl x22, x22, #1", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -3045,16 +3041,15 @@ ] }, "cmpsd": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 11, "Comment": [ "0xa7" ], "ExpectedArm64ASM": [ "ldr w20, [x11]", "ldr w21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x4", - "sub x22, x23, x22, lsl #3", + "ldrsb x22, [x28, #714]", + "lsl x22, x22, #2", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -3065,16 +3060,15 @@ ] }, "cmpsq": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 11, "Comment": [ "0xa7" ], "ExpectedArm64ASM": [ "ldr x20, [x11]", "ldr x21, [x10]", - "ldrb w22, [x28, #714]", - "mov w23, #0x8", - "sub x22, x23, x22, lsl #4", + "ldrsb x22, [x28, #714]", + "lsl x22, x22, #3", "add x11, x11, x22", "add x10, x10, x22", "eor w27, w21, w20", @@ -3085,12 +3079,10 @@ ] }, "repz cmpsb": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 15, "Comment": "0xa6", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x38", "ldrb w21, [x11]", "ldrb w22, [x10]", @@ -3108,12 +3100,11 @@ ] }, "repz cmpsw": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 16, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x38", "ldrh w21, [x11]", "ldrh w22, [x10]", @@ -3131,12 +3122,11 @@ ] }, "repz cmpsd": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x30", "ldr w21, [x11]", "ldr w22, [x10]", @@ -3152,12 +3142,11 @@ ] }, "repz cmpsq": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x30", "ldr x21, [x11]", "ldr x22, [x10]", @@ -3173,12 +3162,10 @@ ] }, "repnz cmpsb": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 15, "Comment": "0xa6", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x38", "ldrb w21, [x11]", "ldrb w22, [x10]", @@ -3196,12 +3183,11 @@ ] }, "repnz cmpsw": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 16, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x38", "ldrh w21, [x11]", "ldrh w22, [x10]", @@ -3219,12 +3205,11 @@ ] }, "repnz cmpsd": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x30", "ldr w21, [x11]", "ldr w22, [x10]", @@ -3240,12 +3225,11 @@ ] }, "repnz cmpsq": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xa7", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x30", "ldr x21, [x11]", "ldr x22, [x10]", @@ -3321,50 +3305,39 @@ ] }, "stosb": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 3, "Comment": "0xaa", "ExpectedArm64ASM": [ - "uxtb w20, w4", - "strb w20, [x11]", - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "strb w4, [x11]", + "ldrsb x20, [x28, #714]", "add x11, x11, x20" ] }, "stosw": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 3, "Comment": "0xab", "ExpectedArm64ASM": [ - "uxth w20, w4", - "strh w20, [x11]", - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", - "add x11, x11, x20" + "strh w4, [x11]", + "ldrsb x20, [x28, #714]", + "add x11, x11, x20, lsl #1" ] }, "stosd": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 3, "Comment": "0xab", "ExpectedArm64ASM": [ - "mov w20, w4", - "str w20, [x11]", - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", - "add x11, x11, x20" + "str w4, [x11]", + "ldrsb x20, [x28, #714]", + "add x11, x11, x20, lsl #2" ] }, "stosq": { - "ExpectedInstructionCount": 5, + "ExpectedInstructionCount": 3, "Comment": "0xab", "ExpectedArm64ASM": [ "str x4, [x11]", - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", - "add x11, x11, x20" + "ldrsb x20, [x28, #714]", + "add x11, x11, x20, lsl #3" ] }, "rep stosb": { @@ -3372,10 +3345,10 @@ "Comment": "0xaa", "ExpectedArm64ASM": [ "uxtb w20, w4", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", "mov x0, x5", "mov x1, x11", - "cbnz x21, #+0x1c", + "tbnz w21, #1, #+0x1c", "cbz x0, #+0x10", "strb w20, [x1], #1", "sub x0, x0, #0x1 (1)", @@ -3395,10 +3368,10 @@ "Comment": "0xab", "ExpectedArm64ASM": [ "uxth w20, w4", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", "mov x0, x5", "mov x1, x11", - "cbnz x21, #+0x1c", + "tbnz w21, #1, #+0x1c", "cbz x0, #+0x10", "strh w20, [x1], #2", "sub x0, x0, #0x1 (1)", @@ -3418,10 +3391,10 @@ "Comment": "0xab", "ExpectedArm64ASM": [ "mov w20, w4", - "ldrb w21, [x28, #714]", + "ldrsb x21, [x28, #714]", "mov x0, x5", "mov x1, x11", - "cbnz x21, #+0x1c", + "tbnz w21, #1, #+0x1c", "cbz x0, #+0x10", "str w20, [x1], #4", "sub x0, x0, #0x1 (1)", @@ -3444,10 +3417,10 @@ "0xab" ], "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", + "ldrsb x20, [x28, #714]", "mov x0, x5", "mov x1, x11", - "cbnz x20, #+0x1c", + "tbnz w20, #1, #+0x1c", "cbz x0, #+0x10", "str x4, [x1], #8", "sub x0, x0, #0x1 (1)", @@ -3463,58 +3436,48 @@ ] }, "lodsb": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 4, "Comment": "0xac", "ExpectedArm64ASM": [ "ldrb w20, [x10]", "bfxil x4, x20, #0, #8", - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "add x10, x10, x20" ] }, "lodsw": { - "ExpectedInstructionCount": 6, + "ExpectedInstructionCount": 4, "Comment": "0xad", "ExpectedArm64ASM": [ "ldrh w20, [x10]", "bfxil x4, x20, #0, #16", - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", - "add x10, x10, x20" + "ldrsb x20, [x28, #714]", + "add x10, x10, x20, lsl #1" ] }, "lodsd": { - "ExpectedInstructionCount": 5, + "ExpectedInstructionCount": 3, "Comment": "0xad", "ExpectedArm64ASM": [ "ldr w4, [x10]", - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", - "add x10, x10, x20" + "ldrsb x20, [x28, #714]", + "add x10, x10, x20, lsl #2" ] }, "lodsq": { - "ExpectedInstructionCount": 5, + "ExpectedInstructionCount": 3, "Comment": "0xad", "ExpectedArm64ASM": [ "ldr x4, [x10]", - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", - "add x10, x10, x20" + "ldrsb x20, [x28, #714]", + "add x10, x10, x20, lsl #3" ] }, "rep lodsb": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 7, "Comment": "0xac", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x18", "ldrb w21, [x10]", "bfxil x4, x21, #0, #8", @@ -3524,12 +3487,11 @@ ] }, "rep lodsw": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 8, "Comment": "0xad", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x18", "ldrh w21, [x10]", "bfxil x4, x21, #0, #16", @@ -3539,12 +3501,11 @@ ] }, "rep lodsd": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 7, "Comment": "0xad", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x14", "ldr w4, [x10]", "sub x5, x5, #0x1 (1)", @@ -3553,12 +3514,11 @@ ] }, "rep lodsq": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 7, "Comment": "0xad", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x14", "ldr x4, [x10]", "sub x5, x5, #0x1 (1)", @@ -3567,13 +3527,11 @@ ] }, "scasb": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 10, "Comment": "0xae", "ExpectedArm64ASM": [ "ldrb w20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x1", - "sub x21, x22, x21, lsl #1", + "ldrsb x21, [x28, #714]", "add x11, x11, x21", "eor w27, w4, w20", "lsl w0, w4, #24", @@ -3585,14 +3543,12 @@ ] }, "scasw": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 10, "Comment": "0xaf", "ExpectedArm64ASM": [ "ldrh w20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x2", - "sub x21, x22, x21, lsl #2", - "add x11, x11, x21", + "ldrsb x21, [x28, #714]", + "add x11, x11, x21, lsl #1", "eor w27, w4, w20", "lsl w0, w4, #16", "cmp w0, w20, lsl #16", @@ -3603,14 +3559,12 @@ ] }, "scasd": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 8, "Comment": "0xaf", "ExpectedArm64ASM": [ "ldr w20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x4", - "sub x21, x22, x21, lsl #3", - "add x11, x11, x21", + "ldrsb x21, [x28, #714]", + "add x11, x11, x21, lsl #2", "eor w27, w4, w20", "subs w26, w4, w20", "mrs x20, nzcv", @@ -3619,14 +3573,12 @@ ] }, "scasq": { - "ExpectedInstructionCount": 10, + "ExpectedInstructionCount": 8, "Comment": "0xaf", "ExpectedArm64ASM": [ "ldr x20, [x11]", - "ldrb w21, [x28, #714]", - "mov w22, #0x8", - "sub x21, x22, x21, lsl #4", - "add x11, x11, x21", + "ldrsb x21, [x28, #714]", + "add x11, x11, x21, lsl #3", "eor w27, w4, w20", "subs x26, x4, x20", "mrs x20, nzcv", @@ -3635,12 +3587,10 @@ ] }, "repz scasb": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 13, "Comment": "0xae", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x30", "ldrb w21, [x11]", "eor w27, w4, w21", @@ -3656,12 +3606,11 @@ ] }, "repz scasw": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x30", "ldrh w21, [x11]", "eor w27, w4, w21", @@ -3677,12 +3626,11 @@ ] }, "repz scasd": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x28", "ldr w21, [x11]", "eor w27, w4, w21", @@ -3696,12 +3644,11 @@ ] }, "repz scasq": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x28", "ldr x21, [x11]", "eor w27, w4, w21", @@ -3715,12 +3662,10 @@ ] }, "repnz scasb": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 13, "Comment": "0xae", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x1", - "sub x20, x21, x20, lsl #1", + "ldrsb x20, [x28, #714]", "cbz x5, #+0x30", "ldrb w21, [x11]", "eor w27, w4, w21", @@ -3736,12 +3681,11 @@ ] }, "repnz scasw": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 14, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x2", - "sub x20, x21, x20, lsl #2", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #1", "cbz x5, #+0x30", "ldrh w21, [x11]", "eor w27, w4, w21", @@ -3757,12 +3701,11 @@ ] }, "repnz scasd": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x4", - "sub x20, x21, x20, lsl #3", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #2", "cbz x5, #+0x28", "ldr w21, [x11]", "eor w27, w4, w21", @@ -3776,12 +3719,11 @@ ] }, "repnz scasq": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 12, "Comment": "0xaf", "ExpectedArm64ASM": [ - "ldrb w20, [x28, #714]", - "mov w21, #0x8", - "sub x20, x21, x20, lsl #4", + "ldrsb x20, [x28, #714]", + "lsl x20, x20, #3", "cbz x5, #+0x28", "ldr x21, [x11]", "eor w27, w4, w21", @@ -3909,7 +3851,7 @@ "ExpectedInstructionCount": 2, "Comment": "0xfc", "ExpectedArm64ASM": [ - "mov w20, #0x0", + "mov w20, #0x1", "strb w20, [x28, #714]" ] }, @@ -3917,7 +3859,7 @@ "ExpectedInstructionCount": 2, "Comment": "0xfd", "ExpectedArm64ASM": [ - "mov w20, #0x1", + "mov x20, #0xffffffffffffffff", "strb w20, [x28, #714]" ] }