diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp index 40692c84f..71380ce54 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp @@ -1020,14 +1020,22 @@ DEF_OP(Bfi) { const auto SrcDst = GetReg(Op->Dest.ID()); const auto Src = GetReg(Op->Src.ID()); - mov(EmitSize, TMP1, SrcDst); - bfi(EmitSize, TMP1, Src, Op->lsb, Op->Width); - - if (OpSize == 8) { - mov(EmitSize, Dst, TMP1.R()); + if (Dst == SrcDst) { + // If Dst and SrcDst match then this turns in to a simple BFI instruction. + bfi(EmitSize, Dst, Src, Op->lsb, Op->Width); } else { - ubfx(EmitSize, Dst, TMP1, 0, OpSize * 8); + // Destination didn't match the dst source register. + // TODO: Inefficient until FEX can have RA constraints here. + mov(EmitSize, TMP1, SrcDst); + bfi(EmitSize, TMP1, Src, Op->lsb, Op->Width); + + if (OpSize == 8) { + mov(EmitSize, Dst, TMP1.R()); + } + else { + ubfx(EmitSize, Dst, TMP1, 0, OpSize * 8); + } } } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 1749aac7d..ccd603132 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1554,7 +1554,7 @@ void OpDispatchBuilder::SAHFOp(OpcodeArgs) { } void OpDispatchBuilder::LAHFOp(OpcodeArgs) { // Load the lower 8 bits of the Rflags register - auto RFLAG = GetPackedRFLAG(true); + auto RFLAG = GetPackedRFLAG(0xFF); // Store the lower 8 bits of the rflags register in to AH StoreGPRRegister(X86State::REG_RAX, RFLAG, 1, 8); @@ -4269,7 +4269,7 @@ void OpDispatchBuilder::BSWAPOp(OpcodeArgs) { void OpDispatchBuilder::PUSHFOp(OpcodeArgs) { const uint8_t Size = GetSrcSize(Op); - OrderedNode *Src = GetPackedRFLAG(false); + OrderedNode *Src = GetPackedRFLAG(); if (Size != 8) { Src = _Bfe(Size * 8, 0, Src); } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 7ff483103..d390578e6 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -827,7 +827,7 @@ public: void InvalidOp(OpcodeArgs); void SetPackedRFLAG(bool Lower8, OrderedNode *Src); - OrderedNode *GetPackedRFLAG(bool Lower8); + OrderedNode *GetPackedRFLAG(uint32_t FlagsMask = ~0U); void SetMultiblock(bool _Multiblock) { Multiblock = _Multiblock; } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index a61c9f904..0eddf0e59 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -59,22 +59,19 @@ void OpDispatchBuilder::SetPackedRFLAG(bool Lower8, OrderedNode *Src) { } } -OrderedNode *OpDispatchBuilder::GetPackedRFLAG(bool Lower8) { +OrderedNode *OpDispatchBuilder::GetPackedRFLAG(uint32_t FlagsMask) { // Calculate flags early. CalculateDeferredFlags(); OrderedNode *Original = _Constant(2); - size_t NumFlags = FlagOffsets.size(); - if (Lower8) { - NumFlags = 5; - } - - for (size_t i = 0; i < NumFlags; ++i) { + for (size_t i = 0; i < FlagOffsets.size(); ++i) { const auto FlagOffset = FlagOffsets[i]; + if (!((1U << FlagOffset) & FlagsMask)) { + continue; + } + OrderedNode *Flag = _LoadFlag(FlagOffset); - Flag = _Bfe(4, 32, 0, Flag); - Flag = _Lshl(Flag, _Constant(FlagOffset)); - Original = _Or(Original, Flag); + Original = _Bfi(4, 1, FlagOffset, Original, Flag); } return Original; } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index c9c89abf6..7356b6c96 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -1356,7 +1356,7 @@ void OpDispatchBuilder::X87FCMOV(OpcodeArgs) { auto MaskConst = _Constant(FLAGMask); - auto RFLAG = GetPackedRFLAG(false); + auto RFLAG = GetPackedRFLAG(FLAGMask); auto AndOp = _And(RFLAG, MaskConst); switch (Type) {