xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/X86/X86InstrArithmetic.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric//===-- X86InstrArithmetic.td - Integer Arithmetic Instrs --*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the integer arithmetic instructions in the X86
100b57cec5SDimitry Andric// architecture.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// LEA - Load Effective Address
160b57cec5SDimitry Andriclet SchedRW = [WriteLEA] in {
170b57cec5SDimitry Andric  let hasSideEffects = 0 in
180b57cec5SDimitry Andric    def LEA16r   : I<0x8D, MRMSrcMem,
190b57cec5SDimitry Andric                     (outs GR16:$dst), (ins anymem:$src),
200b57cec5SDimitry Andric                     "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize16;
210b57cec5SDimitry Andric  let isReMaterializable = 1 in
220b57cec5SDimitry Andric    def LEA32r   : I<0x8D, MRMSrcMem,
230b57cec5SDimitry Andric                     (outs GR32:$dst), (ins anymem:$src),
240b57cec5SDimitry Andric                     "lea{l}\t{$src|$dst}, {$dst|$src}",
250b57cec5SDimitry Andric                     [(set GR32:$dst, lea32addr:$src)]>,
260b57cec5SDimitry Andric                     OpSize32, Requires<[Not64BitMode]>;
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric  def LEA64_32r : I<0x8D, MRMSrcMem,
290b57cec5SDimitry Andric                    (outs GR32:$dst), (ins lea64_32mem:$src),
300b57cec5SDimitry Andric                    "lea{l}\t{$src|$dst}, {$dst|$src}",
310b57cec5SDimitry Andric                    [(set GR32:$dst, lea64_32addr:$src)]>,
320b57cec5SDimitry Andric                    OpSize32, Requires<[In64BitMode]>;
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric  let isReMaterializable = 1 in
350b57cec5SDimitry Andric    def LEA64r   : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src),
360b57cec5SDimitry Andric                      "lea{q}\t{$src|$dst}, {$dst|$src}",
370b57cec5SDimitry Andric                      [(set GR64:$dst, lea64addr:$src)]>;
380b57cec5SDimitry Andric} // SchedRW
390b57cec5SDimitry Andric
4006c3fb27SDimitry Andric// Pseudo instruction for lea that prevent optimizer from eliminating
4106c3fb27SDimitry Andric// the instruction.
4206c3fb27SDimitry Andriclet SchedRW = [WriteLEA], isPseudo = true, hasSideEffects = 1 in {
4306c3fb27SDimitry Andric  def PLEA32r   : PseudoI<(outs GR32:$dst), (ins anymem:$src), []>;
4406c3fb27SDimitry Andric  def PLEA64r   : PseudoI<(outs GR64:$dst), (ins anymem:$src), []>;
4506c3fb27SDimitry Andric}
4606c3fb27SDimitry Andric
47647cbc5dSDimitry Andric//===----------------------------------------------------------------------===//
48647cbc5dSDimitry Andric// MUL/IMUL and DIV/IDIV Instructions
49647cbc5dSDimitry Andric//
50647cbc5dSDimitry Andricclass MulDivOpR<bits<8> o, Format f, string m, X86TypeInfo t,
51cb14a3feSDimitry Andric             X86FoldableSchedWrite sched, list<dag> p>
52647cbc5dSDimitry Andric  : UnaryOpR<o, f, m, "$src1", t, (outs), p> {
53647cbc5dSDimitry Andric  let SchedRW = [sched];
54cb14a3feSDimitry Andric}
5506c3fb27SDimitry Andric
56647cbc5dSDimitry Andricclass MulDivOpM<bits<8> o, Format f, string m, X86TypeInfo t,
57647cbc5dSDimitry Andric             X86FoldableSchedWrite sched, list<dag> p>
58647cbc5dSDimitry Andric  : UnaryOpM<o, f, m, "$src1", t, (outs), p> {
59647cbc5dSDimitry Andric  let SchedRW =
60647cbc5dSDimitry Andric    [sched.Folded,
61647cbc5dSDimitry Andric     // Memory operand.
62647cbc5dSDimitry Andric     ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
63647cbc5dSDimitry Andric     // Register reads (implicit or explicit).
64647cbc5dSDimitry Andric     sched.ReadAfterFold, sched.ReadAfterFold];
65647cbc5dSDimitry Andric}
6606c3fb27SDimitry Andric
67647cbc5dSDimitry Andricmulticlass Mul<bits<8> o, string m, Format RegMRM, Format MemMRM, SDPatternOperator node> {
68647cbc5dSDimitry Andric  // AL is really implied by AX, but the registers in Defs must match the
69647cbc5dSDimitry Andric  // SDNode results (i8, i32).
70647cbc5dSDimitry Andric  //
71647cbc5dSDimitry Andric  // FIXME: Used for 8-bit mul, ignore result upper 8 bits.
72647cbc5dSDimitry Andric  // This probably ought to be moved to a def : Pat<> if the
73647cbc5dSDimitry Andric  // syntax can be accepted.
74647cbc5dSDimitry Andric  let Defs = [AL, EFLAGS, AX], Uses = [AL] in
75647cbc5dSDimitry Andric    def 8r : MulDivOpR<o, RegMRM, m, Xi8, WriteIMul8,
76647cbc5dSDimitry Andric                       [(set AL, (node AL, GR8:$src1)), (implicit EFLAGS)]>;
77647cbc5dSDimitry Andric  let Defs = [AX, DX, EFLAGS], Uses = [AX] in
78647cbc5dSDimitry Andric    def 16r : MulDivOpR<o, RegMRM, m, Xi16, WriteIMul16, []>, OpSize16;
79647cbc5dSDimitry Andric  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
80647cbc5dSDimitry Andric    def 32r : MulDivOpR<o, RegMRM, m, Xi32, WriteIMul32, []>, OpSize32;
81647cbc5dSDimitry Andric  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
82647cbc5dSDimitry Andric    def 64r : MulDivOpR<o, RegMRM, m, Xi64, WriteIMul64, []>;
83647cbc5dSDimitry Andric  let Defs = [AL, EFLAGS, AX], Uses = [AL] in
84647cbc5dSDimitry Andric    def 8m : MulDivOpM<o, MemMRM, m, Xi8, WriteIMul8,
85647cbc5dSDimitry Andric                       [(set AL, (node AL, (loadi8 addr:$src1))), (implicit EFLAGS)]>;
86647cbc5dSDimitry Andric  let Defs = [AX, DX, EFLAGS], Uses = [AX] in
87647cbc5dSDimitry Andric    def 16m : MulDivOpM<o, MemMRM, m, Xi16, WriteIMul16, []>, OpSize16;
88647cbc5dSDimitry Andric  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
89647cbc5dSDimitry Andric    def 32m : MulDivOpM<o, MemMRM, m, Xi32, WriteIMul32, []>, OpSize32;
90647cbc5dSDimitry Andric  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
91647cbc5dSDimitry Andric    def 64m : MulDivOpM<o, MemMRM, m, Xi64, WriteIMul64, []>, Requires<[In64BitMode]>;
921db9f3b2SDimitry Andric
931db9f3b2SDimitry Andric  let Predicates = [In64BitMode] in {
941db9f3b2SDimitry Andric    let Defs = [AL, AX], Uses = [AL] in
951db9f3b2SDimitry Andric      def 8r_NF : MulDivOpR<o, RegMRM, m, Xi8, WriteIMul8, []>, NF;
961db9f3b2SDimitry Andric    let Defs = [AX, DX], Uses = [AX] in
971db9f3b2SDimitry Andric      def 16r_NF : MulDivOpR<o, RegMRM, m, Xi16, WriteIMul16, []>, NF, PD;
981db9f3b2SDimitry Andric    let Defs = [EAX, EDX], Uses = [EAX] in
991db9f3b2SDimitry Andric      def 32r_NF : MulDivOpR<o, RegMRM, m, Xi32, WriteIMul32, []>, NF;
1001db9f3b2SDimitry Andric    let Defs = [RAX, RDX], Uses = [RAX] in
1011db9f3b2SDimitry Andric      def 64r_NF : MulDivOpR<o, RegMRM, m, Xi64, WriteIMul64, []>, NF;
1021db9f3b2SDimitry Andric    let Defs = [AL, AX], Uses = [AL] in
1031db9f3b2SDimitry Andric      def 8m_NF : MulDivOpM<o, MemMRM, m, Xi8, WriteIMul8, []>, NF;
1041db9f3b2SDimitry Andric    let Defs = [AX, DX], Uses = [AX] in
1051db9f3b2SDimitry Andric      def 16m_NF : MulDivOpM<o, MemMRM, m, Xi16, WriteIMul16, []>, NF, PD;
1061db9f3b2SDimitry Andric    let Defs = [EAX, EDX], Uses = [EAX] in
1071db9f3b2SDimitry Andric      def 32m_NF : MulDivOpM<o, MemMRM, m, Xi32, WriteIMul32, []>, NF;
1081db9f3b2SDimitry Andric    let Defs = [RAX, RDX], Uses = [RAX] in
1091db9f3b2SDimitry Andric      def 64m_NF : MulDivOpM<o, MemMRM, m, Xi64, WriteIMul64, []>, NF;
1101db9f3b2SDimitry Andric
1111db9f3b2SDimitry Andric    let Defs = [AL, EFLAGS, AX], Uses = [AL] in
1121db9f3b2SDimitry Andric      def 8r_EVEX : MulDivOpR<o, RegMRM, m, Xi8, WriteIMul8, []>, PL;
1131db9f3b2SDimitry Andric    let Defs = [AX, DX, EFLAGS], Uses = [AX] in
1141db9f3b2SDimitry Andric      def 16r_EVEX : MulDivOpR<o, RegMRM, m, Xi16, WriteIMul16, []>, PL, PD;
1151db9f3b2SDimitry Andric    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
1161db9f3b2SDimitry Andric      def 32r_EVEX : MulDivOpR<o, RegMRM, m, Xi32, WriteIMul32, []>, PL;
1171db9f3b2SDimitry Andric    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
1181db9f3b2SDimitry Andric      def 64r_EVEX : MulDivOpR<o, RegMRM, m, Xi64, WriteIMul64, []>, PL;
1191db9f3b2SDimitry Andric    let Defs = [AL, EFLAGS, AX], Uses = [AL] in
1201db9f3b2SDimitry Andric      def 8m_EVEX : MulDivOpM<o, MemMRM, m, Xi8, WriteIMul8, []>, PL;
1211db9f3b2SDimitry Andric    let Defs = [AX, DX, EFLAGS], Uses = [AX] in
1221db9f3b2SDimitry Andric      def 16m_EVEX : MulDivOpM<o, MemMRM, m, Xi16, WriteIMul16, []>, PL, PD;
1231db9f3b2SDimitry Andric    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
1241db9f3b2SDimitry Andric      def 32m_EVEX : MulDivOpM<o, MemMRM, m, Xi32, WriteIMul32, []>, PL;
1251db9f3b2SDimitry Andric    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
1261db9f3b2SDimitry Andric      def 64m_EVEX : MulDivOpM<o, MemMRM, m, Xi64, WriteIMul64, []>, PL;
1271db9f3b2SDimitry Andric  }
128647cbc5dSDimitry Andric}
129cb14a3feSDimitry Andric
130647cbc5dSDimitry Andricdefm MUL : Mul<0xF7, "mul", MRM4r, MRM4m, mul>;
131647cbc5dSDimitry Andricdefm IMUL : Mul<0xF7, "imul", MRM5r, MRM5m, null_frag>;
13206c3fb27SDimitry Andric
133647cbc5dSDimitry Andricmulticlass Div<bits<8> o, string m, Format RegMRM, Format MemMRM> {
134647cbc5dSDimitry Andric  defvar sched8 = !if(!eq(m, "div"), WriteDiv8, WriteIDiv8);
135647cbc5dSDimitry Andric  defvar sched16 = !if(!eq(m, "div"), WriteDiv16, WriteIDiv16);
136647cbc5dSDimitry Andric  defvar sched32 = !if(!eq(m, "div"), WriteDiv32, WriteIDiv32);
137647cbc5dSDimitry Andric  defvar sched64 = !if(!eq(m, "div"), WriteDiv64, WriteIDiv64);
138647cbc5dSDimitry Andric  let Defs = [AL, AH, EFLAGS], Uses = [AX] in
139647cbc5dSDimitry Andric    def 8r  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>;
140647cbc5dSDimitry Andric  let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
141647cbc5dSDimitry Andric    def 16r : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, OpSize16;
142647cbc5dSDimitry Andric  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
143647cbc5dSDimitry Andric    def 32r : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, OpSize32;
144647cbc5dSDimitry Andric  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
145647cbc5dSDimitry Andric    def 64r : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>;
146647cbc5dSDimitry Andric  let Defs = [AL, AH, EFLAGS], Uses = [AX] in
147647cbc5dSDimitry Andric    def 8m  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>;
148647cbc5dSDimitry Andric  let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
149647cbc5dSDimitry Andric    def 16m : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, OpSize16;
150647cbc5dSDimitry Andric  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
151647cbc5dSDimitry Andric    def 32m : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, OpSize32;
152647cbc5dSDimitry Andric  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
153647cbc5dSDimitry Andric    def 64m : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, Requires<[In64BitMode]>;
1541db9f3b2SDimitry Andric
1551db9f3b2SDimitry Andric  let Predicates = [In64BitMode] in {
1561db9f3b2SDimitry Andric    let Defs = [AL, AH], Uses = [AX] in
1571db9f3b2SDimitry Andric      def 8r_NF  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>, NF;
1581db9f3b2SDimitry Andric    let Defs = [AX, DX], Uses = [AX, DX] in
1591db9f3b2SDimitry Andric      def 16r_NF : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, NF, PD;
1601db9f3b2SDimitry Andric    let Defs = [EAX, EDX], Uses = [EAX, EDX] in
1611db9f3b2SDimitry Andric      def 32r_NF : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, NF;
1621db9f3b2SDimitry Andric    let Defs = [RAX, RDX], Uses = [RAX, RDX] in
1631db9f3b2SDimitry Andric      def 64r_NF : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>, NF;
1641db9f3b2SDimitry Andric    let Defs = [AL, AH], Uses = [AX] in
1651db9f3b2SDimitry Andric      def 8m_NF  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>, NF;
1661db9f3b2SDimitry Andric    let Defs = [AX, DX], Uses = [AX, DX] in
1671db9f3b2SDimitry Andric      def 16m_NF : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, NF, PD;
1681db9f3b2SDimitry Andric    let Defs = [EAX, EDX], Uses = [EAX, EDX] in
1691db9f3b2SDimitry Andric      def 32m_NF : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, NF;
1701db9f3b2SDimitry Andric    let Defs = [RAX, RDX], Uses = [RAX, RDX] in
1711db9f3b2SDimitry Andric      def 64m_NF : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, NF;
1721db9f3b2SDimitry Andric
1731db9f3b2SDimitry Andric    let Defs = [AL, AH, EFLAGS], Uses = [AX] in
1741db9f3b2SDimitry Andric      def 8r_EVEX  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>, PL;
1751db9f3b2SDimitry Andric    let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
1761db9f3b2SDimitry Andric      def 16r_EVEX : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, PL, PD;
1771db9f3b2SDimitry Andric    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
1781db9f3b2SDimitry Andric      def 32r_EVEX : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, PL;
1791db9f3b2SDimitry Andric    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
1801db9f3b2SDimitry Andric      def 64r_EVEX : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>, PL;
1811db9f3b2SDimitry Andric    let Defs = [AL, AH, EFLAGS], Uses = [AX] in
1821db9f3b2SDimitry Andric      def 8m_EVEX  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>, PL;
1831db9f3b2SDimitry Andric    let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
1841db9f3b2SDimitry Andric      def 16m_EVEX : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, PL, PD;
1851db9f3b2SDimitry Andric    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
1861db9f3b2SDimitry Andric      def 32m_EVEX : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, PL;
1871db9f3b2SDimitry Andric    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
1881db9f3b2SDimitry Andric      def 64m_EVEX : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, PL;
189647cbc5dSDimitry Andric  }
1901db9f3b2SDimitry Andric}
1911db9f3b2SDimitry Andric
192647cbc5dSDimitry Andriclet hasSideEffects = 1 in { // so that we don't speculatively execute
193647cbc5dSDimitry Andric  defm DIV: Div<0xF7, "div", MRM6r, MRM6m>;
194647cbc5dSDimitry Andric  defm IDIV: Div<0xF7, "idiv", MRM7r, MRM7m>;
195647cbc5dSDimitry Andric}
19606c3fb27SDimitry Andric
1971db9f3b2SDimitry Andricclass IMulOpRR_R<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
1981db9f3b2SDimitry Andric  : BinOpRR_R<0xAF, "imul", t, ndd> {
199cb14a3feSDimitry Andric  let Form = MRMSrcReg;
200cb14a3feSDimitry Andric  let SchedRW = [sched];
201cb14a3feSDimitry Andric  // X = IMUL Y, Z --> X = IMUL Z, Y
202cb14a3feSDimitry Andric  let isCommutable = 1;
203cb14a3feSDimitry Andric}
2041db9f3b2SDimitry Andricclass IMulOpRR_RF<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
2051db9f3b2SDimitry Andric  : BinOpRR_RF<0xAF, "imul", t, X86smul_flag, ndd> {
2061db9f3b2SDimitry Andric  let Form = MRMSrcReg;
2071db9f3b2SDimitry Andric  let SchedRW = [sched];
2081db9f3b2SDimitry Andric  // X = IMUL Y, Z --> X = IMUL Z, Y
2091db9f3b2SDimitry Andric  let isCommutable = 1;
2101db9f3b2SDimitry Andric}
2111db9f3b2SDimitry Andricclass IMulOpRM_R<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
2121db9f3b2SDimitry Andric  : BinOpRM_R<0xAF, "imul", t, ndd> {
2131db9f3b2SDimitry Andric  let Form = MRMSrcMem;
2141db9f3b2SDimitry Andric  let SchedRW = [sched.Folded, sched.ReadAfterFold];
2151db9f3b2SDimitry Andric}
2161db9f3b2SDimitry Andricclass IMulOpRM_RF<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
2171db9f3b2SDimitry Andric  : BinOpRM_RF<0xAF, "imul", t, X86smul_flag, ndd> {
218cb14a3feSDimitry Andric  let Form = MRMSrcMem;
219cb14a3feSDimitry Andric  let SchedRW = [sched.Folded, sched.ReadAfterFold];
220cb14a3feSDimitry Andric}
22106c3fb27SDimitry Andric
2221db9f3b2SDimitry Andriclet Predicates = [NoNDD] in {
2231db9f3b2SDimitry Andric  def IMUL16rr : IMulOpRR_RF<Xi16, WriteIMul16Reg>, TB, OpSize16;
2241db9f3b2SDimitry Andric  def IMUL32rr : IMulOpRR_RF<Xi32, WriteIMul32Reg>, TB, OpSize32;
2251db9f3b2SDimitry Andric  def IMUL64rr : IMulOpRR_RF<Xi64, WriteIMul64Reg>, TB;
2261db9f3b2SDimitry Andric  def IMUL16rm : IMulOpRM_RF<Xi16, WriteIMul16Reg>, TB, OpSize16;
2271db9f3b2SDimitry Andric  def IMUL32rm : IMulOpRM_RF<Xi32, WriteIMul32Reg>, TB, OpSize32;
2281db9f3b2SDimitry Andric  def IMUL64rm : IMulOpRM_RF<Xi64, WriteIMul64Reg>, TB;
2291db9f3b2SDimitry Andric}
2301db9f3b2SDimitry Andriclet Predicates = [HasNDD, In64BitMode] in {
2311db9f3b2SDimitry Andric  def IMUL16rr_ND : IMulOpRR_RF<Xi16, WriteIMul16Reg, 1>, PD;
2321db9f3b2SDimitry Andric  def IMUL32rr_ND : IMulOpRR_RF<Xi32, WriteIMul32Reg, 1>;
2331db9f3b2SDimitry Andric  def IMUL64rr_ND : IMulOpRR_RF<Xi64, WriteIMul64Reg, 1>;
2341db9f3b2SDimitry Andric  def IMUL16rm_ND : IMulOpRM_RF<Xi16, WriteIMul16Reg, 1>, PD;
2351db9f3b2SDimitry Andric  def IMUL32rm_ND : IMulOpRM_RF<Xi32, WriteIMul32Reg, 1>;
2361db9f3b2SDimitry Andric  def IMUL64rm_ND : IMulOpRM_RF<Xi64, WriteIMul64Reg, 1>;
2371db9f3b2SDimitry Andric}
2381db9f3b2SDimitry Andric
2391db9f3b2SDimitry Andriclet Predicates = [In64BitMode], Pattern = [(null_frag)] in {
2401db9f3b2SDimitry Andric  def IMUL16rr_NF : IMulOpRR_R<Xi16, WriteIMul16Reg>, NF, PD;
2411db9f3b2SDimitry Andric  def IMUL32rr_NF : IMulOpRR_R<Xi32, WriteIMul32Reg>, NF;
2421db9f3b2SDimitry Andric  def IMUL64rr_NF : IMulOpRR_R<Xi64, WriteIMul64Reg>, NF;
2431db9f3b2SDimitry Andric  def IMUL16rm_NF : IMulOpRM_R<Xi16, WriteIMul16Reg>, NF, PD;
2441db9f3b2SDimitry Andric  def IMUL32rm_NF : IMulOpRM_R<Xi32, WriteIMul32Reg>, NF;
2451db9f3b2SDimitry Andric  def IMUL64rm_NF : IMulOpRM_R<Xi64, WriteIMul64Reg>, NF;
2461db9f3b2SDimitry Andric
2471db9f3b2SDimitry Andric  def IMUL16rr_NF_ND : IMulOpRR_R<Xi16, WriteIMul16Reg, 1>, EVEX_NF, PD;
2481db9f3b2SDimitry Andric  def IMUL32rr_NF_ND : IMulOpRR_R<Xi32, WriteIMul32Reg, 1>, EVEX_NF;
2491db9f3b2SDimitry Andric  def IMUL64rr_NF_ND : IMulOpRR_R<Xi64, WriteIMul64Reg, 1>, EVEX_NF;
2501db9f3b2SDimitry Andric  def IMUL16rm_NF_ND : IMulOpRM_R<Xi16, WriteIMul16Reg, 1>, EVEX_NF, PD;
2511db9f3b2SDimitry Andric  def IMUL32rm_NF_ND : IMulOpRM_R<Xi32, WriteIMul32Reg, 1>, EVEX_NF;
2521db9f3b2SDimitry Andric  def IMUL64rm_NF_ND : IMulOpRM_R<Xi64, WriteIMul64Reg, 1>, EVEX_NF;
2531db9f3b2SDimitry Andric
2541db9f3b2SDimitry Andric  def IMUL16rr_EVEX : IMulOpRR_RF<Xi16, WriteIMul16Reg>, PL, PD;
2551db9f3b2SDimitry Andric  def IMUL32rr_EVEX : IMulOpRR_RF<Xi32, WriteIMul32Reg>, PL;
2561db9f3b2SDimitry Andric  def IMUL64rr_EVEX : IMulOpRR_RF<Xi64, WriteIMul64Reg>, PL;
2571db9f3b2SDimitry Andric  def IMUL16rm_EVEX : IMulOpRM_RF<Xi16, WriteIMul16Reg>, PL, PD;
2581db9f3b2SDimitry Andric  def IMUL32rm_EVEX : IMulOpRM_RF<Xi32, WriteIMul32Reg>, PL;
2591db9f3b2SDimitry Andric  def IMUL64rm_EVEX : IMulOpRM_RF<Xi64, WriteIMul64Reg>, PL;
2601db9f3b2SDimitry Andric}
26106c3fb27SDimitry Andric
262647cbc5dSDimitry Andricclass IMulOpRI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
263647cbc5dSDimitry Andric  : BinOpRI8<0x6B, "imul", binop_ndd_args, t, MRMSrcReg,
2641db9f3b2SDimitry Andric             (outs t.RegClass:$dst)> {
265647cbc5dSDimitry Andric  let SchedRW = [sched];
266647cbc5dSDimitry Andric}
267647cbc5dSDimitry Andricclass IMulOpRI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
268647cbc5dSDimitry Andric  : BinOpRI<0x69, "imul", binop_ndd_args, t, MRMSrcReg,
2691db9f3b2SDimitry Andric            (outs t.RegClass:$dst), []> {
2701db9f3b2SDimitry Andric  let SchedRW = [sched];
2711db9f3b2SDimitry Andric}
2721db9f3b2SDimitry Andricclass IMulOpRI_RF<X86TypeInfo t, X86FoldableSchedWrite sched>
2731db9f3b2SDimitry Andric  : BinOpRI<0x69, "imul", binop_ndd_args, t, MRMSrcReg,
274647cbc5dSDimitry Andric            (outs t.RegClass:$dst),
275cb14a3feSDimitry Andric            [(set t.RegClass:$dst, EFLAGS, (X86smul_flag t.RegClass:$src1,
276647cbc5dSDimitry Andric             t.ImmNoSuOperator:$src2))]>, DefEFLAGS {
277647cbc5dSDimitry Andric  let SchedRW = [sched];
27806c3fb27SDimitry Andric}
279647cbc5dSDimitry Andricclass IMulOpMI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
2801db9f3b2SDimitry Andric  : BinOpMI8<"imul", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)> {
281647cbc5dSDimitry Andric  let Opcode = 0x6B;
282647cbc5dSDimitry Andric  let SchedRW = [sched.Folded];
28306c3fb27SDimitry Andric}
284647cbc5dSDimitry Andricclass IMulOpMI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
285647cbc5dSDimitry Andric  : BinOpMI<0x69, "imul", binop_ndd_args, t, MRMSrcMem,
2861db9f3b2SDimitry Andric            (outs t.RegClass:$dst), []> {
2871db9f3b2SDimitry Andric  let SchedRW = [sched.Folded];
2881db9f3b2SDimitry Andric}
2891db9f3b2SDimitry Andricclass IMulOpMI_RF<X86TypeInfo t, X86FoldableSchedWrite sched>
2901db9f3b2SDimitry Andric  : BinOpMI<0x69, "imul", binop_ndd_args, t, MRMSrcMem,
291647cbc5dSDimitry Andric            (outs t.RegClass:$dst),
292647cbc5dSDimitry Andric            [(set t.RegClass:$dst, EFLAGS, (X86smul_flag (t.LoadNode addr:$src1),
293647cbc5dSDimitry Andric             t.ImmNoSuOperator:$src2))]>,
294647cbc5dSDimitry Andric    DefEFLAGS {
295647cbc5dSDimitry Andric  let SchedRW = [sched.Folded];
29606c3fb27SDimitry Andric}
2971db9f3b2SDimitry Andricdef IMUL16rri8 : IMulOpRI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, OpSize16;
2981db9f3b2SDimitry Andricdef IMUL32rri8 : IMulOpRI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, OpSize32;
2991db9f3b2SDimitry Andricdef IMUL64rri8 : IMulOpRI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS;
3001db9f3b2SDimitry Andricdef IMUL16rri  : IMulOpRI_RF<Xi16, WriteIMul16Imm>, OpSize16;
3011db9f3b2SDimitry Andricdef IMUL32rri  : IMulOpRI_RF<Xi32, WriteIMul32Imm>, OpSize32;
3021db9f3b2SDimitry Andricdef IMUL64rri32 : IMulOpRI_RF<Xi64, WriteIMul64Imm>;
3031db9f3b2SDimitry Andricdef IMUL16rmi8 : IMulOpMI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, OpSize16;
3041db9f3b2SDimitry Andricdef IMUL32rmi8 : IMulOpMI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, OpSize32;
3051db9f3b2SDimitry Andricdef IMUL64rmi8 : IMulOpMI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS;
3061db9f3b2SDimitry Andricdef IMUL16rmi  : IMulOpMI_RF<Xi16, WriteIMul16Imm>, OpSize16;
3071db9f3b2SDimitry Andricdef IMUL32rmi  : IMulOpMI_RF<Xi32, WriteIMul32Imm>, OpSize32;
3081db9f3b2SDimitry Andricdef IMUL64rmi32 : IMulOpMI_RF<Xi64, WriteIMul64Imm>;
30906c3fb27SDimitry Andric
3101db9f3b2SDimitry Andriclet Predicates = [In64BitMode] in {
3111db9f3b2SDimitry Andric  def IMUL16rri8_NF : IMulOpRI8_R<Xi16, WriteIMul16Imm>, NF, PD;
3121db9f3b2SDimitry Andric  def IMUL32rri8_NF : IMulOpRI8_R<Xi32, WriteIMul32Imm>, NF;
3131db9f3b2SDimitry Andric  def IMUL64rri8_NF : IMulOpRI8_R<Xi64, WriteIMul64Imm>, NF;
3141db9f3b2SDimitry Andric  def IMUL16rri_NF  : IMulOpRI_R<Xi16, WriteIMul16Imm>, NF, PD;
3151db9f3b2SDimitry Andric  def IMUL32rri_NF  : IMulOpRI_R<Xi32, WriteIMul32Imm>, NF;
3161db9f3b2SDimitry Andric  def IMUL64rri32_NF : IMulOpRI_R<Xi64, WriteIMul64Imm>, NF;
3171db9f3b2SDimitry Andric  def IMUL16rmi8_NF : IMulOpMI8_R<Xi16, WriteIMul16Imm>, NF, PD;
3181db9f3b2SDimitry Andric  def IMUL32rmi8_NF : IMulOpMI8_R<Xi32, WriteIMul32Imm>, NF;
3191db9f3b2SDimitry Andric  def IMUL64rmi8_NF : IMulOpMI8_R<Xi64, WriteIMul64Imm>, NF;
3201db9f3b2SDimitry Andric  def IMUL16rmi_NF  : IMulOpMI_R<Xi16, WriteIMul16Imm>, NF, PD;
3211db9f3b2SDimitry Andric  def IMUL32rmi_NF  : IMulOpMI_R<Xi32, WriteIMul32Imm>, NF;
3221db9f3b2SDimitry Andric  def IMUL64rmi32_NF : IMulOpMI_R<Xi64, WriteIMul64Imm>, NF;
32306c3fb27SDimitry Andric
3241db9f3b2SDimitry Andric  def IMUL16rri8_EVEX : IMulOpRI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, PL, PD;
3251db9f3b2SDimitry Andric  def IMUL32rri8_EVEX : IMulOpRI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, PL;
3261db9f3b2SDimitry Andric  def IMUL64rri8_EVEX : IMulOpRI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS, PL;
3271db9f3b2SDimitry Andric  def IMUL16rri_EVEX  : IMulOpRI_RF<Xi16, WriteIMul16Imm>, PL, PD;
3281db9f3b2SDimitry Andric  def IMUL32rri_EVEX  : IMulOpRI_RF<Xi32, WriteIMul32Imm>, PL;
3291db9f3b2SDimitry Andric  def IMUL64rri32_EVEX : IMulOpRI_RF<Xi64, WriteIMul64Imm>, PL;
3301db9f3b2SDimitry Andric  def IMUL16rmi8_EVEX : IMulOpMI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, PL, PD;
3311db9f3b2SDimitry Andric  def IMUL32rmi8_EVEX : IMulOpMI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, PL;
3321db9f3b2SDimitry Andric  def IMUL64rmi8_EVEX : IMulOpMI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS, PL;
3331db9f3b2SDimitry Andric  def IMUL16rmi_EVEX  : IMulOpMI_RF<Xi16, WriteIMul16Imm>, PL, PD;
3341db9f3b2SDimitry Andric  def IMUL32rmi_EVEX  : IMulOpMI_RF<Xi32, WriteIMul32Imm>, PL;
3351db9f3b2SDimitry Andric  def IMUL64rmi32_EVEX : IMulOpMI_RF<Xi64, WriteIMul64Imm>, PL;
3361db9f3b2SDimitry Andric}
337*0fca6ea1SDimitry Andric
338*0fca6ea1SDimitry Andric// IMULZU instructions
339*0fca6ea1SDimitry Andricclass IMulZUOpRI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
340*0fca6ea1SDimitry Andric  : BinOpRI8<0x6B, "imulzu", binop_ndd_args, t, MRMSrcReg,
341*0fca6ea1SDimitry Andric             (outs t.RegClass:$dst)> {
342*0fca6ea1SDimitry Andric  let SchedRW = [sched];
343*0fca6ea1SDimitry Andric}
344*0fca6ea1SDimitry Andricclass IMulZUOpRI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
345*0fca6ea1SDimitry Andric  : BinOpRI<0x69, "imulzu", binop_ndd_args, t, MRMSrcReg,
346*0fca6ea1SDimitry Andric            (outs t.RegClass:$dst), []> {
347*0fca6ea1SDimitry Andric  let SchedRW = [sched];
348*0fca6ea1SDimitry Andric}
349*0fca6ea1SDimitry Andricclass IMulZUOpMI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
350*0fca6ea1SDimitry Andric  : BinOpMI8<"imulzu", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)> {
351*0fca6ea1SDimitry Andric  let Opcode = 0x6B;
352*0fca6ea1SDimitry Andric  let SchedRW = [sched.Folded];
353*0fca6ea1SDimitry Andric}
354*0fca6ea1SDimitry Andricclass IMulZUOpMI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
355*0fca6ea1SDimitry Andric  : BinOpMI<0x69, "imulzu", binop_ndd_args, t, MRMSrcMem,
356*0fca6ea1SDimitry Andric            (outs t.RegClass:$dst), []> {
357*0fca6ea1SDimitry Andric  let SchedRW = [sched.Folded];
358*0fca6ea1SDimitry Andric}
359*0fca6ea1SDimitry Andric
360*0fca6ea1SDimitry Andriclet Defs = [EFLAGS], Predicates = [HasEGPR, In64BitMode] in {
361*0fca6ea1SDimitry Andric  def IMULZU16rri8 : IMulZUOpRI8_R<Xi16, WriteIMul16Imm>, ZU, PD;
362*0fca6ea1SDimitry Andric  def IMULZU16rmi8 : IMulZUOpMI8_R<Xi16, WriteIMul16Imm>, ZU, PD;
363*0fca6ea1SDimitry Andric  def IMULZU16rri : IMulZUOpRI_R<Xi16, WriteIMul16Imm>, ZU, PD;
364*0fca6ea1SDimitry Andric  def IMULZU16rmi : IMulZUOpMI_R<Xi16, WriteIMul16Imm>, ZU, PD;
365*0fca6ea1SDimitry Andric  def IMULZU32rri8 : IMulZUOpRI8_R<Xi32, WriteIMul32Imm>, ZU;
366*0fca6ea1SDimitry Andric  def IMULZU32rmi8 : IMulZUOpMI8_R<Xi32, WriteIMul32Imm>, ZU;
367*0fca6ea1SDimitry Andric  def IMULZU32rri : IMulZUOpRI_R<Xi32, WriteIMul32Imm>, ZU;
368*0fca6ea1SDimitry Andric  def IMULZU32rmi : IMulZUOpMI_R<Xi32, WriteIMul32Imm>, ZU;
369*0fca6ea1SDimitry Andric  def IMULZU64rri8 : IMulZUOpRI8_R<Xi64, WriteIMul64Imm>, ZU;
370*0fca6ea1SDimitry Andric  def IMULZU64rmi8 : IMulZUOpMI8_R<Xi64, WriteIMul64Imm>, ZU;
371*0fca6ea1SDimitry Andric  def IMULZU64rri32 : IMulZUOpRI_R<Xi64, WriteIMul64Imm>, ZU;
372*0fca6ea1SDimitry Andric  def IMULZU64rmi32 : IMulZUOpMI_R<Xi64, WriteIMul64Imm>, ZU;
373*0fca6ea1SDimitry Andric}
374*0fca6ea1SDimitry Andric
375647cbc5dSDimitry Andric//===----------------------------------------------------------------------===//
376647cbc5dSDimitry Andric// INC and DEC Instructions
377647cbc5dSDimitry Andric//
3781db9f3b2SDimitry Andricclass IncOpR_RF<X86TypeInfo t, bit ndd = 0> : UnaryOpR_RF<0xFF, MRM0r, "inc", t, null_frag, ndd> {
379647cbc5dSDimitry Andric  let Pattern = [(set t.RegClass:$dst, EFLAGS,
380647cbc5dSDimitry Andric                 (X86add_flag_nocf t.RegClass:$src1, 1))];
381cb14a3feSDimitry Andric}
3821db9f3b2SDimitry Andricclass DecOpR_RF<X86TypeInfo t, bit ndd = 0> : UnaryOpR_RF<0xFF, MRM1r, "dec", t, null_frag, ndd> {
383647cbc5dSDimitry Andric  let Pattern = [(set t.RegClass:$dst, EFLAGS,
384647cbc5dSDimitry Andric                 (X86sub_flag_nocf t.RegClass:$src1, 1))];
385647cbc5dSDimitry Andric}
3861db9f3b2SDimitry Andricclass IncOpR_R<X86TypeInfo t, bit ndd = 0> : UnaryOpR_R<0xFF, MRM0r, "inc", t, null_frag, ndd>;
3871db9f3b2SDimitry Andricclass DecOpR_R<X86TypeInfo t, bit ndd = 0> : UnaryOpR_R<0xFF, MRM1r, "dec", t, null_frag, ndd>;
3881db9f3b2SDimitry Andricclass IncOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM0m, "inc", t, null_frag> {
389647cbc5dSDimitry Andric  let Pattern = [(store (add (t.LoadNode addr:$src1), 1), addr:$src1),
390647cbc5dSDimitry Andric                 (implicit EFLAGS)];
391647cbc5dSDimitry Andric}
3921db9f3b2SDimitry Andricclass DecOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM1m, "dec", t, null_frag> {
393647cbc5dSDimitry Andric  let Pattern = [(store (add (t.LoadNode addr:$src1), -1), addr:$src1),
394647cbc5dSDimitry Andric                 (implicit EFLAGS)];
395647cbc5dSDimitry Andric}
3961db9f3b2SDimitry Andricclass IncOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM0m, "inc", t, null_frag> {
3971db9f3b2SDimitry Andric  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), 1))];
3981db9f3b2SDimitry Andric}
3991db9f3b2SDimitry Andricclass DecOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM1m, "dec", t, null_frag> {
4001db9f3b2SDimitry Andric  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), -1))];
4011db9f3b2SDimitry Andric}
4021db9f3b2SDimitry Andricclass IncOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM0m, "inc", t, null_frag>;
4031db9f3b2SDimitry Andricclass DecOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM1m, "dec", t, null_frag>;
4041db9f3b2SDimitry Andricclass IncOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM0m, "inc", t, null_frag>;
4051db9f3b2SDimitry Andricclass DecOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM1m, "dec", t, null_frag>;
4061db9f3b2SDimitry Andric
407647cbc5dSDimitry Andric// IncDec_Alt - Instructions like "inc reg" short forms.
408647cbc5dSDimitry Andric// Short forms only valid in 32-bit mode. Selected during MCInst lowering.
409647cbc5dSDimitry Andricclass IncDec_Alt<bits<8> o, string m, X86TypeInfo t>
410647cbc5dSDimitry Andric  : UnaryOpR_RF<o, AddRegFrm, m, t, null_frag>, Requires<[Not64BitMode]>;
411cb14a3feSDimitry Andric
412647cbc5dSDimitry Andriclet isConvertibleToThreeAddress = 1 in {
413647cbc5dSDimitry Andric  def INC16r_alt : IncDec_Alt<0x40, "inc", Xi16>, OpSize16;
414647cbc5dSDimitry Andric  def INC32r_alt : IncDec_Alt<0x40, "inc", Xi32>, OpSize32;
415647cbc5dSDimitry Andric  def DEC16r_alt : IncDec_Alt<0x48, "dec", Xi16>, OpSize16;
416647cbc5dSDimitry Andric  def DEC32r_alt : IncDec_Alt<0x48, "dec", Xi32>, OpSize32;
4171db9f3b2SDimitry Andric  let Predicates = [NoNDD] in {
418647cbc5dSDimitry Andric    def INC8r  : IncOpR_RF<Xi8>;
419647cbc5dSDimitry Andric    def INC16r : IncOpR_RF<Xi16>, OpSize16;
420647cbc5dSDimitry Andric    def INC32r : IncOpR_RF<Xi32>, OpSize32;
421647cbc5dSDimitry Andric    def INC64r : IncOpR_RF<Xi64>;
422647cbc5dSDimitry Andric    def DEC8r  : DecOpR_RF<Xi8>;
423647cbc5dSDimitry Andric    def DEC16r : DecOpR_RF<Xi16>, OpSize16;
424647cbc5dSDimitry Andric    def DEC32r : DecOpR_RF<Xi32>, OpSize32;
425647cbc5dSDimitry Andric    def DEC64r : DecOpR_RF<Xi64>;
426647cbc5dSDimitry Andric  }
4271db9f3b2SDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
4281db9f3b2SDimitry Andric    def INC8r_ND  : IncOpR_RF<Xi8, 1>;
4291db9f3b2SDimitry Andric    def INC16r_ND : IncOpR_RF<Xi16, 1>, PD;
4301db9f3b2SDimitry Andric    def INC32r_ND : IncOpR_RF<Xi32, 1>;
4311db9f3b2SDimitry Andric    def INC64r_ND : IncOpR_RF<Xi64, 1>;
4321db9f3b2SDimitry Andric    def DEC8r_ND  : DecOpR_RF<Xi8, 1>;
4331db9f3b2SDimitry Andric    def DEC16r_ND : DecOpR_RF<Xi16, 1>, PD;
4341db9f3b2SDimitry Andric    def DEC32r_ND : DecOpR_RF<Xi32, 1>;
4351db9f3b2SDimitry Andric    def DEC64r_ND : DecOpR_RF<Xi64, 1>;
4361db9f3b2SDimitry Andric  }
4371db9f3b2SDimitry Andric  let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
4381db9f3b2SDimitry Andric    def INC8r_NF  : IncOpR_R<Xi8>, NF;
4391db9f3b2SDimitry Andric    def INC16r_NF : IncOpR_R<Xi16>, NF, PD;
4401db9f3b2SDimitry Andric    def INC32r_NF : IncOpR_R<Xi32>, NF;
4411db9f3b2SDimitry Andric    def INC64r_NF : IncOpR_R<Xi64>, NF;
4421db9f3b2SDimitry Andric    def DEC8r_NF  : DecOpR_R<Xi8>, NF;
4431db9f3b2SDimitry Andric    def DEC16r_NF : DecOpR_R<Xi16>, NF, PD;
4441db9f3b2SDimitry Andric    def DEC32r_NF : DecOpR_R<Xi32>, NF;
4451db9f3b2SDimitry Andric    def DEC64r_NF : DecOpR_R<Xi64>, NF;
4461db9f3b2SDimitry Andric    def INC8r_NF_ND  : IncOpR_R<Xi8, 1>, NF;
4471db9f3b2SDimitry Andric    def INC16r_NF_ND : IncOpR_R<Xi16, 1>, NF, PD;
4481db9f3b2SDimitry Andric    def INC32r_NF_ND : IncOpR_R<Xi32, 1>, NF;
4491db9f3b2SDimitry Andric    def INC64r_NF_ND : IncOpR_R<Xi64, 1>, NF;
4501db9f3b2SDimitry Andric    def DEC8r_NF_ND  : DecOpR_R<Xi8, 1>, NF;
4511db9f3b2SDimitry Andric    def DEC16r_NF_ND : DecOpR_R<Xi16, 1>, NF, PD;
4521db9f3b2SDimitry Andric    def DEC32r_NF_ND : DecOpR_R<Xi32, 1>, NF;
4531db9f3b2SDimitry Andric    def DEC64r_NF_ND : DecOpR_R<Xi64, 1>, NF;
4541db9f3b2SDimitry Andric    def INC8r_EVEX  : IncOpR_RF<Xi8>, PL;
4551db9f3b2SDimitry Andric    def INC16r_EVEX : IncOpR_RF<Xi16>, PL, PD;
4561db9f3b2SDimitry Andric    def INC32r_EVEX : IncOpR_RF<Xi32>, PL;
4571db9f3b2SDimitry Andric    def INC64r_EVEX : IncOpR_RF<Xi64>, PL;
4581db9f3b2SDimitry Andric    def DEC8r_EVEX  : DecOpR_RF<Xi8>, PL;
4591db9f3b2SDimitry Andric    def DEC16r_EVEX : DecOpR_RF<Xi16>, PL, PD;
4601db9f3b2SDimitry Andric    def DEC32r_EVEX : DecOpR_RF<Xi32>, PL;
4611db9f3b2SDimitry Andric    def DEC64r_EVEX : DecOpR_RF<Xi64>, PL;
4621db9f3b2SDimitry Andric  }
4631db9f3b2SDimitry Andric}
46406c3fb27SDimitry Andriclet Predicates = [UseIncDec] in {
4651db9f3b2SDimitry Andric  def INC8m  : IncOpM_MF<Xi8>;
4661db9f3b2SDimitry Andric  def INC16m : IncOpM_MF<Xi16>, OpSize16;
4671db9f3b2SDimitry Andric  def INC32m : IncOpM_MF<Xi32>, OpSize32;
4681db9f3b2SDimitry Andric  def DEC8m  : DecOpM_MF<Xi8>;
4691db9f3b2SDimitry Andric  def DEC16m : DecOpM_MF<Xi16>, OpSize16;
4701db9f3b2SDimitry Andric  def DEC32m : DecOpM_MF<Xi32>, OpSize32;
471cb14a3feSDimitry Andric}
47206c3fb27SDimitry Andriclet Predicates = [UseIncDec, In64BitMode] in {
4731db9f3b2SDimitry Andric  def INC64m : IncOpM_MF<Xi64>;
4741db9f3b2SDimitry Andric  def DEC64m : DecOpM_MF<Xi64>;
4751db9f3b2SDimitry Andric}
4761db9f3b2SDimitry Andriclet Predicates = [HasNDD, In64BitMode, UseIncDec] in {
4771db9f3b2SDimitry Andric  def INC8m_ND  : IncOpM_RF<Xi8>;
4781db9f3b2SDimitry Andric  def INC16m_ND : IncOpM_RF<Xi16>, PD;
4791db9f3b2SDimitry Andric  def INC32m_ND : IncOpM_RF<Xi32>;
4801db9f3b2SDimitry Andric  def DEC8m_ND  : DecOpM_RF<Xi8>;
4811db9f3b2SDimitry Andric  def DEC16m_ND : DecOpM_RF<Xi16>, PD;
4821db9f3b2SDimitry Andric  def DEC32m_ND : DecOpM_RF<Xi32>;
4831db9f3b2SDimitry Andric  def INC64m_ND : IncOpM_RF<Xi64>;
4841db9f3b2SDimitry Andric  def DEC64m_ND : DecOpM_RF<Xi64>;
4851db9f3b2SDimitry Andric}
4861db9f3b2SDimitry Andriclet Predicates = [In64BitMode], Pattern = [(null_frag)] in {
4871db9f3b2SDimitry Andric  def INC8m_NF  : IncOpM_M<Xi8>, NF;
4881db9f3b2SDimitry Andric  def INC16m_NF : IncOpM_M<Xi16>, NF, PD;
4891db9f3b2SDimitry Andric  def INC32m_NF : IncOpM_M<Xi32>, NF;
4901db9f3b2SDimitry Andric  def INC64m_NF : IncOpM_M<Xi64>, NF;
4911db9f3b2SDimitry Andric  def DEC8m_NF  : DecOpM_M<Xi8>, NF;
4921db9f3b2SDimitry Andric  def DEC16m_NF : DecOpM_M<Xi16>, NF, PD;
4931db9f3b2SDimitry Andric  def DEC32m_NF : DecOpM_M<Xi32>, NF;
4941db9f3b2SDimitry Andric  def DEC64m_NF : DecOpM_M<Xi64>, NF;
4951db9f3b2SDimitry Andric  def INC8m_NF_ND  : IncOpM_R<Xi8>, NF;
4961db9f3b2SDimitry Andric  def INC16m_NF_ND : IncOpM_R<Xi16>, NF, PD;
4971db9f3b2SDimitry Andric  def INC32m_NF_ND : IncOpM_R<Xi32>, NF;
4981db9f3b2SDimitry Andric  def INC64m_NF_ND : IncOpM_R<Xi64>, NF;
4991db9f3b2SDimitry Andric  def DEC8m_NF_ND  : DecOpM_R<Xi8>, NF;
5001db9f3b2SDimitry Andric  def DEC16m_NF_ND : DecOpM_R<Xi16>, NF, PD;
5011db9f3b2SDimitry Andric  def DEC32m_NF_ND : DecOpM_R<Xi32>, NF;
5021db9f3b2SDimitry Andric  def DEC64m_NF_ND : DecOpM_R<Xi64>, NF;
5031db9f3b2SDimitry Andric  def INC8m_EVEX  : IncOpM_MF<Xi8>, PL;
5041db9f3b2SDimitry Andric  def INC16m_EVEX : IncOpM_MF<Xi16>, PL, PD;
5051db9f3b2SDimitry Andric  def INC32m_EVEX : IncOpM_MF<Xi32>, PL;
5061db9f3b2SDimitry Andric  def INC64m_EVEX : IncOpM_MF<Xi64>, PL;
5071db9f3b2SDimitry Andric  def DEC8m_EVEX  : DecOpM_MF<Xi8>, PL;
5081db9f3b2SDimitry Andric  def DEC16m_EVEX : DecOpM_MF<Xi16>, PL, PD;
5091db9f3b2SDimitry Andric  def DEC32m_EVEX : DecOpM_MF<Xi32>, PL;
5101db9f3b2SDimitry Andric  def DEC64m_EVEX : DecOpM_MF<Xi64>, PL;
511cb14a3feSDimitry Andric}
51206c3fb27SDimitry Andric
513647cbc5dSDimitry Andric//===----------------------------------------------------------------------===//
514647cbc5dSDimitry Andric// NEG and NOT Instructions
515647cbc5dSDimitry Andric//
516647cbc5dSDimitry Andricclass NegOpR_R<X86TypeInfo t, bit ndd = 0>
517647cbc5dSDimitry Andric  : UnaryOpR_R<0xF7, MRM3r, "neg", t, ineg, ndd>;
518647cbc5dSDimitry Andricclass NegOpR_RF<X86TypeInfo t, bit ndd = 0>
519647cbc5dSDimitry Andric  : UnaryOpR_RF<0xF7, MRM3r, "neg", t, ineg, ndd>;
520647cbc5dSDimitry Andricclass NegOpM_M<X86TypeInfo t> : UnaryOpM_M<0xF7, MRM3m, "neg", t, null_frag>;
521647cbc5dSDimitry Andricclass NegOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xF7, MRM3m, "neg", t, ineg>;
522647cbc5dSDimitry Andricclass NegOpM_R<X86TypeInfo t> : UnaryOpM_R<0xF7, MRM3m, "neg", t, null_frag>;
523647cbc5dSDimitry Andricclass NegOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xF7, MRM3m, "neg", t, ineg>;
52406c3fb27SDimitry Andric
525647cbc5dSDimitry Andricclass NotOpR_R<X86TypeInfo t, bit ndd = 0>
526647cbc5dSDimitry Andric  : UnaryOpR_R<0xF7, MRM2r, "not", t, not, ndd>;
527647cbc5dSDimitry Andricclass NotOpM_M<X86TypeInfo t> : UnaryOpM_M<0xF7, MRM2m, "not", t, not>;
528647cbc5dSDimitry Andricclass NotOpM_R<X86TypeInfo t> : UnaryOpM_R<0xF7, MRM2m, "not", t, not>;
52906c3fb27SDimitry Andric
530647cbc5dSDimitry Andriclet Predicates = [NoNDD] in {
531647cbc5dSDimitry Andricdef NEG8r  : NegOpR_RF<Xi8>;
532647cbc5dSDimitry Andricdef NEG16r : NegOpR_RF<Xi16>, OpSize16;
533647cbc5dSDimitry Andricdef NEG32r : NegOpR_RF<Xi32>, OpSize32;
534647cbc5dSDimitry Andricdef NEG64r : NegOpR_RF<Xi64>;
535647cbc5dSDimitry Andricdef NOT8r  : NotOpR_R<Xi8>;
536647cbc5dSDimitry Andricdef NOT16r : NotOpR_R<Xi16>, OpSize16;
537647cbc5dSDimitry Andricdef NOT32r : NotOpR_R<Xi32>, OpSize32;
538647cbc5dSDimitry Andricdef NOT64r : NotOpR_R<Xi64>;
539cb14a3feSDimitry Andric}
54006c3fb27SDimitry Andric
541647cbc5dSDimitry Andriclet Predicates = [HasNDD, In64BitMode] in {
542647cbc5dSDimitry Andricdef NEG8r_ND  : NegOpR_RF<Xi8, 1>;
543647cbc5dSDimitry Andricdef NEG16r_ND : NegOpR_RF<Xi16, 1>, PD;
544647cbc5dSDimitry Andricdef NEG32r_ND : NegOpR_RF<Xi32, 1>;
545647cbc5dSDimitry Andricdef NEG64r_ND : NegOpR_RF<Xi64, 1>;
54606c3fb27SDimitry Andric
547647cbc5dSDimitry Andricdef NOT8r_ND  : NotOpR_R<Xi8, 1>;
548647cbc5dSDimitry Andricdef NOT16r_ND : NotOpR_R<Xi16, 1>, PD;
549647cbc5dSDimitry Andricdef NOT32r_ND : NotOpR_R<Xi32, 1>;
550647cbc5dSDimitry Andricdef NOT64r_ND : NotOpR_R<Xi64, 1>;
55106c3fb27SDimitry Andric
552647cbc5dSDimitry Andricdef NEG8r_NF_ND  : NegOpR_R<Xi8, 1>, EVEX_NF;
553647cbc5dSDimitry Andricdef NEG16r_NF_ND : NegOpR_R<Xi16, 1>, EVEX_NF, PD;
554647cbc5dSDimitry Andricdef NEG32r_NF_ND : NegOpR_R<Xi32, 1>, EVEX_NF;
555647cbc5dSDimitry Andricdef NEG64r_NF_ND : NegOpR_R<Xi64, 1>, EVEX_NF;
55606c3fb27SDimitry Andric}
55706c3fb27SDimitry Andric
558647cbc5dSDimitry Andricdef NEG8m  : NegOpM_MF<Xi8>;
559647cbc5dSDimitry Andricdef NEG16m : NegOpM_MF<Xi16>, OpSize16;
560647cbc5dSDimitry Andricdef NEG32m : NegOpM_MF<Xi32>, OpSize32;
561647cbc5dSDimitry Andricdef NEG64m : NegOpM_MF<Xi64>, Requires<[In64BitMode]>;
56206c3fb27SDimitry Andric
563647cbc5dSDimitry Andriclet Predicates = [HasNDD, In64BitMode] in {
564647cbc5dSDimitry Andricdef NEG8m_ND  : NegOpM_RF<Xi8>;
565647cbc5dSDimitry Andricdef NEG16m_ND : NegOpM_RF<Xi16>, PD;
566647cbc5dSDimitry Andricdef NEG32m_ND : NegOpM_RF<Xi32>;
567647cbc5dSDimitry Andricdef NEG64m_ND : NegOpM_RF<Xi64>;
56806c3fb27SDimitry Andric
569647cbc5dSDimitry Andricdef NEG8m_NF_ND  : NegOpM_R<Xi8>, EVEX_NF;
570647cbc5dSDimitry Andricdef NEG16m_NF_ND : NegOpM_R<Xi16>, EVEX_NF, PD;
571647cbc5dSDimitry Andricdef NEG32m_NF_ND : NegOpM_R<Xi32>, EVEX_NF;
572647cbc5dSDimitry Andricdef NEG64m_NF_ND : NegOpM_R<Xi64>, EVEX_NF;
573cb14a3feSDimitry Andric}
57406c3fb27SDimitry Andric
575647cbc5dSDimitry Andricdef NOT8m  : NotOpM_M<Xi8>;
576647cbc5dSDimitry Andricdef NOT16m : NotOpM_M<Xi16>, OpSize16;
577647cbc5dSDimitry Andricdef NOT32m : NotOpM_M<Xi32>, OpSize32;
578647cbc5dSDimitry Andricdef NOT64m : NotOpM_M<Xi64>, Requires<[In64BitMode]>;
57906c3fb27SDimitry Andric
580647cbc5dSDimitry Andriclet Predicates = [HasNDD, In64BitMode] in {
581647cbc5dSDimitry Andricdef NOT8m_ND  : NotOpM_R<Xi8>;
582647cbc5dSDimitry Andricdef NOT16m_ND : NotOpM_R<Xi16>, PD;
583647cbc5dSDimitry Andricdef NOT32m_ND : NotOpM_R<Xi32>;
584647cbc5dSDimitry Andricdef NOT64m_ND : NotOpM_R<Xi64>;
585cb14a3feSDimitry Andric}
58606c3fb27SDimitry Andric
587647cbc5dSDimitry Andriclet Predicates = [In64BitMode], Pattern = [(null_frag)] in {
588647cbc5dSDimitry Andricdef NEG8r_NF  : NegOpR_R<Xi8>, NF;
589647cbc5dSDimitry Andricdef NEG16r_NF : NegOpR_R<Xi16>, NF, PD;
590647cbc5dSDimitry Andricdef NEG32r_NF : NegOpR_R<Xi32>, NF;
591647cbc5dSDimitry Andricdef NEG64r_NF : NegOpR_R<Xi64>, NF;
592647cbc5dSDimitry Andricdef NEG8m_NF  : NegOpM_M<Xi8>, NF;
593647cbc5dSDimitry Andricdef NEG16m_NF : NegOpM_M<Xi16>, NF, PD;
594647cbc5dSDimitry Andricdef NEG32m_NF : NegOpM_M<Xi32>, NF;
595647cbc5dSDimitry Andricdef NEG64m_NF : NegOpM_M<Xi64>, NF;
596647cbc5dSDimitry Andric
597647cbc5dSDimitry Andricdef NEG8r_EVEX  : NegOpR_RF<Xi8>, PL;
598647cbc5dSDimitry Andricdef NEG16r_EVEX : NegOpR_RF<Xi16>, PL, PD;
599647cbc5dSDimitry Andricdef NEG32r_EVEX : NegOpR_RF<Xi32>, PL;
600647cbc5dSDimitry Andricdef NEG64r_EVEX : NegOpR_RF<Xi64>, PL;
601647cbc5dSDimitry Andric
602647cbc5dSDimitry Andricdef NOT8r_EVEX  : NotOpR_R<Xi8>, PL;
603647cbc5dSDimitry Andricdef NOT16r_EVEX : NotOpR_R<Xi16>, PL, PD;
604647cbc5dSDimitry Andricdef NOT32r_EVEX : NotOpR_R<Xi32>, PL;
605647cbc5dSDimitry Andricdef NOT64r_EVEX : NotOpR_R<Xi64>, PL;
606647cbc5dSDimitry Andric
607647cbc5dSDimitry Andricdef NEG8m_EVEX  : NegOpM_MF<Xi8>, PL;
608647cbc5dSDimitry Andricdef NEG16m_EVEX : NegOpM_MF<Xi16>, PL, PD;
609647cbc5dSDimitry Andricdef NEG32m_EVEX : NegOpM_MF<Xi32>, PL;
610647cbc5dSDimitry Andricdef NEG64m_EVEX : NegOpM_MF<Xi64>, PL;
611647cbc5dSDimitry Andric
612647cbc5dSDimitry Andricdef NOT8m_EVEX  : NotOpM_M<Xi8>, PL;
613647cbc5dSDimitry Andricdef NOT16m_EVEX : NotOpM_M<Xi16>, PL, PD;
614647cbc5dSDimitry Andricdef NOT32m_EVEX : NotOpM_M<Xi32>, PL;
615647cbc5dSDimitry Andricdef NOT64m_EVEX : NotOpM_M<Xi64>, PL;
616647cbc5dSDimitry Andric}
61706c3fb27SDimitry Andric
6180b57cec5SDimitry Andric/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
6190b57cec5SDimitry Andric/// defined with "(set GPR:$dst, EFLAGS, (...".
6200b57cec5SDimitry Andric///
6210b57cec5SDimitry Andric/// It would be nice to get rid of the second and third argument here, but
6220b57cec5SDimitry Andric/// tblgen can't handle dependent type references aggressively enough: PR8330
6230b57cec5SDimitry Andricmulticlass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
6240b57cec5SDimitry Andric                         string mnemonic, Format RegMRM, Format MemMRM,
6250b57cec5SDimitry Andric                         SDNode opnodeflag, SDNode opnode,
6260b57cec5SDimitry Andric                         bit CommutableRR, bit ConvertibleToThreeAddress,
6270b57cec5SDimitry Andric                         bit ConvertibleToThreeAddressRR> {
628cb14a3feSDimitry Andric  let isCommutable = CommutableRR,
629cb14a3feSDimitry Andric      isConvertibleToThreeAddress = ConvertibleToThreeAddressRR in {
630647cbc5dSDimitry Andric    let Predicates = [NoNDD] in {
6311db9f3b2SDimitry Andric      def 8rr  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
6321db9f3b2SDimitry Andric      def 16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>, OpSize16;
6331db9f3b2SDimitry Andric      def 32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>, OpSize32;
6341db9f3b2SDimitry Andric      def 64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
635cb14a3feSDimitry Andric    }
636647cbc5dSDimitry Andric    let Predicates = [HasNDD, In64BitMode] in {
6371db9f3b2SDimitry Andric      def 8rr_ND  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag, 1>;
6381db9f3b2SDimitry Andric      def 16rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag, 1>, PD;
6391db9f3b2SDimitry Andric      def 32rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag, 1>;
6401db9f3b2SDimitry Andric      def 64rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag, 1>;
6411db9f3b2SDimitry Andric      def 8rr_NF_ND  : BinOpRR_R<BaseOpc, mnemonic, Xi8, 1>, EVEX_NF;
6421db9f3b2SDimitry Andric      def 16rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi16, 1>, EVEX_NF, PD;
6431db9f3b2SDimitry Andric      def 32rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi32, 1>, EVEX_NF;
6441db9f3b2SDimitry Andric      def 64rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi64, 1>, EVEX_NF;
645647cbc5dSDimitry Andric    }
646647cbc5dSDimitry Andric    let Predicates = [In64BitMode] in {
6471db9f3b2SDimitry Andric      def 8rr_NF  : BinOpRR_R<BaseOpc, mnemonic, Xi8>, NF;
6481db9f3b2SDimitry Andric      def 16rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi16>, NF, PD;
6491db9f3b2SDimitry Andric      def 32rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi32>, NF;
6501db9f3b2SDimitry Andric      def 64rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi64>, NF;
6511db9f3b2SDimitry Andric      def 8rr_EVEX  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
6521db9f3b2SDimitry Andric      def 16rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
6531db9f3b2SDimitry Andric      def 32rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
6541db9f3b2SDimitry Andric      def 64rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
655647cbc5dSDimitry Andric    }
656647cbc5dSDimitry Andric  }
6570b57cec5SDimitry Andric
6581db9f3b2SDimitry Andric  def 8rr_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>;
6591db9f3b2SDimitry Andric  def 16rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
6601db9f3b2SDimitry Andric  def 32rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
6611db9f3b2SDimitry Andric  def 64rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>;
662647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
6631db9f3b2SDimitry Andric    def 8rr_EVEX_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
6641db9f3b2SDimitry Andric    def 16rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
6651db9f3b2SDimitry Andric    def 32rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
6661db9f3b2SDimitry Andric    def 64rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
6671db9f3b2SDimitry Andric    def 8rr_ND_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
6681db9f3b2SDimitry Andric    def 16rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
6691db9f3b2SDimitry Andric    def 32rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
6701db9f3b2SDimitry Andric    def 64rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
6711db9f3b2SDimitry Andric    def 8rr_NF_REV  : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8>, NF;
6721db9f3b2SDimitry Andric    def 16rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16>, NF, PD;
6731db9f3b2SDimitry Andric    def 32rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32>, NF;
6741db9f3b2SDimitry Andric    def 64rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64>, NF;
6751db9f3b2SDimitry Andric    def 8rr_NF_ND_REV  : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
6761db9f3b2SDimitry Andric    def 16rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
6771db9f3b2SDimitry Andric    def 32rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
6781db9f3b2SDimitry Andric    def 64rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
679647cbc5dSDimitry Andric  }
6800b57cec5SDimitry Andric
681647cbc5dSDimitry Andric  let Predicates = [NoNDD] in {
6821db9f3b2SDimitry Andric    def 8rm   : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
6831db9f3b2SDimitry Andric    def 16rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>, OpSize16;
6841db9f3b2SDimitry Andric    def 32rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>, OpSize32;
6851db9f3b2SDimitry Andric    def 64rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
686647cbc5dSDimitry Andric  }
687647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
6881db9f3b2SDimitry Andric    def 8rm_ND  : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag, 1>;
6891db9f3b2SDimitry Andric    def 16rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag, 1>, PD;
6901db9f3b2SDimitry Andric    def 32rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag, 1>;
6911db9f3b2SDimitry Andric    def 64rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag, 1>;
6921db9f3b2SDimitry Andric    def 8rm_NF_ND  : BinOpRM_R<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
6931db9f3b2SDimitry Andric    def 16rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
6941db9f3b2SDimitry Andric    def 32rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
6951db9f3b2SDimitry Andric    def 64rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
696647cbc5dSDimitry Andric  }
697647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
6981db9f3b2SDimitry Andric    def 8rm_NF  : BinOpRM_R<BaseOpc2, mnemonic, Xi8>, NF;
6991db9f3b2SDimitry Andric    def 16rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi16>, NF, PD;
7001db9f3b2SDimitry Andric    def 32rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi32>, NF;
7011db9f3b2SDimitry Andric    def 64rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi64>, NF;
7021db9f3b2SDimitry Andric    def 8rm_EVEX  : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , null_frag>, PL;
7031db9f3b2SDimitry Andric    def 16rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, null_frag>, PL, PD;
7041db9f3b2SDimitry Andric    def 32rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, null_frag>, PL;
7051db9f3b2SDimitry Andric    def 64rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, null_frag>, PL;
706647cbc5dSDimitry Andric  }
7070b57cec5SDimitry Andric
708cb14a3feSDimitry Andric  let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
709647cbc5dSDimitry Andric    let Predicates = [NoNDD] in {
7100b57cec5SDimitry Andric      // NOTE: These are order specific, we want the ri8 forms to be listed
7110b57cec5SDimitry Andric      // first so that they are slightly preferred to the ri forms.
7121db9f3b2SDimitry Andric      def 16ri8 : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
7131db9f3b2SDimitry Andric      def 32ri8 : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
7141db9f3b2SDimitry Andric      def 64ri8 : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>;
7151db9f3b2SDimitry Andric      def 8ri   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
7161db9f3b2SDimitry Andric      def 16ri  : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM>, OpSize16;
7171db9f3b2SDimitry Andric      def 32ri  : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM>, OpSize32;
7181db9f3b2SDimitry Andric      def 64ri32: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM>;
7190b57cec5SDimitry Andric    }
720647cbc5dSDimitry Andric    let Predicates = [HasNDD, In64BitMode] in {
7211db9f3b2SDimitry Andric      def 16ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
7221db9f3b2SDimitry Andric      def 32ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
7231db9f3b2SDimitry Andric      def 64ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
7241db9f3b2SDimitry Andric      def 8ri_ND   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM, 1>;
7251db9f3b2SDimitry Andric      def 16ri_ND  : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM, 1>, PD;
7261db9f3b2SDimitry Andric      def 32ri_ND  : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM, 1>;
7271db9f3b2SDimitry Andric      def 64ri32_ND: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM, 1>;
7281db9f3b2SDimitry Andric      def 16ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
7291db9f3b2SDimitry Andric      def 32ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
7301db9f3b2SDimitry Andric      def 64ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
7311db9f3b2SDimitry Andric      def 8ri_NF_ND  : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM, 1>, EVEX_NF;
7321db9f3b2SDimitry Andric      def 16ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
7331db9f3b2SDimitry Andric      def 32ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
7341db9f3b2SDimitry Andric      def 64ri32_NF_ND : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
735647cbc5dSDimitry Andric    }
736647cbc5dSDimitry Andric    let Predicates = [In64BitMode] in {
7371db9f3b2SDimitry Andric      def 16ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM>, NF, PD;
7381db9f3b2SDimitry Andric      def 32ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM>, NF;
7391db9f3b2SDimitry Andric      def 64ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM>, NF;
7401db9f3b2SDimitry Andric      def 8ri_NF  : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM>, NF;
7411db9f3b2SDimitry Andric      def 16ri_NF : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM>, NF, PD;
7421db9f3b2SDimitry Andric      def 32ri_NF : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM>, NF;
7431db9f3b2SDimitry Andric      def 64ri32_NF : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM>, NF;
7441db9f3b2SDimitry Andric      def 16ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
7451db9f3b2SDimitry Andric      def 32ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
7461db9f3b2SDimitry Andric      def 64ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
7471db9f3b2SDimitry Andric      def 8ri_EVEX   : BinOpRI_RF<0x80, mnemonic, Xi8 , null_frag, RegMRM>, PL;
7481db9f3b2SDimitry Andric      def 16ri_EVEX  : BinOpRI_RF<0x81, mnemonic, Xi16, null_frag, RegMRM>, PL, PD;
7491db9f3b2SDimitry Andric      def 32ri_EVEX  : BinOpRI_RF<0x81, mnemonic, Xi32, null_frag, RegMRM>, PL;
7501db9f3b2SDimitry Andric      def 64ri32_EVEX: BinOpRI_RF<0x81, mnemonic, Xi64, null_frag, RegMRM>, PL;
751647cbc5dSDimitry Andric    }
752647cbc5dSDimitry Andric  }
7530b57cec5SDimitry Andric
7541db9f3b2SDimitry Andric  def 8mr    : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , opnode>;
7551db9f3b2SDimitry Andric  def 16mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
7561db9f3b2SDimitry Andric  def 32mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
7571db9f3b2SDimitry Andric  def 64mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi64, opnode>;
758647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
759*0fca6ea1SDimitry Andric    defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
760*0fca6ea1SDimitry Andric    def 8mr_ND    : BinOpMR_RF<BaseOpc, mnemonic, Xi8 , node>;
761*0fca6ea1SDimitry Andric    def 16mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi16, node>, PD;
762*0fca6ea1SDimitry Andric    def 32mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi32, node>;
763*0fca6ea1SDimitry Andric    def 64mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi64, node>;
7641db9f3b2SDimitry Andric    def 8mr_NF_ND    : BinOpMR_R<BaseOpc, mnemonic, Xi8>, EVEX_NF;
7651db9f3b2SDimitry Andric    def 16mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi16>, EVEX_NF, PD;
7661db9f3b2SDimitry Andric    def 32mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi32>, EVEX_NF;
7671db9f3b2SDimitry Andric    def 64mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi64>, EVEX_NF;
768647cbc5dSDimitry Andric  }
769647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
7701db9f3b2SDimitry Andric    def 8mr_NF    : BinOpMR_M<BaseOpc, mnemonic, Xi8>, NF;
7711db9f3b2SDimitry Andric    def 16mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi16>, NF, PD;
7721db9f3b2SDimitry Andric    def 32mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi32>, NF;
7731db9f3b2SDimitry Andric    def 64mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi64>, NF;
7741db9f3b2SDimitry Andric    def 8mr_EVEX    : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
7751db9f3b2SDimitry Andric    def 16mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
7761db9f3b2SDimitry Andric    def 32mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
7771db9f3b2SDimitry Andric    def 64mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
778647cbc5dSDimitry Andric  }
7790b57cec5SDimitry Andric
7800b57cec5SDimitry Andric  // NOTE: These are order specific, we want the mi8 forms to be listed
7810b57cec5SDimitry Andric  // first so that they are slightly preferred to the mi forms.
7821db9f3b2SDimitry Andric  def 16mi8  : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, OpSize16;
7831db9f3b2SDimitry Andric  def 32mi8  : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, OpSize32;
7840b57cec5SDimitry Andric  let Predicates = [In64BitMode] in
7851db9f3b2SDimitry Andric    def 64mi8  : BinOpMI8_MF<mnemonic, Xi64, MemMRM>;
7861db9f3b2SDimitry Andric  def 8mi    : BinOpMI_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
7871db9f3b2SDimitry Andric  def 16mi   : BinOpMI_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
7881db9f3b2SDimitry Andric  def 32mi   : BinOpMI_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
7890b57cec5SDimitry Andric  let Predicates = [In64BitMode] in
7901db9f3b2SDimitry Andric    def 64mi32 : BinOpMI_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
791647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
7921db9f3b2SDimitry Andric    def 16mi8_ND  : BinOpMI8_RF<mnemonic, Xi16, MemMRM>, PD;
7931db9f3b2SDimitry Andric    def 32mi8_ND  : BinOpMI8_RF<mnemonic, Xi32, MemMRM>;
7941db9f3b2SDimitry Andric    def 64mi8_ND  : BinOpMI8_RF<mnemonic, Xi64, MemMRM>;
7951db9f3b2SDimitry Andric    def 8mi_ND    : BinOpMI_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
7961db9f3b2SDimitry Andric    def 16mi_ND   : BinOpMI_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
7971db9f3b2SDimitry Andric    def 32mi_ND   : BinOpMI_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
7981db9f3b2SDimitry Andric    def 64mi32_ND : BinOpMI_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
7991db9f3b2SDimitry Andric    def 16mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi16, MemMRM>, NF, PD;
8001db9f3b2SDimitry Andric    def 32mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi32, MemMRM>, NF;
8011db9f3b2SDimitry Andric    def 64mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi64, MemMRM>, NF;
8021db9f3b2SDimitry Andric    def 8mi_NF_ND    : BinOpMI_R<0x80, mnemonic, Xi8, MemMRM>, NF;
8031db9f3b2SDimitry Andric    def 16mi_NF_ND   : BinOpMI_R<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
8041db9f3b2SDimitry Andric    def 32mi_NF_ND   : BinOpMI_R<0x81, mnemonic, Xi32, MemMRM>, NF;
8051db9f3b2SDimitry Andric    def 64mi32_NF_ND : BinOpMI_R<0x81, mnemonic, Xi64, MemMRM>, NF;
806647cbc5dSDimitry Andric  }
807647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
8081db9f3b2SDimitry Andric    def 16mi8_NF  : BinOpMI8_M<mnemonic, Xi16, MemMRM>, NF, PD;
8091db9f3b2SDimitry Andric    def 32mi8_NF  : BinOpMI8_M<mnemonic, Xi32, MemMRM>, NF;
8101db9f3b2SDimitry Andric    def 64mi8_NF  : BinOpMI8_M<mnemonic, Xi64, MemMRM>, NF;
8111db9f3b2SDimitry Andric    def 8mi_NF    : BinOpMI_M<0x80, mnemonic, Xi8, MemMRM>, NF;
8121db9f3b2SDimitry Andric    def 16mi_NF   : BinOpMI_M<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
8131db9f3b2SDimitry Andric    def 32mi_NF   : BinOpMI_M<0x81, mnemonic, Xi32, MemMRM>, NF;
8141db9f3b2SDimitry Andric    def 64mi32_NF : BinOpMI_M<0x81, mnemonic, Xi64, MemMRM>, NF;
8151db9f3b2SDimitry Andric    def 16mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, PL, PD;
8161db9f3b2SDimitry Andric    def 32mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, PL;
8171db9f3b2SDimitry Andric    def 64mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi64, MemMRM>, PL;
8181db9f3b2SDimitry Andric    def 8mi_EVEX    : BinOpMI_MF<0x80, mnemonic, Xi8 , null_frag, MemMRM>, PL;
8191db9f3b2SDimitry Andric    def 16mi_EVEX   : BinOpMI_MF<0x81, mnemonic, Xi16, null_frag, MemMRM>, PL, PD;
8201db9f3b2SDimitry Andric    def 32mi_EVEX   : BinOpMI_MF<0x81, mnemonic, Xi32, null_frag, MemMRM>, PL;
8211db9f3b2SDimitry Andric    def 64mi32_EVEX : BinOpMI_MF<0x81, mnemonic, Xi64, null_frag, MemMRM>, PL;
822647cbc5dSDimitry Andric  }
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
8250b57cec5SDimitry Andric  // not in 64-bit mode.
826cb14a3feSDimitry Andric  let Predicates = [Not64BitMode] in {
8271db9f3b2SDimitry Andric    def 8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
8281db9f3b2SDimitry Andric    def 8mi8 : BinOpMI8_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
8290b57cec5SDimitry Andric  }
8300b57cec5SDimitry Andric
831*0fca6ea1SDimitry Andric  def 8i8 : BinOpAI_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
832*0fca6ea1SDimitry Andric  def 16i16 : BinOpAI_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
833*0fca6ea1SDimitry Andric  def 32i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
834*0fca6ea1SDimitry Andric  def 64i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
8350b57cec5SDimitry Andric}
8360b57cec5SDimitry Andric
8370b57cec5SDimitry Andric/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
8380b57cec5SDimitry Andric/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
8390b57cec5SDimitry Andric/// SBB.
8400b57cec5SDimitry Andric///
8410b57cec5SDimitry Andric/// It would be nice to get rid of the second and third argument here, but
8420b57cec5SDimitry Andric/// tblgen can't handle dependent type references aggressively enough: PR8330
8430b57cec5SDimitry Andricmulticlass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
8440b57cec5SDimitry Andric                          string mnemonic, Format RegMRM, Format MemMRM,
8450b57cec5SDimitry Andric                          SDNode opnode, bit CommutableRR,
8460b57cec5SDimitry Andric                           bit ConvertibleToThreeAddress> {
8470b57cec5SDimitry Andric  let isCommutable = CommutableRR in {
848647cbc5dSDimitry Andric    let Predicates = [NoNDD] in {
8491db9f3b2SDimitry Andric      def 8rr  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , opnode>;
8500b57cec5SDimitry Andric      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
8511db9f3b2SDimitry Andric        def 16rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
8521db9f3b2SDimitry Andric        def 32rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
8531db9f3b2SDimitry Andric        def 64rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, opnode>;
854647cbc5dSDimitry Andric      }
855647cbc5dSDimitry Andric    }
856647cbc5dSDimitry Andric    let Predicates = [HasNDD, In64BitMode] in {
8571db9f3b2SDimitry Andric      def 8rr_ND  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , opnode, 1>;
858647cbc5dSDimitry Andric      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
8591db9f3b2SDimitry Andric        def 16rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, opnode, 1>, PD;
8601db9f3b2SDimitry Andric        def 32rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, opnode, 1>;
8611db9f3b2SDimitry Andric        def 64rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, opnode, 1>;
862647cbc5dSDimitry Andric      }
863647cbc5dSDimitry Andric    }
8640b57cec5SDimitry Andric  } // isCommutable
8650b57cec5SDimitry Andric
866647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
8671db9f3b2SDimitry Andric    def 8rr_EVEX  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
8681db9f3b2SDimitry Andric    def 16rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
8691db9f3b2SDimitry Andric    def 32rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
8701db9f3b2SDimitry Andric    def 64rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
871647cbc5dSDimitry Andric  }
872647cbc5dSDimitry Andric
8731db9f3b2SDimitry Andric  def 8rr_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8>;
8741db9f3b2SDimitry Andric  def 16rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
8751db9f3b2SDimitry Andric  def 32rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
8761db9f3b2SDimitry Andric  def 64rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64>;
877647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
8781db9f3b2SDimitry Andric    def 8rr_ND_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
8791db9f3b2SDimitry Andric    def 16rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
8801db9f3b2SDimitry Andric    def 32rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
8811db9f3b2SDimitry Andric    def 64rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
8821db9f3b2SDimitry Andric    def 8rr_EVEX_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
8831db9f3b2SDimitry Andric    def 16rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
8841db9f3b2SDimitry Andric    def 32rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
8851db9f3b2SDimitry Andric    def 64rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
886647cbc5dSDimitry Andric  }
8870b57cec5SDimitry Andric
888647cbc5dSDimitry Andric  let Predicates = [NoNDD] in {
8891db9f3b2SDimitry Andric    def 8rm   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode>;
8901db9f3b2SDimitry Andric    def 16rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode>, OpSize16;
8911db9f3b2SDimitry Andric    def 32rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode>, OpSize32;
8921db9f3b2SDimitry Andric    def 64rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode>;
893647cbc5dSDimitry Andric  }
894647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
8951db9f3b2SDimitry Andric    def 8rm_ND   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode, 1>;
8961db9f3b2SDimitry Andric    def 16rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode, 1>, PD;
8971db9f3b2SDimitry Andric    def 32rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode, 1>;
8981db9f3b2SDimitry Andric    def 64rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode, 1>;
899647cbc5dSDimitry Andric  }
900647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
9011db9f3b2SDimitry Andric    def 8rm_EVEX   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode>, PL;
9021db9f3b2SDimitry Andric    def 16rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode>, PL, PD;
9031db9f3b2SDimitry Andric    def 32rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode>, PL;
9041db9f3b2SDimitry Andric    def 64rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode>, PL;
905647cbc5dSDimitry Andric  }
9060b57cec5SDimitry Andric
907647cbc5dSDimitry Andric  let Predicates = [NoNDD] in {
9081db9f3b2SDimitry Andric    def 8ri   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
909cb14a3feSDimitry Andric    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
9100b57cec5SDimitry Andric      // NOTE: These are order specific, we want the ri8 forms to be listed
9110b57cec5SDimitry Andric      // first so that they are slightly preferred to the ri forms.
9121db9f3b2SDimitry Andric      def 16ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
9131db9f3b2SDimitry Andric      def 32ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
9141db9f3b2SDimitry Andric      def 64ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM>;
9150b57cec5SDimitry Andric
9161db9f3b2SDimitry Andric      def 16ri  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM>, OpSize16;
9171db9f3b2SDimitry Andric      def 32ri  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM>, OpSize32;
9181db9f3b2SDimitry Andric      def 64ri32: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM>;
9190b57cec5SDimitry Andric    }
920647cbc5dSDimitry Andric  }
921647cbc5dSDimitry Andric
922647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
9231db9f3b2SDimitry Andric    def 8ri_ND   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM, 1>;
924647cbc5dSDimitry Andric    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
9251db9f3b2SDimitry Andric      def 16ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
9261db9f3b2SDimitry Andric      def 32ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
9271db9f3b2SDimitry Andric      def 64ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
9281db9f3b2SDimitry Andric      def 16ri_ND  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM, 1>, PD;
9291db9f3b2SDimitry Andric      def 32ri_ND  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM, 1>;
9301db9f3b2SDimitry Andric      def 64ri32_ND: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM, 1>;
931647cbc5dSDimitry Andric    }
932647cbc5dSDimitry Andric  }
933647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
9341db9f3b2SDimitry Andric    def 8ri_EVEX   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM>, PL;
9351db9f3b2SDimitry Andric    def 16ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
9361db9f3b2SDimitry Andric    def 32ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
9371db9f3b2SDimitry Andric    def 64ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
9381db9f3b2SDimitry Andric    def 16ri_EVEX  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM>, PL, PD;
9391db9f3b2SDimitry Andric    def 32ri_EVEX  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM>, PL;
9401db9f3b2SDimitry Andric    def 64ri32_EVEX: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM>, PL;
941647cbc5dSDimitry Andric  }
9420b57cec5SDimitry Andric
9431db9f3b2SDimitry Andric  def 8mr    : BinOpMRF_MF<BaseOpc, mnemonic, Xi8 , opnode>;
9441db9f3b2SDimitry Andric  def 16mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
9451db9f3b2SDimitry Andric  def 32mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
9461db9f3b2SDimitry Andric  def 64mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi64, opnode>;
947647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
948*0fca6ea1SDimitry Andric    defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
949*0fca6ea1SDimitry Andric    def 8mr_ND    : BinOpMRF_RF<BaseOpc, mnemonic, Xi8 , node>;
950*0fca6ea1SDimitry Andric    def 16mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi16, node>, PD;
951*0fca6ea1SDimitry Andric    def 32mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi32, node>;
952*0fca6ea1SDimitry Andric    def 64mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi64, node>;
953647cbc5dSDimitry Andric  }
954647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
9551db9f3b2SDimitry Andric    def 8mr_EVEX    : BinOpMRF_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
9561db9f3b2SDimitry Andric    def 16mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
9571db9f3b2SDimitry Andric    def 32mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
9581db9f3b2SDimitry Andric    def 64mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
959647cbc5dSDimitry Andric  }
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andric  // NOTE: These are order specific, we want the mi8 forms to be listed
9620b57cec5SDimitry Andric  // first so that they are slightly preferred to the mi forms.
9631db9f3b2SDimitry Andric  def 8mi    : BinOpMIF_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
9641db9f3b2SDimitry Andric  def 16mi8  : BinOpMI8F_MF<mnemonic, Xi16, MemMRM>, OpSize16;
9651db9f3b2SDimitry Andric  def 32mi8  : BinOpMI8F_MF<mnemonic, Xi32, MemMRM>, OpSize32;
9660b57cec5SDimitry Andric  let Predicates = [In64BitMode] in
9671db9f3b2SDimitry Andric    def 64mi8  : BinOpMI8F_MF<mnemonic, Xi64, MemMRM>;
9681db9f3b2SDimitry Andric  def 16mi   : BinOpMIF_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
9691db9f3b2SDimitry Andric  def 32mi   : BinOpMIF_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
9700b57cec5SDimitry Andric  let Predicates = [In64BitMode] in
9711db9f3b2SDimitry Andric    def 64mi32 : BinOpMIF_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
9720b57cec5SDimitry Andric
973647cbc5dSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
9741db9f3b2SDimitry Andric    def 8mi_ND    : BinOpMIF_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
9751db9f3b2SDimitry Andric    def 16mi8_ND  : BinOpMI8F_RF<mnemonic, Xi16, MemMRM>, PD;
9761db9f3b2SDimitry Andric    def 32mi8_ND  : BinOpMI8F_RF<mnemonic, Xi32, MemMRM>;
9771db9f3b2SDimitry Andric    def 64mi8_ND  : BinOpMI8F_RF<mnemonic, Xi64, MemMRM>;
9781db9f3b2SDimitry Andric    def 16mi_ND   : BinOpMIF_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
9791db9f3b2SDimitry Andric    def 32mi_ND   : BinOpMIF_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
9801db9f3b2SDimitry Andric    def 64mi32_ND : BinOpMIF_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
981647cbc5dSDimitry Andric  }
982647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
9831db9f3b2SDimitry Andric    def 8mi_EVEX    : BinOpMIF_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>, PL;
9841db9f3b2SDimitry Andric    def 16mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi16, MemMRM>, PL, PD;
9851db9f3b2SDimitry Andric    def 32mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi32, MemMRM>, PL;
9861db9f3b2SDimitry Andric    def 64mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi64, MemMRM>, PL;
9871db9f3b2SDimitry Andric    def 16mi_EVEX   : BinOpMIF_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, PL, PD;
9881db9f3b2SDimitry Andric    def 32mi_EVEX   : BinOpMIF_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, PL;
9891db9f3b2SDimitry Andric    def 64mi32_EVEX : BinOpMIF_MF<0x81, mnemonic, Xi64, opnode, MemMRM>, PL;
990647cbc5dSDimitry Andric  }
991647cbc5dSDimitry Andric
9920b57cec5SDimitry Andric  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
9930b57cec5SDimitry Andric  // not in 64-bit mode.
994cb14a3feSDimitry Andric  let Predicates = [Not64BitMode]  in {
9951db9f3b2SDimitry Andric    def 8ri8 : BinOpRI8F_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
9961db9f3b2SDimitry Andric    def 8mi8 : BinOpMI8F_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
9970b57cec5SDimitry Andric  }
9980b57cec5SDimitry Andric
999*0fca6ea1SDimitry Andric  def 8i8 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
1000*0fca6ea1SDimitry Andric  def 16i16 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1001*0fca6ea1SDimitry Andric  def 32i32 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1002*0fca6ea1SDimitry Andric  def 64i32 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
10030b57cec5SDimitry Andric}
10040b57cec5SDimitry Andric
10050b57cec5SDimitry Andric/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
10060b57cec5SDimitry Andric/// defined with "(set EFLAGS, (...".  It would be really nice to find a way
10070b57cec5SDimitry Andric/// to factor this with the other ArithBinOp_*.
10080b57cec5SDimitry Andric///
10090b57cec5SDimitry Andricmulticlass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
10100b57cec5SDimitry Andric                        string mnemonic, Format RegMRM, Format MemMRM,
1011cb14a3feSDimitry Andric                        SDNode opnode, bit CommutableRR,
1012cb14a3feSDimitry Andric                        bit ConvertibleToThreeAddress> {
10130b57cec5SDimitry Andric  let isCommutable = CommutableRR in {
10141db9f3b2SDimitry Andric    def 8rr  : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
10150b57cec5SDimitry Andric    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
10161db9f3b2SDimitry Andric      def 16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
10171db9f3b2SDimitry Andric      def 32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
10181db9f3b2SDimitry Andric      def 64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1019cb14a3feSDimitry Andric    } // isConvertibleToThreeAddress
10200b57cec5SDimitry Andric  } // isCommutable
10210b57cec5SDimitry Andric
10221db9f3b2SDimitry Andric  def 8rr_REV  : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>;
10231db9f3b2SDimitry Andric  def 16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
10241db9f3b2SDimitry Andric  def 32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
10251db9f3b2SDimitry Andric  def 64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>;
10260b57cec5SDimitry Andric
10271db9f3b2SDimitry Andric  def 8rm   : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
10281db9f3b2SDimitry Andric  def 16rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>, OpSize16;
10291db9f3b2SDimitry Andric  def 32rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>, OpSize32;
10301db9f3b2SDimitry Andric  def 64rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
10310b57cec5SDimitry Andric
10321db9f3b2SDimitry Andric  def 8ri   : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
10330b57cec5SDimitry Andric
1034cb14a3feSDimitry Andric  let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
10350b57cec5SDimitry Andric    // NOTE: These are order specific, we want the ri8 forms to be listed
10360b57cec5SDimitry Andric    // first so that they are slightly preferred to the ri forms.
10371db9f3b2SDimitry Andric    def 16ri8 : BinOpRI8_F<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
10381db9f3b2SDimitry Andric    def 32ri8 : BinOpRI8_F<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
10391db9f3b2SDimitry Andric    def 64ri8 : BinOpRI8_F<0x83, mnemonic, Xi64, RegMRM>;
10400b57cec5SDimitry Andric
10411db9f3b2SDimitry Andric    def 16ri  : BinOpRI_F<0x81, mnemonic, Xi16, opnode, RegMRM>, OpSize16;
10421db9f3b2SDimitry Andric    def 32ri  : BinOpRI_F<0x81, mnemonic, Xi32, opnode, RegMRM>, OpSize32;
10431db9f3b2SDimitry Andric    def 64ri32: BinOpRI_F<0x81, mnemonic, Xi64, opnode, RegMRM>;
10440b57cec5SDimitry Andric  }
10450b57cec5SDimitry Andric
10461db9f3b2SDimitry Andric  def 8mr    : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
10471db9f3b2SDimitry Andric  def 16mr   : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
10481db9f3b2SDimitry Andric  def 32mr   : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
10491db9f3b2SDimitry Andric  def 64mr   : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
10500b57cec5SDimitry Andric
10510b57cec5SDimitry Andric  // NOTE: These are order specific, we want the mi8 forms to be listed
10520b57cec5SDimitry Andric  // first so that they are slightly preferred to the mi forms.
10531db9f3b2SDimitry Andric  def 16mi8  : BinOpMI8_F<mnemonic, Xi16, MemMRM>, OpSize16;
10541db9f3b2SDimitry Andric  def 32mi8  : BinOpMI8_F<mnemonic, Xi32, MemMRM>, OpSize32;
10550b57cec5SDimitry Andric  let Predicates = [In64BitMode] in
10561db9f3b2SDimitry Andric  def 64mi8  : BinOpMI8_F<mnemonic, Xi64, MemMRM>;
10570b57cec5SDimitry Andric
10581db9f3b2SDimitry Andric  def 8mi    : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>;
10591db9f3b2SDimitry Andric  def 16mi   : BinOpMI_F<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
10601db9f3b2SDimitry Andric  def 32mi   : BinOpMI_F<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
10610b57cec5SDimitry Andric  let Predicates = [In64BitMode] in
10621db9f3b2SDimitry Andric    def 64mi32 : BinOpMI_F<0x81, mnemonic, Xi64, opnode, MemMRM>;
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
10650b57cec5SDimitry Andric  // not in 64-bit mode.
1066cb14a3feSDimitry Andric  let Predicates = [Not64BitMode] in {
10671db9f3b2SDimitry Andric    def 8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
10680b57cec5SDimitry Andric    let mayLoad = 1 in
10691db9f3b2SDimitry Andric      def 8mi8 : BinOpMI8_F<mnemonic, Xi8, MemMRM>;
10700b57cec5SDimitry Andric  }
10710b57cec5SDimitry Andric
1072*0fca6ea1SDimitry Andric  def 8i8 : BinOpAI_F<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
1073*0fca6ea1SDimitry Andric  def 16i16 : BinOpAI_F<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1074*0fca6ea1SDimitry Andric  def 32i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1075*0fca6ea1SDimitry Andric  def 64i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
10760b57cec5SDimitry Andric}
10770b57cec5SDimitry Andric
10780b57cec5SDimitry Andric
1079cb14a3feSDimitry Andricdefm AND : ArithBinOp_RF<0x21, 0x23, 0x25, "and", MRM4r, MRM4m,
10800b57cec5SDimitry Andric                         X86and_flag, and, 1, 0, 0>;
1081cb14a3feSDimitry Andricdefm OR  : ArithBinOp_RF<0x09, 0x0B, 0x0D, "or", MRM1r, MRM1m,
10820b57cec5SDimitry Andric                         X86or_flag, or, 1, 0, 0>;
1083cb14a3feSDimitry Andricdefm XOR : ArithBinOp_RF<0x31, 0x33, 0x35, "xor", MRM6r, MRM6m,
10840b57cec5SDimitry Andric                         X86xor_flag, xor, 1, 0, 0>;
1085cb14a3feSDimitry Andricdefm ADD : ArithBinOp_RF<0x01, 0x03, 0x05, "add", MRM0r, MRM0m,
10860b57cec5SDimitry Andric                         X86add_flag, add, 1, 1, 1>;
10870b57cec5SDimitry Andriclet isCompare = 1 in {
1088cb14a3feSDimitry Andric  defm SUB : ArithBinOp_RF<0x29, 0x2B, 0x2D, "sub", MRM5r, MRM5m,
10890b57cec5SDimitry Andric                           X86sub_flag, sub, 0, 1, 0>;
10900b57cec5SDimitry Andric}
10910b57cec5SDimitry Andric
1092e8d8bef9SDimitry Andric// Version of XOR8rr_NOREX that use GR8_NOREX. This is used by the handling of
1093e8d8bef9SDimitry Andric// __builtin_parity where the last step xors an h-register with an l-register.
1094e8d8bef9SDimitry Andriclet isCodeGenOnly = 1, hasSideEffects = 0, Constraints = "$src1 = $dst",
1095e8d8bef9SDimitry Andric    Defs = [EFLAGS], isCommutable = 1 in
1096e8d8bef9SDimitry Andric  def XOR8rr_NOREX : I<0x30, MRMDestReg, (outs GR8_NOREX:$dst),
1097e8d8bef9SDimitry Andric                       (ins GR8_NOREX:$src1, GR8_NOREX:$src2),
1098e8d8bef9SDimitry Andric                       "xor{b}\t{$src2, $dst|$dst, $src2}", []>,
1099e8d8bef9SDimitry Andric                       Sched<[WriteALU]>;
1100e8d8bef9SDimitry Andric
11010b57cec5SDimitry Andric// Arithmetic.
1102cb14a3feSDimitry Andricdefm ADC : ArithBinOp_RFF<0x11, 0x13, 0x15, "adc", MRM2r, MRM2m, X86adc_flag,
11030b57cec5SDimitry Andric                          1, 0>;
1104cb14a3feSDimitry Andricdefm SBB : ArithBinOp_RFF<0x19, 0x1B, 0x1D, "sbb", MRM3r, MRM3m, X86sbb_flag,
11050b57cec5SDimitry Andric                          0, 0>;
11060b57cec5SDimitry Andric
11070b57cec5SDimitry Andriclet isCompare = 1 in {
1108cb14a3feSDimitry Andric  defm CMP : ArithBinOp_F<0x39, 0x3B, 0x3D, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
11090b57cec5SDimitry Andric}
11100b57cec5SDimitry Andric
11110b57cec5SDimitry Andric// Patterns to recognize loads on the LHS of an ADC. We can't make X86adc_flag
11120b57cec5SDimitry Andric// commutable since it has EFLAGs as an input.
1113*0fca6ea1SDimitry Andriclet Predicates = [NoNDD] in {
11140b57cec5SDimitry Andric  def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
11150b57cec5SDimitry Andric            (ADC8rm GR8:$src1, addr:$src2)>;
11160b57cec5SDimitry Andric  def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
11170b57cec5SDimitry Andric            (ADC16rm GR16:$src1, addr:$src2)>;
11180b57cec5SDimitry Andric  def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
11190b57cec5SDimitry Andric            (ADC32rm GR32:$src1, addr:$src2)>;
11200b57cec5SDimitry Andric  def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
11210b57cec5SDimitry Andric            (ADC64rm GR64:$src1, addr:$src2)>;
1122*0fca6ea1SDimitry Andric}
1123*0fca6ea1SDimitry Andriclet Predicates = [HasNDD] in {
1124*0fca6ea1SDimitry Andric  def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1125*0fca6ea1SDimitry Andric            (ADC8rm_ND GR8:$src1, addr:$src2)>;
1126*0fca6ea1SDimitry Andric  def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1127*0fca6ea1SDimitry Andric            (ADC16rm_ND GR16:$src1, addr:$src2)>;
1128*0fca6ea1SDimitry Andric  def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1129*0fca6ea1SDimitry Andric            (ADC32rm_ND GR32:$src1, addr:$src2)>;
1130*0fca6ea1SDimitry Andric  def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1131*0fca6ea1SDimitry Andric            (ADC64rm_ND GR64:$src1, addr:$src2)>;
1132*0fca6ea1SDimitry Andric}
11330b57cec5SDimitry Andric
11340b57cec5SDimitry Andric// Patterns to recognize RMW ADC with loads in operand 1.
11350b57cec5SDimitry Andricdef : Pat<(store (X86adc_flag GR8:$src, (loadi8 addr:$dst), EFLAGS),
11360b57cec5SDimitry Andric                 addr:$dst),
11370b57cec5SDimitry Andric          (ADC8mr addr:$dst, GR8:$src)>;
11380b57cec5SDimitry Andricdef : Pat<(store (X86adc_flag GR16:$src, (loadi16 addr:$dst), EFLAGS),
11390b57cec5SDimitry Andric                 addr:$dst),
11400b57cec5SDimitry Andric          (ADC16mr addr:$dst, GR16:$src)>;
11410b57cec5SDimitry Andricdef : Pat<(store (X86adc_flag GR32:$src, (loadi32 addr:$dst), EFLAGS),
11420b57cec5SDimitry Andric                 addr:$dst),
11430b57cec5SDimitry Andric          (ADC32mr addr:$dst, GR32:$src)>;
11440b57cec5SDimitry Andricdef : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
11450b57cec5SDimitry Andric                 addr:$dst),
11460b57cec5SDimitry Andric          (ADC64mr addr:$dst, GR64:$src)>;
11470b57cec5SDimitry Andric
11485ffd83dbSDimitry Andric// Patterns for basic arithmetic ops with relocImm for the immediate field.
11495ffd83dbSDimitry Andricmulticlass ArithBinOp_RF_relocImm_Pats<SDNode OpNodeFlag, SDNode OpNode> {
1150297eecfbSDimitry Andric  let Predicates = [NoNDD] in {
11515ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
11525ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
11535ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
11545ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
11555ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
11565ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
11575ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
11585ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
11595ffd83dbSDimitry Andric
11605ffd83dbSDimitry Andric    def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst),
11615ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
11625ffd83dbSDimitry Andric    def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst),
11635ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
11645ffd83dbSDimitry Andric    def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst),
11655ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
11665ffd83dbSDimitry Andric    def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst),
11675ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
11685ffd83dbSDimitry Andric  }
1169297eecfbSDimitry Andric  let Predicates = [HasNDD] in {
1170297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1171297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
1172297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1173297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
1174297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1175297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
1176297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1177297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1178297eecfbSDimitry Andric
1179297eecfbSDimitry Andric    def : Pat<(OpNode (load addr:$dst), relocImm8_su:$src),
1180297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
1181297eecfbSDimitry Andric    def : Pat<(OpNode (load addr:$dst), relocImm16_su:$src),
1182297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
1183297eecfbSDimitry Andric    def : Pat<(OpNode (load addr:$dst), relocImm32_su:$src),
1184297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
1185297eecfbSDimitry Andric    def : Pat<(OpNode (load addr:$dst), i64relocImmSExt32_su:$src),
1186297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
1187297eecfbSDimitry Andric  }
1188297eecfbSDimitry Andric}
11895ffd83dbSDimitry Andric
11905ffd83dbSDimitry Andricmulticlass ArithBinOp_RFF_relocImm_Pats<SDNode OpNodeFlag> {
1191297eecfbSDimitry Andric  let Predicates = [NoNDD] in {
11925ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
11935ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
11945ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
11955ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
11965ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
11975ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
11985ffd83dbSDimitry Andric    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
11995ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
12005ffd83dbSDimitry Andric
12015ffd83dbSDimitry Andric    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst),
12025ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
12035ffd83dbSDimitry Andric    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst),
12045ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
12055ffd83dbSDimitry Andric    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst),
12065ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
12075ffd83dbSDimitry Andric    def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst),
12085ffd83dbSDimitry Andric              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
12095ffd83dbSDimitry Andric  }
1210297eecfbSDimitry Andric  let Predicates = [HasNDD] in {
1211297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1212297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
1213297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
1214297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
1215297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
1216297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
1217297eecfbSDimitry Andric    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
1218297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1219297eecfbSDimitry Andric
1220297eecfbSDimitry Andric    def : Pat<(OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS),
1221297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
1222297eecfbSDimitry Andric    def : Pat<(OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS),
1223297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
1224297eecfbSDimitry Andric    def : Pat<(OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS),
1225297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
1226297eecfbSDimitry Andric    def : Pat<(OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS),
1227297eecfbSDimitry Andric              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
1228297eecfbSDimitry Andric  }
1229297eecfbSDimitry Andric}
12305ffd83dbSDimitry Andric
12315ffd83dbSDimitry Andricmulticlass ArithBinOp_F_relocImm_Pats<SDNode OpNodeFlag> {
12325ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
12335ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
12345ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
12355ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
12365ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
12375ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
12385ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
12395ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
12405ffd83dbSDimitry Andric
12415ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag (loadi8 addr:$src1), relocImm8_su:$src2),
12425ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"8mi") addr:$src1, relocImm8_su:$src2)>;
12435ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag (loadi16 addr:$src1), relocImm16_su:$src2),
12445ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"16mi") addr:$src1, relocImm16_su:$src2)>;
12455ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag (loadi32 addr:$src1), relocImm32_su:$src2),
12465ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"32mi") addr:$src1, relocImm32_su:$src2)>;
12475ffd83dbSDimitry Andric  def : Pat<(OpNodeFlag (loadi64 addr:$src1), i64relocImmSExt32_su:$src2),
12485ffd83dbSDimitry Andric            (!cast<Instruction>(NAME#"64mi32") addr:$src1, i64relocImmSExt32_su:$src2)>;
12495ffd83dbSDimitry Andric}
12505ffd83dbSDimitry Andric
12515ffd83dbSDimitry Andricdefm AND : ArithBinOp_RF_relocImm_Pats<X86and_flag, and>;
12525ffd83dbSDimitry Andricdefm OR  : ArithBinOp_RF_relocImm_Pats<X86or_flag, or>;
12535ffd83dbSDimitry Andricdefm XOR : ArithBinOp_RF_relocImm_Pats<X86xor_flag, xor>;
12545ffd83dbSDimitry Andricdefm ADD : ArithBinOp_RF_relocImm_Pats<X86add_flag, add>;
12555ffd83dbSDimitry Andricdefm SUB : ArithBinOp_RF_relocImm_Pats<X86sub_flag, sub>;
12565ffd83dbSDimitry Andric
12575ffd83dbSDimitry Andricdefm ADC : ArithBinOp_RFF_relocImm_Pats<X86adc_flag>;
12585ffd83dbSDimitry Andricdefm SBB : ArithBinOp_RFF_relocImm_Pats<X86sbb_flag>;
12595ffd83dbSDimitry Andric
12605ffd83dbSDimitry Andricdefm CMP : ArithBinOp_F_relocImm_Pats<X86cmp>;
12615ffd83dbSDimitry Andric
12625ffd83dbSDimitry Andric// ADC is commutable, but we can't indicate that to tablegen. So manually
12635ffd83dbSDimitry Andric// reverse the operands.
12645ffd83dbSDimitry Andricdef : Pat<(X86adc_flag GR8:$src1, relocImm8_su:$src2, EFLAGS),
12655ffd83dbSDimitry Andric          (ADC8ri relocImm8_su:$src2, GR8:$src1)>;
12665ffd83dbSDimitry Andricdef : Pat<(X86adc_flag i16relocImmSExt8_su:$src2, GR16:$src1, EFLAGS),
12675ffd83dbSDimitry Andric          (ADC16ri8 GR16:$src1, i16relocImmSExt8_su:$src2)>;
12685ffd83dbSDimitry Andricdef : Pat<(X86adc_flag relocImm16_su:$src2, GR16:$src1, EFLAGS),
12695ffd83dbSDimitry Andric          (ADC16ri GR16:$src1, relocImm16_su:$src2)>;
12705ffd83dbSDimitry Andricdef : Pat<(X86adc_flag i32relocImmSExt8_su:$src2, GR32:$src1, EFLAGS),
12715ffd83dbSDimitry Andric          (ADC32ri8 GR32:$src1, i32relocImmSExt8_su:$src2)>;
12725ffd83dbSDimitry Andricdef : Pat<(X86adc_flag relocImm32_su:$src2, GR32:$src1, EFLAGS),
12735ffd83dbSDimitry Andric          (ADC32ri GR32:$src1, relocImm32_su:$src2)>;
12745ffd83dbSDimitry Andricdef : Pat<(X86adc_flag i64relocImmSExt8_su:$src2, GR64:$src1, EFLAGS),
12755ffd83dbSDimitry Andric          (ADC64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>;
12765ffd83dbSDimitry Andricdef : Pat<(X86adc_flag i64relocImmSExt32_su:$src2, GR64:$src1, EFLAGS),
12775ffd83dbSDimitry Andric          (ADC64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
12785ffd83dbSDimitry Andric
12795ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag relocImm8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12805ffd83dbSDimitry Andric          (ADC8mi addr:$dst, relocImm8_su:$src)>;
12815ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag i16relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12825ffd83dbSDimitry Andric          (ADC16mi8 addr:$dst, i16relocImmSExt8_su:$src)>;
12835ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag relocImm16_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12845ffd83dbSDimitry Andric          (ADC16mi addr:$dst, relocImm16_su:$src)>;
12855ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag i32relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12865ffd83dbSDimitry Andric          (ADC32mi8 addr:$dst, i32relocImmSExt8_su:$src)>;
12875ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag relocImm32_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12885ffd83dbSDimitry Andric          (ADC32mi addr:$dst, relocImm32_su:$src)>;
12895ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag i64relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12905ffd83dbSDimitry Andric          (ADC64mi8 addr:$dst, i64relocImmSExt8_su:$src)>;
12915ffd83dbSDimitry Andricdef : Pat<(store (X86adc_flag i64relocImmSExt32_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
12925ffd83dbSDimitry Andric          (ADC64mi32 addr:$dst, i64relocImmSExt32_su:$src)>;
12935ffd83dbSDimitry Andric
12940b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
12950b57cec5SDimitry Andric// Semantically, test instructions are similar like AND, except they don't
12960b57cec5SDimitry Andric// generate a result.  From an encoding perspective, they are very different:
12970b57cec5SDimitry Andric// they don't have all the usual imm8 and REV forms, and are encoded into a
12980b57cec5SDimitry Andric// different space.
12990b57cec5SDimitry Andriclet isCompare = 1 in {
13000b57cec5SDimitry Andric  let isCommutable = 1 in {
13010b57cec5SDimitry Andric  // Avoid selecting these and instead use a test+and. Post processing will
13020b57cec5SDimitry Andric  // combine them. This gives bunch of other patterns that start with
13030b57cec5SDimitry Andric  // and a chance to match.
13040b57cec5SDimitry Andric    def TEST8rr  : BinOpRR_F<0x84, "test", Xi8 , null_frag>;
1305cb14a3feSDimitry Andric    def TEST16rr : BinOpRR_F<0x85, "test", Xi16, null_frag>, OpSize16;
1306cb14a3feSDimitry Andric    def TEST32rr : BinOpRR_F<0x85, "test", Xi32, null_frag>, OpSize32;
1307cb14a3feSDimitry Andric    def TEST64rr : BinOpRR_F<0x85, "test", Xi64, null_frag>;
13080b57cec5SDimitry Andric  } // isCommutable
13090b57cec5SDimitry Andric
13100b57cec5SDimitry Andric  def TEST8mr    : BinOpMR_F<0x84, "test", Xi8 , null_frag>;
1311cb14a3feSDimitry Andric  def TEST16mr   : BinOpMR_F<0x85, "test", Xi16, null_frag>, OpSize16;
1312cb14a3feSDimitry Andric  def TEST32mr   : BinOpMR_F<0x85, "test", Xi32, null_frag>, OpSize32;
1313cb14a3feSDimitry Andric  def TEST64mr   : BinOpMR_F<0x85, "test", Xi64, null_frag>;
13140b57cec5SDimitry Andric
13150b57cec5SDimitry Andric  def TEST8ri    : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1316cb14a3feSDimitry Andric  def TEST16ri   : BinOpRI_F<0xF7, "test", Xi16, X86testpat, MRM0r>, OpSize16;
1317cb14a3feSDimitry Andric  def TEST32ri   : BinOpRI_F<0xF7, "test", Xi32, X86testpat, MRM0r>, OpSize32;
1318cb14a3feSDimitry Andric  def TEST64ri32 : BinOpRI_F<0xF7, "test", Xi64, X86testpat, MRM0r>;
13190b57cec5SDimitry Andric
13200b57cec5SDimitry Andric  def TEST8mi    : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>;
1321cb14a3feSDimitry Andric  def TEST16mi   : BinOpMI_F<0xF7, "test", Xi16, X86testpat, MRM0m>, OpSize16;
1322cb14a3feSDimitry Andric  def TEST32mi   : BinOpMI_F<0xF7, "test", Xi32, X86testpat, MRM0m>, OpSize32;
13230b57cec5SDimitry Andric
1324cb14a3feSDimitry Andric  let Predicates = [In64BitMode] in
1325cb14a3feSDimitry Andric    def TEST64mi32 : BinOpMI_F<0xF7, "test", Xi64, X86testpat, MRM0m>;
1326cb14a3feSDimitry Andric
1327cb14a3feSDimitry Andric  def TEST8i8 : BinOpAI_F<0xA8, "test", Xi8 , AL, "{$src, %al|al, $src}">;
1328cb14a3feSDimitry Andric  def TEST16i16 : BinOpAI_F<0xA9, "test", Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1329cb14a3feSDimitry Andric  def TEST32i32 : BinOpAI_F<0xA9, "test", Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1330cb14a3feSDimitry Andric  def TEST64i32 : BinOpAI_F<0xA9, "test", Xi64, RAX, "{$src, %rax|rax, $src}">;
13310b57cec5SDimitry Andric} // isCompare
13320b57cec5SDimitry Andric
13335ffd83dbSDimitry Andric// Patterns to match a relocImm into the immediate field.
13345ffd83dbSDimitry Andricdef : Pat<(X86testpat GR8:$src1, relocImm8_su:$src2),
13355ffd83dbSDimitry Andric          (TEST8ri GR8:$src1, relocImm8_su:$src2)>;
13365ffd83dbSDimitry Andricdef : Pat<(X86testpat GR16:$src1, relocImm16_su:$src2),
13375ffd83dbSDimitry Andric          (TEST16ri GR16:$src1, relocImm16_su:$src2)>;
13385ffd83dbSDimitry Andricdef : Pat<(X86testpat GR32:$src1, relocImm32_su:$src2),
13395ffd83dbSDimitry Andric          (TEST32ri GR32:$src1, relocImm32_su:$src2)>;
13405ffd83dbSDimitry Andricdef : Pat<(X86testpat GR64:$src1, i64relocImmSExt32_su:$src2),
13415ffd83dbSDimitry Andric          (TEST64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
13425ffd83dbSDimitry Andric
13435ffd83dbSDimitry Andricdef : Pat<(X86testpat (loadi8 addr:$src1), relocImm8_su:$src2),
13445ffd83dbSDimitry Andric          (TEST8mi addr:$src1, relocImm8_su:$src2)>;
13455ffd83dbSDimitry Andricdef : Pat<(X86testpat (loadi16 addr:$src1), relocImm16_su:$src2),
13465ffd83dbSDimitry Andric          (TEST16mi addr:$src1, relocImm16_su:$src2)>;
13475ffd83dbSDimitry Andricdef : Pat<(X86testpat (loadi32 addr:$src1), relocImm32_su:$src2),
13485ffd83dbSDimitry Andric          (TEST32mi addr:$src1, relocImm32_su:$src2)>;
13495ffd83dbSDimitry Andricdef : Pat<(X86testpat (loadi64 addr:$src1), i64relocImmSExt32_su:$src2),
13505ffd83dbSDimitry Andric          (TEST64mi32 addr:$src1, i64relocImmSExt32_su:$src2)>;
13515ffd83dbSDimitry Andric
13520b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
13530b57cec5SDimitry Andric// ANDN Instruction
13540b57cec5SDimitry Andric//
1355*0fca6ea1SDimitry Andricmulticlass AndN<X86TypeInfo t, SDPatternOperator node, string suffix = ""> {
1356647cbc5dSDimitry Andric  defvar andn_rr_p =
1357*0fca6ea1SDimitry Andric    [(set t.RegClass:$dst, EFLAGS, (node (not t.RegClass:$src1),
1358647cbc5dSDimitry Andric     t.RegClass:$src2))];
1359647cbc5dSDimitry Andric  defvar andn_rm_p =
1360*0fca6ea1SDimitry Andric    [(set t.RegClass:$dst, EFLAGS, (node (not t.RegClass:$src1),
1361647cbc5dSDimitry Andric     (t.LoadNode addr:$src2)))];
1362647cbc5dSDimitry Andric  def rr#suffix : ITy<0xF2, MRMSrcReg, t, (outs t.RegClass:$dst),
1363647cbc5dSDimitry Andric                      (ins t.RegClass:$src1, t.RegClass:$src2), "andn",
1364*0fca6ea1SDimitry Andric                      binop_ndd_args, andn_rr_p>, VVVV, Sched<[WriteALU]>, T8;
1365647cbc5dSDimitry Andric  def rm#suffix : ITy<0xF2, MRMSrcMem, t, (outs t.RegClass:$dst),
1366647cbc5dSDimitry Andric                       (ins t.RegClass:$src1, t.MemOperand:$src2), "andn",
1367647cbc5dSDimitry Andric                       binop_ndd_args, andn_rm_p>, VVVV,
1368*0fca6ea1SDimitry Andric                       Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, T8;
13690b57cec5SDimitry Andric}
13700b57cec5SDimitry Andric
13710b57cec5SDimitry Andric// Complexity is reduced to give and with immediate a chance to match first.
1372647cbc5dSDimitry Andriclet AddedComplexity = -6 in {
1373*0fca6ea1SDimitry Andricdefm ANDN32 : AndN<Xi32, X86and_flag>, VEX, Requires<[HasBMI, NoEGPR]>, DefEFLAGS;
1374*0fca6ea1SDimitry Andricdefm ANDN64 : AndN<Xi64, X86and_flag>, VEX, Requires<[HasBMI, NoEGPR]>, DefEFLAGS;
1375*0fca6ea1SDimitry Andricdefm ANDN32 : AndN<Xi32, X86and_flag, "_EVEX">, EVEX, Requires<[HasBMI, HasEGPR, In64BitMode]>, DefEFLAGS;
1376*0fca6ea1SDimitry Andricdefm ANDN64 : AndN<Xi64, X86and_flag, "_EVEX">, EVEX, Requires<[HasBMI, HasEGPR, In64BitMode]>, DefEFLAGS;
1377*0fca6ea1SDimitry Andricdefm ANDN32 : AndN<Xi32, null_frag, "_NF">, EVEX, EVEX_NF, Requires<[In64BitMode]>;
1378*0fca6ea1SDimitry Andricdefm ANDN64 : AndN<Xi64, null_frag, "_NF">, EVEX, EVEX_NF, Requires<[In64BitMode]>;
13790b57cec5SDimitry Andric}
13800b57cec5SDimitry Andric
13817a6dacacSDimitry Andricmulticlass Andn_Pats<string suffix> {
13820b57cec5SDimitry Andric  def : Pat<(and (not GR32:$src1), GR32:$src2),
13837a6dacacSDimitry Andric            (!cast<Instruction>(ANDN32rr#suffix) GR32:$src1, GR32:$src2)>;
13840b57cec5SDimitry Andric  def : Pat<(and (not GR64:$src1), GR64:$src2),
13857a6dacacSDimitry Andric            (!cast<Instruction>(ANDN64rr#suffix) GR64:$src1, GR64:$src2)>;
13860b57cec5SDimitry Andric  def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
13877a6dacacSDimitry Andric            (!cast<Instruction>(ANDN32rm#suffix) GR32:$src1, addr:$src2)>;
13880b57cec5SDimitry Andric  def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
13897a6dacacSDimitry Andric            (!cast<Instruction>(ANDN64rm#suffix) GR64:$src1, addr:$src2)>;
13900b57cec5SDimitry Andric}
13910b57cec5SDimitry Andric
13927a6dacacSDimitry Andriclet Predicates = [HasBMI, NoEGPR], AddedComplexity = -6 in
13937a6dacacSDimitry Andric  defm : Andn_Pats<"">;
13947a6dacacSDimitry Andric
13957a6dacacSDimitry Andriclet Predicates = [HasBMI, HasEGPR], AddedComplexity = -6 in
13967a6dacacSDimitry Andric  defm : Andn_Pats<"_EVEX">;
13977a6dacacSDimitry Andric
13980b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
13990b57cec5SDimitry Andric// MULX Instruction
14000b57cec5SDimitry Andric//
1401647cbc5dSDimitry Andricmulticlass MulX<X86TypeInfo t, X86FoldableSchedWrite sched> {
1402647cbc5dSDimitry Andric  defvar mulx_args = "{$src, $dst2, $dst1|$dst1, $dst2, $src}";
1403647cbc5dSDimitry Andric  defvar mulx_rm_sched =
1404647cbc5dSDimitry Andric    [WriteIMulHLd, sched.Folded,
1405349cc55cSDimitry Andric     // Memory operand.
1406349cc55cSDimitry Andric     ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
1407349cc55cSDimitry Andric     // Implicit read of EDX/RDX
1408647cbc5dSDimitry Andric     sched.ReadAfterFold];
14095ffd83dbSDimitry Andric
1410647cbc5dSDimitry Andric  def rr : ITy<0xF6, MRMSrcReg, t, (outs t.RegClass:$dst1, t.RegClass:$dst2),
1411647cbc5dSDimitry Andric               (ins t.RegClass:$src), "mulx", mulx_args, []>, T8, XD, VEX,
1412647cbc5dSDimitry Andric           VVVV, Sched<[WriteIMulH, sched]>;
1413647cbc5dSDimitry Andric  let mayLoad = 1 in
1414647cbc5dSDimitry Andric    def rm : ITy<0xF6, MRMSrcMem, t, (outs t.RegClass:$dst1, t.RegClass:$dst2),
1415647cbc5dSDimitry Andric                 (ins t.MemOperand:$src), "mulx", mulx_args, []>, T8, XD, VEX,
1416647cbc5dSDimitry Andric                 VVVV, Sched<mulx_rm_sched>;
1417647cbc5dSDimitry Andric
1418647cbc5dSDimitry Andric  let Predicates = [In64BitMode] in {
1419647cbc5dSDimitry Andric    def rr_EVEX : ITy<0xF6, MRMSrcReg, t,
1420647cbc5dSDimitry Andric                      (outs t.RegClass:$dst1, t.RegClass:$dst2),
1421647cbc5dSDimitry Andric                      (ins t.RegClass:$src), "mulx", mulx_args, []>, T8, XD,
1422647cbc5dSDimitry Andric                  EVEX, VVVV, Sched<[WriteIMulH, sched]>;
1423647cbc5dSDimitry Andric    let mayLoad = 1 in
1424647cbc5dSDimitry Andric      def rm_EVEX : ITy<0xF6, MRMSrcMem, t,
1425647cbc5dSDimitry Andric                        (outs t.RegClass:$dst1, t.RegClass:$dst2),
1426647cbc5dSDimitry Andric                        (ins t.MemOperand:$src), "mulx", mulx_args, []>, T8, XD,
1427647cbc5dSDimitry Andric                    EVEX, VVVV, Sched<mulx_rm_sched>;
1428647cbc5dSDimitry Andric  }
14295ffd83dbSDimitry Andric  // Pseudo instructions to be used when the low result isn't used. The
14305ffd83dbSDimitry Andric  // instruction is defined to keep the high if both destinations are the same.
1431647cbc5dSDimitry Andric  def Hrr : PseudoI<(outs t.RegClass:$dst), (ins t.RegClass:$src), []>,
1432647cbc5dSDimitry Andric            Sched<[sched]>;
14335ffd83dbSDimitry Andric  let mayLoad = 1 in
1434647cbc5dSDimitry Andric  def Hrm : PseudoI<(outs t.RegClass:$dst), (ins t.MemOperand:$src), []>,
1435647cbc5dSDimitry Andric            Sched<[sched.Folded]>;
14360b57cec5SDimitry Andric}
14370b57cec5SDimitry Andric
14380b57cec5SDimitry Andriclet Uses = [EDX] in
1439647cbc5dSDimitry Andric  defm MULX32 : MulX<Xi32, WriteMULX32>;
1440647cbc5dSDimitry Andric
14410b57cec5SDimitry Andriclet Uses = [RDX] in
1442647cbc5dSDimitry Andric  defm MULX64 : MulX<Xi64, WriteMULX64>, REX_W;
14430b57cec5SDimitry Andric
14440b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
14450b57cec5SDimitry Andric// ADCX and ADOX Instructions
14460b57cec5SDimitry Andric//
14470b57cec5SDimitry Andric// We don't have patterns for these as there is no advantage over ADC for
14480b57cec5SDimitry Andric// most code.
1449647cbc5dSDimitry Andriclet Form = MRMSrcReg in {
14501db9f3b2SDimitry Andric  def ADCX32rr : BinOpRRF_RF<0xF6, "adcx", Xi32>, T8, PD;
14511db9f3b2SDimitry Andric  def ADCX64rr : BinOpRRF_RF<0xF6, "adcx", Xi64>, T8, PD;
14521db9f3b2SDimitry Andric  def ADOX32rr : BinOpRRF_RF<0xF6, "adox", Xi32>, T8, XS;
14531db9f3b2SDimitry Andric  def ADOX64rr : BinOpRRF_RF<0xF6, "adox", Xi64>, T8, XS;
14541db9f3b2SDimitry Andric  let Predicates =[In64BitMode] in {
14551db9f3b2SDimitry Andric    def ADCX32rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
14561db9f3b2SDimitry Andric    def ADCX64rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
14571db9f3b2SDimitry Andric    def ADOX32rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
14581db9f3b2SDimitry Andric    def ADOX64rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
14591db9f3b2SDimitry Andric    def ADCX32rr_ND : BinOpRRF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
14601db9f3b2SDimitry Andric    def ADCX64rr_ND : BinOpRRF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
14611db9f3b2SDimitry Andric    def ADOX32rr_ND : BinOpRRF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
14621db9f3b2SDimitry Andric    def ADOX64rr_ND : BinOpRRF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
14631db9f3b2SDimitry Andric  }
146406c3fb27SDimitry Andric}
1465647cbc5dSDimitry Andriclet Form = MRMSrcMem in {
14661db9f3b2SDimitry Andric  def ADCX32rm : BinOpRMF_RF<0xF6, "adcx", Xi32>, T8, PD;
14671db9f3b2SDimitry Andric  def ADCX64rm : BinOpRMF_RF<0xF6, "adcx", Xi64>, T8, PD;
14681db9f3b2SDimitry Andric  def ADOX32rm : BinOpRMF_RF<0xF6, "adox", Xi32>, T8, XS;
14691db9f3b2SDimitry Andric  def ADOX64rm : BinOpRMF_RF<0xF6, "adox", Xi64>, T8, XS;
14701db9f3b2SDimitry Andric  let Predicates =[In64BitMode] in {
14711db9f3b2SDimitry Andric    def ADCX32rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
14721db9f3b2SDimitry Andric    def ADCX64rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
14731db9f3b2SDimitry Andric    def ADOX32rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
14741db9f3b2SDimitry Andric    def ADOX64rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
14751db9f3b2SDimitry Andric    def ADCX32rm_ND : BinOpRMF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
14761db9f3b2SDimitry Andric    def ADCX64rm_ND : BinOpRMF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
14771db9f3b2SDimitry Andric    def ADOX32rm_ND : BinOpRMF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
14781db9f3b2SDimitry Andric    def ADOX64rm_ND : BinOpRMF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
14791db9f3b2SDimitry Andric  }
14800b57cec5SDimitry Andric}
1481