1385 lines
62 KiB
TableGen
1385 lines
62 KiB
TableGen
|
//===-- X86InstrUtils.td - X86 Instruction Utilities --------*- tablegen -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// This file provides utilities for simplifying the instruction definitions.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
// Classes for setting the fields of X86Inst
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
// Prefix byte classes which are used to indicate to the ad-hoc machine code
|
||
|
// emitter that various prefix bytes are required.
|
||
|
class OpSize16 { OperandSize OpSize = OpSize16; }
|
||
|
class OpSize32 { OperandSize OpSize = OpSize32; }
|
||
|
class AdSize16 { AddressSize AdSize = AdSize16; }
|
||
|
class AdSize32 { AddressSize AdSize = AdSize32; }
|
||
|
class AdSize64 { AddressSize AdSize = AdSize64; }
|
||
|
class REX_W { bit hasREX_W = 1; }
|
||
|
class LOCK { bit hasLockPrefix = 1; }
|
||
|
class REP { bit hasREPPrefix = 1; }
|
||
|
class TB { Map OpMap = TB; }
|
||
|
class T8 { Map OpMap = T8; }
|
||
|
class TA { Map OpMap = TA; }
|
||
|
class T_MAP4 { Map OpMap = T_MAP4; }
|
||
|
class T_MAP5 { Map OpMap = T_MAP5; }
|
||
|
class T_MAP6 { Map OpMap = T_MAP6; }
|
||
|
class T_MAP7 { Map OpMap = T_MAP7; }
|
||
|
class XOP8 { Map OpMap = XOP8; }
|
||
|
class XOP9 { Map OpMap = XOP9; }
|
||
|
class XOPA { Map OpMap = XOPA; }
|
||
|
class ThreeDNow { Map OpMap = ThreeDNow; }
|
||
|
class PS { Prefix OpPrefix = PS; }
|
||
|
class PD { Prefix OpPrefix = PD; }
|
||
|
class XD { Prefix OpPrefix = XD; }
|
||
|
class XS { Prefix OpPrefix = XS; }
|
||
|
class XOP { Encoding OpEnc = EncXOP; }
|
||
|
class VEX { Encoding OpEnc = EncVEX; }
|
||
|
class EVEX { Encoding OpEnc = EncEVEX; }
|
||
|
class WIG { bit IgnoresW = 1; }
|
||
|
class VEX_L { bit hasVEX_L = 1; }
|
||
|
class VEX_LIG { bit ignoresVEX_L = 1; }
|
||
|
class VVVV { bit hasVEX_4V = 1; }
|
||
|
class EVEX_K { bit hasEVEX_K = 1; }
|
||
|
class EVEX_KZ : EVEX_K { bit hasEVEX_Z = 1; }
|
||
|
class EVEX_B { bit hasEVEX_B = 1; }
|
||
|
class EVEX_NF { bit hasEVEX_NF = 1; }
|
||
|
class EVEX_RC { bit hasEVEX_RC = 1; }
|
||
|
class EVEX_V512 { bit hasEVEX_L2 = 1; bit hasVEX_L = 0; }
|
||
|
class EVEX_V256 { bit hasEVEX_L2 = 0; bit hasVEX_L = 1; }
|
||
|
class EVEX_V128 { bit hasEVEX_L2 = 0; bit hasVEX_L = 0; }
|
||
|
class NOTRACK { bit hasNoTrackPrefix = 1; }
|
||
|
class SIMD_EXC { list<Register> Uses = [MXCSR]; bit mayRaiseFPException = 1; }
|
||
|
// Specify AVX512 8-bit compressed displacement encoding based on the vector
|
||
|
// element size in bits (8, 16, 32, 64) and the CDisp8 form.
|
||
|
class EVEX_CD8<int esize, CD8VForm form> {
|
||
|
int CD8_EltSize = !srl(esize, 3);
|
||
|
bits<3> CD8_Form = form.Value;
|
||
|
}
|
||
|
class NoCD8 { bits<7> CD8_Scale = 0; }
|
||
|
|
||
|
class AVX512BIi8Base : TB, PD {
|
||
|
Domain ExeDomain = SSEPackedInt;
|
||
|
ImmType ImmT = Imm8;
|
||
|
}
|
||
|
class AVX512XSIi8Base : TB, XS {
|
||
|
Domain ExeDomain = SSEPackedInt;
|
||
|
ImmType ImmT = Imm8;
|
||
|
}
|
||
|
class AVX512XDIi8Base : TB, XD {
|
||
|
Domain ExeDomain = SSEPackedInt;
|
||
|
ImmType ImmT = Imm8;
|
||
|
}
|
||
|
class AVX512PSIi8Base : TB {
|
||
|
Domain ExeDomain = SSEPackedSingle;
|
||
|
ImmType ImmT = Imm8;
|
||
|
}
|
||
|
class AVX512PDIi8Base : TB, PD {
|
||
|
Domain ExeDomain = SSEPackedDouble;
|
||
|
ImmType ImmT = Imm8;
|
||
|
}
|
||
|
class ExplicitREX2Prefix { ExplicitOpPrefix explicitOpPrefix = ExplicitREX2; }
|
||
|
class ExplicitVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitVEX; }
|
||
|
class ExplicitEVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitEVEX; }
|
||
|
class DefEFLAGS { list<Register> Defs = [EFLAGS]; }
|
||
|
class UseEFLAGS { list<Register> Uses = [EFLAGS]; }
|
||
|
class DisassembleOnly {
|
||
|
// The disassembler should know about this, but not the asmparser.
|
||
|
bit isCodeGenOnly = 1;
|
||
|
bit ForceDisassemble = 1;
|
||
|
}
|
||
|
|
||
|
defvar unaryop_args = "$src1";
|
||
|
defvar unaryop_ndd_args = "{$src1, $dst|$dst, $src1}";
|
||
|
defvar binop_args = "{$src2, $src1|$src1, $src2}";
|
||
|
defvar binop_ndd_args = "{$src2, $src1, $dst|$dst, $src1, $src2}";
|
||
|
defvar binop_cl_args = "{%cl, $src1|$src1, cl}";
|
||
|
defvar binop_cl_ndd_args = "{%cl, $src1, $dst|$dst, $src1, cl}";
|
||
|
defvar triop_args = "{$src3, $src2, $src1|$src1, $src2, $src3}";
|
||
|
defvar triop_ndd_args = "{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}";
|
||
|
defvar triop_cl_args = "{%cl, $src2, $src1|$src1, $src2, cl}";
|
||
|
defvar triop_cl_ndd_args = "{%cl, $src2, $src1, $dst|$dst, $src1, $src2, cl}";
|
||
|
defvar tie_dst_src1 = "$src1 = $dst";
|
||
|
|
||
|
// NDD - Helper for new data destination instructions
|
||
|
class NDD<bit ndd> {
|
||
|
string Constraints = !if(!eq(ndd, 0), tie_dst_src1, "");
|
||
|
Encoding OpEnc = !if(!eq(ndd, 0), EncNormal, EncEVEX);
|
||
|
bit hasEVEX_B = ndd;
|
||
|
bit hasVEX_4V = ndd;
|
||
|
Map OpMap = !if(!eq(ndd, 0), OB, T_MAP4);
|
||
|
}
|
||
|
// NF - Helper for NF (no flags update) instructions
|
||
|
class NF: T_MAP4, EVEX, EVEX_NF;
|
||
|
// PL - Helper for promoted legacy instructions
|
||
|
class PL: T_MAP4, EVEX, ExplicitEVEXPrefix;
|
||
|
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
// X86 Type infomation definitions
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
/// X86TypeInfo - This is a bunch of information that describes relevant X86
|
||
|
/// information about value types. For example, it can tell you what the
|
||
|
/// register class and preferred load to use.
|
||
|
class X86TypeInfo<ValueType vt, string instrsuffix, RegisterClass regclass,
|
||
|
PatFrag loadnode, X86MemOperand memoperand, ImmType immkind,
|
||
|
Operand immoperand, SDPatternOperator immoperator,
|
||
|
SDPatternOperator immnosuoperator, Operand imm8operand,
|
||
|
SDPatternOperator imm8operator, SDPatternOperator imm8nosuoperator,
|
||
|
bit hasEvenOpcode, bit hasREX_W> {
|
||
|
/// VT - This is the value type itself.
|
||
|
ValueType VT = vt;
|
||
|
|
||
|
/// InstrSuffix - This is the suffix used on instructions with this type. For
|
||
|
/// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q".
|
||
|
string InstrSuffix = instrsuffix;
|
||
|
|
||
|
/// RegClass - This is the register class associated with this type. For
|
||
|
/// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64.
|
||
|
RegisterClass RegClass = regclass;
|
||
|
|
||
|
/// LoadNode - This is the load node associated with this type. For
|
||
|
/// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64.
|
||
|
PatFrag LoadNode = loadnode;
|
||
|
|
||
|
/// MemOperand - This is the memory operand associated with this type. For
|
||
|
/// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem.
|
||
|
X86MemOperand MemOperand = memoperand;
|
||
|
|
||
|
/// ImmEncoding - This is the encoding of an immediate of this type. For
|
||
|
/// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32
|
||
|
/// since the immediate fields of i64 instructions is a 32-bit sign extended
|
||
|
/// value.
|
||
|
ImmType ImmEncoding = immkind;
|
||
|
|
||
|
/// ImmOperand - This is the operand kind of an immediate of this type. For
|
||
|
/// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 ->
|
||
|
/// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign
|
||
|
/// extended value.
|
||
|
Operand ImmOperand = immoperand;
|
||
|
|
||
|
/// ImmOperator - This is the operator that should be used to match an
|
||
|
/// immediate of this kind in a pattern (e.g. imm, or i64immSExt32).
|
||
|
SDPatternOperator ImmOperator = immoperator;
|
||
|
|
||
|
SDPatternOperator ImmNoSuOperator = immnosuoperator;
|
||
|
|
||
|
/// Imm8Operand - This is the operand kind to use for an imm8 of this type.
|
||
|
/// For example, i8 -> <invalid>, i16 -> i16i8imm, i32 -> i32i8imm. This is
|
||
|
/// only used for instructions that have a sign-extended imm8 field form.
|
||
|
Operand Imm8Operand = imm8operand;
|
||
|
|
||
|
/// Imm8Operator - This is the operator that should be used to match an 8-bit
|
||
|
/// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8).
|
||
|
SDPatternOperator Imm8Operator = imm8operator;
|
||
|
|
||
|
SDPatternOperator Imm8NoSuOperator = imm8nosuoperator;
|
||
|
|
||
|
/// HasEvenOpcode - This bit is true if the instruction should have an even (as
|
||
|
/// opposed to odd) opcode. Operations on i8 are even, operations on
|
||
|
/// other datatypes are usually odd.
|
||
|
bit HasEvenOpcode = hasEvenOpcode;
|
||
|
|
||
|
/// HasREX_W - This bit is set to true if the instruction should have
|
||
|
/// the 0x40 REX prefix. This is set for i64 types.
|
||
|
bit HasREX_W = hasREX_W;
|
||
|
}
|
||
|
|
||
|
def invalid_node : SDNode<"<<invalid_node>>", SDTIntLeaf,[],"<<invalid_node>>">;
|
||
|
|
||
|
def Xi8 : X86TypeInfo<i8, "b", GR8, loadi8, i8mem, Imm8, i8imm,
|
||
|
imm_su, imm, i8imm, invalid_node, invalid_node,
|
||
|
1, 0>;
|
||
|
def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem, Imm16, i16imm,
|
||
|
imm_su, imm, i16i8imm, i16immSExt8_su, i16immSExt8,
|
||
|
0, 0>;
|
||
|
def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem, Imm32, i32imm,
|
||
|
imm_su, imm, i32i8imm, i32immSExt8_su, i32immSExt8,
|
||
|
0, 0>;
|
||
|
def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem, Imm32S, i64i32imm,
|
||
|
i64immSExt32_su, i64immSExt32, i64i8imm, i64immSExt8_su,
|
||
|
i64immSExt8, 0, 1>;
|
||
|
|
||
|
// Group template arguments that can be derived from the vector type (EltNum x
|
||
|
// EltVT). These are things like the register class for the writemask, etc.
|
||
|
// The idea is to pass one of these as the template argument rather than the
|
||
|
// individual arguments.
|
||
|
// The template is also used for scalar types, in this case numelts is 1.
|
||
|
class X86VectorVTInfo<int numelts, ValueType eltvt, RegisterClass rc,
|
||
|
string suffix = ""> {
|
||
|
RegisterClass RC = rc;
|
||
|
ValueType EltVT = eltvt;
|
||
|
int NumElts = numelts;
|
||
|
|
||
|
// Corresponding mask register class.
|
||
|
RegisterClass KRC = !cast<RegisterClass>("VK" # NumElts);
|
||
|
|
||
|
// Corresponding mask register pair class.
|
||
|
RegisterOperand KRPC = !if (!gt(NumElts, 16), ?,
|
||
|
!cast<RegisterOperand>("VK" # NumElts # "Pair"));
|
||
|
|
||
|
// Corresponding write-mask register class.
|
||
|
RegisterClass KRCWM = !cast<RegisterClass>("VK" # NumElts # "WM");
|
||
|
|
||
|
// The mask VT.
|
||
|
ValueType KVT = !cast<ValueType>("v" # NumElts # "i1");
|
||
|
|
||
|
// Suffix used in the instruction mnemonic.
|
||
|
string Suffix = suffix;
|
||
|
|
||
|
// VTName is a string name for vector VT. For vector types it will be
|
||
|
// v # NumElts # EltVT, so for vector of 8 elements of i32 it will be v8i32
|
||
|
// It is a little bit complex for scalar types, where NumElts = 1.
|
||
|
// In this case we build v4f32 or v2f64
|
||
|
string VTName = "v" # !if (!eq (NumElts, 1),
|
||
|
!if (!eq (EltVT.Size, 16), 8,
|
||
|
!if (!eq (EltVT.Size, 32), 4,
|
||
|
!if (!eq (EltVT.Size, 64), 2, NumElts))), NumElts) # EltVT;
|
||
|
|
||
|
// The vector VT.
|
||
|
ValueType VT = !cast<ValueType>(VTName);
|
||
|
|
||
|
string EltTypeName = !cast<string>(EltVT);
|
||
|
// Size of the element type in bits, e.g. 32 for v16i32.
|
||
|
string EltSizeName = !subst("i", "", !subst("f", "", !subst("b", "", EltTypeName)));
|
||
|
int EltSize = EltVT.Size;
|
||
|
|
||
|
// "i" for integer types and "f" for floating-point types
|
||
|
string TypeVariantName = !subst("b", "", !subst(EltSizeName, "", EltTypeName));
|
||
|
|
||
|
// Size of RC in bits, e.g. 512 for VR512.
|
||
|
int Size = VT.Size;
|
||
|
|
||
|
// The corresponding memory operand, e.g. i512mem for VR512.
|
||
|
X86MemOperand MemOp = !cast<X86MemOperand>(TypeVariantName # Size # "mem");
|
||
|
X86MemOperand ScalarMemOp = !cast<X86MemOperand>(!subst("b", "", EltTypeName) # "mem");
|
||
|
// FP scalar memory operand for intrinsics - ssmem/sdmem.
|
||
|
Operand IntScalarMemOp = !if (!eq (EltTypeName, "f16"), !cast<Operand>("shmem"),
|
||
|
!if (!eq (EltTypeName, "bf16"), !cast<Operand>("shmem"),
|
||
|
!if (!eq (EltTypeName, "f32"), !cast<Operand>("ssmem"),
|
||
|
!if (!eq (EltTypeName, "f64"), !cast<Operand>("sdmem"), ?))));
|
||
|
|
||
|
// Load patterns
|
||
|
PatFrag LdFrag = !cast<PatFrag>("load" # VTName);
|
||
|
|
||
|
PatFrag AlignedLdFrag = !cast<PatFrag>("alignedload" # VTName);
|
||
|
|
||
|
PatFrag ScalarLdFrag = !cast<PatFrag>("load" # !subst("b", "", EltTypeName));
|
||
|
PatFrag BroadcastLdFrag = !cast<PatFrag>("X86VBroadcastld" # EltSizeName);
|
||
|
|
||
|
PatFrags ScalarIntMemFrags = !if (!eq (EltTypeName, "f16"), !cast<PatFrags>("sse_load_f16"),
|
||
|
!if (!eq (EltTypeName, "bf16"), !cast<PatFrags>("sse_load_f16"),
|
||
|
!if (!eq (EltTypeName, "f32"), !cast<PatFrags>("sse_load_f32"),
|
||
|
!if (!eq (EltTypeName, "f64"), !cast<PatFrags>("sse_load_f64"), ?))));
|
||
|
|
||
|
// The string to specify embedded broadcast in assembly.
|
||
|
string BroadcastStr = "{1to" # NumElts # "}";
|
||
|
|
||
|
// 8-bit compressed displacement tuple/subvector format. This is only
|
||
|
// defined for NumElts <= 8.
|
||
|
CD8VForm CD8TupleForm = !if (!eq (!srl(NumElts, 4), 0),
|
||
|
!cast<CD8VForm>("CD8VT" # NumElts), ?);
|
||
|
|
||
|
SubRegIndex SubRegIdx = !if (!eq (Size, 128), sub_xmm,
|
||
|
!if (!eq (Size, 256), sub_ymm, ?));
|
||
|
|
||
|
Domain ExeDomain = !if (!eq (EltTypeName, "f32"), SSEPackedSingle,
|
||
|
!if (!eq (EltTypeName, "f64"), SSEPackedDouble,
|
||
|
!if (!eq (EltTypeName, "f16"), SSEPackedSingle, // FIXME?
|
||
|
!if (!eq (EltTypeName, "bf16"), SSEPackedSingle, // FIXME?
|
||
|
SSEPackedInt))));
|
||
|
|
||
|
RegisterClass FRC = !if (!eq (EltTypeName, "f32"), FR32X,
|
||
|
!if (!eq (EltTypeName, "f16"), FR16X,
|
||
|
!if (!eq (EltTypeName, "bf16"), FR16X,
|
||
|
FR64X)));
|
||
|
|
||
|
dag ImmAllZerosV = (VT immAllZerosV);
|
||
|
|
||
|
string ZSuffix = !if (!eq (Size, 128), "Z128",
|
||
|
!if (!eq (Size, 256), "Z256", "Z"));
|
||
|
}
|
||
|
|
||
|
def v64i8_info : X86VectorVTInfo<64, i8, VR512, "b">;
|
||
|
def v32i16_info : X86VectorVTInfo<32, i16, VR512, "w">;
|
||
|
def v16i32_info : X86VectorVTInfo<16, i32, VR512, "d">;
|
||
|
def v8i64_info : X86VectorVTInfo<8, i64, VR512, "q">;
|
||
|
def v32f16_info : X86VectorVTInfo<32, f16, VR512, "ph">;
|
||
|
def v32bf16_info: X86VectorVTInfo<32, bf16, VR512, "pbf">;
|
||
|
def v16f32_info : X86VectorVTInfo<16, f32, VR512, "ps">;
|
||
|
def v8f64_info : X86VectorVTInfo<8, f64, VR512, "pd">;
|
||
|
|
||
|
// "x" in v32i8x_info means RC = VR256X
|
||
|
def v32i8x_info : X86VectorVTInfo<32, i8, VR256X, "b">;
|
||
|
def v16i16x_info : X86VectorVTInfo<16, i16, VR256X, "w">;
|
||
|
def v8i32x_info : X86VectorVTInfo<8, i32, VR256X, "d">;
|
||
|
def v4i64x_info : X86VectorVTInfo<4, i64, VR256X, "q">;
|
||
|
def v16f16x_info : X86VectorVTInfo<16, f16, VR256X, "ph">;
|
||
|
def v16bf16x_info: X86VectorVTInfo<16, bf16, VR256X, "pbf">;
|
||
|
def v8f32x_info : X86VectorVTInfo<8, f32, VR256X, "ps">;
|
||
|
def v4f64x_info : X86VectorVTInfo<4, f64, VR256X, "pd">;
|
||
|
|
||
|
def v16i8x_info : X86VectorVTInfo<16, i8, VR128X, "b">;
|
||
|
def v8i16x_info : X86VectorVTInfo<8, i16, VR128X, "w">;
|
||
|
def v4i32x_info : X86VectorVTInfo<4, i32, VR128X, "d">;
|
||
|
def v2i64x_info : X86VectorVTInfo<2, i64, VR128X, "q">;
|
||
|
def v8f16x_info : X86VectorVTInfo<8, f16, VR128X, "ph">;
|
||
|
def v8bf16x_info : X86VectorVTInfo<8, bf16, VR128X, "pbf">;
|
||
|
def v4f32x_info : X86VectorVTInfo<4, f32, VR128X, "ps">;
|
||
|
def v2f64x_info : X86VectorVTInfo<2, f64, VR128X, "pd">;
|
||
|
|
||
|
// We map scalar types to the smallest (128-bit) vector type
|
||
|
// with the appropriate element type. This allows to use the same masking logic.
|
||
|
def i32x_info : X86VectorVTInfo<1, i32, GR32, "si">;
|
||
|
def i64x_info : X86VectorVTInfo<1, i64, GR64, "sq">;
|
||
|
def f16x_info : X86VectorVTInfo<1, f16, VR128X, "sh">;
|
||
|
def bf16x_info : X86VectorVTInfo<1, bf16, VR128X, "sbf">;
|
||
|
def f32x_info : X86VectorVTInfo<1, f32, VR128X, "ss">;
|
||
|
def f64x_info : X86VectorVTInfo<1, f64, VR128X, "sd">;
|
||
|
|
||
|
class AVX512VLVectorVTInfo<X86VectorVTInfo i512, X86VectorVTInfo i256,
|
||
|
X86VectorVTInfo i128> {
|
||
|
X86VectorVTInfo info512 = i512;
|
||
|
X86VectorVTInfo info256 = i256;
|
||
|
X86VectorVTInfo info128 = i128;
|
||
|
}
|
||
|
|
||
|
def avx512vl_i8_info : AVX512VLVectorVTInfo<v64i8_info, v32i8x_info,
|
||
|
v16i8x_info>;
|
||
|
def avx512vl_i16_info : AVX512VLVectorVTInfo<v32i16_info, v16i16x_info,
|
||
|
v8i16x_info>;
|
||
|
def avx512vl_i32_info : AVX512VLVectorVTInfo<v16i32_info, v8i32x_info,
|
||
|
v4i32x_info>;
|
||
|
def avx512vl_i64_info : AVX512VLVectorVTInfo<v8i64_info, v4i64x_info,
|
||
|
v2i64x_info>;
|
||
|
def avx512vl_f16_info : AVX512VLVectorVTInfo<v32f16_info, v16f16x_info,
|
||
|
v8f16x_info>;
|
||
|
def avx512vl_bf16_info : AVX512VLVectorVTInfo<v32bf16_info, v16bf16x_info,
|
||
|
v8bf16x_info>;
|
||
|
def avx512vl_f32_info : AVX512VLVectorVTInfo<v16f32_info, v8f32x_info,
|
||
|
v4f32x_info>;
|
||
|
def avx512vl_f64_info : AVX512VLVectorVTInfo<v8f64_info, v4f64x_info,
|
||
|
v2f64x_info>;
|
||
|
|
||
|
class X86KVectorVTInfo<RegisterClass _krc, RegisterClass _krcwm,
|
||
|
ValueType _vt> {
|
||
|
RegisterClass KRC = _krc;
|
||
|
RegisterClass KRCWM = _krcwm;
|
||
|
ValueType KVT = _vt;
|
||
|
}
|
||
|
|
||
|
def v1i1_info : X86KVectorVTInfo<VK1, VK1WM, v1i1>;
|
||
|
def v2i1_info : X86KVectorVTInfo<VK2, VK2WM, v2i1>;
|
||
|
def v4i1_info : X86KVectorVTInfo<VK4, VK4WM, v4i1>;
|
||
|
def v8i1_info : X86KVectorVTInfo<VK8, VK8WM, v8i1>;
|
||
|
def v16i1_info : X86KVectorVTInfo<VK16, VK16WM, v16i1>;
|
||
|
def v32i1_info : X86KVectorVTInfo<VK32, VK32WM, v32i1>;
|
||
|
def v64i1_info : X86KVectorVTInfo<VK64, VK64WM, v64i1>;
|
||
|
|
||
|
// Subclasses of X86Inst
|
||
|
class PseudoI<dag oops, dag iops, list<dag> pattern>
|
||
|
: X86Inst<0, Pseudo, NoImm, oops, iops, ""> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
class I<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d = GenericDomain>
|
||
|
: X86Inst<o, f, NoImm, outs, ins, asm, d> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
class Ii8<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d = GenericDomain>
|
||
|
: X86Inst<o, f, Imm8, outs, ins, asm, d> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
class Ii8Reg<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d = GenericDomain>
|
||
|
: X86Inst<o, f, Imm8Reg, outs, ins, asm, d> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
class Ii8PCRel<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm8PCRel, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
class Ii16<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm16, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
class Ii32<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm32, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
class Ii32S<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm32S, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
class Ii64<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm64, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
class Ii16PCRel<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm16PCRel, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
class Ii32PCRel<bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm32PCRel, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
// FPStack Instruction Templates:
|
||
|
// FPI - Floating Point Instruction template.
|
||
|
class FPI<bits<8> o, Format F, dag outs, dag ins, string asm>
|
||
|
: I<o, F, outs, ins, asm, []> {
|
||
|
let Defs = [FPSW];
|
||
|
let Predicates = [HasX87];
|
||
|
}
|
||
|
|
||
|
// FpI_ - Floating Point Pseudo Instruction template.
|
||
|
class FpI_<dag outs, dag ins, FPFormat fp, list<dag> pattern>
|
||
|
: PseudoI<outs, ins, pattern> {
|
||
|
let FPForm = fp;
|
||
|
let Defs = [FPSW];
|
||
|
let Predicates = [HasX87];
|
||
|
}
|
||
|
|
||
|
// Templates for instructions that use a 16- or 32-bit segmented address as
|
||
|
// their only operand: lcall (FAR CALL) and ljmp (FAR JMP)
|
||
|
//
|
||
|
// Iseg16 - 16-bit segment selector, 16-bit offset
|
||
|
// Iseg32 - 16-bit segment selector, 32-bit offset
|
||
|
|
||
|
class Iseg16 <bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm16, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
class Iseg32 <bits<8> o, Format f, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: X86Inst<o, f, Imm32, outs, ins, asm> {
|
||
|
let Pattern = pattern;
|
||
|
}
|
||
|
|
||
|
// SI - SSE 1 & 2 scalar instructions
|
||
|
class SI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d = GenericDomain>
|
||
|
: I<o, F, outs, ins, asm, pattern, d> {
|
||
|
let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512],
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX],
|
||
|
!if(!eq(OpPrefix.Value, XS.Value), [UseSSE1],
|
||
|
!if(!eq(OpPrefix.Value, XD.Value), [UseSSE2],
|
||
|
!if(!eq(OpPrefix.Value, PD.Value), [UseSSE2],
|
||
|
[UseSSE1])))));
|
||
|
|
||
|
// AVX instructions have a 'v' prefix in the mnemonic
|
||
|
let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm),
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm),
|
||
|
asm));
|
||
|
}
|
||
|
|
||
|
// SI - SSE 1 & 2 scalar intrinsics - vex form available on AVX512
|
||
|
class SI_Int<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d = GenericDomain>
|
||
|
: I<o, F, outs, ins, asm, pattern, d> {
|
||
|
let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512],
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX],
|
||
|
!if(!eq(OpPrefix.Value, XS.Value), [UseSSE1],
|
||
|
!if(!eq(OpPrefix.Value, XD.Value), [UseSSE2],
|
||
|
!if(!eq(OpPrefix.Value, PD.Value), [UseSSE2],
|
||
|
[UseSSE1])))));
|
||
|
|
||
|
// AVX instructions have a 'v' prefix in the mnemonic
|
||
|
let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm),
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm),
|
||
|
asm));
|
||
|
}
|
||
|
// SIi8 - SSE 1 & 2 scalar instructions - vex form available on AVX512
|
||
|
class SIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern> {
|
||
|
let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512],
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX],
|
||
|
!if(!eq(OpPrefix.Value, XS.Value), [UseSSE1],
|
||
|
[UseSSE2])));
|
||
|
|
||
|
// AVX instructions have a 'v' prefix in the mnemonic
|
||
|
let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm),
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm),
|
||
|
asm));
|
||
|
}
|
||
|
|
||
|
// PI - SSE 1 & 2 packed instructions
|
||
|
class PI<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag> pattern,
|
||
|
Domain d>
|
||
|
: I<o, F, outs, ins, asm, pattern, d> {
|
||
|
let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512],
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX],
|
||
|
!if(!eq(OpPrefix.Value, PD.Value), [UseSSE2],
|
||
|
[UseSSE1])));
|
||
|
|
||
|
// AVX instructions have a 'v' prefix in the mnemonic
|
||
|
let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm),
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm),
|
||
|
asm));
|
||
|
}
|
||
|
|
||
|
// MMXPI - SSE 1 & 2 packed instructions with MMX operands
|
||
|
class MMXPI<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag> pattern,
|
||
|
Domain d>
|
||
|
: I<o, F, outs, ins, asm, pattern, d> {
|
||
|
let Predicates = !if(!eq(OpPrefix.Value, PD.Value), [HasMMX, HasSSE2],
|
||
|
[HasMMX, HasSSE1]);
|
||
|
}
|
||
|
|
||
|
// PIi8 - SSE 1 & 2 packed instructions with immediate
|
||
|
class PIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, d> {
|
||
|
let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512],
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX],
|
||
|
!if(!eq(OpPrefix.Value, PD.Value), [UseSSE2],
|
||
|
[UseSSE1])));
|
||
|
|
||
|
// AVX instructions have a 'v' prefix in the mnemonic
|
||
|
let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm),
|
||
|
!if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm),
|
||
|
asm));
|
||
|
}
|
||
|
|
||
|
// SSE1 Instruction Templates:
|
||
|
//
|
||
|
// SSI - SSE1 instructions with XS prefix.
|
||
|
// PSI - SSE1 instructions with PS prefix.
|
||
|
// PSIi8 - SSE1 instructions with ImmT == Imm8 and PS prefix.
|
||
|
// VSSI - SSE1 instructions with XS prefix in AVX form.
|
||
|
// VPSI - SSE1 instructions with PS prefix in AVX form, packed single.
|
||
|
|
||
|
class SSI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, XS, Requires<[UseSSE1]>;
|
||
|
class SSIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, TB, XS, Requires<[UseSSE1]>;
|
||
|
class PSI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedSingle>, TB,
|
||
|
Requires<[UseSSE1]>;
|
||
|
class PSIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedSingle>, TB,
|
||
|
Requires<[UseSSE1]>;
|
||
|
class VSSI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, !strconcat("v", asm), pattern>, TB, XS,
|
||
|
Requires<[HasAVX]>;
|
||
|
class VPSI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, !strconcat("v", asm), pattern, SSEPackedSingle>,
|
||
|
TB, Requires<[HasAVX]>;
|
||
|
|
||
|
// SSE2 Instruction Templates:
|
||
|
//
|
||
|
// SDI - SSE2 instructions with XD prefix.
|
||
|
// SDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix.
|
||
|
// S2SI - SSE2 instructions with XS prefix.
|
||
|
// SSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix.
|
||
|
// PDI - SSE2 instructions with PD prefix, packed double domain.
|
||
|
// PDIi8 - SSE2 instructions with ImmT == Imm8 and PD prefix.
|
||
|
// VSDI - SSE2 scalar instructions with XD prefix in AVX form.
|
||
|
// VPDI - SSE2 vector instructions with PD prefix in AVX form,
|
||
|
// packed double domain.
|
||
|
// VS2I - SSE2 scalar instructions with PD prefix in AVX form.
|
||
|
// S2I - SSE2 scalar instructions with PD prefix.
|
||
|
// MMXSDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix as well as
|
||
|
// MMX operands.
|
||
|
// MMXSSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix as well as
|
||
|
// MMX operands.
|
||
|
|
||
|
class SDI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, XD, Requires<[UseSSE2]>;
|
||
|
class SDIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, TB, XD, Requires<[UseSSE2]>;
|
||
|
class S2SI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, XS, Requires<[UseSSE2]>;
|
||
|
class S2SIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, TB, XS, Requires<[UseSSE2]>;
|
||
|
class PDI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedDouble>, TB, PD,
|
||
|
Requires<[UseSSE2]>;
|
||
|
class PDIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedDouble>, TB, PD,
|
||
|
Requires<[UseSSE2]>;
|
||
|
class VSDI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, !strconcat("v", asm), pattern>, TB, XD,
|
||
|
Requires<[UseAVX]>;
|
||
|
class VS2SI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, !strconcat("v", asm), pattern>, TB, XS,
|
||
|
Requires<[HasAVX]>;
|
||
|
class VPDI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, !strconcat("v", asm), pattern, SSEPackedDouble>,
|
||
|
TB, PD, Requires<[HasAVX]>;
|
||
|
class VS2I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, !strconcat("v", asm), pattern>, TB, PD,
|
||
|
Requires<[UseAVX]>;
|
||
|
class S2I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, PD, Requires<[UseSSE2]>;
|
||
|
class MMXSDIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, TB, XD, Requires<[HasMMX, HasSSE2]>;
|
||
|
class MMXS2SIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, TB, XS, Requires<[HasMMX, HasSSE2]>;
|
||
|
|
||
|
// SSE3 Instruction Templates:
|
||
|
//
|
||
|
// S3I - SSE3 instructions with PD prefixes.
|
||
|
// S3SI - SSE3 instructions with XS prefix.
|
||
|
// S3DI - SSE3 instructions with XD prefix.
|
||
|
|
||
|
class S3SI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedSingle>, TB, XS,
|
||
|
Requires<[UseSSE3]>;
|
||
|
class S3DI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedDouble>, TB, XD,
|
||
|
Requires<[UseSSE3]>;
|
||
|
class S3I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedDouble>, TB, PD,
|
||
|
Requires<[UseSSE3]>;
|
||
|
|
||
|
|
||
|
// SSSE3 Instruction Templates:
|
||
|
//
|
||
|
// SS38I - SSSE3 instructions with T8 prefix.
|
||
|
// SS3AI - SSSE3 instructions with TA prefix.
|
||
|
// MMXSS38I - SSSE3 instructions with T8 prefix and MMX operands.
|
||
|
// MMXSS3AI - SSSE3 instructions with TA prefix and MMX operands.
|
||
|
//
|
||
|
// Note: SSSE3 instructions have 64-bit and 128-bit versions. The 64-bit version
|
||
|
// uses the MMX registers. The 64-bit versions are grouped with the MMX
|
||
|
// classes. They need to be enabled even if AVX is enabled.
|
||
|
|
||
|
class SS38I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[UseSSSE3]>;
|
||
|
class SS3AI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[UseSSSE3]>;
|
||
|
class MMXSS38I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8,
|
||
|
Requires<[HasMMX, HasSSSE3]>;
|
||
|
class MMXSS3AI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA,
|
||
|
Requires<[HasMMX, HasSSSE3]>;
|
||
|
|
||
|
// SSE4.1 Instruction Templates:
|
||
|
//
|
||
|
// SS48I - SSE 4.1 instructions with T8 prefix.
|
||
|
// SS41AIi8 - SSE 4.1 instructions with TA prefix and ImmT == Imm8.
|
||
|
//
|
||
|
class SS48I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[UseSSE41]>;
|
||
|
class SS4AIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[UseSSE41]>;
|
||
|
|
||
|
// SSE4.2 Instruction Templates:
|
||
|
//
|
||
|
// SS428I - SSE 4.2 instructions with T8 prefix.
|
||
|
class SS428I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[UseSSE42]>;
|
||
|
|
||
|
// SS42AI = SSE 4.2 instructions with TA prefix
|
||
|
class SS42AI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[UseSSE42]>;
|
||
|
|
||
|
// AVX Instruction Templates:
|
||
|
// Instructions introduced in AVX (no SSE equivalent forms)
|
||
|
//
|
||
|
// AVX8I - AVX instructions with T8, PD prefix.
|
||
|
// AVXAIi8 - AVX instructions with TA, PD prefix and ImmT = Imm8.
|
||
|
class AVX8I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[HasAVX]>;
|
||
|
class AVXAIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[HasAVX]>;
|
||
|
|
||
|
// AVX2 Instruction Templates:
|
||
|
// Instructions introduced in AVX2 (no SSE equivalent forms)
|
||
|
//
|
||
|
// AVX28I - AVX2 instructions with T8, PD prefix.
|
||
|
// AVX2AIi8 - AVX2 instructions with TA, PD prefix and ImmT = Imm8.
|
||
|
class AVX28I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[HasAVX2]>;
|
||
|
class AVX2AIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[HasAVX2]>;
|
||
|
|
||
|
|
||
|
// AVX-512 Instruction Templates:
|
||
|
// Instructions introduced in AVX-512 (no SSE equivalent forms)
|
||
|
//
|
||
|
// AVX5128I - AVX-512 instructions with T8, PD prefix.
|
||
|
// AVX512AIi8 - AVX-512 instructions with TA, PD prefix and ImmT = Imm8.
|
||
|
// AVX512PDI - AVX-512 instructions with PD, double packed.
|
||
|
// AVX512PSI - AVX-512 instructions with PS, single packed.
|
||
|
// AVX512XS8I - AVX-512 instructions with T8 and XS prefixes.
|
||
|
// AVX512XSI - AVX-512 instructions with XS prefix, generic domain.
|
||
|
// AVX512BI - AVX-512 instructions with PD, int packed domain.
|
||
|
// AVX512SI - AVX-512 scalar instructions with PD prefix.
|
||
|
|
||
|
class AVX5128I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX5128IBase : T8, PD {
|
||
|
Domain ExeDomain = SSEPackedInt;
|
||
|
}
|
||
|
class AVX512XS8I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, XS,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512XSI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, XS,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512XDI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, TB, XD,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512BI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, TB, PD,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512BIBase : TB, PD {
|
||
|
Domain ExeDomain = SSEPackedInt;
|
||
|
}
|
||
|
class AVX512BIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TB, PD,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512AIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512AIi8Base : TA, PD {
|
||
|
ImmType ImmT = Imm8;
|
||
|
}
|
||
|
class AVX512Ii8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512PDI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedDouble>, TB, PD,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512PSI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedSingle>, TB,
|
||
|
Requires<[HasAVX512]>;
|
||
|
class AVX512PIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, d>, Requires<[HasAVX512]>;
|
||
|
class AVX512PI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern, Domain d>
|
||
|
: I<o, F, outs, ins, asm, pattern, d>, Requires<[HasAVX512]>;
|
||
|
class AVX512FMA3S<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, T8, PD,
|
||
|
EVEX, VVVV, Requires<[HasAVX512]>;
|
||
|
|
||
|
class AVX512<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, Requires<[HasAVX512]>;
|
||
|
|
||
|
// AES Instruction Templates:
|
||
|
//
|
||
|
// AES8I
|
||
|
// These use the same encoding as the SSE4.2 T8 and TA encodings.
|
||
|
class AES8I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, PD,
|
||
|
Requires<[NoAVX, HasAES]>;
|
||
|
|
||
|
class AESAI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
Requires<[NoAVX, HasAES]>;
|
||
|
|
||
|
// PCLMUL Instruction Templates
|
||
|
class PCLMULIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD;
|
||
|
|
||
|
// FMA3 Instruction Templates
|
||
|
class FMA3<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, T8, PD,
|
||
|
VEX, VVVV, FMASC, Requires<[HasFMA, NoFMA4, NoVLX]>;
|
||
|
class FMA3S<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, T8, PD,
|
||
|
VEX, VVVV, FMASC, Requires<[HasFMA, NoFMA4, NoAVX512]>;
|
||
|
class FMA3S_Int<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, T8, PD,
|
||
|
VEX, VVVV, FMASC, Requires<[HasFMA, NoAVX512]>;
|
||
|
|
||
|
// FMA4 Instruction Templates
|
||
|
class FMA4<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: Ii8Reg<o, F, outs, ins, asm, pattern>, TA, PD,
|
||
|
VEX, VVVV, FMASC, Requires<[HasFMA4, NoVLX]>;
|
||
|
class FMA4S<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: Ii8Reg<o, F, outs, ins, asm, pattern>, TA, PD,
|
||
|
VEX, VVVV, FMASC, Requires<[HasFMA4, NoAVX512]>;
|
||
|
class FMA4S_Int<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: Ii8Reg<o, F, outs, ins, asm, pattern>, TA, PD,
|
||
|
VEX, VVVV, FMASC, Requires<[HasFMA4]>;
|
||
|
|
||
|
// XOP 2, 3 and 4 Operand Instruction Template
|
||
|
class IXOP<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern, SSEPackedDouble>,
|
||
|
XOP9, Requires<[HasXOP]>;
|
||
|
|
||
|
// XOP 2 and 3 Operand Instruction Templates with imm byte
|
||
|
class IXOPi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern, SSEPackedDouble>,
|
||
|
XOP8, Requires<[HasXOP]>;
|
||
|
// XOP 4 Operand Instruction Templates with imm byte
|
||
|
class IXOPi8Reg<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8Reg<o, F, outs, ins, asm, pattern, SSEPackedDouble>,
|
||
|
XOP8, Requires<[HasXOP]>;
|
||
|
|
||
|
// XOP 5 operand instruction (VEX encoding!)
|
||
|
class IXOP5<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag>pattern>
|
||
|
: Ii8Reg<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, PD,
|
||
|
VEX, VVVV, Requires<[HasXOP]>;
|
||
|
|
||
|
// X86-64 Instruction templates...
|
||
|
//
|
||
|
|
||
|
class RI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
class RIi8 <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
class RIi16 <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii16<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
class RIi32 <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii32<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
class RIi32S <bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii32S<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
class RIi64<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii64<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
|
||
|
class RS2I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: S2I<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
class VRS2I<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: VS2I<o, F, outs, ins, asm, pattern>, REX_W;
|
||
|
|
||
|
// MMX Instruction templates
|
||
|
//
|
||
|
// MMXI - MMX instructions with TB prefix.
|
||
|
// MMXRI - MMX instructions with TB prefix and REX.W.
|
||
|
// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix.
|
||
|
class MMXI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, Requires<[HasMMX]>;
|
||
|
class MMXRI<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: I<o, F, outs, ins, asm, pattern>, TB, REX_W,
|
||
|
Requires<[HasMMX,In64BitMode]>;
|
||
|
class MMXIi8<bits<8> o, Format F, dag outs, dag ins, string asm,
|
||
|
list<dag> pattern>
|
||
|
: Ii8<o, F, outs, ins, asm, pattern>, TB, Requires<[HasMMX]>;
|
||
|
|
||
|
/// ITy - This instruction base class takes the type info for the instruction.
|
||
|
/// Using this, it:
|
||
|
/// 1. Concatenates together the instruction mnemonic with the appropriate
|
||
|
/// suffix letter, a tab, and the arguments.
|
||
|
/// 2. Infers whether the instruction should have a 0x40 REX_W prefix.
|
||
|
/// 3. Infers whether the low bit of the opcode should be 0 (for i8 operations)
|
||
|
/// or 1 (for i16,i32,i64 operations).
|
||
|
class ITy<bits<8> o, Format f, X86TypeInfo t, dag outs, dag ins, string m,
|
||
|
string args, list<dag> p>
|
||
|
: I<{o{7}, o{6}, o{5}, o{4}, o{3}, o{2}, o{1},
|
||
|
!if(!eq(t.HasEvenOpcode, 1), 0, o{0})}, f, outs, ins,
|
||
|
!strconcat(m, "{", t.InstrSuffix, "}\t", args), p>, NoCD8 {
|
||
|
let hasSideEffects = 0;
|
||
|
let hasREX_W = t.HasREX_W;
|
||
|
}
|
||
|
|
||
|
// BinOpRR - Instructions that read "reg, reg".
|
||
|
class BinOpRR<bits<8> o, string m, string args, X86TypeInfo t, dag out, list<dag> p>
|
||
|
: ITy<o, MRMDestReg, t, out, (ins t.RegClass:$src1, t.RegClass:$src2), m,
|
||
|
args, p>, Sched<[WriteALU]>;
|
||
|
// BinOpRR_F - Instructions that read "reg, reg" and write EFLAGS only.
|
||
|
class BinOpRR_F<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node>
|
||
|
: BinOpRR<o, m, binop_args, t, (outs),
|
||
|
[(set EFLAGS, (node t.RegClass:$src1, t.RegClass:$src2))]>,
|
||
|
DefEFLAGS;
|
||
|
// BinOpRR_F_Rev - Reversed encoding of BinOpRR_F
|
||
|
class BinOpRR_F_Rev<bits<8> o, string m, X86TypeInfo t>
|
||
|
: BinOpRR_F<o, m, t, null_frag>, DisassembleOnly {
|
||
|
let Form = MRMSrcReg;
|
||
|
}
|
||
|
// BinOpRR_R - Instructions that read "reg, reg" and write "reg".
|
||
|
class BinOpRR_R<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
|
||
|
: BinOpRR<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t,
|
||
|
(outs t.RegClass:$dst), []>, NDD<ndd>;
|
||
|
// BinOpRR_R_Rev - Reversed encoding of BinOpRR_R
|
||
|
class BinOpRR_R_Rev<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
|
||
|
: BinOpRR_R<o, m, t, ndd>, DisassembleOnly {
|
||
|
let Form = MRMSrcReg;
|
||
|
}
|
||
|
// BinOpRR_RF - Instructions that read "reg, reg", and write "reg", EFLAGS.
|
||
|
class BinOpRR_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node, bit ndd = 0>
|
||
|
: BinOpRR<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t,
|
||
|
(outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS,
|
||
|
(node t.RegClass:$src1, t.RegClass:$src2))]>, DefEFLAGS, NDD<ndd>;
|
||
|
// BinOpRR_RF_Rev - Reversed encoding of BinOpRR_RF.
|
||
|
class BinOpRR_RF_Rev<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
|
||
|
: BinOpRR_RF<o, m, t, null_frag, ndd>, DisassembleOnly {
|
||
|
let Form = MRMSrcReg;
|
||
|
}
|
||
|
// BinOpRRF_RF - Instructions that read "reg, reg", write "reg" and read/write
|
||
|
// EFLAGS.
|
||
|
class BinOpRRF_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
|
||
|
: BinOpRR<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS,
|
||
|
(node t.RegClass:$src1, t.RegClass:$src2,
|
||
|
EFLAGS))]>, DefEFLAGS, UseEFLAGS, NDD<ndd> {
|
||
|
let SchedRW = [WriteADC];
|
||
|
}
|
||
|
// BinOpRRF_RF_Rev - Reversed encoding of BinOpRRF_RF
|
||
|
class BinOpRRF_RF_Rev<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
|
||
|
: BinOpRRF_RF<o, m, t, null_frag, ndd>, DisassembleOnly {
|
||
|
let Form = MRMSrcReg;
|
||
|
}
|
||
|
|
||
|
// BinOpRM - Instructions that read "reg, [mem]".
|
||
|
class BinOpRM<bits<8> o, string m, string args, X86TypeInfo t, dag out, list<dag> p>
|
||
|
: ITy<o, MRMSrcMem, t, out, (ins t.RegClass:$src1, t.MemOperand:$src2), m,
|
||
|
args, p>,
|
||
|
Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]> {
|
||
|
let mayLoad = 1;
|
||
|
}
|
||
|
// BinOpRM_F - Instructions that read "reg, [mem]" and write EFLAGS only.
|
||
|
class BinOpRM_F<bits<8> o, string m, X86TypeInfo t, SDNode node>
|
||
|
: BinOpRM<o, m, binop_args, t, (outs),
|
||
|
[(set EFLAGS, (node t.RegClass:$src1,
|
||
|
(t.LoadNode addr:$src2)))]>, DefEFLAGS;
|
||
|
// BinOpRM_R - Instructions that read "reg, [mem]", and write "reg".
|
||
|
class BinOpRM_R<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
|
||
|
: BinOpRM<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, (outs t.RegClass:$dst),
|
||
|
[]>, NDD<ndd>;
|
||
|
// BinOpRM_RF - Instructions that read "reg, [mem]", and write "reg", EFLAGS.
|
||
|
class BinOpRM_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node, bit ndd = 0>
|
||
|
: BinOpRM<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS, (node t.RegClass:$src1,
|
||
|
(t.LoadNode addr:$src2)))]>, DefEFLAGS, NDD<ndd>;
|
||
|
// BinOpRMF_RF - Instructions that read "reg, [mem]", write "reg" and read/write
|
||
|
// EFLAGS.
|
||
|
class BinOpRMF_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
|
||
|
: BinOpRM<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS,
|
||
|
(node t.RegClass:$src1, (t.LoadNode addr:$src2), EFLAGS))]>,
|
||
|
DefEFLAGS, UseEFLAGS, NDD<ndd> {
|
||
|
let SchedRW = [WriteADC.Folded, WriteADC.ReadAfterFold,
|
||
|
// base, scale, index, offset, segment.
|
||
|
ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
|
||
|
// implicit register read.
|
||
|
WriteADC.ReadAfterFold];
|
||
|
}
|
||
|
|
||
|
// BinOpRI - Instructions that read "reg, imm".
|
||
|
class BinOpRI<bits<8> o, string m, string args, X86TypeInfo t, Format f, dag out, list<dag> p>
|
||
|
: ITy<o, f, t, out, (ins t.RegClass:$src1, t.ImmOperand:$src2), m,
|
||
|
args, p>, Sched<[WriteALU]> {
|
||
|
let ImmT = t.ImmEncoding;
|
||
|
}
|
||
|
// BinOpRI_F - Instructions that read "reg, imm" and write EFLAGS only.
|
||
|
class BinOpRI_F<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node,
|
||
|
Format f>
|
||
|
: BinOpRI<o, m, binop_args, t, f, (outs),
|
||
|
[(set EFLAGS, (node t.RegClass:$src1,
|
||
|
t.ImmOperator:$src2))]>, DefEFLAGS;
|
||
|
// BinOpRI_R - Instructions that read "reg, imm" and write "reg".
|
||
|
class BinOpRI_R<bits<8> o, string m, X86TypeInfo t, Format f, bit ndd = 0>
|
||
|
: BinOpRI<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, f, (outs t.RegClass:$dst),
|
||
|
[]>, NDD<ndd>;
|
||
|
// BinOpRI8U_R - Instructions that read "reg, u8imm" and write "reg".
|
||
|
class BinOpRI8U_R<string m, Format f, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
|
||
|
: ITy<0xC1, f, t, (outs t.RegClass:$dst), (ins t.RegClass:$src1, u8imm:$src2), m,
|
||
|
!if(!eq(ndd, 0), binop_args, binop_ndd_args),
|
||
|
[(set t.RegClass:$dst, (node t.RegClass:$src1, (i8 imm:$src2)))]>, NDD<ndd> {
|
||
|
let ImmT = Imm8;
|
||
|
}
|
||
|
// BinOpRI_RF - Instructions that read "reg, imm" and write "reg", EFLAGS.
|
||
|
class BinOpRI_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node, Format f, bit ndd = 0>
|
||
|
: BinOpRI<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, f, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS,
|
||
|
(node t.RegClass:$src1, t.ImmOperator:$src2))]>, DefEFLAGS, NDD<ndd>;
|
||
|
// BinOpRIF_RF - Instructions that read "reg, imm", write "reg" and read/write
|
||
|
// EFLAGS.
|
||
|
class BinOpRIF_RF<bits<8> o, string m, X86TypeInfo t, SDNode node, Format f, bit ndd = 0>
|
||
|
: BinOpRI<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, f, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS,
|
||
|
(node t.RegClass:$src1, t.ImmOperator:$src2,
|
||
|
EFLAGS))]>, DefEFLAGS, UseEFLAGS, NDD<ndd> {
|
||
|
let SchedRW = [WriteADC];
|
||
|
}
|
||
|
// BinOpRI8 - Instructions that read "reg, imm8".
|
||
|
class BinOpRI8<bits<8> o, string m, string args, X86TypeInfo t, Format f, dag out>
|
||
|
: ITy<o, f, t, out, (ins t.RegClass:$src1, t.Imm8Operand:$src2), m,
|
||
|
args, []>, Sched<[WriteALU]> {
|
||
|
let ImmT = Imm8;
|
||
|
}
|
||
|
// BinOpRI8_F - Instructions that read "reg, imm8" and write EFLAGS only.
|
||
|
class BinOpRI8_F<bits<8> o, string m, X86TypeInfo t, Format f>
|
||
|
: BinOpRI8<o, m, binop_args, t, f, (outs)>, DefEFLAGS;
|
||
|
// BinOpRI8_R - Instructions that read "reg, imm8" and write "reg".
|
||
|
class BinOpRI8_R<bits<8> o, string m, X86TypeInfo t, Format f, bit ndd = 0>
|
||
|
: BinOpRI8<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, f, (outs t.RegClass:$dst)>, NDD<ndd>;
|
||
|
// BinOpRI8_RF - Instructions that read "reg, imm8" and write "reg", EFLAGS.
|
||
|
class BinOpRI8_RF<bits<8> o, string m, X86TypeInfo t, Format f, bit ndd = 0>
|
||
|
: BinOpRI8<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, f, (outs t.RegClass:$dst)>, DefEFLAGS, NDD<ndd>;
|
||
|
// BinOpRI8F_RF - Instructions that read "reg, imm", write "reg" and read/write
|
||
|
// EFLAGS.
|
||
|
class BinOpRI8F_RF<bits<8> o, string m, X86TypeInfo t, Format f, bit ndd = 0>
|
||
|
: BinOpRI8<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t, f, (outs t.RegClass:$dst)>, DefEFLAGS, UseEFLAGS, NDD<ndd> {
|
||
|
let SchedRW = [WriteADC];
|
||
|
}
|
||
|
|
||
|
// BinOpMR - Instructions that read "[mem], reg".
|
||
|
class BinOpMR<bits<8> o, string m, string args, X86TypeInfo t, dag out, list<dag> p>
|
||
|
: ITy<o, MRMDestMem, t, out, (ins t.MemOperand:$src1, t.RegClass:$src2), m,
|
||
|
args, p> {
|
||
|
let mayLoad = 1;
|
||
|
let SchedRW = [WriteALU.Folded, WriteALU.ReadAfterFold];
|
||
|
}
|
||
|
// BinOpMR_R - Instructions that read "[mem], reg", and write "reg".
|
||
|
class BinOpMR_R<bits<8> o, string m, X86TypeInfo t>
|
||
|
: BinOpMR<o, m, binop_ndd_args, t, (outs t.RegClass:$dst), []>, NDD<1>;
|
||
|
// BinOpMR_RF - Instructions that read "[mem], reg", and write "reg", EFLAGS.
|
||
|
class BinOpMR_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node>
|
||
|
: BinOpMR<o, m, binop_ndd_args, t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS, (node (t.LoadNode addr:$src1),
|
||
|
t.RegClass:$src2))]>, DefEFLAGS, NDD<1>;
|
||
|
// BinOpMR_F - Instructions that read "[mem], imm8" and write EFLAGS only.
|
||
|
class BinOpMR_F<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node>
|
||
|
: BinOpMR<o, m, binop_args, t, (outs),
|
||
|
[(set EFLAGS, (node (t.LoadNode addr:$src1), t.RegClass:$src2))]>,
|
||
|
Sched<[WriteALU.Folded, ReadDefault, ReadDefault, ReadDefault,
|
||
|
ReadDefault, ReadDefault, WriteALU.ReadAfterFold]>, DefEFLAGS;
|
||
|
// BinOpMR_M - Instructions that read "[mem], reg" and write "[mem]".
|
||
|
class BinOpMR_M<bits<8> o, string m, X86TypeInfo t>
|
||
|
: BinOpMR<o, m, binop_args, t, (outs), []>,
|
||
|
Sched<[WriteALURMW,
|
||
|
// base, scale, index, offset, segment
|
||
|
ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault]> {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMR_MF - Instructions that read "[mem], reg" and write "[mem]", EFLAGS.
|
||
|
class BinOpMR_MF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node>
|
||
|
: BinOpMR<o, m, binop_args, t, (outs),
|
||
|
[(store (node (load addr:$src1), t.RegClass:$src2), addr:$src1),
|
||
|
(implicit EFLAGS)]>,
|
||
|
Sched<[WriteALURMW,
|
||
|
// base, scale, index, offset, segment
|
||
|
ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
|
||
|
WriteALU.ReadAfterFold]>, // reg
|
||
|
DefEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMRF_RF - Instructions that read "[mem], reg", write "reg" and
|
||
|
// read/write EFLAGS.
|
||
|
class BinOpMRF_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node>
|
||
|
: BinOpMR<o, m, binop_ndd_args, t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS, (node (load addr:$src1),
|
||
|
t.RegClass:$src2, EFLAGS))]>, DefEFLAGS, UseEFLAGS, NDD<1>,
|
||
|
Sched<[WriteADC.Folded, WriteADC.ReadAfterFold]>;
|
||
|
// BinOpMRF_MF - Instructions that read "[mem], reg", write "[mem]" and
|
||
|
// read/write EFLAGS.
|
||
|
class BinOpMRF_MF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node>
|
||
|
: BinOpMR<o, m, binop_args, t, (outs),
|
||
|
[(store (node (load addr:$src1), t.RegClass:$src2, EFLAGS),
|
||
|
addr:$src1), (implicit EFLAGS)]>,
|
||
|
Sched<[WriteADCRMW,
|
||
|
// base, scale, index, offset, segment
|
||
|
ReadDefault, ReadDefault, ReadDefault,
|
||
|
ReadDefault, ReadDefault,
|
||
|
WriteALU.ReadAfterFold, // reg
|
||
|
WriteALU.ReadAfterFold]>, // EFLAGS
|
||
|
DefEFLAGS, UseEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
|
||
|
// BinOpMI - Instructions that read "[mem], imm".
|
||
|
class BinOpMI<bits<8> o, string m, string args, X86TypeInfo t, Format f, dag out, list<dag> p>
|
||
|
: ITy<o, f, t, out, (ins t.MemOperand:$src1, t.ImmOperand:$src2), m,
|
||
|
args, p> {
|
||
|
let ImmT = t.ImmEncoding;
|
||
|
let mayLoad = 1;
|
||
|
}
|
||
|
// BinOpMI_F - Instructions that read "[mem], imm" and write EFLAGS only.
|
||
|
class BinOpMI_F<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node,
|
||
|
Format f>
|
||
|
: BinOpMI<o, m, binop_args, t, f, (outs),
|
||
|
[(set EFLAGS, (node (t.LoadNode addr:$src1), t.ImmOperator:$src2))]>,
|
||
|
Sched<[WriteALU.Folded]>, DefEFLAGS;
|
||
|
// BinOpMI_R - Instructions that read "[mem], imm" and write "reg".
|
||
|
class BinOpMI_R<bits<8> o, string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI<o, m, binop_ndd_args, t, f, (outs t.RegClass:$dst), []>,
|
||
|
Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, NDD<1>;
|
||
|
// BinOpMI_R - Instructions that read "[mem], imm" and write "reg", EFLAGS.
|
||
|
class BinOpMI_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node,
|
||
|
Format f>
|
||
|
: BinOpMI<o, m, binop_ndd_args, t, f, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS, (node (t.LoadNode addr:$src1), t.ImmOperator:$src2))]>,
|
||
|
Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, DefEFLAGS, NDD<1>;
|
||
|
// BinOpMI_M - Instructions that read "[mem], imm" and write "[mem]".
|
||
|
class BinOpMI_M<bits<8> o, string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI<o, m, binop_args, t, f, (outs), []>, Sched<[WriteALURMW]> {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMI_MF - Instructions that read "[mem], imm" and write "[mem]", EFLAGS.
|
||
|
class BinOpMI_MF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node, Format f>
|
||
|
: BinOpMI<o, m, binop_args, t, f, (outs),
|
||
|
[(store (node (t.VT (load addr:$src1)),
|
||
|
t.ImmOperator:$src2), addr:$src1), (implicit EFLAGS)]>,
|
||
|
Sched<[WriteALURMW]>, DefEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMIF_RF - Instructions that read "[mem], imm", write "reg" and
|
||
|
// read/write EFLAGS.
|
||
|
class BinOpMIF_RF<bits<8> o, string m, X86TypeInfo t, SDNode node, Format f>
|
||
|
: BinOpMI<o, m, binop_ndd_args, t, f, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS, (node (t.VT (load addr:$src1)),
|
||
|
t.ImmOperator:$src2, EFLAGS))]>,
|
||
|
Sched<[WriteADC.Folded, WriteADC.ReadAfterFold]>, DefEFLAGS, UseEFLAGS, NDD<1>;
|
||
|
// BinOpMIF_MF - Instructions that read "[mem], imm", write "[mem]" and
|
||
|
// read/write EFLAGS.
|
||
|
class BinOpMIF_MF<bits<8> o, string m, X86TypeInfo t, SDNode node, Format f>
|
||
|
: BinOpMI<o, m, binop_args, t, f, (outs),
|
||
|
[(store (node (t.VT (load addr:$src1)),
|
||
|
t.ImmOperator:$src2, EFLAGS), addr:$src1), (implicit EFLAGS)]>,
|
||
|
Sched<[WriteADCRMW]>, DefEFLAGS, UseEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
|
||
|
// BinOpMI8 - Instructions that read "[mem], imm8".
|
||
|
class BinOpMI8<string m, string args, X86TypeInfo t, Format f, dag out>
|
||
|
: ITy<0x83, f, t, out, (ins t.MemOperand:$src1, t.Imm8Operand:$src2), m,
|
||
|
args, []> {
|
||
|
let ImmT = Imm8;
|
||
|
let mayLoad = 1;
|
||
|
}
|
||
|
// BinOpMI8U - Instructions that read "[mem], u8imm".
|
||
|
class BinOpMI8U<string m, string args, X86TypeInfo t, Format f, dag out, list<dag> p>
|
||
|
: ITy<0xC1, f, t, out, (ins t.MemOperand:$src1, u8imm:$src2), m, args, p> {
|
||
|
let ImmT = Imm8;
|
||
|
let mayLoad = 1;
|
||
|
}
|
||
|
// BinOpMI8_F - Instructions that read "[mem], imm8" and write EFLAGS only.
|
||
|
class BinOpMI8_F<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_args, t, f, (outs)>, Sched<[WriteALU.Folded]>, DefEFLAGS;
|
||
|
// BinOpMI8_R - Instructions that read "[mem], imm8" and write "reg".
|
||
|
class BinOpMI8_R<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_ndd_args, t, f, (outs t.RegClass:$dst)>, Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, NDD<1>;
|
||
|
// BinOpMI8U_R - Instructions that read "[mem], u8imm" and write "reg".
|
||
|
class BinOpMI8U_R<string m, Format f, X86TypeInfo t, SDPatternOperator node = null_frag>
|
||
|
: BinOpMI8U<m, binop_ndd_args, t, f, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, (node (t.LoadNode addr:$src1), (i8 imm:$src2)))]>, NDD<1>;
|
||
|
// BinOpMI8_RF - Instructions that read "[mem], imm8" and write "reg"/EFLAGS.
|
||
|
class BinOpMI8_RF<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_ndd_args, t, f, (outs t.RegClass:$dst)>, Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, DefEFLAGS, NDD<1>;
|
||
|
// BinOpMI8_M - Instructions that read "[mem], imm8" and write "[mem]".
|
||
|
class BinOpMI8_M<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_args, t, f, (outs)>, Sched<[WriteALURMW]> {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMI8U_M - Instructions that read "[mem], u8imm" and write "[mem]".
|
||
|
class BinOpMI8U_M<string m, Format f, X86TypeInfo t, SDPatternOperator node = null_frag>
|
||
|
: BinOpMI8U<m, binop_args, t, f, (outs),
|
||
|
[(store (node (t.LoadNode addr:$src1), (i8 imm:$src2)), addr:$src1)]> {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMI8_MF - Instructions that read "[mem], imm8" and write "[mem]", EFLAGS.
|
||
|
class BinOpMI8_MF<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_args, t, f, (outs)>, Sched<[WriteALURMW]>, DefEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMI8F_RF - Instructions that read "[mem], imm8", write "reg" and
|
||
|
// read/write EFLAGS.
|
||
|
class BinOpMI8F_RF<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_ndd_args, t, f, (outs t.RegClass:$dst)>,
|
||
|
Sched<[WriteADC.Folded, WriteADC.ReadAfterFold]>, DefEFLAGS, UseEFLAGS, NDD<1>;
|
||
|
// BinOpMI8F_MF - Instructions that read "[mem], imm8", write "[mem]" and
|
||
|
// read/write EFLAGS.
|
||
|
class BinOpMI8F_MF<string m, X86TypeInfo t, Format f>
|
||
|
: BinOpMI8<m, binop_args, t, f, (outs)>, Sched<[WriteADCRMW]>, DefEFLAGS, UseEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
|
||
|
// BinOpAI - Instructions that read "a-reg imm" (Accumulator register).
|
||
|
class BinOpAI<bits<8> o, string m, X86TypeInfo t, Register areg, string args>
|
||
|
: ITy<o, RawFrm, t, (outs), (ins t.ImmOperand:$src), m, args, []>,
|
||
|
Sched<[WriteALU]> {
|
||
|
let ImmT = t.ImmEncoding;
|
||
|
let Uses = [areg];
|
||
|
}
|
||
|
// BinOpAI_F - Instructions that read "a-reg imm" and write EFLAGS only.
|
||
|
class BinOpAI_F<bits<8> o, string m, X86TypeInfo t, Register areg, string args>
|
||
|
: BinOpAI<o, m, t, areg, args>, DefEFLAGS;
|
||
|
|
||
|
// BinOpAI_AF - Instructions that read "a-reg imm" and write a-reg/EFLAGS.
|
||
|
class BinOpAI_AF<bits<8> o, string m, X86TypeInfo t, Register areg,
|
||
|
string args> : BinOpAI<o, m, t, areg, args> {
|
||
|
let Defs = [areg, EFLAGS];
|
||
|
}
|
||
|
// BinOpAIF_AF - Instructions that read "a-reg imm", write a-reg and read/write
|
||
|
// EFLAGS.
|
||
|
class BinOpAIF_AF<bits<8> o, string m, X86TypeInfo t, Register areg,
|
||
|
string args> : BinOpAI<o, m, t, areg, args> {
|
||
|
let Uses = [areg, EFLAGS];
|
||
|
let Defs = [areg, EFLAGS];
|
||
|
let SchedRW = [WriteADC];
|
||
|
}
|
||
|
// BinOpRC_R - Instructions that read "reg, cl" and write reg.
|
||
|
class BinOpRC_R<string m, Format f, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
|
||
|
: ITy<0xD3, f, t, (outs t.RegClass:$dst), (ins t.RegClass:$src1), m,
|
||
|
!if(!eq(ndd, 0), binop_cl_args, binop_cl_ndd_args),
|
||
|
[(set t.RegClass:$dst, (node t.RegClass:$src1, CL))]>, NDD<ndd> {
|
||
|
let Uses = [CL];
|
||
|
}
|
||
|
// BinOpMC_M - Instructions that read "[mem], cl" and write [mem].
|
||
|
class BinOpMC_M<string m, Format f, X86TypeInfo t, SDPatternOperator node = null_frag>
|
||
|
: ITy<0xD3, f, t, (outs), (ins t.MemOperand:$src1), m, binop_cl_args,
|
||
|
[(store (node (t.LoadNode addr:$src1), CL), addr:$src1)]> {
|
||
|
let Uses = [CL];
|
||
|
let mayLoad = 1;
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// BinOpMC_R - Instructions that read "[mem], cl" and write reg.
|
||
|
class BinOpMC_R<string m, Format f, X86TypeInfo t, SDPatternOperator node = null_frag>
|
||
|
: ITy<0xD3, f, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1), m, binop_cl_ndd_args,
|
||
|
[(set t.RegClass:$dst, (node (t.LoadNode addr:$src1), CL))]>, NDD<1> {
|
||
|
let Uses = [CL];
|
||
|
let mayLoad = 1;
|
||
|
}
|
||
|
|
||
|
// UnaryOpR - Instructions that read "reg".
|
||
|
class UnaryOpR<bits<8> o, Format f, string m, string args, X86TypeInfo t,
|
||
|
dag out, list<dag> p>
|
||
|
: ITy<o, f, t, out, (ins t.RegClass:$src1), m, args, p>, Sched<[WriteALU]>;
|
||
|
// UnaryOpR_R - Instructions that read "reg" and write "reg".
|
||
|
class UnaryOpR_R<bits<8> o, Format f, string m, X86TypeInfo t,
|
||
|
SDPatternOperator node = null_frag, bit ndd = 0>
|
||
|
: UnaryOpR<o, f, m, !if(!eq(ndd, 0), unaryop_args, unaryop_ndd_args), t,
|
||
|
(outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, (node t.RegClass:$src1))]>, NDD<ndd>;
|
||
|
// UnaryOpR_RF - Instructions that read "reg" and write "reg"/EFLAGS.
|
||
|
class UnaryOpR_RF<bits<8> o, Format f, string m, X86TypeInfo t,
|
||
|
SDPatternOperator node = null_frag, bit ndd = 0>
|
||
|
: UnaryOpR<o, f, m, !if(!eq(ndd, 0), unaryop_args, unaryop_ndd_args), t,
|
||
|
(outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, (node t.RegClass:$src1)),
|
||
|
(implicit EFLAGS)]>, DefEFLAGS, NDD<ndd>;
|
||
|
|
||
|
// UnaryOpM - Instructions that read "[mem]".
|
||
|
class UnaryOpM<bits<8> o, Format f, string m, string args, X86TypeInfo t,
|
||
|
dag out, list<dag> p>
|
||
|
: ITy<o, f, t, out, (ins t.MemOperand:$src1), m, args, p> {
|
||
|
let mayLoad = 1;
|
||
|
}
|
||
|
// UnaryOpM_R - Instructions that read "[mem]" and writes "reg".
|
||
|
class UnaryOpM_R<bits<8> o, Format f, string m, X86TypeInfo t,
|
||
|
SDPatternOperator node = null_frag>
|
||
|
: UnaryOpM<o, f, m, unaryop_ndd_args, t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, (node (t.LoadNode addr:$src1)))]>,
|
||
|
Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, NDD<1>;
|
||
|
// UnaryOpM_RF - Instructions that read "[mem]" and writes "reg"/EFLAGS.
|
||
|
class UnaryOpM_RF<bits<8> o, Format f, string m, X86TypeInfo t,
|
||
|
SDPatternOperator node = null_frag>
|
||
|
: UnaryOpM<o, f, m, unaryop_ndd_args, t, (outs t.RegClass:$dst),
|
||
|
[(set t.RegClass:$dst, EFLAGS, (node (t.LoadNode addr:$src1)))]>,
|
||
|
Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, DefEFLAGS, NDD<1>;
|
||
|
// UnaryOpM_M - Instructions that read "[mem]" and writes "[mem]".
|
||
|
class UnaryOpM_M<bits<8> o, Format f, string m, X86TypeInfo t,
|
||
|
SDPatternOperator node = null_frag>
|
||
|
: UnaryOpM<o, f, m, unaryop_args, t, (outs),
|
||
|
[(store (node (t.LoadNode addr:$src1)), addr:$src1)]>,
|
||
|
Sched<[WriteALURMW]>{
|
||
|
let mayStore = 1;
|
||
|
}
|
||
|
// UnaryOpM_MF - Instructions that read "[mem]" and writes "[mem]"/EFLAGS.
|
||
|
class UnaryOpM_MF<bits<8> o, Format f, string m, X86TypeInfo t,
|
||
|
SDPatternOperator node = null_frag>
|
||
|
: UnaryOpM<o, f, m, unaryop_args, t, (outs),
|
||
|
[(store (node (t.LoadNode addr:$src1)), addr:$src1),
|
||
|
(implicit EFLAGS)]>, Sched<[WriteALURMW]>, DefEFLAGS {
|
||
|
let mayStore = 1;
|
||
|
}
|