diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index b7e50e25e..4ff689957 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4250,7 +4250,7 @@ void OpDispatchBuilder::StoreGPRRegister(uint32_t GPR, const Ref Src, IR::OpSize Ref Reg = Src; if (Size != GPRSize || Offset != 0) { // Need to do an insert if not automatic size or zero offset. - Reg = _Bfi(GPRSize, IR::OpSizeAsBits(Size), Offset, LoadGPRRegister(GPR), Src); + Reg = ARef(Reg).BfiInto(LoadGPRRegister(GPR), Offset, IR::OpSizeAsBits(Size)); } StoreRegister(GPR, false, Reg); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index a9b37fc2e..6135e89d0 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -2553,6 +2553,25 @@ private: } } + Ref BfiInto(Ref Bitfield, unsigned Start, unsigned Size) { + if (IsConstant && (Size > 0 && Size < 64)) { + uint64_t SourceMask = (1ULL << Size) - 1; + uint64_t SourceMaskShifted = SourceMask << Start; + + if (C == 0) { + return E->_And(OpSize::i64Bit, Bitfield, E->_InlineConstant(~SourceMaskShifted)); + } else if (C == SourceMask) { + return E->_Or(OpSize::i64Bit, Bitfield, E->_InlineConstant(SourceMaskShifted)); + } + } + + if (IsConstant) { + return E->_Bfi(OpSize::i64Bit, Size, Start, Bitfield, E->_Constant(C)); + } else { + return E->_Bfi(OpSize::i64Bit, Size, Start, Bitfield, R); + } + } + ArithRef MaskBit(OpSize Size) { if (IsConstant) { uint64_t ShiftMask = Size == OpSize::i64Bit ? 63 : 31;