llvm/llvm/lib/Target/X86/X86InstrUtils.td

//===-- 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;
// ZU - Helper for Zero Upper instructions
class ZU: T_MAP4, EVEX, EVEX_B;

//===----------------------------------------------------------------------===//
// 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, "pbf16">;
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, "pbf16">;
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, "pbf16">;
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;
  let IgnoresW = !if(!eq(t.VT, i8), 1, 0);
}

// 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;
}