mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 17:00:19 +02:00
IR: introduce & use constant add helpers
more ergonomic and gives us a place to stash more logic. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
1 parent
54873992ab
commit
c6324b83ea
7 files changed
+66
-41
No files matched your search
@@ -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) {
|
||||
|
||||
@@ -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<int32_t>(IR::OpSizeToSize(Size))));
|
||||
Dest_RDI = Add(OpSize::i64Bit, Dest_RDI, PtrDir * static_cast<int32_t>(IR::OpSizeToSize(Size)));
|
||||
StoreGPRRegister(X86State::REG_RDI, Dest_RDI);
|
||||
|
||||
// Offset second pointer
|
||||
Dest_RSI = _Add(OpSize::i64Bit, Dest_RSI, Constant(PtrDir * static_cast<int32_t>(IR::OpSizeToSize(Size))));
|
||||
Dest_RSI = Add(OpSize::i64Bit, Dest_RSI, PtrDir * static_cast<int32_t>(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<int32_t>(IR::OpSizeToSize(Size))));
|
||||
TailDest_RSI = Add(OpSize::i64Bit, TailDest_RSI, PtrDir * static_cast<int32_t>(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<int32_t>(IR::OpSizeToSize(Size))));
|
||||
TailDest_RDI = Add(OpSize::i64Bit, TailDest_RDI, Dir * static_cast<int32_t>(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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user