diff --git a/FEXCore/Source/Interface/Core/Addressing.cpp b/FEXCore/Source/Interface/Core/Addressing.cpp index 6e0fecca3..43ac1d27c 100644 --- a/FEXCore/Source/Interface/Core/Addressing.cpp +++ b/FEXCore/Source/Interface/Core/Addressing.cpp @@ -24,7 +24,7 @@ Ref LoadEffectiveAddress(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, b Tmp = IREmit->_Lshl(GPRSize, A.Index, IREmit->Constant(Log2)); } } else { - Tmp = Tmp ? IREmit->_Add(GPRSize, Tmp, A.Index) : A.Index; + Tmp = Tmp ? IREmit->Add(GPRSize, Tmp, A.Index) : A.Index; } } @@ -45,7 +45,7 @@ Ref LoadEffectiveAddress(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, b } if (A.Segment && AddSegmentBase) { - Tmp = Tmp ? IREmit->_Add(GPRSize, Tmp, A.Segment) : A.Segment; + Tmp = Tmp ? IREmit->Add(GPRSize, Tmp, A.Segment) : A.Segment; } return Tmp ?: IREmit->Constant(0); @@ -114,7 +114,7 @@ AddressMode SelectAddressMode(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSi auto ScaledRegisterLoadstore = [IREmit, GPRSize](AddressMode A) -> AddressMode { if (A.Index && A.Segment) { - A.Base = IREmit->_Add(GPRSize, A.Base, A.Segment); + A.Base = IREmit->Add(GPRSize, A.Base, A.Segment); } else if (A.Segment) { A.Index = A.Segment; A.IndexScale = 1; diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 3b61cb8ff..b6cbb5746 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -166,7 +166,7 @@ void OpDispatchBuilder::RETOp(OpcodeArgs) { if (Op->OP == 0xC2) { auto Offset = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); - SP = _Add(GPRSize, SP, Offset); + SP = Add(GPRSize, SP, Offset); } // Store the new stack pointer @@ -1393,7 +1393,7 @@ void OpDispatchBuilder::SHLDOp(OpcodeArgs) { // a64 masks the bottom bits, so if we're using a native 32/64-bit shift, we // can negate to do the subtract (it's congruent), which saves a constant. - auto ShiftRight = Size >= 32 ? _Neg(OpSize::i64Bit, Shift) : _Sub(OpSize::i64Bit, Constant(Size), Shift); + auto ShiftRight = Size >= 32 ? _Neg(OpSize::i64Bit, Shift) : Sub(OpSize::i64Bit, Constant(Size), Shift); auto Tmp1 = _Lshl(OpSize::i64Bit, Dest, Shift); auto Tmp2 = _Lshr(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Src, ShiftRight); @@ -1464,7 +1464,7 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) { Shift = _And(OpSize::i64Bit, Shift, _InlineConstant(0x1F)); } - auto ShiftLeft = _Sub(OpSize::i64Bit, Constant(Size), Shift); + auto ShiftLeft = Sub(OpSize::i64Bit, Constant(Size), Shift); auto Tmp1 = _Lshr(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Dest, Shift); auto Tmp2 = _Lshl(OpSize::i64Bit, Src, ShiftLeft); @@ -2839,7 +2839,7 @@ void OpDispatchBuilder::AADOp(OpcodeArgs) { auto A = LoadGPRRegister(X86State::REG_RAX); auto AH = _Lshr(OpSize::i32Bit, A, Constant(8)); auto Imm8 = Constant(Op->Src[0].Data.Literal.Value & 0xFF); - auto NewAL = _Add(OpSize::i64Bit, A, _Mul(OpSize::i64Bit, AH, Imm8)); + auto NewAL = Add(OpSize::i64Bit, A, _Mul(OpSize::i64Bit, AH, Imm8)); auto Result = _And(OpSize::i64Bit, NewAL, Constant(0xFF)); StoreGPRRegister(X86State::REG_RAX, Result, OpSize::i16Bit); @@ -3165,11 +3165,11 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { auto SrcSegment = GetSegment(Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); if (DstSegment) { - DstAddr = _Add(OpSize::i64Bit, DstAddr, DstSegment); + DstAddr = Add(OpSize::i64Bit, DstAddr, DstSegment); } if (SrcSegment) { - SrcAddr = _Add(OpSize::i64Bit, SrcAddr, SrcSegment); + SrcAddr = Add(OpSize::i64Bit, SrcAddr, SrcSegment); } Ref Result_Src = _AllocateGPR(false); @@ -3177,11 +3177,11 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { _MemCpy(CTX->IsAtomicTSOEnabled(), Size, DstAddr, SrcAddr, Counter, LoadDir(1), Result_Dst, Result_Src); if (DstSegment) { - Result_Dst = _Sub(OpSize::i64Bit, Result_Dst, DstSegment); + Result_Dst = Sub(OpSize::i64Bit, Result_Dst, DstSegment); } if (SrcSegment) { - Result_Src = _Sub(OpSize::i64Bit, Result_Src, SrcSegment); + Result_Src = Sub(OpSize::i64Bit, Result_Src, SrcSegment); } StoreGPRRegister(X86State::REG_RCX, Constant(0)); @@ -3197,8 +3197,8 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { _StoreMemAutoTSO(GPRClass, Size, RDI, Src, Size); auto PtrDir = LoadDir(IR::OpSizeToSize(Size)); - RSI = _Add(OpSize::i64Bit, RSI, PtrDir); - RDI = _Add(OpSize::i64Bit, RDI, PtrDir); + RSI = Add(OpSize::i64Bit, RSI, PtrDir); + RDI = Add(OpSize::i64Bit, RDI, PtrDir); StoreGPRRegister(X86State::REG_RSI, RSI); StoreGPRRegister(X86State::REG_RDI, RDI); @@ -3229,11 +3229,11 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { auto PtrDir = LoadDir(IR::OpSizeToSize(Size)); // Offset the pointer - Dest_RDI = _Add(OpSize::i64Bit, Dest_RDI, PtrDir); + Dest_RDI = Add(OpSize::i64Bit, Dest_RDI, PtrDir); StoreGPRRegister(X86State::REG_RDI, Dest_RDI); // Offset second pointer - Dest_RSI = _Add(OpSize::i64Bit, Dest_RSI, PtrDir); + Dest_RSI = Add(OpSize::i64Bit, Dest_RSI, PtrDir); StoreGPRRegister(X86State::REG_RSI, Dest_RSI); } else { // Calculate flags early. @@ -3940,7 +3940,7 @@ Ref OpDispatchBuilder::GetSegment(uint32_t Flags, uint32_t DefaultPrefix, bool O Ref OpDispatchBuilder::AppendSegmentOffset(Ref Value, uint32_t Flags, uint32_t DefaultPrefix, bool Override) { auto Segment = GetSegment(Flags, DefaultPrefix, Override); if (Segment) { - Value = _Add(std::max(OpSize::i32Bit, std::max(GetOpSize(Value), GetOpSize(Segment))), Value, Segment); + Value = Add(std::max(OpSize::i32Bit, std::max(GetOpSize(Value), GetOpSize(Segment))), Value, Segment); } return Value; @@ -4371,7 +4371,7 @@ void OpDispatchBuilder::ALUOp(OpcodeArgs, FEXCore::IR::IROps ALUIROp, FEXCore::I auto Zero = LoadGPR(Op->Dest.Data.GPR.GPR); HandleNZ00Write(); InvalidateAF(); - CalculatePF(_SubWithFlags(OpSize::i32Bit, Zero, Zero)); + CalculatePF(SubWithFlags(OpSize::i32Bit, Zero, Zero)); CFInverted = true; FlushRegisterCache(); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 6b4908c0a..081e2807b 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1691,7 +1691,7 @@ private: // This is currently worse for 8/16-bit, but that should be optimized. TODO if (SrcSize >= OpSize::i32Bit) { if (SetPF) { - CalculatePF(SubWithFlags(SrcSize, Res, 0)); + CalculatePF(SubWithFlags(SrcSize, Res, (uint64_t)0)); } else { _SubNZCV(SrcSize, Res, Constant(0)); } @@ -2591,7 +2591,7 @@ private: } ArithRef Presub(uint64_t K) { - return IsConstant ? ArithRef(E, K - C) : ArithRef(E, E->_Sub(OpSize::i64Bit, E->Constant(K), R)); + return IsConstant ? ArithRef(E, K - C) : ArithRef(E, E->Sub(OpSize::i64Bit, E->Constant(K), R)); } ArithRef Lshl(uint64_t Shift) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 7f6a2e786..2232bb4a3 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -286,7 +286,7 @@ Ref OpDispatchBuilder::CalculateFlags_ADC(IR::OpSize SrcSize, Ref Src1, Ref Src2 Ref Src2PlusCF = IncrementByCarry(OpSize, Src2); // Need to zero-extend for the comparison. - Res = _Add(OpSize, Src1, Src2PlusCF); + Res = Add(OpSize, Src1, Src2PlusCF); Res = _Bfe(OpSize, IR::OpSizeAsBits(SrcSize), 0, Res); // TODO: We can fold that second Bfe in (cmp uxth). @@ -321,7 +321,7 @@ Ref OpDispatchBuilder::CalculateFlags_SBB(IR::OpSize SrcSize, Ref Src1, Ref Src2 auto Src2PlusCF = IncrementByCarry(OpSize, Src2); - Res = _Sub(OpSize, Src1, Src2PlusCF); + Res = Sub(OpSize, Src1, Src2PlusCF); Res = _Bfe(OpSize, IR::OpSizeAsBits(SrcSize), 0, Res); auto SelectCFInv = Select01(OpSize, CondClassType {COND_UGE}, Src1, Src2PlusCF); @@ -345,10 +345,10 @@ Ref OpDispatchBuilder::CalculateFlags_SUB(IR::OpSize SrcSize, Ref Src1, Ref Src2 Ref Res; if (SrcSize >= OpSize::i32Bit) { - Res = _SubWithFlags(SrcSize, Src1, Src2); + Res = SubWithFlags(SrcSize, Src1, Src2); } else { _SubNZCV(SrcSize, Src1, Src2); - Res = _Sub(OpSize::i32Bit, Src1, Src2); + Res = Sub(OpSize::i32Bit, Src1, Src2); } CalculatePF(Res); @@ -375,10 +375,10 @@ Ref OpDispatchBuilder::CalculateFlags_ADD(IR::OpSize SrcSize, Ref Src1, Ref Src2 Ref Res; if (SrcSize >= OpSize::i32Bit) { - Res = _AddWithFlags(SrcSize, Src1, Src2); + Res = AddWithFlags(SrcSize, Src1, Src2); } else { _AddNZCV(SrcSize, Src1, Src2); - Res = _Add(OpSize::i32Bit, Src1, Src2); + Res = Add(OpSize::i32Bit, Src1, Src2); } CalculatePF(Res); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index 17e7d3368..cfa819695 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -114,10 +114,10 @@ void OpDispatchBuilder::FILD(OpcodeArgs) { auto absolute = _Neg(OpSize::i64Bit, Data, CondClassType {COND_MI}); // left justify the absolute integer - auto shift = _Sub(OpSize::i64Bit, Constant(63), _FindMSB(IR::OpSize::i64Bit, absolute)); + auto shift = Sub(OpSize::i64Bit, Constant(63), _FindMSB(IR::OpSize::i64Bit, absolute)); auto shifted = _Lshl(OpSize::i64Bit, absolute, shift); - auto adjusted_exponent = _Sub(OpSize::i64Bit, Constant(0x3fff + 63), shift); + auto adjusted_exponent = Sub(OpSize::i64Bit, Constant(0x3fff + 63), shift); auto zeroed_exponent = _Select(COND_EQ, absolute, zero, zero, adjusted_exponent); auto upper = _Or(OpSize::i64Bit, sign, zeroed_exponent); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index 8db9223da..dbbee1220 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -382,7 +382,7 @@ void OpDispatchBuilder::X87FXTRACTF64(OpcodeArgs) { // non zero case Ref ExpNZ = _Bfe(OpSize::i64Bit, 11, 52, Gpr); - ExpNZ = _Sub(OpSize::i64Bit, ExpNZ, Constant(1023)); + ExpNZ = Sub(OpSize::i64Bit, ExpNZ, Constant(1023)); Ref ExpNZV = _Float_FromGPR_S(OpSize::i64Bit, OpSize::i64Bit, ExpNZ); Ref SigNZ = _And(OpSize::i64Bit, Gpr, Constant(0x800f'ffff'ffff'ffffLL)); diff --git a/FEXCore/Source/Interface/IR/IREmitter.h b/FEXCore/Source/Interface/IR/IREmitter.h index ebf29cc18..4a6c769c6 100644 --- a/FEXCore/Source/Interface/IR/IREmitter.h +++ b/FEXCore/Source/Interface/IR/IREmitter.h @@ -120,10 +120,29 @@ public: return Addsub(Size, OP_SUB, OP_ADD, Src1, Src2); } + Ref AddWithFlags(IR::OpSize Size, Ref Src1, uint64_t Src2) { + return Addsub(Size, OP_ADDWITHFLAGS, OP_SUBWITHFLAGS, Src1, Src2); + } + Ref SubWithFlags(IR::OpSize Size, Ref Src1, uint64_t Src2) { return Addsub(Size, OP_SUBWITHFLAGS, OP_ADDWITHFLAGS, Src1, Src2); } +#define DEF_ADDSUB(Op) \ + Ref Op(IR::OpSize Size, Ref Src1, Ref Src2) { \ + uint64_t Constant; \ + if (IsValueConstant(WrapNode(Src2), &Constant)) { \ + return Op(Size, Src1, Constant); \ + } else { \ + return _##Op(Size, Src1, Src2); \ + } \ + } + + DEF_ADDSUB(Add) + DEF_ADDSUB(Sub) + DEF_ADDSUB(AddWithFlags) + DEF_ADDSUB(SubWithFlags) + int64_t Constants[32]; Ref ConstantRefs[32]; uint32_t NrConstants; diff --git a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp index dc19f1fdc..5c7d7b98c 100644 --- a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp +++ b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp @@ -410,7 +410,7 @@ inline Ref X87StackOptimization::GetOffsetTopWithCache_Slow(uint8_t Offset) { auto* OffsetTop = GetTopWithCache_Slow(); if (Offset != 0) { - OffsetTop = IREmit->_And(OpSize::i32Bit, IREmit->_Add(OpSize::i32Bit, OffsetTop, GetConstant(Offset)), GetConstant(7)); + OffsetTop = IREmit->_And(OpSize::i32Bit, IREmit->Add(OpSize::i32Bit, OffsetTop, Offset), GetConstant(7)); // GetTopWithCache_Slow already sets the cache so we don't need to set it here for offset == 0 TopOffsetCache[Offset] = OffsetTop; } @@ -542,7 +542,7 @@ void X87StackOptimization::HandleBinopStack(IROps Op64, bool VFOp64, IROps Op80, inline void X87StackOptimization::UpdateTopForPop_Slow() { // Pop the top of the x87 stack auto* TopOffset = GetTopWithCache_Slow(); - TopOffset = IREmit->_Add(OpSize::i32Bit, TopOffset, GetConstant(1)); + TopOffset = IREmit->Add(OpSize::i32Bit, TopOffset, 1); TopOffset = IREmit->_And(OpSize::i32Bit, TopOffset, GetConstant(7)); SetTopWithCache_Slow(TopOffset); } @@ -550,7 +550,7 @@ inline void X87StackOptimization::UpdateTopForPop_Slow() { inline void X87StackOptimization::UpdateTopForPush_Slow() { // Pop the top of the x87 stack auto* TopOffset = GetTopWithCache_Slow(); - TopOffset = IREmit->_Sub(OpSize::i32Bit, TopOffset, GetConstant(1)); + TopOffset = IREmit->Sub(OpSize::i32Bit, TopOffset, 1); TopOffset = IREmit->_And(OpSize::i32Bit, TopOffset, GetConstant(7)); SetTopWithCache_Slow(TopOffset); } @@ -569,12 +569,7 @@ Ref X87StackOptimization::SynchronizeStackValues() { if (TopOffset != 0) { auto* OrigTop = GetTopWithCache_Slow(); - Ref NewTop {}; - if (TopOffset > 0) { - NewTop = IREmit->_And(OpSize::i32Bit, IREmit->_Sub(OpSize::i32Bit, OrigTop, GetConstant(TopOffset)), GetConstant(0x7)); - } else { - NewTop = IREmit->_And(OpSize::i32Bit, IREmit->_Add(OpSize::i32Bit, OrigTop, GetConstant(-TopOffset)), GetConstant(0x7)); - } + Ref NewTop = IREmit->_And(OpSize::i32Bit, IREmit->Sub(OpSize::i32Bit, OrigTop, TopOffset), GetConstant(0x7)); SetTopWithCache_Slow(NewTop); } StackData.TopOffset = 0; @@ -832,7 +827,7 @@ void X87StackOptimization::Run(IREmitter* Emit) { auto* TopValue = GetTopWithCache_Slow(); if (Offset != 0) { auto* Mask = GetConstant(7); - TopValue = IREmit->_And(OpSize::i32Bit, IREmit->_Add(OpSize::i32Bit, TopValue, GetConstant(Offset)), Mask); + TopValue = IREmit->_And(OpSize::i32Bit, IREmit->Add(OpSize::i32Bit, TopValue, Offset), Mask); } SetX87ValidTag(TopValue, false); } else {