diff --git a/FEXCore/Source/Interface/Core/Addressing.cpp b/FEXCore/Source/Interface/Core/Addressing.cpp index c585d3b54..6e0fecca3 100644 --- a/FEXCore/Source/Interface/Core/Addressing.cpp +++ b/FEXCore/Source/Interface/Core/Addressing.cpp @@ -11,8 +11,7 @@ Ref LoadEffectiveAddress(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, b Ref Tmp = A.Base; if (A.Offset) { - Ref Offset = IREmit->Constant(A.Offset); - Tmp = Tmp ? IREmit->_Add(GPRSize, Tmp, Offset) : Offset; + Tmp = Tmp ? IREmit->Add(GPRSize, Tmp, A.Offset) : IREmit->Constant(A.Offset); } if (A.Index) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ee53597e5..3b61cb8ff 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -453,7 +453,7 @@ void OpDispatchBuilder::POPAOp(OpcodeArgs) { StoreGPRRegister(X86State::REG_RBP, Pop(Size, SP), Size); // Skip loading RSP because it'll be correct at the end - SP = _RMWHandle(_Add(OpSize::i64Bit, SP, _InlineConstant(IR::OpSizeToSize(Size)))); + SP = _RMWHandle(Add(OpSize::i64Bit, SP, IR::OpSizeToSize(Size))); StoreGPRRegister(X86State::REG_RBX, Pop(Size, SP), Size); StoreGPRRegister(X86State::REG_RDX, Pop(Size, SP), Size); @@ -524,7 +524,7 @@ void OpDispatchBuilder::CALLOp(OpcodeArgs) { int64_t TargetOffset = Op->Src[0].Literal(); auto NewRIP = GetRelocatedPC(Op, TargetOffset); - auto ConstantPC = _Sub(GPRSize, NewRIP, Constant(TargetOffset)); + auto ConstantPC = Sub(GPRSize, NewRIP, TargetOffset); // Push the return address. Push(GPRSize, ConstantPC); @@ -826,7 +826,7 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { uint64_t Target = Op->PC + Op->InstSize + Op->Src[1].Literal(); Ref CondReg = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], SrcSize, Op->Flags); - CondReg = _Sub(OpSize, CondReg, _InlineConstant(1)); + CondReg = Sub(OpSize, CondReg, 1); StoreResult(GPRClass, Op, Op->Src[0], CondReg, OpSize::iInvalid); // If LOOPE then jumps to target if RCX != 0 && ZF == 1 @@ -1678,7 +1678,7 @@ void OpDispatchBuilder::BLSMSKBMIOp(OpcodeArgs) { const auto Size = OpSizeFromSrc(Op); auto* Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); - auto Result = _Xor(Size, _Sub(Size, Src, _InlineConstant(1)), Src); + auto Result = _Xor(Size, Sub(Size, Src, 1), Src); StoreResult(GPRClass, Op, Result, OpSize::iInvalid); InvalidatePF_AF(); @@ -1698,7 +1698,7 @@ void OpDispatchBuilder::BLSRBMIOp(OpcodeArgs) { const auto Size = OpSizeFromSrc(Op); auto* Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); - auto Result = _And(Size, _Sub(Size, Src, _InlineConstant(1)), Src); + auto Result = _And(Size, Sub(Size, Src, 1), Src); StoreResult(GPRClass, Op, Result, OpSize::iInvalid); @@ -2021,7 +2021,7 @@ void OpDispatchBuilder::RCROp(OpcodeArgs) { // Our new CF will be bit (Shift - 1) of the source. this is hoisted up to // avoid the need to copy the source. Again, the Lshr absorbs the masking. - auto NewCF = _Lshr(OpSize, Dest, _Sub(OpSize, Src, _InlineConstant(1))); + auto NewCF = _Lshr(OpSize, Dest, Sub(OpSize, Src, 1)); SetCFDirect(NewCF, 0, true); // Since shift != 0 we can inject the CF @@ -2125,7 +2125,7 @@ void OpDispatchBuilder::RCRSmallerOp(OpcodeArgs) { if (Src.IsConstant) { SetCFDirect(Tmp, (Src.C & 0x1f) - 1, true); } else { - auto NewCF = _Lshr(OpSize::i32Bit, Tmp, _Sub(OpSize::i32Bit, Src.Ref(), _InlineConstant(1))); + auto NewCF = _Lshr(OpSize::i32Bit, Tmp, Sub(OpSize::i32Bit, Src.Ref(), 1)); SetCFDirect(NewCF, 0, true); } @@ -2235,7 +2235,7 @@ void OpDispatchBuilder::RCLOp(OpcodeArgs) { SetCFDirect(NewCF, 0, true); // Since Shift != 0 we can inject the CF. Shift absorbs the masking. - Ref CFShl = _Sub(OpSize, Src, _InlineConstant(1)); + Ref CFShl = Sub(OpSize, Src, 1); auto TmpCF = _Lshl(OpSize, CF, CFShl); Res = _Or(OpSize, Res, TmpCF); @@ -2748,10 +2748,10 @@ void OpDispatchBuilder::DAAOp(OpcodeArgs) { CFInv = _And(OpSize::i64Bit, CFInv, Select01(OpSize::i64Bit, CondClassType {COND_ULE}, AL, Constant(0x99))); // AL = AF ? (AL + 0x6) : AL; - AL = _Select(FEXCore::IR::COND_NEQ, AF, Constant(0), _Add(OpSize::i64Bit, AL, Constant(0x6)), AL); + AL = _Select(FEXCore::IR::COND_NEQ, AF, Constant(0), Add(OpSize::i64Bit, AL, 0x6), AL); // AL = CF ? (AL + 0x60) : AL; - AL = _Select(FEXCore::IR::COND_EQ, CFInv, Constant(0), _Add(OpSize::i64Bit, AL, Constant(0x60)), AL); + AL = _Select(FEXCore::IR::COND_EQ, CFInv, Constant(0), Add(OpSize::i64Bit, AL, 0x60), AL); // SF, ZF, PF set according to result. CF set per above. OF undefined. StoreGPRRegister(X86State::REG_RAX, AL, OpSize::i8Bit); @@ -2774,10 +2774,10 @@ void OpDispatchBuilder::DASOp(OpcodeArgs) { auto NewCF = _Or(OpSize::i32Bit, CF, _Select(FEXCore::IR::COND_ULT, AL, Constant(6), AF, CF)); // AL = AF ? (AL - 0x6) : AL; - AL = _Select(FEXCore::IR::COND_NEQ, AF, Constant(0), _Sub(OpSize::i64Bit, AL, Constant(0x6)), AL); + AL = _Select(FEXCore::IR::COND_NEQ, AF, Constant(0), Sub(OpSize::i64Bit, AL, 0x6), AL); // AL = CF ? (AL - 0x60) : AL; - AL = _Select(FEXCore::IR::COND_NEQ, CF, Constant(0), _Sub(OpSize::i64Bit, AL, Constant(0x60)), AL); + AL = _Select(FEXCore::IR::COND_NEQ, CF, Constant(0), Sub(OpSize::i64Bit, AL, 0x60), AL); // SF, ZF, PF set according to result. CF set per above. OF undefined. StoreGPRRegister(X86State::REG_RAX, AL, OpSize::i8Bit); @@ -2797,7 +2797,7 @@ void OpDispatchBuilder::AAAOp(OpcodeArgs) { CalculateDeferredFlags(); // AX = CF ? (AX + 0x106) : 0 - A = NZCVSelect(OpSize::i32Bit, {COND_UGE} /* CF = 1 */, _Add(OpSize::i32Bit, A, Constant(0x106)), A); + A = NZCVSelect(OpSize::i32Bit, {COND_UGE} /* CF = 1 */, Add(OpSize::i32Bit, A, 0x106), A); // AL = AL & 0x0F A = _And(OpSize::i32Bit, A, Constant(0xFF0F)); @@ -2814,7 +2814,7 @@ void OpDispatchBuilder::AASOp(OpcodeArgs) { CalculateDeferredFlags(); // AX = CF ? (AX - 0x106) : 0 - A = NZCVSelect(OpSize::i32Bit, {COND_UGE} /* CF = 1 */, _Sub(OpSize::i32Bit, A, Constant(0x106)), A); + A = NZCVSelect(OpSize::i32Bit, {COND_UGE} /* CF = 1 */, Sub(OpSize::i32Bit, A, 0x106), A); // AL = AL & 0x0F A = _And(OpSize::i32Bit, A, Constant(0xFF0F)); @@ -2908,14 +2908,13 @@ void OpDispatchBuilder::EnterOp(OpcodeArgs) { if (Level > 0) { for (uint8_t i = 1; i < Level; ++i) { - auto Offset = Constant(i * IR::OpSizeToSize(GPRSize)); - auto MemLoc = _Sub(GPRSize, OldBP, Offset); + auto MemLoc = Sub(GPRSize, OldBP, i * IR::OpSizeToSize(GPRSize)); auto Mem = _LoadMem(GPRClass, GPRSize, MemLoc, GPRSize); NewSP = PushValue(GPRSize, Mem); } NewSP = PushValue(GPRSize, temp_RBP); } - NewSP = _Sub(GPRSize, NewSP, Constant(AllocSpace)); + NewSP = Sub(GPRSize, NewSP, AllocSpace); StoreGPRRegister(X86State::REG_RSP, NewSP); StoreGPRRegister(X86State::REG_RBP, temp_RBP); } @@ -3045,7 +3044,7 @@ void OpDispatchBuilder::INCOp(OpcodeArgs) { if (Size < 32 && CTX->HostFeatures.SupportsFlagM) { // Addition producing upper garbage - Result = _Add(OpSize::i32Bit, Dest, _InlineConstant(1)); + Result = Add(OpSize::i32Bit, Dest, 1); CalculatePF(Result); CalculateAF(Dest, Constant(1)); @@ -3086,7 +3085,7 @@ void OpDispatchBuilder::DECOp(OpcodeArgs) { if (Size < 32 && CTX->HostFeatures.SupportsFlagM) { // Subtraction producing upper garbage - Result = _Sub(OpSize::i32Bit, Dest, _InlineConstant(1)); + Result = Sub(OpSize::i32Bit, Dest, 1); CalculatePF(Result); CalculateAF(Dest, Constant(1)); @@ -3278,17 +3277,17 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { Ref TailCounter = LoadGPRRegister(X86State::REG_RCX); // Decrement counter - TailCounter = _SubWithFlags(OpSize::i64Bit, TailCounter, Constant(1)); + TailCounter = SubWithFlags(OpSize::i64Bit, TailCounter, 1); // Store the counter since we don't have phis StoreGPRRegister(X86State::REG_RCX, TailCounter); // Offset the pointer - Dest_RDI = _Add(OpSize::i64Bit, Dest_RDI, Constant(PtrDir * static_cast(IR::OpSizeToSize(Size)))); + Dest_RDI = Add(OpSize::i64Bit, Dest_RDI, PtrDir * static_cast(IR::OpSizeToSize(Size))); StoreGPRRegister(X86State::REG_RDI, Dest_RDI); // Offset second pointer - Dest_RSI = _Add(OpSize::i64Bit, Dest_RSI, Constant(PtrDir * static_cast(IR::OpSizeToSize(Size)))); + Dest_RSI = Add(OpSize::i64Bit, Dest_RSI, PtrDir * static_cast(IR::OpSizeToSize(Size))); StoreGPRRegister(X86State::REG_RSI, Dest_RSI); // If TailCounter != 0, compare sources. @@ -3388,13 +3387,13 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { Ref TailDest_RSI = LoadGPRRegister(X86State::REG_RSI); // Decrement counter - TailCounter = _Sub(OpSize::i64Bit, TailCounter, Constant(1)); + TailCounter = Sub(OpSize::i64Bit, TailCounter, 1); // Store the counter since we don't have phis StoreGPRRegister(X86State::REG_RCX, TailCounter); // Offset the pointer - TailDest_RSI = _Add(OpSize::i64Bit, TailDest_RSI, Constant(PtrDir * static_cast(IR::OpSizeToSize(Size)))); + TailDest_RSI = Add(OpSize::i64Bit, TailDest_RSI, PtrDir * static_cast(IR::OpSizeToSize(Size))); StoreGPRRegister(X86State::REG_RSI, TailDest_RSI); // Jump back to the start, we have more work to do @@ -3472,13 +3471,13 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { Ref TailDest_RDI = LoadGPRRegister(X86State::REG_RDI); // Decrement counter - TailCounter = _Sub(OpSize::i64Bit, TailCounter, Constant(1)); + TailCounter = Sub(OpSize::i64Bit, TailCounter, 1); // Store the counter since we don't have phis StoreGPRRegister(X86State::REG_RCX, TailCounter); // Offset the pointer - TailDest_RDI = _Add(OpSize::i64Bit, TailDest_RDI, Constant(Dir * static_cast(IR::OpSizeToSize(Size)))); + TailDest_RDI = Add(OpSize::i64Bit, TailDest_RDI, Dir * static_cast(IR::OpSizeToSize(Size))); StoreGPRRegister(X86State::REG_RDI, TailDest_RDI); CalculateDeferredFlags(); @@ -4169,7 +4168,7 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T } else { // For X87 extended doubles, Split the load. auto Res = _LoadMem(Class, OpSize::i64Bit, MemSrc, Align == OpSize::iInvalid ? OpSize : Align); - return _VLoadVectorElement(OpSize::i128Bit, OpSize::i16Bit, Res, 4, _Add(OpSize::i64Bit, MemSrc, _InlineConstant(8))); + return _VLoadVectorElement(OpSize::i128Bit, OpSize::i16Bit, Res, 4, Add(OpSize::i64Bit, MemSrc, 8)); } } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 52394c2c6..6b4908c0a 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, Constant(0))); + CalculatePF(SubWithFlags(SrcSize, Res, 0)); } else { _SubNZCV(SrcSize, Res, Constant(0)); } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp index 841e3133f..d793a2adc 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp @@ -2513,7 +2513,7 @@ OpDispatchBuilder::RefPair OpDispatchBuilder::AVX128_VPGatherImpl(OpSize Size, O ///< BaseAddr doesn't need to exist, calculate that here. Ref BaseAddr = VSIB.BaseAddr; if (BaseAddr && VSIB.Displacement) { - BaseAddr = _Add(OpSize::i64Bit, BaseAddr, Constant(VSIB.Displacement)); + BaseAddr = Add(OpSize::i64Bit, BaseAddr, VSIB.Displacement); } else if (VSIB.Displacement) { BaseAddr = Constant(VSIB.Displacement); } else if (!BaseAddr) { @@ -2608,7 +2608,7 @@ OpDispatchBuilder::RefPair OpDispatchBuilder::AVX128_VPGatherQPSImpl(Ref Dest, R ///< BaseAddr doesn't need to exist, calculate that here. Ref BaseAddr = VSIB.BaseAddr; if (BaseAddr && VSIB.Displacement) { - BaseAddr = _Add(OpSize::i64Bit, BaseAddr, Constant(VSIB.Displacement)); + BaseAddr = Add(OpSize::i64Bit, BaseAddr, VSIB.Displacement); } else if (VSIB.Displacement) { BaseAddr = Constant(VSIB.Displacement); } else if (!BaseAddr) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index a19738c96..c37b637de 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -5078,7 +5078,7 @@ void OpDispatchBuilder::VPGATHER(OpcodeArgs) { ///< BaseAddr doesn't need to exist, calculate that here. Ref BaseAddr = VSIB.BaseAddr; if (BaseAddr && VSIB.Displacement) { - BaseAddr = _Add(OpSize::i64Bit, BaseAddr, Constant(VSIB.Displacement)); + BaseAddr = Add(OpSize::i64Bit, BaseAddr, VSIB.Displacement); } else if (VSIB.Displacement) { BaseAddr = Constant(VSIB.Displacement); } else if (!BaseAddr) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index dd50705ff..17e7d3368 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -168,7 +168,7 @@ void OpDispatchBuilder::FIST(OpcodeArgs, bool Truncate) { // For overflow detection, check if exponent indicates a value >= 2^15 // Biased exponent for 2^15 is 0x3fff + 15 = 0x400e - _SubWithFlags(OpSize::i64Bit, Exponent, Constant(0x400e)); + SubWithFlags(OpSize::i64Bit, Exponent, 0x400e); Ref IsOverflow = _NZCVSelect01({COND_UGE}); // Set Invalid Operation flag if overflow or special value @@ -443,13 +443,13 @@ void OpDispatchBuilder::X87LDENV(OpcodeArgs) { auto NewFCW = _LoadMem(GPRClass, OpSize::i16Bit, Mem, OpSize::i16Bit); _StoreContext(OpSize::i16Bit, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); - Ref MemLocation = _Add(OpSize::i64Bit, Mem, Constant(IR::OpSizeToSize(Size) * 1)); + Ref MemLocation = Add(OpSize::i64Bit, Mem, IR::OpSizeToSize(Size) * 1); auto NewFSW = _LoadMem(GPRClass, Size, MemLocation, Size); ReconstructX87StateFromFSW_Helper(NewFSW); { // FTW - Ref MemLocation = _Add(OpSize::i64Bit, Mem, Constant(IR::OpSizeToSize(Size) * 2)); + Ref MemLocation = Add(OpSize::i64Bit, Mem, IR::OpSizeToSize(Size) * 2); SetX87FTW(_LoadMem(GPRClass, Size, MemLocation, Size)); } } @@ -512,7 +512,6 @@ void OpDispatchBuilder::X87FNSAVE(OpcodeArgs) { _StoreMem(GPRClass, Size, ZeroConst, Mem, Constant(IR::OpSizeToSize(Size) * 6), Size, MEM_OFFSET_SXTX, 1); } - auto OneConst = Constant(1); auto SevenConst = Constant(7); const auto LoadSize = ReducedPrecisionMode ? OpSize::i64Bit : OpSize::i128Bit; for (int i = 0; i < 7; ++i) { @@ -521,7 +520,7 @@ void OpDispatchBuilder::X87FNSAVE(OpcodeArgs) { data = _F80CVTTo(data, OpSize::i64Bit); } _StoreMem(FPRClass, OpSize::i128Bit, data, Mem, Constant((IR::OpSizeToSize(Size) * 7) + (10 * i)), OpSize::i8Bit, MEM_OFFSET_SXTX, 1); - Top = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, Top, OneConst), SevenConst); + Top = _And(OpSize::i32Bit, Add(OpSize::i32Bit, Top, 1), SevenConst); } // The final st(7) needs a bit of special handling here @@ -565,9 +564,7 @@ void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) { SetX87FTW(_LoadMem(GPRClass, Size, Mem, Constant(IR::OpSizeToSize(Size) * 2), Size, MEM_OFFSET_SXTX, 1)); } - auto OneConst = Constant(1); auto SevenConst = Constant(7); - auto low = Constant(~0ULL); auto high = Constant(0xFFFF); Ref Mask = _VLoadTwoGPRs(low, high); @@ -582,7 +579,7 @@ void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) { } _StoreContextIndexed(Reg, Top, StoreSize, MMBaseOffset(), IR::OpSizeToSize(OpSize::i128Bit), FPRClass); - Top = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, Top, OneConst), SevenConst); + Top = _And(OpSize::i32Bit, Add(OpSize::i32Bit, Top, 1), SevenConst); } // The final st(7) needs a bit of special handling here diff --git a/FEXCore/Source/Interface/IR/IREmitter.h b/FEXCore/Source/Interface/IR/IREmitter.h index 1c3b63d95..ebf29cc18 100644 --- a/FEXCore/Source/Interface/IR/IREmitter.h +++ b/FEXCore/Source/Interface/IR/IREmitter.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT #pragma once +#include "CodeEmitter/Emitter.h" #include "Interface/IR/IR.h" #include "Interface/IR/IntrusiveIRList.h" @@ -94,6 +95,35 @@ public: return _NZCVSelect(OpSize::i64Bit, Cond, _InlineConstant(1), _InlineConstant(0)); } + Ref Addsub(IR::OpSize Size, IROps Op, IROps NegatedOp, Ref Src1, uint64_t Src2) { + // Sign-extend the constant + if (Size == OpSize::i32Bit) { + Src2 = (int64_t)(int32_t)Src2; + } + + // Negative constants need to be negated to inline. + if (Src2 & (1ull << 63) && ARMEmitter::IsImmAddSub(-Src2)) { + Op = NegatedOp; + Src2 = -Src2; + } + + auto Dest = _Add(Size, Src1, Constant(Src2)); + Dest.first->Header.Op = Op; + return Dest; + } + + Ref Add(IR::OpSize Size, Ref Src1, uint64_t Src2) { + return Addsub(Size, OP_ADD, OP_SUB, Src1, Src2); + } + + Ref Sub(IR::OpSize Size, Ref Src1, uint64_t Src2) { + return Addsub(Size, OP_SUB, OP_ADD, Src1, Src2); + } + + Ref SubWithFlags(IR::OpSize Size, Ref Src1, uint64_t Src2) { + return Addsub(Size, OP_SUBWITHFLAGS, OP_ADDWITHFLAGS, Src1, Src2); + } + int64_t Constants[32]; Ref ConstantRefs[32]; uint32_t NrConstants;