diff --git a/FEXCore/Source/CMakeLists.txt b/FEXCore/Source/CMakeLists.txt index 8dd47388f..12ce2002d 100644 --- a/FEXCore/Source/CMakeLists.txt +++ b/FEXCore/Source/CMakeLists.txt @@ -70,6 +70,7 @@ set (SRCS Interface/Core/LookupCache.cpp Interface/Core/Core.cpp Interface/Core/CPUBackend.cpp + Interface/Core/Addressing.cpp Interface/Core/CPUID.cpp Interface/Core/Frontend.cpp Interface/Core/ObjectCache/JobHandling.cpp diff --git a/FEXCore/Source/Interface/Core/Addressing.cpp b/FEXCore/Source/Interface/Core/Addressing.cpp new file mode 100644 index 000000000..ae4155125 --- /dev/null +++ b/FEXCore/Source/Interface/Core/Addressing.cpp @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +#include "Interface/Core/Addressing.h" + +#include "Interface/IR/IREmitter.h" +#include "FEXCore/Utils/MathUtils.h" +#include "Interface/IR/IR.h" + +namespace FEXCore::IR { + +Ref LoadEffectiveAddress(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, bool AddSegmentBase, bool AllowUpperGarbage) { + Ref Tmp = A.Base; + + if (A.Offset) { + Ref Offset = IREmit->_Constant(A.Offset); + Tmp = Tmp ? IREmit->_Add(GPRSize, Tmp, Offset) : Offset; + } + + if (A.Index) { + if (A.IndexScale != 1) { + LOGMAN_THROW_A_FMT((A.IndexScale & (A.IndexScale - 1)) == 0, "power of two"); + uint32_t Log2 = FEXCore::ilog2(A.IndexScale); + + if (Tmp) { + Tmp = IREmit->_AddShift(GPRSize, Tmp, A.Index, ShiftType::LSL, Log2); + } else { + Tmp = IREmit->_Lshl(GPRSize, A.Index, IREmit->_Constant(Log2)); + } + } else { + Tmp = Tmp ? IREmit->_Add(GPRSize, Tmp, A.Index) : A.Index; + } + } + + // For 64-bit AddrSize can be 32-bit or 64-bit + // For 32-bit AddrSize can be 32-bit or 16-bit + // + // If the AddrSize is not the GPRSize then we need to clear the upper bits. + if ((A.AddrSize < GPRSize) && !AllowUpperGarbage && Tmp) { + Tmp = IREmit->_Bfe(GPRSize, IR::OpSizeAsBits(A.AddrSize), 0, Tmp); + } + + if (A.Segment && AddSegmentBase) { + Tmp = Tmp ? IREmit->_Add(GPRSize, Tmp, A.Segment) : A.Segment; + } + + return Tmp ?: IREmit->_Constant(0); +} + +AddressMode SelectAddressMode(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, bool HostSupportsTSOImm9, bool AtomicTSO, bool Vector, + IR::OpSize AccessSize) { + auto SoftwareAddressCalculation = [IREmit, &A, GPRSize]() -> AddressMode { + return { + .Base = LoadEffectiveAddress(IREmit, A, GPRSize, true), + .Index = IREmit->Invalid(), + }; + }; + + const auto Is32Bit = GPRSize == OpSize::i32Bit; + const auto GPRSizeMatchesAddrSize = A.AddrSize == GPRSize; + const auto OffsetIndexToLargeFor32Bit = Is32Bit && (A.Offset <= -16384 || A.Offset >= 16384); + if (!GPRSizeMatchesAddrSize || OffsetIndexToLargeFor32Bit) { + // If address size doesn't match GPR size then no optimizations can occur. + return SoftwareAddressCalculation(); + } + + // Loadstore rules: + // Non-TSO GPR: + // * LDR/STR: [Reg] + // * LDR/STR: [Reg + Reg, {Shift }] + // * Can't use with 32-bit + // * LDR/STR: [Reg + [0,4095] * ] + // * Imm must be smaller than 16k with 32-bit + // * LDUR/STUR: [Reg + [-256, 255]] + // + // TSO GPR: + // * ARMv8.0: + // LDAR/STLR: [Reg] + // * FEAT_LRCPC: + // LDAPR: [Reg] + // * FEAT_LRCPC2: + // LDAPUR/STLUR: [Reg + [-256, 255]] + // + // Non-TSO Vector: + // * LDR/STR: [Reg + [0,4095] * ] + // * LDUR/STUR: [Reg + [-256,255]] + // + // TSO Vector: + // * ARMv8.0: + // Just DMB + previous + // * FEAT_LRCPC3 (Unsupported by FEXCore currently): + // LDAPUR/STLUR: [Reg + [-256,255]] + + const auto AccessSizeAsImm = OpSizeToSize(AccessSize); + const bool OffsetIsSIMM9 = A.Offset && A.Offset >= -256 && A.Offset <= 255; + const bool OffsetIsUnsignedScaled = A.Offset > 0 && (A.Offset & (AccessSizeAsImm - 1)) == 0 && (A.Offset / AccessSizeAsImm) <= 4095; + + auto InlineImmOffsetLoadstore = [IREmit, &GPRSize](AddressMode A) -> AddressMode { + // Peel off the offset + AddressMode B = A; + B.Offset = 0; + + return { + .Base = LoadEffectiveAddress(IREmit, B, GPRSize, true /* AddSegmentBase */, false), + .Index = IREmit->_Constant(A.Offset), + .IndexType = MEM_OFFSET_SXTX, + .IndexScale = 1, + }; + }; + + auto ScaledRegisterLoadstore = [IREmit, GPRSize](AddressMode A) -> AddressMode { + if (A.Index && A.Segment) { + A.Base = IREmit->_Add(GPRSize, A.Base, A.Segment); + } else if (A.Segment) { + A.Index = A.Segment; + A.IndexScale = 1; + } + return A; + }; + + if (AtomicTSO) { + if (!Vector) { + if (HostSupportsTSOImm9 && OffsetIsSIMM9) { + return InlineImmOffsetLoadstore(A); + } + } else { + // TODO: LRCPC3 support for vector Imm9. + } + } else { + if (OffsetIsSIMM9 || OffsetIsUnsignedScaled) { + return InlineImmOffsetLoadstore(A); + } else if (!Is32Bit && A.Base && (A.Index || A.Segment) & !A.Offset && (A.IndexScale == 1 || A.IndexScale == AccessSizeAsImm)) { + return ScaledRegisterLoadstore(A); + } + } + + if (Vector || !AtomicTSO) { + if ((A.Base || A.Segment) && A.Offset) { + const bool Const_16K = A.Offset > -16384 && A.Offset < 16384 && GPRSizeMatchesAddrSize && Is32Bit; + + if (!Is32Bit || Const_16K) { + // Peel off the offset + AddressMode B = A; + B.Offset = 0; + + return { + .Base = LoadEffectiveAddress(IREmit, B, GPRSize, true /* AddSegmentBase */, false), + .Index = IREmit->_Constant(A.Offset), + .IndexType = MEM_OFFSET_SXTX, + .IndexScale = 1, + }; + } + } + } + + // Fallback on software address calculation + return SoftwareAddressCalculation(); +} + + +}; // namespace FEXCore::IR \ No newline at end of file diff --git a/FEXCore/Source/Interface/Core/Addressing.h b/FEXCore/Source/Interface/Core/Addressing.h new file mode 100644 index 000000000..96c4f7c3b --- /dev/null +++ b/FEXCore/Source/Interface/Core/Addressing.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +#pragma once + +#include "Interface/IR/IR.h" +#include + +namespace FEXCore::IR { +class IREmitter; + +struct AddressMode { + Ref Segment {nullptr}; + Ref Base {nullptr}; + Ref Index {nullptr}; + MemOffsetType IndexType = MEM_OFFSET_SXTX; + uint8_t IndexScale = 1; + int64_t Offset = 0; + + // Size in bytes for the address calculation. 8 for an arm64 hardware mode. + IR::OpSize AddrSize; + bool NonTSO; +}; + +Ref LoadEffectiveAddress(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, bool AddSegmentBase, bool AllowUpperGarbage = false); +AddressMode SelectAddressMode(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, bool HostSupportsTSOImm9, bool AtomicTSO, bool Vector, + IR::OpSize AccessSize); + +}; // namespace FEXCore::IR \ No newline at end of file diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 5900f0594..cf03a8fc6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -27,7 +27,6 @@ $end_info$ #include #include -#include #include #include @@ -2479,7 +2478,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { if (DestIsLockedMem(Op)) { HandledLock = true; - Value = _AtomicFetchCLR(OpSize::i8Bit, BitMask, LoadEffectiveAddress(Address, true)); + Value = _AtomicFetchCLR(OpSize::i8Bit, BitMask, LoadEffectiveAddress(this, Address, CTX->GetGPROpSize(), true)); } else { Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); @@ -2494,7 +2493,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { if (DestIsLockedMem(Op)) { HandledLock = true; - Value = _AtomicFetchOr(OpSize::i8Bit, BitMask, LoadEffectiveAddress(Address, true)); + Value = _AtomicFetchOr(OpSize::i8Bit, BitMask, LoadEffectiveAddress(this, Address, CTX->GetGPROpSize(), true)); } else { Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); @@ -2509,7 +2508,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { if (DestIsLockedMem(Op)) { HandledLock = true; - Value = _AtomicFetchXor(OpSize::i8Bit, BitMask, LoadEffectiveAddress(Address, true)); + Value = _AtomicFetchXor(OpSize::i8Bit, BitMask, LoadEffectiveAddress(this, Address, CTX->GetGPROpSize(), true)); } else { Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); @@ -4142,155 +4141,6 @@ void OpDispatchBuilder::UpdatePrefixFromSegment(Ref Segment, uint32_t SegmentReg } } -Ref OpDispatchBuilder::LoadEffectiveAddress(AddressMode A, bool AddSegmentBase, bool AllowUpperGarbage) { - const auto GPRSize = CTX->GetGPROpSize(); - Ref Tmp = A.Base; - - if (A.Offset) { - Ref Offset = _Constant(A.Offset); - Tmp = Tmp ? _Add(GPRSize, Tmp, Offset) : Offset; - } - - if (A.Index) { - if (A.IndexScale != 1) { - LOGMAN_THROW_A_FMT((A.IndexScale & (A.IndexScale - 1)) == 0, "power of two"); - uint32_t Log2 = FEXCore::ilog2(A.IndexScale); - - if (Tmp) { - Tmp = _AddShift(GPRSize, Tmp, A.Index, ShiftType::LSL, Log2); - } else { - Tmp = _Lshl(GPRSize, A.Index, _Constant(Log2)); - } - } else { - Tmp = Tmp ? _Add(GPRSize, Tmp, A.Index) : A.Index; - } - } - - // For 64-bit AddrSize can be 32-bit or 64-bit - // For 32-bit AddrSize can be 32-bit or 16-bit - // - // If the AddrSize is not the GPRSize then we need to clear the upper bits. - if ((A.AddrSize < GPRSize) && !AllowUpperGarbage && Tmp) { - Tmp = _Bfe(GPRSize, IR::OpSizeAsBits(A.AddrSize), 0, Tmp); - } - - if (A.Segment && AddSegmentBase) { - Tmp = Tmp ? _Add(GPRSize, Tmp, A.Segment) : A.Segment; - } - - return Tmp ?: _Constant(0); -} - -AddressMode OpDispatchBuilder::SelectAddressMode(AddressMode A, bool AtomicTSO, bool Vector, IR::OpSize AccessSize) { - auto SoftwareAddressCalculation = [this, &A]() -> AddressMode { - return { - .Base = LoadEffectiveAddress(A, true), - .Index = InvalidNode, - }; - }; - - const auto GPRSize = CTX->GetGPROpSize(); - const auto Is32Bit = GPRSize == OpSize::i32Bit; - const auto GPRSizeMatchesAddrSize = A.AddrSize == GPRSize; - const auto OffsetIndexToLargeFor32Bit = Is32Bit && (A.Offset <= -16384 || A.Offset >= 16384); - if (!GPRSizeMatchesAddrSize || OffsetIndexToLargeFor32Bit) { - // If address size doesn't match GPR size then no optimizations can occur. - return SoftwareAddressCalculation(); - } - - // Loadstore rules: - // Non-TSO GPR: - // * LDR/STR: [Reg] - // * LDR/STR: [Reg + Reg, {Shift }] - // * Can't use with 32-bit - // * LDR/STR: [Reg + [0,4095] * ] - // * Imm must be smaller than 16k with 32-bit - // * LDUR/STUR: [Reg + [-256, 255]] - // - // TSO GPR: - // * ARMv8.0: - // LDAR/STLR: [Reg] - // * FEAT_LRCPC: - // LDAPR: [Reg] - // * FEAT_LRCPC2: - // LDAPUR/STLUR: [Reg + [-256, 255]] - // - // Non-TSO Vector: - // * LDR/STR: [Reg + [0,4095] * ] - // * LDUR/STUR: [Reg + [-256,255]] - // - // TSO Vector: - // * ARMv8.0: - // Just DMB + previous - // * FEAT_LRCPC3 (Unsupported by FEXCore currently): - // LDAPUR/STLUR: [Reg + [-256,255]] - - const auto AccessSizeAsImm = OpSizeToSize(AccessSize); - const bool OffsetIsSIMM9 = A.Offset && A.Offset >= -256 && A.Offset <= 255; - const bool OffsetIsUnsignedScaled = A.Offset > 0 && (A.Offset & (AccessSizeAsImm - 1)) == 0 && (A.Offset / AccessSizeAsImm) <= 4095; - - auto InlineImmOffsetLoadstore = [this](AddressMode A) -> AddressMode { - // Peel off the offset - AddressMode B = A; - B.Offset = 0; - - return { - .Base = LoadEffectiveAddress(B, true /* AddSegmentBase */, false), - .Index = _InlineConstant(A.Offset), - .IndexType = MEM_OFFSET_SXTX, - .IndexScale = 1, - }; - }; - - auto ScaledRegisterLoadstore = [this, &GPRSize](AddressMode A) -> AddressMode { - if (A.Index && A.Segment) { - A.Base = _Add(GPRSize, A.Base, A.Segment); - } else if (A.Segment) { - A.Index = A.Segment; - A.IndexScale = 1; - } - return A; - }; - - if (AtomicTSO) { - if (!Vector) { - if (CTX->HostFeatures.SupportsTSOImm9 && OffsetIsSIMM9) { - return InlineImmOffsetLoadstore(A); - } - } else { - // TODO: LRCPC3 support for vector Imm9. - } - } else { - if (OffsetIsSIMM9 || OffsetIsUnsignedScaled) { - return InlineImmOffsetLoadstore(A); - } else if (!Is32Bit && A.Base && (A.Index || A.Segment) & !A.Offset && (A.IndexScale == 1 || A.IndexScale == AccessSizeAsImm)) { - return ScaledRegisterLoadstore(A); - } - } - - if (Vector || !AtomicTSO) { - if ((A.Base || A.Segment) && A.Offset) { - const bool Const_16K = A.Offset > -16384 && A.Offset < 16384 && GPRSizeMatchesAddrSize && Is32Bit; - - if (!Is32Bit || Const_16K) { - // Peel off the offset - AddressMode B = A; - B.Offset = 0; - - return { - .Base = LoadEffectiveAddress(B, true /* AddSegmentBase */, false), - .Index = _Constant(A.Offset), - .IndexType = MEM_OFFSET_SXTX, - .IndexScale = 1, - }; - } - } - } - - // Fallback on software address calculation - return SoftwareAddressCalculation(); -} - AddressMode OpDispatchBuilder::DecodeAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, MemoryAccessType AccessType, bool IsLoad) { const auto GPRSize = CTX->GetGPROpSize(); @@ -4388,7 +4238,7 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T if ((IsOperandMem(Operand, true) && LoadData) || ForceLoad) { if (OpSize == OpSize::f80Bit) { - Ref MemSrc = LoadEffectiveAddress(A, true); + Ref MemSrc = LoadEffectiveAddress(this, A, CTX->GetGPROpSize(), true); if (CTX->HostFeatures.SupportsSVE128 || CTX->HostFeatures.SupportsSVE256) { return _LoadMemX87SVEOptPredicate(OpSize::i128Bit, OpSize::i16Bit, MemSrc); } else { @@ -4400,7 +4250,7 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T return _LoadMemAutoTSO(Class, OpSize, A, Align == OpSize::iInvalid ? OpSize : Align); } else { - return LoadEffectiveAddress(A, false, AllowUpperGarbage); + return LoadEffectiveAddress(this, A, CTX->GetGPROpSize(), false, AllowUpperGarbage); } } @@ -4521,7 +4371,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl AddressMode A = DecodeAddress(Op, Operand, AccessType, false /* IsLoad */); if (OpSize == OpSize::f80Bit) { - Ref MemStoreDst = LoadEffectiveAddress(A, true); + Ref MemStoreDst = LoadEffectiveAddress(this, A, CTX->GetGPROpSize(), true); if (CTX->HostFeatures.SupportsSVE128 || CTX->HostFeatures.SupportsSVE256) { _StoreMemX87SVEOptPredicate(OpSize::i128Bit, OpSize::i16Bit, Src, MemStoreDst); } else { @@ -5579,9 +5429,9 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { // 1 = Invalid - {OPDReg(0xD9, 2) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSTF64, OpSize::i32Bit>}, + {OPDReg(0xD9, 2) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FST, OpSize::i32Bit>}, - {OPDReg(0xD9, 3) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSTF64, OpSize::i32Bit>}, + {OPDReg(0xD9, 3) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FST, OpSize::i32Bit>}, {OPDReg(0xD9, 4) | 0x00, 8, &OpDispatchBuilder::X87LDENVF64}, @@ -5676,7 +5526,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { // 6 = Invalid - {OPDReg(0xDB, 7) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSTF64, OpSize::f80Bit>}, + {OPDReg(0xDB, 7) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FST, OpSize::f80Bit>}, {OPD(0xDB, 0xC0), 8, &OpDispatchBuilder::X87FCMOV}, @@ -5727,9 +5577,9 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {OPDReg(0xDD, 1) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FISTF64, true>}, - {OPDReg(0xDD, 2) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSTF64, OpSize::i64Bit>}, + {OPDReg(0xDD, 2) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FST, OpSize::i64Bit>}, - {OPDReg(0xDD, 3) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSTF64, OpSize::i64Bit>}, + {OPDReg(0xDD, 3) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FST, OpSize::i64Bit>}, {OPDReg(0xDD, 4) | 0x00, 8, &OpDispatchBuilder::X87FRSTOR}, diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 1f71c34e9..d3cfc23b7 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -3,6 +3,7 @@ #include "Interface/Core/Frontend.h" #include "Interface/Core/X86Tables/X86Tables.h" +#include "Interface/Core/Addressing.h" #include "Interface/Context/Context.h" #include "Interface/IR/IR.h" #include "Interface/IR/IREmitter.h" @@ -72,19 +73,6 @@ struct LoadSourceOptions { bool AllowUpperGarbage = false; }; -struct AddressMode { - Ref Segment {nullptr}; - Ref Base {nullptr}; - Ref Index {nullptr}; - MemOffsetType IndexType = MEM_OFFSET_SXTX; - uint8_t IndexScale = 1; - int64_t Offset = 0; - - // Size in bytes for the address calculation. 8 for an arm64 hardware mode. - IR::OpSize AddrSize; - bool NonTSO; -}; - class OpDispatchBuilder final : public IREmitter { friend class FEXCore::IR::Pass; friend class FEXCore::IR::PassManager; @@ -753,7 +741,6 @@ public: void FLDF64_Const(OpcodeArgs, uint64_t Num); void FLDF64(OpcodeArgs, IR::OpSize Width); void FMULF64(OpcodeArgs, IR::OpSize Width, bool Integer, OpResult ResInST0); - void FSTF64(OpcodeArgs, IR::OpSize Width); void FSUBF64(OpcodeArgs, IR::OpSize Width, bool Integer, bool Reverse, OpResult ResInST0); void FTSTF64(OpcodeArgs); void X87FLDCWF64(OpcodeArgs); @@ -1492,9 +1479,6 @@ private: Ref GetRelocatedPC(const FEXCore::X86Tables::DecodedOp& Op, int64_t Offset = 0); - Ref LoadEffectiveAddress(AddressMode A, bool AddSegmentBase, bool AllowUpperGarbage = false); - AddressMode SelectAddressMode(AddressMode A, bool AtomicTSO, bool Vector, IR::OpSize AccessSize); - bool IsOperandMem(const X86Tables::DecodedOperand& Operand, bool Load) { // Literals are immediates as sources but memory addresses as destinations. return !(Load && Operand.IsLiteral()) && !Operand.IsGPR(); @@ -2387,7 +2371,7 @@ private: Ref _LoadMemAutoTSO(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, AddressMode A, IR::OpSize Align = IR::OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; - A = SelectAddressMode(A, AtomicTSO, Class != GPRClass, Size); + A = SelectAddressMode(this, A, CTX->GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, AtomicTSO, Class != GPRClass, Size); if (AtomicTSO) { return _LoadMemTSO(Class, Size, A.Base, A.Index, Align, A.IndexType, A.IndexScale); @@ -2407,7 +2391,7 @@ private: A.Offset = 0; } - Out.Base = LoadEffectiveAddress(A, true, false); + Out.Base = LoadEffectiveAddress(this, A, CTX->GetGPROpSize(), true, false); return Out; } @@ -2438,7 +2422,7 @@ private: Ref _StoreMemAutoTSO(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, AddressMode A, Ref Value, IR::OpSize Align = IR::OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; - A = SelectAddressMode(A, AtomicTSO, Class != GPRClass, Size); + A = SelectAddressMode(this, A, CTX->GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, AtomicTSO, Class != GPRClass, Size); if (AtomicTSO) { return _StoreMemTSO(Class, Size, Value, A.Base, A.Index, Align, A.IndexType, A.IndexScale); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index 6366687b7..3441e3896 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -9,6 +9,7 @@ $end_info$ #include "Interface/Core/OpcodeDispatcher.h" #include "Interface/Core/X86Tables/X86Tables.h" #include "Interface/IR/IR.h" +#include "Interface/Core/Addressing.h" #include #include @@ -129,23 +130,12 @@ void OpDispatchBuilder::FILD(OpcodeArgs) { } void OpDispatchBuilder::FST(OpcodeArgs, IR::OpSize Width) { - // Ref Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); - // FIXME: Is TSO relevant for x87? + const auto SourceSize = ReducedPrecisionMode ? OpSize::i64Bit : OpSize::i128Bit; AddressMode A = DecodeAddress(Op, Op->Dest, MemoryAccessType::DEFAULT, false); - // Index scale is a power of 2? - LOGMAN_THROW_A_FMT(A.IndexScale > 0 && (A.IndexScale & (A.IndexScale - 1)) == 0, "Invalid index scale"); + A = SelectAddressMode(this, A, CTX->GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, false, false, Width); + _StoreStackMem(SourceSize, Width, A.Base, A.Index, OpSize::iInvalid, A.IndexType, A.IndexScale, /*Float=*/true); - Ref Addr = A.Base ? A.Base : _Constant(0); - if (A.Index) { - Ref ScaledIndex = A.Index; - if (A.IndexScale > 1) { - ScaledIndex = _Lshl(A.AddrSize, ScaledIndex, _Constant(std::log2(A.IndexScale))); - } - Addr = _Add(A.AddrSize, Addr, ScaledIndex); - } - - _StoreStackMem(OpSize::i128Bit, Width, Addr, _Constant(A.Offset), /*Float=*/true); if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) { _PopStackDestroy(); } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index c1c09f967..840e90620 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -103,27 +103,6 @@ void OpDispatchBuilder::FILDF64(OpcodeArgs) { _PushStack(ConvertedData, Data, ReadWidth, false); } -void OpDispatchBuilder::FSTF64(OpcodeArgs, IR::OpSize Width) { - AddressMode A = DecodeAddress(Op, Op->Dest, MemoryAccessType::DEFAULT, false); - - // Index scale is a power of 2? - LOGMAN_THROW_A_FMT(A.IndexScale > 0 && (A.IndexScale & (A.IndexScale - 1)) == 0, "Invalid index scale"); - - Ref Addr = A.Base ? A.Base : _Constant(0); - if (A.Index) { - Ref ScaledIndex = A.Index; - if (A.IndexScale > 1) { - ScaledIndex = _Lshl(A.AddrSize, ScaledIndex, _Constant(std::log2(A.IndexScale))); - } - Addr = _Add(A.AddrSize, Addr, ScaledIndex); - } - - _StoreStackMem(OpSize::i64Bit, Width, Addr, _Constant(A.Offset), /*Float=*/true); - if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) { - _PopStackDestroy(); - } -} - void OpDispatchBuilder::FISTF64(OpcodeArgs, bool Truncate) { const auto Size = OpSizeFromSrc(Op); diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index 52c676904..e74e23037 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -2852,7 +2852,7 @@ "HasSideEffects": true, "X87": true }, - "StoreStackMem OpSize:$SourceSize, OpSize:$StoreSize, GPR:$Addr, GPR:$Offset, i1:$Float": { + "StoreStackMem OpSize:$SourceSize, OpSize:$StoreSize, GPR:$Addr, GPR:$Offset, OpSize:$Align, MemOffsetType:$OffsetType, u8:$OffsetScale, i1:$Float": { "Desc": [ "Takes the top value off the x87 stack and stores it to memory.", "SourceSize is 128bit for F80 values, 64-bit for low precision.", diff --git a/FEXCore/Source/Interface/IR/PassManager.cpp b/FEXCore/Source/Interface/IR/PassManager.cpp index fccbd41c5..337de1d21 100644 --- a/FEXCore/Source/Interface/IR/PassManager.cpp +++ b/FEXCore/Source/Interface/IR/PassManager.cpp @@ -70,7 +70,7 @@ void PassManager::AddDefaultPasses(FEXCore::Context::ContextImpl* ctx) { FEX_CONFIG_OPT(DisablePasses, O0); if (!DisablePasses()) { - InsertPass(CreateX87StackOptimizationPass(ctx->HostFeatures)); + InsertPass(CreateX87StackOptimizationPass(ctx->HostFeatures, ctx->GetGPROpSize())); InsertPass(CreateConstProp(ctx->HostFeatures.SupportsTSOImm9, &ctx->CPUID)); InsertPass(CreateDeadFlagCalculationEliminination()); } diff --git a/FEXCore/Source/Interface/IR/Passes.h b/FEXCore/Source/Interface/IR/Passes.h index 7da05bc6a..ffdcb8f10 100644 --- a/FEXCore/Source/Interface/IR/Passes.h +++ b/FEXCore/Source/Interface/IR/Passes.h @@ -20,7 +20,7 @@ class RegisterAllocationData; fextl::unique_ptr CreateConstProp(bool SupportsTSOImm9, const FEXCore::CPUIDEmu* CPUID); fextl::unique_ptr CreateDeadFlagCalculationEliminination(); fextl::unique_ptr CreateRegisterAllocationPass(); -fextl::unique_ptr CreateX87StackOptimizationPass(const FEXCore::HostFeatures&); +fextl::unique_ptr CreateX87StackOptimizationPass(const FEXCore::HostFeatures&, OpSize GPROpSize); namespace Validation { fextl::unique_ptr CreateIRValidation(); diff --git a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp index 30c9a5b0e..5b2204a48 100644 --- a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp +++ b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp @@ -6,8 +6,9 @@ #include "Interface/IR/PassManager.h" #include "FEXCore/IR/IR.h" #include "FEXCore/Utils/Profiler.h" +#include "FEXCore/Utils/MathUtils.h" #include "FEXCore/Core/HostFeatures.h" -#include "Interface/Core/ArchHelpers/Arm64Emitter.h" +#include "Interface/Core/Addressing.h" #include #include @@ -21,7 +22,7 @@ // and apply the operations in a block of code. Once the block finishes, we emit the necessary operations // that we recorded onto the virtual stack. This allows us to save a lot of code movement // to and from stack registers, top management and valid flags. It also allows us to -// perform memcpy optimizations like the one performed in STORESTACKMEMORY. +// perform memcpy optimizations like the one performed in STORESTACKMEM. // // By default we run on the fast path - i.e. we assume all values are in the stack and we have a complete // stack overview. However, if we encounter a value that's not in the virtual stack - maybe it was added @@ -148,8 +149,9 @@ private: class X87StackOptimization final : public Pass { public: - X87StackOptimization(const FEXCore::HostFeatures& Features) - : Features(Features) { + X87StackOptimization(const FEXCore::HostFeatures& Features, OpSize GPROpSize) + : Features(Features) + , GPROpSize(GPROpSize) { FEX_CONFIG_OPT(ReducedPrecision, X87REDUCEDPRECISION); ReducedPrecisionMode = ReducedPrecision; } @@ -157,11 +159,97 @@ public: private: const FEXCore::HostFeatures& Features; + const OpSize GPROpSize; bool ReducedPrecisionMode; // Helpers Ref RotateRight8(uint32_t V, Ref Amount); + void F80SplitStore_Helper(const IROp_StoreStackMem* Op, Ref StackNode) { + Ref AddrNode = IR->GetNode(Op->Addr); + Ref Offset = IR->GetNode(Op->Offset); + OpSize Align = Op->Align; + MemOffsetType OffsetType = Op->OffsetType; + uint8_t OffsetScale = Op->OffsetScale; + + IREmit->_StoreMem(FPRClass, OpSize::i64Bit, StackNode, AddrNode, Offset, Align, OffsetType, OffsetScale); + auto Upper = IREmit->_VExtractToGPR(OpSize::i128Bit, OpSize::i64Bit, StackNode, 1); + + // Store the Upper part of the register (the remaining 2 bytes) into memory. + AddressMode A {.Base = AddrNode, + .Index = Op->Offset.IsInvalid() ? nullptr : Offset, + .IndexType = MEM_OFFSET_SXTX, + .IndexScale = OffsetScale, + .Offset = 8, + .AddrSize = OpSize::i64Bit}; + A = SelectAddressMode(IREmit, A, GPROpSize, Features.SupportsTSOImm9, false, false, OpSize::i16Bit); + IREmit->_StoreMem(GPRClass, OpSize::i16Bit, Upper, A.Base, A.Index, OpSize::i64Bit, MEM_OFFSET_SXTX, A.IndexScale); + } + + void StoreStackMem_Helper(const IROp_StoreStackMem* Op, Ref StackNode) { + Ref AddrNode = IR->GetNode(Op->Addr); + Ref Offset = IR->GetNode(Op->Offset); + OpSize Align = Op->Align; + MemOffsetType OffsetType = Op->OffsetType; + uint8_t OffsetScale = Op->OffsetScale; + + // Normal Precision Mode + switch (Op->StoreSize) { + case OpSize::i32Bit: + case OpSize::i64Bit: { + StackNode = IREmit->_F80CVT(Op->StoreSize, StackNode); + IREmit->_StoreMem(FPRClass, Op->StoreSize, StackNode, AddrNode, Offset, Align, OffsetType, OffsetScale); + break; + } + + case OpSize::f80Bit: { + if (Features.SupportsSVE128 || Features.SupportsSVE256) { + AddressMode A {.Base = AddrNode, + .Index = Op->Offset.IsInvalid() ? nullptr : Offset, + .IndexType = MEM_OFFSET_SXTX, + .IndexScale = OffsetScale, + .AddrSize = OpSize::i64Bit}; + AddrNode = LoadEffectiveAddress(IREmit, A, GPROpSize, false); + IREmit->_StoreMemX87SVEOptPredicate(OpSize::i128Bit, OpSize::i16Bit, StackNode, AddrNode); + } else { // 80bit requires split-store + F80SplitStore_Helper(Op, StackNode); + } + break; + } + default: ERROR_AND_DIE_FMT("Unsupported x87 size"); + } + } + + // Performs a store to memory from a value the stack passed in as StackNode. + // This is the version dealing with the reduced precision case. + void StoreStackMem_Reduced_Helper(const IROp_StoreStackMem* Op, Ref StackNode) { + Ref AddrNode = IR->GetNode(Op->Addr); + Ref Offset = IR->GetNode(Op->Offset); + OpSize Align = Op->Align; + MemOffsetType OffsetType = Op->OffsetType; + uint8_t OffsetScale = Op->OffsetScale; + + switch (Op->StoreSize) { + case OpSize::i32Bit: { + StackNode = IREmit->_Float_FToF(OpSize::i32Bit, OpSize::i64Bit, StackNode); + [[fallthrough]]; + } + case OpSize::i64Bit: { + IREmit->_StoreMem(FPRClass, Op->StoreSize, StackNode, AddrNode, Offset, Align, OffsetType, OffsetScale); + break; + } + + // 80bit requires split-store + case OpSize::f80Bit: { + StackNode = IREmit->_F80CVTTo(StackNode, OpSize::i64Bit); + F80SplitStore_Helper(Op, StackNode); + break; + } + default: ERROR_AND_DIE_FMT("Unsupported x87 size"); + } + } + + // Helper to check if a Ref is a Zero constant bool IsZero(Ref Node) { auto Header = IR->GetOp(Node); @@ -173,7 +261,6 @@ private: return Const->Constant == 0; } - // Handles a Unary operation. // Takes the op we are handling, the Node for the reduced precision case and the node for the normal case. // Depending on the type of Op64, we might need to pass a couple of extra constant arguments, this happens @@ -801,6 +888,9 @@ void X87StackOptimization::Run(IREmitter* Emit) { Ref StackNode = SlowPath ? LoadStackValueAtOffset_Slow() : Value->StackDataNode; Ref AddrNode = CurrentIR.GetNode(Op->Addr); Ref Offset = CurrentIR.GetNode(Op->Offset); + OpSize Align = Op->Align; + MemOffsetType OffsetType = Op->OffsetType; + uint8_t OffsetScale = Op->OffsetScale; // On the fast path we can optimize memory copies. // If we are doing: @@ -812,51 +902,17 @@ void X87StackOptimization::Run(IREmitter* Emit) { // or similar. As long as the source size and dest size are one and the same. // This will avoid any conversions between source and stack element size and conversion back. if (!SlowPath && Value->Source && Value->Source->first == Op->StoreSize && Value->InterpretAsFloat) { - IREmit->_StoreMem(Value->InterpretAsFloat ? FPRClass : GPRClass, Op->StoreSize, Value->Source->second, AddrNode, Offset, - OpSize::iInvalid, MEM_OFFSET_SXTX, 1); - } else { - if (ReducedPrecisionMode) { - switch (Op->StoreSize) { - case OpSize::i32Bit: - case OpSize::i64Bit: { - if (Op->StoreSize == OpSize::i32Bit) { - StackNode = IREmit->_Float_FToF(OpSize::i32Bit, OpSize::i64Bit, StackNode); - } - IREmit->_StoreMem(FPRClass, Op->StoreSize, StackNode, AddrNode, Offset, OpSize::iInvalid, MEM_OFFSET_SXTX, 1); - break; - } - case OpSize::f80Bit: { - StackNode = IREmit->_F80CVTTo(StackNode, OpSize::i64Bit); - IREmit->_StoreMem(FPRClass, OpSize::i64Bit, StackNode, AddrNode, Offset, OpSize::iInvalid, MEM_OFFSET_SXTX, 1); - auto Upper = IREmit->_VExtractToGPR(OpSize::i128Bit, OpSize::i64Bit, StackNode, 1); - auto NewOffset = IREmit->_Add(OpSize::i64Bit, Offset, GetConstant(8)); - IREmit->_StoreMem(GPRClass, OpSize::i16Bit, Upper, AddrNode, NewOffset, OpSize::i64Bit, MEM_OFFSET_SXTX, 1); - break; - } - default: ERROR_AND_DIE_FMT("Unsupported x87 size"); - } - } else { // !ReducedPrecisionMode - if (Op->StoreSize != OpSize::f80Bit) { // if it's not 80bits then convert - StackNode = IREmit->_F80CVT(Op->StoreSize, StackNode); - } - if (Op->StoreSize == OpSize::f80Bit) { - if (Features.SupportsSVE128 || Features.SupportsSVE256) { - if (!IsZero(Offset)) { - AddrNode = IREmit->_Add(OpSize::i64Bit, AddrNode, Offset); - } - IREmit->_StoreMemX87SVEOptPredicate(OpSize::i128Bit, OpSize::i16Bit, StackNode, AddrNode); - } else { - // For X87 extended doubles, split before storing - IREmit->_StoreMem(FPRClass, OpSize::i64Bit, StackNode, AddrNode, Offset, OpSize::iInvalid, MEM_OFFSET_SXTX, 1); - auto Upper = IREmit->_VExtractToGPR(OpSize::i128Bit, OpSize::i64Bit, StackNode, 1); - auto NewOffset = IREmit->_Add(OpSize::i64Bit, Offset, GetConstant(8)); - IREmit->_StoreMem(GPRClass, OpSize::i16Bit, Upper, AddrNode, NewOffset, OpSize::i64Bit, MEM_OFFSET_SXTX, 1); - } - } else { - IREmit->_StoreMem(FPRClass, Op->StoreSize, StackNode, AddrNode, Offset, OpSize::iInvalid, MEM_OFFSET_SXTX, 1); - } - } + IREmit->_StoreMem(Value->InterpretAsFloat ? FPRClass : GPRClass, Op->StoreSize, Value->Source->second, AddrNode, Offset, Align, + OffsetType, OffsetScale); + break; } + + if (ReducedPrecisionMode) { + StoreStackMem_Reduced_Helper(Op, StackNode); + break; + } + + StoreStackMem_Helper(Op, StackNode); break; } @@ -1046,7 +1102,7 @@ void X87StackOptimization::Run(IREmitter* Emit) { return; } -fextl::unique_ptr CreateX87StackOptimizationPass(const FEXCore::HostFeatures& Features) { - return fextl::make_unique(Features); +fextl::unique_ptr CreateX87StackOptimizationPass(const FEXCore::HostFeatures& Features, OpSize GPROpSize) { + return fextl::make_unique(Features, GPROpSize); } } // namespace FEXCore::IR diff --git a/unittests/InstructionCountCI/FlagM/x87-HalfLife.json b/unittests/InstructionCountCI/FlagM/x87-HalfLife.json index f265e096b..ea9102c9c 100644 --- a/unittests/InstructionCountCI/FlagM/x87-HalfLife.json +++ b/unittests/InstructionCountCI/FlagM/x87-HalfLife.json @@ -283,6 +283,7 @@ "ldp x17, x30, [sp], #16", "fmov s7, s0", "str s7, [x8, #16]", + "mov w20, #0x8", "ldr s7, [x7, #8]", "mrs x0, nzcv", "str w0, [x28, #1000]", @@ -1320,42 +1321,41 @@ "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", "ldr x16, [sp], #16", "ldp x17, x30, [sp], #16", - "mov x20, x0", - "ubfx x21, x20, #1, #1", - "ubfx x22, x20, #0, #1", - "ubfx x20, x20, #2, #1", - "orr w21, w21, w20", - "orr w22, w22, w20", - "eor x21, x21, #0x1", - "rmif x21, #63, #nzCv", - "rmif x22, #62, #nZcv", - "mov w21, #0x1", - "eor w26, w20, #0x1", - "ldrb w20, [x28, #1019]", - "sub w20, w20, #0x3 (3)", - "and w20, w20, #0x7", - "strb w20, [x28, #1019]", - "add x0, x28, x20, lsl #4", + "mov x21, x0", + "ubfx x22, x21, #1, #1", + "ubfx x23, x21, #0, #1", + "ubfx x21, x21, #2, #1", + "orr w22, w22, w21", + "orr w23, w23, w21", + "eor x22, x22, #0x1", + "rmif x22, #63, #nzCv", + "rmif x23, #62, #nZcv", + "mov w22, #0x1", + "eor w26, w21, #0x1", + "ldrb w21, [x28, #1019]", + "sub w21, w21, #0x3 (3)", + "and w21, w21, #0x7", + "strb w21, [x28, #1019]", + "add x0, x28, x21, lsl #4", "str q4, [x0, #1040]", - "add w22, w20, #0x1 (1)", - "and w22, w22, #0x7", - "add x0, x28, x22, lsl #4", + "add w23, w21, #0x1 (1)", + "and w23, w23, #0x7", + "add x0, x28, x23, lsl #4", "str q7, [x0, #1040]", - "add w22, w20, #0x2 (2)", - "and w22, w22, #0x7", - "add x0, x28, x22, lsl #4", + "add w23, w21, #0x2 (2)", + "and w23, w23, #0x7", + "add x0, x28, x23, lsl #4", "str q2, [x0, #1040]", - "add w22, w20, #0x3 (3)", - "and w22, w22, #0x7", - "mov w23, #0x8", - "sub w20, w23, w20", - "ldrb w23, [x28, #1298]", + "add w23, w21, #0x3 (3)", + "and w23, w23, #0x7", + "sub w20, w20, w21", + "ldrb w21, [x28, #1298]", "mov w24, #0x707", "lsr w20, w24, w20", - "orr w20, w23, w20", + "orr w20, w21, w20", "strb w20, [x28, #1298]", "ldrb w20, [x28, #1298]", - "lsl w21, w21, w22", + "lsl w21, w22, w23", "bic w20, w20, w21", "strb w20, [x28, #1298]" ] @@ -1602,6 +1602,7 @@ "csetm x21, ls", "dup v5.2d, x21", "bit v3.16b, v4.16b, v5.16b", + "mov w21, #0x8", "ldr s4, [x5, #8]", "mrs x0, nzcv", "str w0, [x28, #1000]", @@ -1687,17 +1688,17 @@ "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", "ldr x16, [sp], #16", "ldp x17, x30, [sp], #16", - "mov x21, x0", - "ubfx x22, x21, #1, #1", - "ubfx x23, x21, #0, #1", - "ubfx x21, x21, #2, #1", - "orr w22, w22, w21", - "orr w21, w23, w21", - "eor x22, x22, #0x1", - "rmif x22, #63, #nzCv", - "rmif x21, #62, #nZcv", - "csetm x21, ls", - "dup v6.2d, x21", + "mov x22, x0", + "ubfx x23, x22, #1, #1", + "ubfx x24, x22, #0, #1", + "ubfx x22, x22, #2, #1", + "orr w23, w23, w22", + "orr w22, w24, w22", + "eor x23, x23, #0x1", + "rmif x23, #63, #nzCv", + "rmif x22, #62, #nZcv", + "csetm x22, ls", + "dup v6.2d, x22", "bit v4.16b, v5.16b, v6.16b", "mrs x0, nzcv", "str w0, [x28, #1000]", @@ -1887,37 +1888,36 @@ "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", "ldr x16, [sp], #16", "ldp x17, x30, [sp], #16", - "mov x21, x0", - "ubfx x22, x21, #1, #1", - "ubfx x23, x21, #0, #1", - "ubfx x21, x21, #2, #1", - "orr w22, w22, w21", - "orr w23, w23, w21", - "eor x22, x22, #0x1", - "rmif x22, #63, #nzCv", - "rmif x23, #62, #nZcv", - "eor w26, w21, #0x1", - "ldrb w21, [x28, #1019]", - "sub w21, w21, #0x2 (2)", - "and w21, w21, #0x7", - "strb w21, [x28, #1019]", - "add x0, x28, x21, lsl #4", - "str q3, [x0, #1040]", - "add w22, w21, #0x1 (1)", + "mov x22, x0", + "ubfx x23, x22, #1, #1", + "ubfx x24, x22, #0, #1", + "ubfx x22, x22, #2, #1", + "orr w23, w23, w22", + "orr w24, w24, w22", + "eor x23, x23, #0x1", + "rmif x23, #63, #nzCv", + "rmif x24, #62, #nZcv", + "eor w26, w22, #0x1", + "ldrb w22, [x28, #1019]", + "sub w22, w22, #0x2 (2)", "and w22, w22, #0x7", + "strb w22, [x28, #1019]", "add x0, x28, x22, lsl #4", + "str q3, [x0, #1040]", + "add w23, w22, #0x1 (1)", + "and w23, w23, #0x7", + "add x0, x28, x23, lsl #4", "str q2, [x0, #1040]", - "add w22, w21, #0x6 (6)", - "and w22, w22, #0x7", - "mov w23, #0x8", - "sub w21, w23, w21", - "ldrb w23, [x28, #1298]", + "add w23, w22, #0x6 (6)", + "and w23, w23, #0x7", + "sub w21, w21, w22", + "ldrb w22, [x28, #1298]", "mov w24, #0x303", "lsr w21, w24, w21", - "orr w21, w23, w21", + "orr w21, w22, w21", "strb w21, [x28, #1298]", "ldrb w21, [x28, #1298]", - "lsl w20, w20, w22", + "lsl w20, w20, w23", "bic w20, w21, w20", "strb w20, [x28, #1298]" ] @@ -4220,6 +4220,7 @@ "ldr x16, [sp], #16", "ldp x17, x30, [sp], #16", "mov v3.16b, v0.16b", + "mov w20, #0x8", "ldr s4, [x7, #8]", "mrs x0, nzcv", "str w0, [x28, #1000]", @@ -4815,46 +4816,45 @@ "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", "ldr x16, [sp], #16", "ldp x17, x30, [sp], #16", - "mov x20, x0", - "ubfx x21, x20, #1, #1", - "ubfx x22, x20, #0, #1", - "ubfx x20, x20, #2, #1", - "orr w21, w21, w20", - "orr w22, w22, w20", - "eor x21, x21, #0x1", - "rmif x21, #63, #nzCv", - "rmif x22, #62, #nZcv", - "mov w21, #0x1", - "eor w26, w20, #0x1", - "ldrb w20, [x28, #1019]", - "sub w20, w20, #0x4 (4)", - "and w20, w20, #0x7", - "strb w20, [x28, #1019]", - "add x0, x28, x20, lsl #4", + "mov x21, x0", + "ubfx x22, x21, #1, #1", + "ubfx x23, x21, #0, #1", + "ubfx x21, x21, #2, #1", + "orr w22, w22, w21", + "orr w23, w23, w21", + "eor x22, x22, #0x1", + "rmif x22, #63, #nzCv", + "rmif x23, #62, #nZcv", + "mov w22, #0x1", + "eor w26, w21, #0x1", + "ldrb w21, [x28, #1019]", + "sub w21, w21, #0x4 (4)", + "and w21, w21, #0x7", + "strb w21, [x28, #1019]", + "add x0, x28, x21, lsl #4", "str q5, [x0, #1040]", - "add w22, w20, #0x1 (1)", - "and w22, w22, #0x7", - "add x0, x28, x22, lsl #4", + "add w23, w21, #0x1 (1)", + "and w23, w23, #0x7", + "add x0, x28, x23, lsl #4", "str q4, [x0, #1040]", - "add w22, w20, #0x2 (2)", - "and w22, w22, #0x7", - "add x0, x28, x22, lsl #4", + "add w23, w21, #0x2 (2)", + "and w23, w23, #0x7", + "add x0, x28, x23, lsl #4", "str q3, [x0, #1040]", - "add w22, w20, #0x3 (3)", - "and w22, w22, #0x7", - "add x0, x28, x22, lsl #4", + "add w23, w21, #0x3 (3)", + "and w23, w23, #0x7", + "add x0, x28, x23, lsl #4", "str q2, [x0, #1040]", - "add w22, w20, #0x7 (7)", - "and w22, w22, #0x7", - "mov w23, #0x8", - "sub w20, w23, w20", - "ldrb w23, [x28, #1298]", + "add w23, w21, #0x7 (7)", + "and w23, w23, #0x7", + "sub w20, w20, w21", + "ldrb w21, [x28, #1298]", "mov w24, #0xf0f", "lsr w20, w24, w20", - "orr w20, w23, w20", + "orr w20, w21, w20", "strb w20, [x28, #1298]", "ldrb w20, [x28, #1298]", - "lsl w21, w21, w22", + "lsl w21, w22, w23", "bic w20, w20, w21", "strb w20, [x28, #1298]" ] diff --git a/unittests/InstructionCountCI/FlagM/x87-Oblivion.json b/unittests/InstructionCountCI/FlagM/x87-Oblivion.json index f85d0766b..1b039c270 100644 --- a/unittests/InstructionCountCI/FlagM/x87-Oblivion.json +++ b/unittests/InstructionCountCI/FlagM/x87-Oblivion.json @@ -70323,7 +70323,7 @@ }, "Block10": { "x86InstructionCount": 206, - "ExpectedInstructionCount": 441, + "ExpectedInstructionCount": 440, "x86Insts": [ "fld dword [0x00b42a74]", "push ecx", @@ -70537,77 +70537,76 @@ "movk w20, #0xb4, lsl #16", "ldr s2, [x20]", "str w7, [x8, #-4]!", - "mov w20, #0x0", - "mov w21, #0x2a20", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", + "mov w20, #0x2a20", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", "add w7, w8, #0x48 (72)", - "mov w21, #0x2a78", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a24", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a7c", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a28", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a68", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a2c", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a6c", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a30", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a70", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a34", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a5c", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a38", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a60", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a3c", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a64", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a40", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a50", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a44", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a54", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a48", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", - "mov w21, #0x2a58", - "movk w21, #0xb4, lsl #16", - "ldr s2, [x21]", - "mov w21, #0x2a4c", - "movk w21, #0xb4, lsl #16", - "str s2, [x20, x21, sxtx]", + "mov w20, #0x2a78", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a24", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a7c", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a28", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a68", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a2c", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a6c", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a30", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a70", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a34", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a5c", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a38", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a60", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a3c", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a64", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a40", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a50", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a44", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a54", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a48", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", + "mov w20, #0x2a58", + "movk w20, #0xb4, lsl #16", + "ldr s2, [x20]", + "mov w20, #0x2a4c", + "movk w20, #0xb4, lsl #16", + "str s2, [x20]", "ldrb w20, [x28, #1019]", "add w20, w20, #0x7 (7)", "and w20, w20, #0x7", diff --git a/unittests/InstructionCountCI/FlagM/x87-Psychonauts.json b/unittests/InstructionCountCI/FlagM/x87-Psychonauts.json index 58bcc90c0..69d0c073c 100644 --- a/unittests/InstructionCountCI/FlagM/x87-Psychonauts.json +++ b/unittests/InstructionCountCI/FlagM/x87-Psychonauts.json @@ -69480,7 +69480,7 @@ }, "Block8": { "x86InstructionCount": 231, - "ExpectedInstructionCount": 8099, + "ExpectedInstructionCount": 8075, "x86Insts": [ "fadd dword [esp + 0x40]", "lea edx,[ecx + ecx*0x2]", @@ -71365,8 +71365,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w6, #2", - "add w22, w4, w22", + "add w22, w4, w6, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -71474,8 +71473,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -71556,8 +71554,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -71682,8 +71679,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -72053,8 +72049,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -72229,8 +72224,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -72653,8 +72647,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -72875,8 +72868,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -73927,8 +73919,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -74036,8 +74027,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -74118,8 +74108,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -74244,8 +74233,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -74583,8 +74571,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -74714,8 +74701,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -75072,8 +75058,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -75189,8 +75174,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -76241,8 +76225,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -76350,8 +76333,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -76432,8 +76414,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -76558,8 +76539,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -76929,8 +76909,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -77108,8 +77087,7 @@ "add x0, x28, x22, lsl #4", "str q2, [x0, #1040]", "strb wzr, [x28, #1017]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -77532,8 +77510,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -77754,8 +77731,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -77818,7 +77794,7 @@ }, "Block9": { "x86InstructionCount": 222, - "ExpectedInstructionCount": 8021, + "ExpectedInstructionCount": 7997, "x86Insts": [ "fadd dword [esp + 0x40]", "lea edx,[ecx + ecx*0x2]", @@ -79688,8 +79664,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w6, #2", - "add w22, w4, w22", + "add w22, w4, w6, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -79797,8 +79772,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -79879,8 +79853,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -79992,8 +79965,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -80356,8 +80328,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -80532,8 +80503,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -80956,8 +80926,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -81178,8 +81147,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -82224,8 +82192,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -82333,8 +82300,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -82415,8 +82381,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -82528,8 +82493,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -82860,8 +82824,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -82991,8 +82954,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -83349,8 +83311,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -83466,8 +83427,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -84512,8 +84472,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -84621,8 +84580,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w7, #2", - "add w22, w4, w22", + "add w22, w4, w7, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -84703,8 +84661,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -84816,8 +84773,7 @@ "mov v2.16b, v0.16b", "add x0, x28, x20, lsl #4", "str q2, [x0, #1040]", - "lsl w22, w5, #2", - "add w22, w4, w22", + "add w22, w4, w5, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -85180,8 +85136,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -85359,8 +85314,7 @@ "add x0, x28, x22, lsl #4", "str q2, [x0, #1040]", "strb wzr, [x28, #1017]", - "lsl w22, w10, #2", - "add w22, w4, w22", + "add w22, w4, w10, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -85783,8 +85737,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", @@ -86005,8 +85958,7 @@ "add w20, w20, #0x1 (1)", "and w20, w20, #0x7", "strb w20, [x28, #1019]", - "lsl w22, w11, #2", - "add w22, w4, w22", + "add w22, w4, w11, lsl #2", "add x0, x28, x20, lsl #4", "ldr q2, [x0, #1040]", "mrs x0, nzcv", diff --git a/unittests/InstructionCountCI/FlagM/x87.json b/unittests/InstructionCountCI/FlagM/x87.json index 2e45f70c0..0286611f4 100644 --- a/unittests/InstructionCountCI/FlagM/x87.json +++ b/unittests/InstructionCountCI/FlagM/x87.json @@ -11292,6 +11292,7 @@ "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", "ldr x30, [sp], #16", "mov v3.16b, v0.16b", + "mov w20, #0x8", "ldr s4, [x4, #8]", "mrs x0, nzcv", "str w0, [x28, #1000]", @@ -11346,32 +11347,31 @@ "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", "ldr x30, [sp], #16", "mov v5.16b, v0.16b", - "ldrb w20, [x28, #1019]", - "sub w20, w20, #0x4 (4)", - "and w20, w20, #0x7", - "strb w20, [x28, #1019]", - "add x0, x28, x20, lsl #4", - "str q5, [x0, #1040]", - "add w21, w20, #0x1 (1)", + "ldrb w21, [x28, #1019]", + "sub w21, w21, #0x4 (4)", "and w21, w21, #0x7", + "strb w21, [x28, #1019]", "add x0, x28, x21, lsl #4", - "str q4, [x0, #1040]", - "add w22, w20, #0x2 (2)", + "str q5, [x0, #1040]", + "add w22, w21, #0x1 (1)", "and w22, w22, #0x7", "add x0, x28, x22, lsl #4", - "str q3, [x0, #1040]", - "add w23, w20, #0x3 (3)", + "str q4, [x0, #1040]", + "add w23, w21, #0x2 (2)", "and w23, w23, #0x7", "add x0, x28, x23, lsl #4", + "str q3, [x0, #1040]", + "add w24, w21, #0x3 (3)", + "and w24, w24, #0x7", + "add x0, x28, x24, lsl #4", "str q2, [x0, #1040]", - "mov w24, #0x8", - "sub w25, w24, w20", + "sub w25, w20, w21", "ldrb w30, [x28, #1298]", "mov w18, #0xf0f", "lsr w25, w18, w25", "orr w25, w30, w25", "strb w25, [x28, #1298]", - "lsl x25, x20, #11", + "lsl x25, x21, #11", "ldrb w30, [x28, #1016]", "orr x25, x25, x30, lsl #8", "ldrb w30, [x28, #1017]", @@ -11381,15 +11381,15 @@ "ldrb w30, [x28, #1022]", "orr x25, x25, x30, lsl #14", "strh w25, [x6]", - "add x0, x28, x20, lsl #4", - "str q5, [x0, #1040]", "add x0, x28, x21, lsl #4", - "str q4, [x0, #1040]", + "str q5, [x0, #1040]", "add x0, x28, x22, lsl #4", - "str q3, [x0, #1040]", + "str q4, [x0, #1040]", "add x0, x28, x23, lsl #4", + "str q3, [x0, #1040]", + "add x0, x28, x24, lsl #4", "str q2, [x0, #1040]", - "sub w20, w24, w20", + "sub w20, w20, w21", "ldrb w21, [x28, #1298]", "lsr w20, w18, w20", "orr w20, w21, w20", diff --git a/unittests/InstructionCountCI/x87.json b/unittests/InstructionCountCI/x87.json index dcf66f33d..4bdd0f977 100644 --- a/unittests/InstructionCountCI/x87.json +++ b/unittests/InstructionCountCI/x87.json @@ -17151,7 +17151,7 @@ }, "Multiple fld/fst": { "x86InstructionCount": 4, - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 22, "x86Insts": [ "fld qword [ebp+16380]", "fstp qword [eax-0x4]", @@ -17163,12 +17163,16 @@ "add x20, x9, x20", "mov w20, w20", "ldr d2, [x20]", - "stur d2, [x4, #-4]", + "sub x20, x4, #0x4 (4)", + "mov w20, w20", + "str d2, [x20]", "sub x20, x9, #0x8 (8)", "mov w20, w20", "ldr d2, [x20]", "mov w20, #0x3ff2", - "str d2, [x4, x20, sxtx]", + "add x20, x4, x20", + "mov w20, w20", + "str d2, [x20]", "ldrb w20, [x28, #1019]", "add w20, w20, #0x7 (7)", "and w20, w20, #0x7", diff --git a/unittests/InstructionCountCI/x87_f64.json b/unittests/InstructionCountCI/x87_f64.json index a5fa5c177..948abb4d1 100644 --- a/unittests/InstructionCountCI/x87_f64.json +++ b/unittests/InstructionCountCI/x87_f64.json @@ -10190,7 +10190,7 @@ }, "Multiple fld/fst": { "x86InstructionCount": 4, - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 22, "x86Insts": [ "fld qword [ebp+16380]", "fstp qword [eax-0x4]", @@ -10202,12 +10202,16 @@ "add x20, x9, x20", "mov w20, w20", "ldr d2, [x20]", - "stur d2, [x4, #-4]", + "sub x20, x4, #0x4 (4)", + "mov w20, w20", + "str d2, [x20]", "sub x20, x9, #0x8 (8)", "mov w20, w20", "ldr d2, [x20]", "mov w20, #0x3ff2", - "str d2, [x4, x20, sxtx]", + "add x20, x4, x20", + "mov w20, w20", + "str d2, [x20]", "ldrb w20, [x28, #1019]", "add w20, w20, #0x7 (7)", "and w20, w20, #0x7", diff --git a/unittests/InstructionCountCI/x87_f64_32Bit.json b/unittests/InstructionCountCI/x87_f64_32Bit.json new file mode 100644 index 000000000..029923d62 --- /dev/null +++ b/unittests/InstructionCountCI/x87_f64_32Bit.json @@ -0,0 +1,42 @@ +{ + "Features": { + "Env": { + "FEX_X87REDUCEDPRECISION": "1" + }, + "Bitness": 32, + "EnabledHostFeatures": [ + "AFP", + "RPRES", + "FLAGM", + "FLAGM2" + ], + "DisabledHostFeatures": [ + "SVE128", + "SVE256", + "CSSC" + ] + }, + "Instructions": { + "fstp dword [ebx*4+0x204a20]": { + "ExpectedInstructionCount": 16, + "ExpectedArm64ASM": [ + "mov w20, #0x4a20", + "movk w20, #0x20, lsl #16", + "add w20, w20, w6, lsl #2", + "ldrb w21, [x28, #1019]", + "add x0, x28, x21, lsl #4", + "ldr d2, [x0, #1040]", + "fcvt s2, d2", + "str s2, [x20]", + "ldrb w20, [x28, #1298]", + "mov w22, #0x1", + "lsl w22, w22, w21", + "bic w20, w20, w22", + "strb w20, [x28, #1298]", + "add w20, w21, #0x1 (1)", + "and w20, w20, #0x7", + "strb w20, [x28, #1019]" + ] + } + } +}