mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
IR: Converts base IR operations to store OpSize sizes
NFC Finally converts the IR operations themselves to store the OpSize for the IR operation size and element sizes. This also finally, FINALLY, converts that remaining `_Constant` helper to stop using a size field that is specified in bits rather than bytes like all the other IR op handlers. That thing was so confusing and now it's gone.
This commit is contained in:
13 files changed
+275
-239
No files matched your search
@@ -323,8 +323,8 @@ def print_ir_structs(defines):
|
||||
output_file.write("struct __attribute__((packed)) IROp_Header {\n")
|
||||
output_file.write("\tvoid* Data[0];\n")
|
||||
output_file.write("\tIROps Op;\n\n")
|
||||
output_file.write("\tuint8_t Size;\n")
|
||||
output_file.write("\tuint8_t ElementSize;\n")
|
||||
output_file.write("\tIR::OpSize Size;\n")
|
||||
output_file.write("\tIR::OpSize ElementSize;\n")
|
||||
|
||||
output_file.write("\ttemplate<typename T>\n")
|
||||
output_file.write("\tT const* C() const { return reinterpret_cast<T const*>(Data); }\n")
|
||||
@@ -630,20 +630,20 @@ def print_ir_allocator_helpers():
|
||||
output_file.write("\t\treturn IRPair<T>{Op, CreateNode(&Op->Header)};\n")
|
||||
output_file.write("\t}\n\n")
|
||||
|
||||
output_file.write("\tuint8_t GetOpSize(const OrderedNode *Op) const {\n")
|
||||
output_file.write("\tIR::OpSize GetOpSize(const OrderedNode *Op) const {\n")
|
||||
output_file.write("\t\tauto HeaderOp = Op->Header.Value.GetNode(DualListData.DataBegin());\n")
|
||||
output_file.write("\t\treturn HeaderOp->Size;\n")
|
||||
output_file.write("\t\treturn IR::SizeToOpSize(HeaderOp->Size);\n")
|
||||
output_file.write("\t}\n\n")
|
||||
|
||||
output_file.write("\tuint8_t GetOpElementSize(const OrderedNode *Op) const {\n")
|
||||
output_file.write("\tIR::OpSize GetOpElementSize(const OrderedNode *Op) const {\n")
|
||||
output_file.write("\t\tauto HeaderOp = Op->Header.Value.GetNode(DualListData.DataBegin());\n")
|
||||
output_file.write("\t\treturn HeaderOp->ElementSize;\n")
|
||||
output_file.write("\t\treturn IR::SizeToOpSize(HeaderOp->ElementSize);\n")
|
||||
output_file.write("\t}\n\n")
|
||||
|
||||
output_file.write("\tuint8_t GetOpElements(const OrderedNode *Op) const {\n")
|
||||
output_file.write("\t\tauto HeaderOp = Op->Header.Value.GetNode(DualListData.DataBegin());\n")
|
||||
output_file.write("\t\tLOGMAN_THROW_A_FMT(OpHasDest(Op), \"Op {} has no dest\\n\", GetName(HeaderOp->Op));\n")
|
||||
output_file.write("\t\treturn HeaderOp->Size / HeaderOp->ElementSize;\n")
|
||||
output_file.write("\t\treturn IR::OpSizeToSize(GetOpSize(Op)) / IR::OpSizeToSize(GetOpElementSize(Op));\n")
|
||||
output_file.write("\t}\n\n")
|
||||
|
||||
output_file.write("\tbool OpHasDest(const OrderedNode *Op) const {\n")
|
||||
@@ -728,11 +728,11 @@ def print_ir_allocator_helpers():
|
||||
# We can only infer a size if we have arguments
|
||||
if op.DestSize == None:
|
||||
# We need to infer destination size
|
||||
output_file.write("\t\tuint8_t InferSize = 0;\n")
|
||||
output_file.write("\t\tIR::OpSize InferSize = OpSize::iUnsized;\n")
|
||||
if len(op.Arguments) != 0:
|
||||
for arg in op.Arguments:
|
||||
if arg.IsSSA:
|
||||
output_file.write("\t\tuint8_t Size{} = GetOpSize({});\n".format(arg.Name, arg.Name))
|
||||
output_file.write("\t\tauto Size{} = GetOpSize({});\n".format(arg.Name, arg.Name))
|
||||
for arg in op.Arguments:
|
||||
if arg.IsSSA:
|
||||
output_file.write("\t\tInferSize = std::max(InferSize, Size{});\n".format(arg.Name))
|
||||
@@ -745,7 +745,7 @@ def print_ir_allocator_helpers():
|
||||
output_file.write("\t\t_Op.first->Header.Size = {};\n".format(op.DestSize))
|
||||
|
||||
if op.NumElements == None:
|
||||
output_file.write("\t\t_Op.first->Header.ElementSize = _Op.first->Header.Size / ({});\n".format(1))
|
||||
output_file.write("\t\t_Op.first->Header.ElementSize = _Op.first->Header.Size;\n")
|
||||
else:
|
||||
output_file.write("\t\t_Op.first->Header.ElementSize = _Op.first->Header.Size / ({});\n".format(op.NumElements))
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace FEXCore::CPU {
|
||||
#define DEF_OP(x) void Arm64JITCore::Op_##x(IR::IROp_Header const* IROp, IR::NodeID Node)
|
||||
DEF_OP(CASPair) {
|
||||
auto Op = IROp->C<IR::IROp_CASPair>();
|
||||
LOGMAN_THROW_AA_FMT(IROp->ElementSize == 4 || IROp->ElementSize == 8, "Wrong element size");
|
||||
LOGMAN_THROW_AA_FMT(IROp->ElementSize == IR::OpSize::i32Bit || IROp->ElementSize == IR::OpSize::i64Bit, "Wrong element size");
|
||||
// Size is the size of each pair element
|
||||
auto Dst0 = GetReg(Op->OutLo.ID());
|
||||
auto Dst1 = GetReg(Op->OutHi.ID());
|
||||
@@ -23,7 +23,7 @@ DEF_OP(CASPair) {
|
||||
auto Desired1 = GetReg(Op->DesiredHi.ID());
|
||||
auto MemSrc = GetReg(Op->Addr.ID());
|
||||
|
||||
const auto EmitSize = IROp->ElementSize == 8 ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit;
|
||||
const auto EmitSize = IROp->ElementSize == IR::OpSize::i64Bit ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit;
|
||||
if (CTX->HostFeatures.SupportsAtomics) {
|
||||
// RA has heuristics to try to pair sources, but we need to handle the cases
|
||||
// where they fail. We do so by moving to temporaries. Note we use 64-bit
|
||||
@@ -112,9 +112,9 @@ DEF_OP(CAS) {
|
||||
ARMEmitter::SingleUseForwardLabel LoopExpected;
|
||||
Bind(&LoopTop);
|
||||
ldaxr(SubEmitSize, TMP2, MemSrc);
|
||||
if (IROp->Size == 1) {
|
||||
if (IROp->Size == IR::OpSize::i8Bit) {
|
||||
cmp(EmitSize, TMP2, Expected, ARMEmitter::ExtendedType::UXTB, 0);
|
||||
} else if (IROp->Size == 2) {
|
||||
} else if (IROp->Size == IR::OpSize::i16Bit) {
|
||||
cmp(EmitSize, TMP2, Expected, ARMEmitter::ExtendedType::UXTH, 0);
|
||||
} else {
|
||||
cmp(EmitSize, TMP2, Expected);
|
||||
@@ -273,18 +273,21 @@ DEF_OP(AtomicNeg) {
|
||||
|
||||
DEF_OP(AtomicSwap) {
|
||||
auto Op = IROp->C<IR::IROp_AtomicSwap>();
|
||||
uint8_t OpSize = IROp->Size;
|
||||
LOGMAN_THROW_AA_FMT(OpSize == 8 || OpSize == 4 || OpSize == 2 || OpSize == 1, "Unexpected CAS size");
|
||||
const auto OpSize = IROp->Size;
|
||||
LOGMAN_THROW_AA_FMT(
|
||||
OpSize == IR::OpSize::i64Bit || OpSize == IR::OpSize::i32Bit || OpSize == IR::OpSize::i16Bit || OpSize == IR::OpSize::i8Bit, "Unexpecte"
|
||||
"d CAS "
|
||||
"size");
|
||||
|
||||
auto MemSrc = GetReg(Op->Addr.ID());
|
||||
auto Src = GetReg(Op->Value.ID());
|
||||
|
||||
const auto EmitSize = ConvertSize(IROp);
|
||||
const auto SubEmitSize = OpSize == 8 ? ARMEmitter::SubRegSize::i64Bit :
|
||||
OpSize == 4 ? ARMEmitter::SubRegSize::i32Bit :
|
||||
OpSize == 2 ? ARMEmitter::SubRegSize::i16Bit :
|
||||
OpSize == 1 ? ARMEmitter::SubRegSize::i8Bit :
|
||||
ARMEmitter::SubRegSize::i8Bit;
|
||||
const auto SubEmitSize = OpSize == IR::OpSize::i64Bit ? ARMEmitter::SubRegSize::i64Bit :
|
||||
OpSize == IR::OpSize::i32Bit ? ARMEmitter::SubRegSize::i32Bit :
|
||||
OpSize == IR::OpSize::i16Bit ? ARMEmitter::SubRegSize::i16Bit :
|
||||
OpSize == IR::OpSize::i8Bit ? ARMEmitter::SubRegSize::i8Bit :
|
||||
ARMEmitter::SubRegSize::i8Bit;
|
||||
|
||||
if (CTX->HostFeatures.SupportsAtomics) {
|
||||
ldswpal(SubEmitSize, Src, GetReg(Node), MemSrc);
|
||||
@@ -294,7 +297,7 @@ DEF_OP(AtomicSwap) {
|
||||
ldaxr(SubEmitSize, TMP2, MemSrc);
|
||||
stlxr(SubEmitSize, TMP4, Src, MemSrc);
|
||||
cbnz(EmitSize, TMP4, &LoopTop);
|
||||
ubfm(EmitSize, GetReg(Node), TMP2, 0, OpSize * 8 - 1);
|
||||
ubfm(EmitSize, GetReg(Node), TMP2, 0, IR::OpSizeAsBits(OpSize) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -626,8 +626,8 @@ bool Arm64JITCore::IsInlineEntrypointOffset(const IR::OrderedNodeWrapper& WNode,
|
||||
auto Op = OpHeader->C<IR::IROp_InlineEntrypointOffset>();
|
||||
if (Value) {
|
||||
uint64_t Mask = ~0ULL;
|
||||
uint8_t OpSize = OpHeader->Size;
|
||||
if (OpSize == 4) {
|
||||
const auto Size = OpHeader->Size;
|
||||
if (Size == IR::OpSize::i32Bit) {
|
||||
Mask = 0xFFFF'FFFFULL;
|
||||
}
|
||||
*Value = (Entry + Op->Offset) & Mask;
|
||||
|
||||
@@ -129,23 +129,25 @@ private:
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::Size ConvertSize(const IR::IROp_Header* Op) {
|
||||
return Op->Size == 8 ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit;
|
||||
return Op->Size == IR::OpSize::i64Bit ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::Size ConvertSize48(const IR::IROp_Header* Op) {
|
||||
LOGMAN_THROW_AA_FMT(Op->Size == 4 || Op->Size == 8, "Invalid size");
|
||||
LOGMAN_THROW_AA_FMT(Op->Size == IR::OpSize::i32Bit || Op->Size == IR::OpSize::i64Bit, "Invalid size");
|
||||
return ConvertSize(Op);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::SubRegSize ConvertSubRegSize16(uint8_t ElementSize) {
|
||||
LOGMAN_THROW_AA_FMT(ElementSize == 1 || ElementSize == 2 || ElementSize == 4 || ElementSize == 8 || ElementSize == 16, "Invalid size");
|
||||
return ElementSize == 1 ? ARMEmitter::SubRegSize::i8Bit :
|
||||
ElementSize == 2 ? ARMEmitter::SubRegSize::i16Bit :
|
||||
ElementSize == 4 ? ARMEmitter::SubRegSize::i32Bit :
|
||||
ElementSize == 8 ? ARMEmitter::SubRegSize::i64Bit :
|
||||
ARMEmitter::SubRegSize::i128Bit;
|
||||
ARMEmitter::SubRegSize ConvertSubRegSize16(IR::OpSize ElementSize) {
|
||||
LOGMAN_THROW_AA_FMT(ElementSize == IR::OpSize::i8Bit || ElementSize == IR::OpSize::i16Bit || ElementSize == IR::OpSize::i32Bit ||
|
||||
ElementSize == IR::OpSize::i64Bit || ElementSize == IR::OpSize::i128Bit,
|
||||
"Invalid size");
|
||||
return ElementSize == IR::OpSize::i8Bit ? ARMEmitter::SubRegSize::i8Bit :
|
||||
ElementSize == IR::OpSize::i16Bit ? ARMEmitter::SubRegSize::i16Bit :
|
||||
ElementSize == IR::OpSize::i32Bit ? ARMEmitter::SubRegSize::i32Bit :
|
||||
ElementSize == IR::OpSize::i64Bit ? ARMEmitter::SubRegSize::i64Bit :
|
||||
ARMEmitter::SubRegSize::i128Bit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -154,8 +156,8 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::SubRegSize ConvertSubRegSize8(uint8_t ElementSize) {
|
||||
LOGMAN_THROW_AA_FMT(ElementSize != 16, "Invalid size");
|
||||
ARMEmitter::SubRegSize ConvertSubRegSize8(IR::OpSize ElementSize) {
|
||||
LOGMAN_THROW_AA_FMT(ElementSize != IR::OpSize::i128Bit, "Invalid size");
|
||||
return ConvertSubRegSize16(ElementSize);
|
||||
}
|
||||
|
||||
@@ -166,13 +168,13 @@ private:
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::SubRegSize ConvertSubRegSize4(const IR::IROp_Header* Op) {
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != 8, "Invalid size");
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != IR::OpSize::i64Bit, "Invalid size");
|
||||
return ConvertSubRegSize8(Op);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::SubRegSize ConvertSubRegSize248(const IR::IROp_Header* Op) {
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != 1, "Invalid size");
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != IR::OpSize::i8Bit, "Invalid size");
|
||||
return ConvertSubRegSize8(Op);
|
||||
}
|
||||
|
||||
@@ -183,13 +185,13 @@ private:
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::VectorRegSizePair ConvertSubRegSizePair8(const IR::IROp_Header* Op) {
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != 16, "Invalid size");
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != IR::OpSize::i128Bit, "Invalid size");
|
||||
return ConvertSubRegSizePair16(Op);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ARMEmitter::VectorRegSizePair ConvertSubRegSizePair248(const IR::IROp_Header* Op) {
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != 1, "Invalid size");
|
||||
LOGMAN_THROW_AA_FMT(Op->ElementSize != IR::OpSize::i8Bit, "Invalid size");
|
||||
return ConvertSubRegSizePair8(Op);
|
||||
}
|
||||
|
||||
|
||||
@@ -1388,7 +1388,7 @@ void OpDispatchBuilder::SHLImmediateOp(OpcodeArgs, bool SHL1Bit) {
|
||||
uint64_t Shift = LoadConstantShift(Op, SHL1Bit);
|
||||
const auto Size = GetSrcBitSize(Op);
|
||||
|
||||
Ref Src = _Constant(Size, Shift);
|
||||
Ref Src = _Constant(OpSizeFromSrc(Op), Shift);
|
||||
Ref Result = _Lshl(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Dest, Src);
|
||||
|
||||
CalculateFlags_ShiftLeftImmediate(OpSizeFromSrc(Op), Result, Dest, Shift);
|
||||
@@ -1411,7 +1411,7 @@ void OpDispatchBuilder::SHRImmediateOp(OpcodeArgs, bool SHR1Bit) {
|
||||
|
||||
uint64_t Shift = LoadConstantShift(Op, SHR1Bit);
|
||||
|
||||
Ref Src = _Constant(Size, Shift);
|
||||
Ref Src = _Constant(OpSizeFromSrc(Op), Shift);
|
||||
auto ALUOp = _Lshr(Size == 64 ? OpSize::i64Bit : OpSize::i32Bit, Dest, Src);
|
||||
|
||||
CalculateFlags_ShiftRightImmediate(OpSizeFromSrc(Op), ALUOp, Dest, Shift);
|
||||
@@ -1664,28 +1664,28 @@ void OpDispatchBuilder::BEXTRBMIOp(OpcodeArgs) {
|
||||
auto* Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true});
|
||||
auto* Src2 = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true});
|
||||
|
||||
const auto Size = GetSrcSize(Op);
|
||||
const auto Size = OpSizeFromSrc(Op);
|
||||
const auto SrcSize = Size * 8;
|
||||
const auto MaxSrcBit = SrcSize - 1;
|
||||
auto MaxSrcBitOp = _Constant(SrcSize, MaxSrcBit);
|
||||
auto MaxSrcBitOp = _Constant(Size, MaxSrcBit);
|
||||
|
||||
// Shift the operand down to the starting bit
|
||||
auto Start = _Bfe(OpSizeFromSrc(Op), 8, 0, Src2);
|
||||
auto Shifted = _Lshr(IR::SizeToOpSize(Size), Src1, Start);
|
||||
auto Shifted = _Lshr(Size, Src1, Start);
|
||||
|
||||
// Shifts larger than operand size need to be set to zero.
|
||||
auto SanitizedShifted = _Select(IR::COND_ULE, Start, MaxSrcBitOp, Shifted, _Constant(SrcSize, 0));
|
||||
auto SanitizedShifted = _Select(IR::COND_ULE, Start, MaxSrcBitOp, Shifted, _Constant(Size, 0));
|
||||
|
||||
// Now handle the length specifier.
|
||||
auto Length = _Bfe(OpSizeFromSrc(Op), 8, 8, Src2);
|
||||
auto Length = _Bfe(Size, 8, 8, Src2);
|
||||
|
||||
// Now build up the mask
|
||||
// (1 << Length) - 1 = ~(~0 << Length)
|
||||
auto AllOnes = _Constant(~0ull);
|
||||
auto InvertedMask = _Lshl(IR::SizeToOpSize(Size), AllOnes, Length);
|
||||
auto InvertedMask = _Lshl(Size, AllOnes, Length);
|
||||
|
||||
// Now put it all together and make the result.
|
||||
auto Masked = _Andn(IR::SizeToOpSize(Size), SanitizedShifted, InvertedMask);
|
||||
auto Masked = _Andn(Size, SanitizedShifted, InvertedMask);
|
||||
|
||||
// Sanitize the length. If it is above the max, we don't do the masking.
|
||||
auto Dest = _Select(IR::COND_ULE, Length, MaxSrcBitOp, Masked, SanitizedShifted);
|
||||
@@ -1787,7 +1787,7 @@ void OpDispatchBuilder::BMI2Shift(OpcodeArgs) {
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::BZHI(OpcodeArgs) {
|
||||
const auto Size = GetSrcSize(Op);
|
||||
const auto Size = OpSizeFromSrc(Op);
|
||||
const auto OperandSize = Size * 8;
|
||||
|
||||
// In 32-bit mode we only look at bottom 32-bit, no 8 or 16-bit BZHI so no
|
||||
@@ -1799,9 +1799,9 @@ void OpDispatchBuilder::BZHI(OpcodeArgs) {
|
||||
// Clear the high bits specified by the index. A64 only considers bottom bits
|
||||
// of the shift, so we don't need to mask bottom 8-bits ourselves.
|
||||
// Out-of-bounds results ignored after.
|
||||
auto NegOne = _Constant(OperandSize, -1);
|
||||
auto Mask = _Lshl(IR::SizeToOpSize(Size), NegOne, Index);
|
||||
auto MaskResult = _Andn(IR::SizeToOpSize(Size), Src, Mask);
|
||||
auto NegOne = _Constant(Size, -1);
|
||||
auto Mask = _Lshl(Size, NegOne, Index);
|
||||
auto MaskResult = _Andn(Size, Src, Mask);
|
||||
|
||||
// If the index is above OperandSize, we don't clear anything. BZHI only
|
||||
// considers the bottom 8-bits, so we really want to know if the bottom 8-bits
|
||||
@@ -1810,7 +1810,7 @@ void OpDispatchBuilder::BZHI(OpcodeArgs) {
|
||||
// Because we're clobbering flags internally we ignore all carry invert
|
||||
// shenanigans and use the raw versions here.
|
||||
_TestNZ(OpSize::i64Bit, Index, _Constant(0xFF & ~(OperandSize - 1)));
|
||||
auto Result = _NZCVSelect(IR::SizeToOpSize(Size), {COND_NEQ}, Src, MaskResult);
|
||||
auto Result = _NZCVSelect(Size, {COND_NEQ}, Src, MaskResult);
|
||||
StoreResult(GPRClass, Op, Result, OpSize::iInvalid);
|
||||
|
||||
auto Zero = _InlineConstant(0);
|
||||
@@ -2065,7 +2065,7 @@ void OpDispatchBuilder::RCROp(OpcodeArgs) {
|
||||
Ref Res = _Lshr(OpSize, Dest, Src);
|
||||
auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC);
|
||||
|
||||
auto One = _Constant(Size, 1);
|
||||
auto One = _Constant(OpSizeFromSrc(Op), 1);
|
||||
|
||||
// Res |= (Dest << (Size - Shift + 1));
|
||||
// Expressed as Res | ((Src << (Size - Shift)) << 1) to get correct
|
||||
@@ -2188,7 +2188,7 @@ void OpDispatchBuilder::RCRSmallerOp(OpcodeArgs) {
|
||||
if (IsSrcConst) {
|
||||
SetCFDirect(Tmp, SrcConst - 1, true);
|
||||
} else {
|
||||
auto One = _Constant(Size, 1);
|
||||
auto One = _Constant(OpSizeFromSrc(Op), 1);
|
||||
auto NewCF = _Lshr(OpSize::i32Bit, Tmp, _Sub(OpSize::i32Bit, Src, One));
|
||||
SetCFDirect(NewCF, 0, true);
|
||||
}
|
||||
@@ -2337,7 +2337,7 @@ void OpDispatchBuilder::RCLSmallerOp(OpcodeArgs) {
|
||||
|
||||
auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_RAW_LOC);
|
||||
|
||||
Ref Tmp = _Constant(64, 0);
|
||||
Ref Tmp = _Constant(OpSize::i64Bit, 0);
|
||||
|
||||
for (size_t i = 0; i < (32 + Size + 1); i += (Size + 1)) {
|
||||
// Insert incoming value
|
||||
@@ -3084,7 +3084,7 @@ void OpDispatchBuilder::INCOp(OpcodeArgs) {
|
||||
Ref Dest;
|
||||
Ref Result;
|
||||
const auto Size = GetSrcBitSize(Op);
|
||||
auto OneConst = _Constant(Size, 1);
|
||||
auto OneConst = _Constant(OpSizeFromSrc(Op), 1);
|
||||
|
||||
const bool IsLocked = DestIsLockedMem(Op);
|
||||
|
||||
@@ -3125,7 +3125,7 @@ void OpDispatchBuilder::DECOp(OpcodeArgs) {
|
||||
Ref Dest;
|
||||
Ref Result;
|
||||
const auto Size = GetSrcBitSize(Op);
|
||||
auto OneConst = _Constant(Size, 1);
|
||||
auto OneConst = _Constant(OpSizeFromSrc(Op), 1);
|
||||
|
||||
const bool IsLocked = DestIsLockedMem(Op);
|
||||
|
||||
@@ -3135,7 +3135,7 @@ void OpDispatchBuilder::DECOp(OpcodeArgs) {
|
||||
Ref DestAddress = MakeSegmentAddress(Op, Op->Dest);
|
||||
|
||||
// Use Add instead of Sub to avoid a NEG
|
||||
Dest = _AtomicFetchAdd(OpSizeFromSrc(Op), _Constant(Size, -1), DestAddress);
|
||||
Dest = _AtomicFetchAdd(OpSizeFromSrc(Op), _Constant(OpSizeFromSrc(Op), -1), DestAddress);
|
||||
} else {
|
||||
Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = Size >= 32});
|
||||
}
|
||||
@@ -3585,7 +3585,7 @@ void OpDispatchBuilder::POPFOp(OpcodeArgs) {
|
||||
// Bit 1 is always 1
|
||||
// Bit 9 is always 1 because we always have interrupts enabled
|
||||
|
||||
Src = _Or(OpSize::i64Bit, Src, _Constant(Size * 8, 0x202));
|
||||
Src = _Or(OpSize::i64Bit, Src, _Constant(Size, 0x202));
|
||||
|
||||
SetPackedRFLAG(false, Src);
|
||||
}
|
||||
|
||||
@@ -2618,14 +2618,14 @@ OpDispatchBuilder::RefPair OpDispatchBuilder::AVX128_VPGatherImpl(OpSize Size, O
|
||||
// If the address element size if half the size of the Element load size then we need to start fetching half-way through the low register.
|
||||
AddrAddressing.Low = VSIB.Low;
|
||||
AddrAddressing.High = VSIB.High;
|
||||
IndexElementOffset = OpSize::i128Bit / AddrElementSize / 2;
|
||||
IndexElementOffset = IR::NumElements(OpSize::i128Bit, AddrElementSize) / 2;
|
||||
} else if (AddrElementSize == OpSize::i64Bit && ElementLoadSize == OpSize::i32Bit) {
|
||||
AddrAddressing.Low = VSIB.High;
|
||||
AddrAddressing.High = Invalid();
|
||||
DestReg = Result.Low; ///< Start mixing with the low register.
|
||||
MaskReg = Mask.Low; ///< Mask starts with the low mask here.
|
||||
IndexElementOffset = 0;
|
||||
DataElementOffset = OpSize::i128Bit / ElementLoadSize / 2;
|
||||
DataElementOffset = IR::NumElements(OpSize::i128Bit, ElementLoadSize) / 2;
|
||||
}
|
||||
|
||||
///< Calculate the high-half.
|
||||
|
||||
@@ -121,7 +121,7 @@ void OpDispatchBuilder::SHA1RNDS4Op(OpcodeArgs) {
|
||||
|
||||
const uint64_t Imm8 = Op->Src[1].Literal() & 0b11;
|
||||
const FnType Fn = fn_array[Imm8];
|
||||
auto K = _Constant(32, k_array[Imm8]);
|
||||
auto K = _Constant(OpSize::i32Bit, k_array[Imm8]);
|
||||
|
||||
Ref Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags);
|
||||
Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags);
|
||||
@@ -137,9 +137,10 @@ void OpDispatchBuilder::SHA1RNDS4Op(OpcodeArgs) {
|
||||
auto D = _VExtractToGPR(OpSize::i128Bit, OpSize::i32Bit, Dest, 0);
|
||||
|
||||
auto A1 =
|
||||
_Add(OpSize::i32Bit, _Add(OpSize::i32Bit, _Add(OpSize::i32Bit, Fn(*this, B, C, D), _Ror(OpSize::i32Bit, A, _Constant(32, 27))), W0E), K);
|
||||
_Add(OpSize::i32Bit,
|
||||
_Add(OpSize::i32Bit, _Add(OpSize::i32Bit, Fn(*this, B, C, D), _Ror(OpSize::i32Bit, A, _Constant(OpSize::i32Bit, 27))), W0E), K);
|
||||
auto B1 = A;
|
||||
auto C1 = _Ror(OpSize::i32Bit, B, _Constant(32, 2));
|
||||
auto C1 = _Ror(OpSize::i32Bit, B, _Constant(OpSize::i32Bit, 2));
|
||||
auto D1 = C;
|
||||
auto E1 = D;
|
||||
|
||||
@@ -151,9 +152,10 @@ void OpDispatchBuilder::SHA1RNDS4Op(OpcodeArgs) {
|
||||
auto Q = _Add(OpSize::i32Bit, W, E);
|
||||
|
||||
auto ANext =
|
||||
_Add(OpSize::i32Bit, _Add(OpSize::i32Bit, _Add(OpSize::i32Bit, Fn(*this, B, C, D), _Ror(OpSize::i32Bit, A, _Constant(32, 27))), Q), K);
|
||||
_Add(OpSize::i32Bit,
|
||||
_Add(OpSize::i32Bit, _Add(OpSize::i32Bit, Fn(*this, B, C, D), _Ror(OpSize::i32Bit, A, _Constant(OpSize::i32Bit, 27))), Q), K);
|
||||
auto BNext = A;
|
||||
auto CNext = _Ror(OpSize::i32Bit, B, _Constant(32, 2));
|
||||
auto CNext = _Ror(OpSize::i32Bit, B, _Constant(OpSize::i32Bit, 2));
|
||||
auto DNext = C;
|
||||
auto ENext = D;
|
||||
|
||||
@@ -183,8 +185,10 @@ void OpDispatchBuilder::SHA256MSG1Op(OpcodeArgs) {
|
||||
Result = _VSha256U0(Dest, Src);
|
||||
} else {
|
||||
const auto Sigma0 = [this](Ref W) -> Ref {
|
||||
return _Xor(OpSize::i32Bit, _Xor(OpSize::i32Bit, _Ror(OpSize::i32Bit, W, _Constant(32, 7)), _Ror(OpSize::i32Bit, W, _Constant(32, 18))),
|
||||
_Lshr(OpSize::i32Bit, W, _Constant(32, 3)));
|
||||
return _Xor(
|
||||
OpSize::i32Bit,
|
||||
_Xor(OpSize::i32Bit, _Ror(OpSize::i32Bit, W, _Constant(OpSize::i32Bit, 7)), _Ror(OpSize::i32Bit, W, _Constant(OpSize::i32Bit, 18))),
|
||||
_Lshr(OpSize::i32Bit, W, _Constant(OpSize::i32Bit, 3)));
|
||||
};
|
||||
|
||||
auto W4 = _VExtractToGPR(OpSize::i128Bit, OpSize::i32Bit, Src, 0);
|
||||
@@ -209,8 +213,10 @@ void OpDispatchBuilder::SHA256MSG1Op(OpcodeArgs) {
|
||||
|
||||
void OpDispatchBuilder::SHA256MSG2Op(OpcodeArgs) {
|
||||
const auto Sigma1 = [this](Ref W) -> Ref {
|
||||
return _Xor(OpSize::i32Bit, _Xor(OpSize::i32Bit, _Ror(OpSize::i32Bit, W, _Constant(32, 17)), _Ror(OpSize::i32Bit, W, _Constant(32, 19))),
|
||||
_Lshr(OpSize::i32Bit, W, _Constant(32, 10)));
|
||||
return _Xor(
|
||||
OpSize::i32Bit,
|
||||
_Xor(OpSize::i32Bit, _Ror(OpSize::i32Bit, W, _Constant(OpSize::i32Bit, 17)), _Ror(OpSize::i32Bit, W, _Constant(OpSize::i32Bit, 19))),
|
||||
_Lshr(OpSize::i32Bit, W, _Constant(OpSize::i32Bit, 10)));
|
||||
};
|
||||
|
||||
Ref Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags);
|
||||
@@ -246,12 +252,12 @@ void OpDispatchBuilder::SHA256RNDS2Op(OpcodeArgs) {
|
||||
return _Xor(OpSize::i32Bit, _And(OpSize::i32Bit, E, F), _Andn(OpSize::i32Bit, G, E));
|
||||
};
|
||||
const auto Sigma0 = [this](Ref A) -> Ref {
|
||||
return _XorShift(OpSize::i32Bit, _XorShift(OpSize::i32Bit, _Ror(OpSize::i32Bit, A, _Constant(32, 2)), A, ShiftType::ROR, 13), A,
|
||||
ShiftType::ROR, 22);
|
||||
return _XorShift(OpSize::i32Bit, _XorShift(OpSize::i32Bit, _Ror(OpSize::i32Bit, A, _Constant(OpSize::i32Bit, 2)), A, ShiftType::ROR, 13),
|
||||
A, ShiftType::ROR, 22);
|
||||
};
|
||||
const auto Sigma1 = [this](Ref E) -> Ref {
|
||||
return _XorShift(OpSize::i32Bit, _XorShift(OpSize::i32Bit, _Ror(OpSize::i32Bit, E, _Constant(32, 6)), E, ShiftType::ROR, 11), E,
|
||||
ShiftType::ROR, 25);
|
||||
return _XorShift(OpSize::i32Bit, _XorShift(OpSize::i32Bit, _Ror(OpSize::i32Bit, E, _Constant(OpSize::i32Bit, 6)), E, ShiftType::ROR, 11),
|
||||
E, ShiftType::ROR, 25);
|
||||
};
|
||||
|
||||
Ref Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags);
|
||||
|
||||
@@ -706,7 +706,7 @@ void OpDispatchBuilder::MOVQMMXOp(OpcodeArgs) {
|
||||
|
||||
void OpDispatchBuilder::MOVMSKOp(OpcodeArgs, IR::OpSize ElementSize) {
|
||||
const auto Size = OpSizeFromSrc(Op);
|
||||
uint8_t NumElements = Size / ElementSize;
|
||||
const auto NumElements = IR::NumElements(Size, ElementSize);
|
||||
|
||||
Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags);
|
||||
|
||||
@@ -893,8 +893,8 @@ Ref OpDispatchBuilder::PShufWLane(IR::OpSize Size, FEXCore::IR::IndexNamedVector
|
||||
constexpr auto IdentityCopy = 0b11'10'01'00;
|
||||
|
||||
const bool Is128BitLane = Size == OpSize::i128Bit;
|
||||
const uint8_t NumElements = Size / 2;
|
||||
const uint8_t HalfNumElements = NumElements >> 1;
|
||||
const auto NumElements = IR::NumElements(Size, IR::OpSize::i16Bit);
|
||||
const auto HalfNumElements = NumElements >> 1;
|
||||
|
||||
// TODO: There can be more optimized copies here.
|
||||
switch (Shuffle) {
|
||||
@@ -4593,7 +4593,7 @@ void OpDispatchBuilder::VPERMQOp(OpcodeArgs) {
|
||||
Result = _VDupElement(DstSize, OpSize::i64Bit, Src, Index);
|
||||
} else {
|
||||
Result = LoadZeroVector(DstSize);
|
||||
for (size_t i = 0; i < DstSize / 8; i++) {
|
||||
for (size_t i = 0; i < IR::NumElements(DstSize, IR::OpSize::i64Bit); i++) {
|
||||
const auto SrcIndex = (Selector >> (i * 2)) & 0b11;
|
||||
Result = _VInsElement(DstSize, OpSize::i64Bit, i, SrcIndex, Result, Src);
|
||||
}
|
||||
@@ -4605,7 +4605,7 @@ Ref OpDispatchBuilder::VBLENDOpImpl(IR::OpSize VecSize, IR::OpSize ElementSize,
|
||||
const std::array Sources {Src1, Src2};
|
||||
|
||||
Ref Result = ZeroRegister;
|
||||
const int NumElements = VecSize / ElementSize;
|
||||
const auto NumElements = IR::NumElements(VecSize, ElementSize);
|
||||
for (int i = 0; i < NumElements; i++) {
|
||||
const auto SelectorIndex = (Selector >> i) & 1;
|
||||
|
||||
|
||||
@@ -733,7 +733,7 @@ void OpDispatchBuilder::FNINIT(OpcodeArgs) {
|
||||
}
|
||||
|
||||
// Init FCW to 0x037F
|
||||
auto NewFCW = _Constant(16, 0x037F);
|
||||
auto NewFCW = _Constant(OpSize::i16Bit, 0x037F);
|
||||
_StoreContext(OpSize::i16Bit, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW));
|
||||
|
||||
// Set top to zero
|
||||
|
||||
@@ -549,6 +549,7 @@ protected:
|
||||
// This must directly match bytes to the named opsize.
|
||||
// Implicit sized IR operations does math to get between sizes.
|
||||
enum OpSize : uint8_t {
|
||||
iUnsized = 0,
|
||||
i8Bit = 1,
|
||||
i16Bit = 2,
|
||||
i32Bit = 4,
|
||||
@@ -580,6 +581,7 @@ enum class ShiftType : uint8_t {
|
||||
// This is a nop operation and will be eliminated by the compiler.
|
||||
static inline OpSize SizeToOpSize(uint8_t Size) {
|
||||
switch (Size) {
|
||||
case 0: return OpSize::iUnsized;
|
||||
case 1: return OpSize::i8Bit;
|
||||
case 2: return OpSize::i16Bit;
|
||||
case 4: return OpSize::i32Bit;
|
||||
@@ -595,6 +597,7 @@ static inline OpSize SizeToOpSize(uint8_t Size) {
|
||||
// This is a nop operation and will be eliminated by the compiler.
|
||||
static inline uint8_t OpSizeToSize(IR::OpSize Size) {
|
||||
switch (Size) {
|
||||
case OpSize::iUnsized: return 0;
|
||||
case OpSize::i8Bit: return 1;
|
||||
case OpSize::i16Bit: return 2;
|
||||
case OpSize::i32Bit: return 4;
|
||||
@@ -607,12 +610,34 @@ static inline uint8_t OpSizeToSize(IR::OpSize Size) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t OpSizeAsBits(IR::OpSize Size) {
|
||||
LOGMAN_THROW_A_FMT(Size != IR::OpSize::iInvalid, "Invalid Size");
|
||||
return IR::OpSizeToSize(Size) * 8u;
|
||||
}
|
||||
|
||||
static inline OpSize MultiplyOpSize(IR::OpSize Size, uint8_t Multiplier) {
|
||||
LOGMAN_THROW_A_FMT(Size != IR::OpSize::iInvalid, "Invalid Size");
|
||||
return IR::SizeToOpSize(IR::OpSizeToSize(Size) * Multiplier);
|
||||
}
|
||||
|
||||
static inline OpSize DivideOpSize(IR::OpSize Size, uint8_t Multiplier) {
|
||||
return IR::SizeToOpSize(IR::OpSizeToSize(Size) / Multiplier);
|
||||
static inline OpSize DivideOpSize(IR::OpSize Size, uint8_t Divisor) {
|
||||
LOGMAN_THROW_A_FMT(Size != IR::OpSize::iInvalid, "Invalid Size");
|
||||
return IR::SizeToOpSize(IR::OpSizeToSize(Size) / Divisor);
|
||||
}
|
||||
|
||||
static inline OpSize operator/(IR::OpSize Size, IR::OpSize Divisor) {
|
||||
LOGMAN_THROW_A_FMT(Size != IR::OpSize::iInvalid, "Invalid Size");
|
||||
return IR::SizeToOpSize(IR::OpSizeToSize(Size) / IR::OpSizeToSize(Divisor));
|
||||
}
|
||||
|
||||
static inline OpSize operator/(IR::OpSize Size, uint8_t Divisor) {
|
||||
LOGMAN_THROW_A_FMT(Size != IR::OpSize::iInvalid, "Invalid Size");
|
||||
return IR::SizeToOpSize(IR::OpSizeToSize(Size) / Divisor);
|
||||
}
|
||||
|
||||
static inline uint8_t NumElements(IR::OpSize RegisterSize, IR::OpSize ElementSize) {
|
||||
LOGMAN_THROW_A_FMT(RegisterSize != IR::OpSize::iInvalid && ElementSize != IR::OpSize::iInvalid, "Invalid Size");
|
||||
return IR::OpSizeToSize(RegisterSize) / IR::OpSizeToSize(ElementSize);
|
||||
}
|
||||
|
||||
#define IROP_ENUM
|
||||
|
||||
+147
-147
@@ -258,7 +258,7 @@
|
||||
"FPR = AllocateFPR OpSize:#RegisterSize, OpSize:#ElementSize": {
|
||||
"Desc": ["Like AllocateGPR, but for FPR"],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"GPR = AllocateGPRAfter GPR:$After": {
|
||||
"Desc": ["Silly pseudo-instruction to allocate a register for a future destination",
|
||||
@@ -405,8 +405,8 @@
|
||||
],
|
||||
"DestSize": "ByteSize",
|
||||
"EmitValidation": [
|
||||
"($Class == GPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8 || #ByteSize == 16 || #ByteSize == 32)) || $Class == GPRClass",
|
||||
"($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass",
|
||||
"!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't LoadContext to GPR\"",
|
||||
"!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't LoadContext to XMM\""
|
||||
]
|
||||
@@ -419,8 +419,8 @@
|
||||
"HasSideEffects": true,
|
||||
"DestSize": "ByteSize",
|
||||
"EmitValidation": [
|
||||
"($Class == GPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8 || #ByteSize == 16 || #ByteSize == 32)) || $Class == GPRClass",
|
||||
"($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass",
|
||||
"!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't LoadContext to GPR\"",
|
||||
"!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't LoadContext to XMM\""
|
||||
]
|
||||
@@ -436,8 +436,8 @@
|
||||
"DestSize": "ByteSize",
|
||||
"EmitValidation": [
|
||||
"WalkFindRegClass($Value) == $Class",
|
||||
"($Class == GPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8 || #ByteSize == 16 || #ByteSize == 32)) || $Class == GPRClass",
|
||||
"($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass",
|
||||
"!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't StoreContext to GPR\"",
|
||||
"!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't StoreContext to XMM\""
|
||||
]
|
||||
@@ -454,8 +454,8 @@
|
||||
"EmitValidation": [
|
||||
"WalkFindRegClass($Value1) == $Class",
|
||||
"WalkFindRegClass($Value2) == $Class",
|
||||
"($Class == GPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8 || #ByteSize == 16 || #ByteSize == 32)) || $Class == GPRClass",
|
||||
"($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass",
|
||||
"!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't StoreContext to GPR\"",
|
||||
"!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't StoreContext to XMM\""
|
||||
]
|
||||
@@ -467,8 +467,8 @@
|
||||
],
|
||||
"DestSize": "ByteSize",
|
||||
"EmitValidation": [
|
||||
"($Class == GPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8 || #ByteSize == 16 || #ByteSize == 32)) || $Class == GPRClass",
|
||||
"($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass",
|
||||
"!($BaseOffset >= offsetof(Core::CPUState, gregs[0]) && $BaseOffset < offsetof(Core::CPUState, gregs[16])) && \"Can't LoadContextIndexed to GPR\"",
|
||||
"!($BaseOffset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $BaseOffset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't LoadContextIndexed to XMM\""
|
||||
]
|
||||
@@ -481,8 +481,8 @@
|
||||
"DestSize": "ByteSize",
|
||||
"EmitValidation": [
|
||||
"WalkFindRegClass($Value) == $Class",
|
||||
"($Class == GPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == 1 || #ByteSize == 2 || #ByteSize == 4 || #ByteSize == 8 || #ByteSize == 16 || #ByteSize == 32)) || $Class == GPRClass",
|
||||
"($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass",
|
||||
"($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass",
|
||||
"!($BaseOffset >= offsetof(Core::CPUState, gregs[0]) && $BaseOffset < offsetof(Core::CPUState, gregs[16])) && \"Can't StoreContextIndexed to GPR\"",
|
||||
"!($BaseOffset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $BaseOffset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't StoreContextIndexed to XMM\""
|
||||
]
|
||||
@@ -588,7 +588,7 @@
|
||||
"determines whether or not that element will be loaded from memory"],
|
||||
"ImplicitFlagClobber": true,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"VStoreVectorMasked OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Mask, FPR:$Data, GPR:$Addr, GPR:$Offset, MemOffsetType:$OffsetType, u8:$OffsetScale": {
|
||||
"Desc": ["Does a masked store similar to VPMASKMOV/VMASKMOV where the upper bit of each element",
|
||||
@@ -596,7 +596,7 @@
|
||||
"HasSideEffects": true,
|
||||
"ImplicitFlagClobber": true,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VLoadVectorGatherMasked OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Incoming, FPR:$Mask, GPR:$AddrBase, FPR:$VectorIndexLow, FPR:$VectorIndexHigh, OpSize:$VectorIndexElementSize, u8:$OffsetScale, u8:$DataElementOffsetStart, u8:$IndexElementOffsetStart": {
|
||||
"Desc": [
|
||||
@@ -607,7 +607,7 @@
|
||||
"TiedSource": 0,
|
||||
"ImplicitFlagClobber": true,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"EmitValidation": [
|
||||
"$VectorIndexElementSize == OpSize::i32Bit || $VectorIndexElementSize == OpSize::i64Bit"
|
||||
]
|
||||
@@ -622,7 +622,7 @@
|
||||
"TiedSource": 0,
|
||||
"ImplicitFlagClobber": true,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"EmitValidation": [
|
||||
"ElementSize == OpSize::i32Bit",
|
||||
"RegisterSize != FEXCore::IR::OpSize::i256Bit && \"What does 256-bit mean in this context?\""
|
||||
@@ -634,19 +634,19 @@
|
||||
"Matches arm64 ld1 semantics"],
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"VStoreVectorElement OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Value, u8:$Index, GPR:$Addr": {
|
||||
"Desc": ["Does a memory store of a single element of a vector.",
|
||||
"Matches arm64 st1 semantics"],
|
||||
"HasSideEffects": true,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VBroadcastFromMem OpSize:#RegisterSize, OpSize:#ElementSize, GPR:$Address": {
|
||||
"Desc": ["Broadcasts an ElementSize value from memory into each element of a vector."],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"GPR = Push OpSize:#Size, OpSize:$ValueSize, GPR:$Value, GPR:$Addr": {
|
||||
"Desc": [
|
||||
@@ -1685,7 +1685,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFSubScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'sub' between Vector1 and Vector2.",
|
||||
@@ -1695,7 +1695,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFMulScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'mul' between Vector1 and Vector2.",
|
||||
@@ -1705,7 +1705,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFDivScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'div' between Vector1 and Vector2.",
|
||||
@@ -1715,7 +1715,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFMinScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'min' between Vector1 and Vector2.",
|
||||
@@ -1728,7 +1728,7 @@
|
||||
"If either source operand is NaN then return the second operand."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"ImplicitFlagClobber": true
|
||||
},
|
||||
"FPR = VFMaxScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
@@ -1742,7 +1742,7 @@
|
||||
"If either source operand is NaN then return the second operand."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"ImplicitFlagClobber": true
|
||||
},
|
||||
"FPR = VFSqrtScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
@@ -1753,7 +1753,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFRSqrtScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'rsqrt' on Vector2, inserting in to Vector1 and storing in to the destination.",
|
||||
@@ -1763,7 +1763,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFRecpScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'recip' on Vector2, inserting in to Vector1 and storing in to the destination.",
|
||||
@@ -1773,7 +1773,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFToFScalarInsert OpSize:#RegisterSize, OpSize:#DstElementSize, OpSize:$SrcElementSize, FPR:$Vector1, FPR:$Vector2, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'cvt' between Vector1 and Vector2.",
|
||||
@@ -1816,7 +1816,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, FloatCompareOp:$Op, i1:$ZeroUpperBits": {
|
||||
"Desc": ["Does a scalar 'cmp' between Vector1 and Vecto2, inserting in to Vector1 and storing in to the destination.",
|
||||
@@ -1827,7 +1827,7 @@
|
||||
"For 256-bit operation with ZeroUpperBits, this matches AVX insert semantics."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFMLAScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Upper, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
"Desc": [
|
||||
@@ -1836,7 +1836,7 @@
|
||||
"Upper elements copied from Upper"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 0
|
||||
},
|
||||
"FPR = VFMLSScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Upper, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
@@ -1846,7 +1846,7 @@
|
||||
"Upper elements copied from Upper"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 0
|
||||
},
|
||||
"FPR = VFNMLAScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Upper, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
@@ -1856,7 +1856,7 @@
|
||||
"Upper elements copied from Upper"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 0
|
||||
},
|
||||
"FPR = VFNMLSScalarInsert OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Upper, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
@@ -1866,7 +1866,7 @@
|
||||
"Upper elements copied from Upper"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 0
|
||||
}
|
||||
},
|
||||
@@ -1883,7 +1883,7 @@
|
||||
"Desc": ["Generates a vector with each element containg the immediate zexted"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = LoadNamedVectorConstant OpSize:#RegisterSize, NamedVectorConstant:$Constant": {
|
||||
@@ -1901,25 +1901,25 @@
|
||||
},
|
||||
"FPR = VNeg OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VNot OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VAbs OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Does an signed integer absolute"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VPopcount OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Does a popcount for each element of the register"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VAddV OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
@@ -1927,49 +1927,49 @@
|
||||
"Result is a zero extended scalar"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUMinV OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Does a horizontal vector unsigned minimum of elements across the source vector",
|
||||
"Result is a zero extended scalar"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUMaxV OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Does a horizontal vector unsigned maximum of elements across the source vector",
|
||||
"Result is a zero extended scalar"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFAbs OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VFNeg OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VFRecp OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VFSqrt OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VFRSqrt OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VCMPEQZ OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VCMPGTZ OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Vector compare signed greater than",
|
||||
@@ -1977,7 +1977,7 @@
|
||||
"Compares the vector against zero"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VCMPLTZ OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Vector compare signed less than",
|
||||
@@ -1985,39 +1985,39 @@
|
||||
"Compares the vector against zero"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VDupElement OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$Index": {
|
||||
"Desc": ["Duplicates one element from the source register across the whole register"],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VShlI OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShrI OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShraI OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$DestVector, FPR:$Vector, u8:$BitShift": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSShrI OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VUShrNI OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift": {
|
||||
"TiedSource": 0,
|
||||
"Desc": "Unsigned shifts right each element and then narrows to the next lower element size",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
|
||||
"FPR = VUShrNI2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper, u8:$BitShift": {
|
||||
@@ -2026,73 +2026,73 @@
|
||||
"Inserts results in to the high elements of the first argument"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSXTL OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": "Sign extends elements from the source element size to the next size up",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSXTL2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Sign extends elements from the source element size to the next size up",
|
||||
"Source elements come from the upper half of the register"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSSHLL OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift{0}": {
|
||||
"Desc": "Sign extends elements from the source element size to the next size up",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSSHLL2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift{0}": {
|
||||
"Desc": ["Sign extends elements from the source element size to the next size up",
|
||||
"Source elements come from the upper half of the register"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VUXTL OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": "Zero extends elements from the source element size to the next size up",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VUXTL2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Zero extends elements from the source element size to the next size up",
|
||||
"Source elements come from the upper half of the register"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSQXTN OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSQXTN2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSQXTNPair OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"Desc": ["Does both VSQXTN and VSQXTN2 in a combined operation."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSQXTUN OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSQXTUN2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSQXTUNPair OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"Desc": ["Does both VSQXTUN and VSQXTUN2 in a combined operation."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)"
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSRSHR OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift": {
|
||||
"Desc": ["Signed rounding shift right by immediate",
|
||||
@@ -2100,7 +2100,7 @@
|
||||
],
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSQSHL OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, u8:$BitShift": {
|
||||
"Desc": ["Signed satuating shift left by immediate",
|
||||
@@ -2108,265 +2108,265 @@
|
||||
],
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VRev32 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc" : ["Reverses elements in 32-bit halfwords",
|
||||
"Available element size: 1byte, 2 byte"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VRev64 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc" : ["Reverses elements in 64-bit halfwords",
|
||||
"Available element size: 1byte, 2 byte, 4 byte"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VAdd OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VSub OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VAnd OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VAndn OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VOr OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VXor OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VUQAdd OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VUQSub OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VSQAdd OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VSQSub OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VAddP OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"Desc": "Does a horizontal pairwise add of elements across the two source vectors",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VURAvg OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": ["Does an unsigned rounded average", "dst_elem = (src1_elem + src2_elem + 1) >> 1"],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUMin OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUMax OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSMin OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSMax OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VZip OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VZip2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUnZip OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUnZip2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VTrn OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VTrn2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VFAdd OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFAddP OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper": {
|
||||
"Desc": "Does a horizontal pairwise add of elements across the two source vectors with float element types",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFAddV OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Does a horizontal float vector add of elements across the source vector",
|
||||
"Result is a zero extended scalar"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFSub OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFMul OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFDiv OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VFMin OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFMax OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VMul OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUMull OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSMull OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": [ "Does a signed integer multiply with extend.",
|
||||
"ElementSize is the source size"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VUMull2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": "Multiplies the high elements with size extension",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VSMull2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": "Multiplies the high elements with size extension",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VUMulH OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": "Wide unsigned multiply returning the high results",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSMulH OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": "Wide signed multiply returning the high results",
|
||||
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUABDL OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": ["Unsigned Absolute Difference Long"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VUABDL2 OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"Desc": ["Unsigned Absolute Difference Long",
|
||||
"Using the high elements of the source vectors"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)"
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))"
|
||||
},
|
||||
"FPR = VUShl OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftVector, i1:$RangeCheck": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShr OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftVector, i1:$RangeCheck": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSShr OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftVector, i1:$RangeCheck": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShlS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftScalar": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShrS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftScalar": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSShrS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftScalar": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShrSWide OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftScalar": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VSShrSWide OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftScalar": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VUShlSWide OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector, FPR:$ShiftScalar": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VInsElement OpSize:#RegisterSize, OpSize:#ElementSize, u8:$DestIdx, u8:$SrcIdx, FPR:$DestVector, FPR:$SrcVector": {
|
||||
"TiedSource": 0,
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VInsGPR OpSize:#RegisterSize, OpSize:#ElementSize, u8:$DestIdx, FPR:$DestVector, GPR:$Src": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VExtr OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$VectorLower, FPR:$VectorUpper, u8:$Index": {
|
||||
@@ -2377,12 +2377,12 @@
|
||||
"Dest = TmpVector >> (ElementSize * Index * 8); // Or can be thought of `concat(&TmpVector[Index], i128)`"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VCMPEQ OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VCMPGT OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
@@ -2391,35 +2391,35 @@
|
||||
],
|
||||
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPEQ OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPNEQ OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPLT OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPGT OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPLE OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPORD OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFCMPUNO OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VTBL1 OpSize:#RegisterSize, FPR:$VectorTable, FPR:$VectorIndices": {
|
||||
"Desc": ["Does a vector table lookup from one register in to the destination",
|
||||
@@ -2484,7 +2484,7 @@
|
||||
},
|
||||
"FPR = VFCADD OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, u16:$Rotate": {
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = VFMLA OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
"Desc": [
|
||||
@@ -2492,7 +2492,7 @@
|
||||
"This explicitly matches x86 FMA semantics because ARM semantics are mind-bending."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 2
|
||||
},
|
||||
"FPR = VFMLS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
@@ -2501,7 +2501,7 @@
|
||||
"This explicitly matches x86 FMA semantics because ARM semantics are mind-bending."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 2
|
||||
},
|
||||
"FPR = VFNMLA OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
@@ -2510,7 +2510,7 @@
|
||||
"This explicitly matches x86 FMA semantics because ARM semantics are mind-bending."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 2
|
||||
},
|
||||
"FPR = VFNMLS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector1, FPR:$Vector2, FPR:$Addend": {
|
||||
@@ -2519,7 +2519,7 @@
|
||||
"This explicitly matches x86 FMA semantics because ARM semantics are mind-bending."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize",
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)",
|
||||
"TiedSource": 2
|
||||
}
|
||||
},
|
||||
@@ -2529,13 +2529,13 @@
|
||||
"No conversion is done on the data as it moves register files"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = VDupFromGPR OpSize:#RegisterSize, OpSize:#ElementSize, GPR:$Src": {
|
||||
"Desc": ["Broadcasts a value in a GPR into each ElementSize-sized element in a vector"],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
|
||||
"FPR = Float_FromGPR_S OpSize:#DstElementSize, OpSize:$SrcElementSize, GPR:$Src": {
|
||||
@@ -2554,19 +2554,19 @@
|
||||
"FPR = Vector_SToF OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": "Vector op: Converts signed integer to same size float",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = Vector_FToS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": ["Vector op: Converts float to signed integer, rounding towards zero",
|
||||
"Rounding mode determined by host rounding mode"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = Vector_FToZS OpSize:#RegisterSize, OpSize:#ElementSize, FPR:$Vector": {
|
||||
"Desc": "Vector op: Converts float to signed integer, rounding towards zero",
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = Vector_FToF OpSize:#RegisterSize, OpSize:#DestElementSize, FPR:$Vector, OpSize:$SrcElementSize": {
|
||||
"Desc": "Vector op: Converts float from source element size to destination size (fp32<->fp64)",
|
||||
@@ -2580,7 +2580,7 @@
|
||||
"Selecting from the high half of the register."
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize << 1)",
|
||||
"NumElements": "RegisterSize / (IR::MultiplyOpSize(ElementSize, 2))",
|
||||
"EmitValidation": [
|
||||
"RegisterSize != FEXCore::IR::OpSize::i256Bit && \"What does 256-bit mean in this context?\""
|
||||
]
|
||||
@@ -2594,7 +2594,7 @@
|
||||
"F64->F32, F32->F16"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / (ElementSize >> 1)",
|
||||
"NumElements": "RegisterSize / (IR::DivideOpSize(ElementSize, 2))",
|
||||
"EmitValidation": [
|
||||
"RegisterSize != FEXCore::IR::OpSize::i256Bit && \"What does 256-bit mean in this context?\""
|
||||
]
|
||||
@@ -2604,7 +2604,7 @@
|
||||
"Rounding mode determined by argument"
|
||||
],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
"NumElements": "IR::NumElements(RegisterSize, ElementSize)"
|
||||
},
|
||||
"FPR = Vector_F64ToI32 OpSize:#RegisterSize, FPR:$Vector, RoundType:$Round, i1:$EnsureZeroUpperHalf": {
|
||||
"Desc": ["Vector op: Rounds 64-bit float to 32-bit integral with round mode",
|
||||
|
||||
@@ -294,14 +294,14 @@ void Dump(fextl::stringstream* out, const IRListView* IR, IR::RegisterAllocation
|
||||
AddIndent();
|
||||
if (GetHasDest(IROp->Op)) {
|
||||
|
||||
uint32_t ElementSize = IROp->ElementSize;
|
||||
uint32_t NumElements = IROp->Size;
|
||||
auto ElementSize = IROp->ElementSize;
|
||||
uint8_t NumElements = 0;
|
||||
if (!IROp->ElementSize) {
|
||||
ElementSize = IROp->Size;
|
||||
}
|
||||
|
||||
if (ElementSize) {
|
||||
NumElements /= ElementSize;
|
||||
NumElements = IR::NumElements(IROp->Size, ElementSize);
|
||||
}
|
||||
|
||||
*out << "%" << std::dec << ID;
|
||||
@@ -333,13 +333,13 @@ void Dump(fextl::stringstream* out, const IRListView* IR, IR::RegisterAllocation
|
||||
*out << " = ";
|
||||
} else {
|
||||
|
||||
uint32_t ElementSize = IROp->ElementSize;
|
||||
auto ElementSize = IROp->ElementSize;
|
||||
if (!IROp->ElementSize) {
|
||||
ElementSize = IROp->Size;
|
||||
}
|
||||
uint32_t NumElements = 0;
|
||||
if (ElementSize) {
|
||||
NumElements = IROp->Size / ElementSize;
|
||||
NumElements = IR::NumElements(IROp->Size, ElementSize);
|
||||
}
|
||||
|
||||
*out << "(%" << std::dec << ID << ' ';
|
||||
|
||||
@@ -59,12 +59,12 @@ public:
|
||||
#define IROP_ALLOCATE_HELPERS
|
||||
#define IROP_DISPATCH_HELPERS
|
||||
#include <FEXCore/IR/IRDefines.inc>
|
||||
IRPair<IROp_Constant> _Constant(uint8_t Size, uint64_t Constant) {
|
||||
IRPair<IROp_Constant> _Constant(IR::OpSize Size, uint64_t Constant) {
|
||||
auto Op = AllocateOp<IROp_Constant, IROps::OP_CONSTANT>();
|
||||
uint64_t Mask = ~0ULL >> (64 - Size);
|
||||
uint64_t Mask = ~0ULL >> (64 - IR::OpSizeAsBits(Size));
|
||||
Op.first->Constant = (Constant & Mask);
|
||||
Op.first->Header.Size = Size / 8;
|
||||
Op.first->Header.ElementSize = Size / 8;
|
||||
Op.first->Header.Size = Size;
|
||||
Op.first->Header.ElementSize = Size;
|
||||
return Op;
|
||||
}
|
||||
IRPair<IROp_Jump> _Jump() {
|
||||
|
||||
Reference in new issue
Block a user