xref: /llvm-project/llvm/lib/Target/X86/X86InstrArithmetic.td (revision 501a58344179242f702f55e0ee5c039290426c54)
1//===-- X86InstrArithmetic.td - Integer Arithmetic Instrs --*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the integer arithmetic instructions in the X86
10// architecture.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// LEA - Load Effective Address
16let SchedRW = [WriteLEA] in {
17  let hasSideEffects = 0 in
18    def LEA16r   : I<0x8D, MRMSrcMem,
19                     (outs GR16:$dst), (ins anymem:$src),
20                     "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize16;
21  let isReMaterializable = 1 in
22    def LEA32r   : I<0x8D, MRMSrcMem,
23                     (outs GR32:$dst), (ins anymem:$src),
24                     "lea{l}\t{$src|$dst}, {$dst|$src}",
25                     [(set GR32:$dst, lea32addr:$src)]>,
26                     OpSize32, Requires<[Not64BitMode]>;
27
28  def LEA64_32r : I<0x8D, MRMSrcMem,
29                    (outs GR32:$dst), (ins lea64_32mem:$src),
30                    "lea{l}\t{$src|$dst}, {$dst|$src}",
31                    [(set GR32:$dst, lea64_32addr:$src)]>,
32                    OpSize32, Requires<[In64BitMode]>;
33
34  let isReMaterializable = 1 in
35    def LEA64r   : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src),
36                      "lea{q}\t{$src|$dst}, {$dst|$src}",
37                      [(set GR64:$dst, lea64addr:$src)]>;
38} // SchedRW
39
40// Pseudo instruction for lea that prevent optimizer from eliminating
41// the instruction.
42let SchedRW = [WriteLEA], isPseudo = true, hasSideEffects = 1 in {
43  def PLEA32r   : PseudoI<(outs GR32:$dst), (ins anymem:$src), []>;
44  def PLEA64r   : PseudoI<(outs GR64:$dst), (ins anymem:$src), []>;
45}
46
47//===----------------------------------------------------------------------===//
48// MUL/IMUL and DIV/IDIV Instructions
49//
50class MulDivOpR<bits<8> o, Format f, string m, X86TypeInfo t,
51             X86FoldableSchedWrite sched, list<dag> p>
52  : UnaryOpR<o, f, m, "$src1", t, (outs), p> {
53  let SchedRW = [sched];
54}
55
56class MulDivOpM<bits<8> o, Format f, string m, X86TypeInfo t,
57             X86FoldableSchedWrite sched, list<dag> p>
58  : UnaryOpM<o, f, m, "$src1", t, (outs), p> {
59  let SchedRW =
60    [sched.Folded,
61     // Memory operand.
62     ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
63     // Register reads (implicit or explicit).
64     sched.ReadAfterFold, sched.ReadAfterFold];
65}
66
67multiclass Mul<bits<8> o, string m, Format RegMRM, Format MemMRM, SDPatternOperator node> {
68  // AL is really implied by AX, but the registers in Defs must match the
69  // SDNode results (i8, i32).
70  //
71  // FIXME: Used for 8-bit mul, ignore result upper 8 bits.
72  // This probably ought to be moved to a def : Pat<> if the
73  // syntax can be accepted.
74  let Defs = [AL, EFLAGS, AX], Uses = [AL] in
75    def 8r : MulDivOpR<o, RegMRM, m, Xi8, WriteIMul8,
76                       [(set AL, EFLAGS, (node AL, GR8:$src1))]>;
77  let Defs = [AX, DX, EFLAGS], Uses = [AX] in
78    def 16r : MulDivOpR<o, RegMRM, m, Xi16, WriteIMul16, []>, OpSize16;
79  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
80    def 32r : MulDivOpR<o, RegMRM, m, Xi32, WriteIMul32, []>, OpSize32;
81  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
82    def 64r : MulDivOpR<o, RegMRM, m, Xi64, WriteIMul64, []>;
83  let Defs = [AL, EFLAGS, AX], Uses = [AL] in
84    def 8m : MulDivOpM<o, MemMRM, m, Xi8, WriteIMul8,
85                       [(set AL, EFLAGS, (node AL, (loadi8 addr:$src1)))]>;
86  let Defs = [AX, DX, EFLAGS], Uses = [AX] in
87    def 16m : MulDivOpM<o, MemMRM, m, Xi16, WriteIMul16, []>, OpSize16;
88  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
89    def 32m : MulDivOpM<o, MemMRM, m, Xi32, WriteIMul32, []>, OpSize32;
90  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
91    def 64m : MulDivOpM<o, MemMRM, m, Xi64, WriteIMul64, []>, Requires<[In64BitMode]>;
92
93  let Predicates = [In64BitMode] in {
94    let Defs = [AL, AX], Uses = [AL] in
95      def 8r_NF : MulDivOpR<o, RegMRM, m, Xi8, WriteIMul8, []>, NF;
96    let Defs = [AX, DX], Uses = [AX] in
97      def 16r_NF : MulDivOpR<o, RegMRM, m, Xi16, WriteIMul16, []>, NF, PD;
98    let Defs = [EAX, EDX], Uses = [EAX] in
99      def 32r_NF : MulDivOpR<o, RegMRM, m, Xi32, WriteIMul32, []>, NF;
100    let Defs = [RAX, RDX], Uses = [RAX] in
101      def 64r_NF : MulDivOpR<o, RegMRM, m, Xi64, WriteIMul64, []>, NF;
102    let Defs = [AL, AX], Uses = [AL] in
103      def 8m_NF : MulDivOpM<o, MemMRM, m, Xi8, WriteIMul8, []>, NF;
104    let Defs = [AX, DX], Uses = [AX] in
105      def 16m_NF : MulDivOpM<o, MemMRM, m, Xi16, WriteIMul16, []>, NF, PD;
106    let Defs = [EAX, EDX], Uses = [EAX] in
107      def 32m_NF : MulDivOpM<o, MemMRM, m, Xi32, WriteIMul32, []>, NF;
108    let Defs = [RAX, RDX], Uses = [RAX] in
109      def 64m_NF : MulDivOpM<o, MemMRM, m, Xi64, WriteIMul64, []>, NF;
110
111    let Defs = [AL, EFLAGS, AX], Uses = [AL] in
112      def 8r_EVEX : MulDivOpR<o, RegMRM, m, Xi8, WriteIMul8, []>, PL;
113    let Defs = [AX, DX, EFLAGS], Uses = [AX] in
114      def 16r_EVEX : MulDivOpR<o, RegMRM, m, Xi16, WriteIMul16, []>, PL, PD;
115    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
116      def 32r_EVEX : MulDivOpR<o, RegMRM, m, Xi32, WriteIMul32, []>, PL;
117    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
118      def 64r_EVEX : MulDivOpR<o, RegMRM, m, Xi64, WriteIMul64, []>, PL;
119    let Defs = [AL, EFLAGS, AX], Uses = [AL] in
120      def 8m_EVEX : MulDivOpM<o, MemMRM, m, Xi8, WriteIMul8, []>, PL;
121    let Defs = [AX, DX, EFLAGS], Uses = [AX] in
122      def 16m_EVEX : MulDivOpM<o, MemMRM, m, Xi16, WriteIMul16, []>, PL, PD;
123    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX] in
124      def 32m_EVEX : MulDivOpM<o, MemMRM, m, Xi32, WriteIMul32, []>, PL;
125    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX] in
126      def 64m_EVEX : MulDivOpM<o, MemMRM, m, Xi64, WriteIMul64, []>, PL;
127  }
128}
129
130defm MUL : Mul<0xF7, "mul", MRM4r, MRM4m, mul>;
131defm IMUL : Mul<0xF7, "imul", MRM5r, MRM5m, null_frag>;
132
133multiclass Div<bits<8> o, string m, Format RegMRM, Format MemMRM> {
134  defvar sched8 = !if(!eq(m, "div"), WriteDiv8, WriteIDiv8);
135  defvar sched16 = !if(!eq(m, "div"), WriteDiv16, WriteIDiv16);
136  defvar sched32 = !if(!eq(m, "div"), WriteDiv32, WriteIDiv32);
137  defvar sched64 = !if(!eq(m, "div"), WriteDiv64, WriteIDiv64);
138  let Defs = [AL, AH, EFLAGS], Uses = [AX] in
139    def 8r  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>;
140  let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
141    def 16r : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, OpSize16;
142  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
143    def 32r : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, OpSize32;
144  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
145    def 64r : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>;
146  let Defs = [AL, AH, EFLAGS], Uses = [AX] in
147    def 8m  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>;
148  let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
149    def 16m : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, OpSize16;
150  let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
151    def 32m : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, OpSize32;
152  let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
153    def 64m : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, Requires<[In64BitMode]>;
154
155  let Predicates = [In64BitMode] in {
156    let Defs = [AL, AH], Uses = [AX] in
157      def 8r_NF  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>, NF;
158    let Defs = [AX, DX], Uses = [AX, DX] in
159      def 16r_NF : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, NF, PD;
160    let Defs = [EAX, EDX], Uses = [EAX, EDX] in
161      def 32r_NF : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, NF;
162    let Defs = [RAX, RDX], Uses = [RAX, RDX] in
163      def 64r_NF : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>, NF;
164    let Defs = [AL, AH], Uses = [AX] in
165      def 8m_NF  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>, NF;
166    let Defs = [AX, DX], Uses = [AX, DX] in
167      def 16m_NF : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, NF, PD;
168    let Defs = [EAX, EDX], Uses = [EAX, EDX] in
169      def 32m_NF : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, NF;
170    let Defs = [RAX, RDX], Uses = [RAX, RDX] in
171      def 64m_NF : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, NF;
172
173    let Defs = [AL, AH, EFLAGS], Uses = [AX] in
174      def 8r_EVEX  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>, PL;
175    let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
176      def 16r_EVEX : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, PL, PD;
177    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
178      def 32r_EVEX : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, PL;
179    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
180      def 64r_EVEX : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>, PL;
181    let Defs = [AL, AH, EFLAGS], Uses = [AX] in
182      def 8m_EVEX  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>, PL;
183    let Defs = [AX, DX, EFLAGS], Uses = [AX, DX] in
184      def 16m_EVEX : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, PL, PD;
185    let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EDX] in
186      def 32m_EVEX : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, PL;
187    let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RDX] in
188      def 64m_EVEX : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, PL;
189  }
190}
191
192let hasSideEffects = 1 in { // so that we don't speculatively execute
193  defm DIV: Div<0xF7, "div", MRM6r, MRM6m>;
194  defm IDIV: Div<0xF7, "idiv", MRM7r, MRM7m>;
195}
196
197class IMulOpRR_R<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
198  : BinOpRR_R<0xAF, "imul", t, ndd> {
199  let Form = MRMSrcReg;
200  let SchedRW = [sched];
201  // X = IMUL Y, Z --> X = IMUL Z, Y
202  let isCommutable = 1;
203}
204class IMulOpRR_RF<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
205  : BinOpRR_RF<0xAF, "imul", t, X86smul_flag, ndd> {
206  let Form = MRMSrcReg;
207  let SchedRW = [sched];
208  // X = IMUL Y, Z --> X = IMUL Z, Y
209  let isCommutable = 1;
210}
211class IMulOpRM_R<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
212  : BinOpRM_R<0xAF, "imul", t, ndd> {
213  let Form = MRMSrcMem;
214  let SchedRW = [sched.Folded, sched.ReadAfterFold];
215}
216class IMulOpRM_RF<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
217  : BinOpRM_RF<0xAF, "imul", t, X86smul_flag, ndd> {
218  let Form = MRMSrcMem;
219  let SchedRW = [sched.Folded, sched.ReadAfterFold];
220}
221
222let Predicates = [NoNDD] in {
223  def IMUL16rr : IMulOpRR_RF<Xi16, WriteIMul16Reg>, TB, OpSize16;
224  def IMUL32rr : IMulOpRR_RF<Xi32, WriteIMul32Reg>, TB, OpSize32;
225  def IMUL64rr : IMulOpRR_RF<Xi64, WriteIMul64Reg>, TB;
226  def IMUL16rm : IMulOpRM_RF<Xi16, WriteIMul16Reg>, TB, OpSize16;
227  def IMUL32rm : IMulOpRM_RF<Xi32, WriteIMul32Reg>, TB, OpSize32;
228  def IMUL64rm : IMulOpRM_RF<Xi64, WriteIMul64Reg>, TB;
229}
230let Predicates = [HasNDD, In64BitMode] in {
231  def IMUL16rr_ND : IMulOpRR_RF<Xi16, WriteIMul16Reg, 1>, PD;
232  def IMUL32rr_ND : IMulOpRR_RF<Xi32, WriteIMul32Reg, 1>;
233  def IMUL64rr_ND : IMulOpRR_RF<Xi64, WriteIMul64Reg, 1>;
234  def IMUL16rm_ND : IMulOpRM_RF<Xi16, WriteIMul16Reg, 1>, PD;
235  def IMUL32rm_ND : IMulOpRM_RF<Xi32, WriteIMul32Reg, 1>;
236  def IMUL64rm_ND : IMulOpRM_RF<Xi64, WriteIMul64Reg, 1>;
237}
238
239let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
240  def IMUL16rr_NF : IMulOpRR_R<Xi16, WriteIMul16Reg>, NF, PD;
241  def IMUL32rr_NF : IMulOpRR_R<Xi32, WriteIMul32Reg>, NF;
242  def IMUL64rr_NF : IMulOpRR_R<Xi64, WriteIMul64Reg>, NF;
243  def IMUL16rm_NF : IMulOpRM_R<Xi16, WriteIMul16Reg>, NF, PD;
244  def IMUL32rm_NF : IMulOpRM_R<Xi32, WriteIMul32Reg>, NF;
245  def IMUL64rm_NF : IMulOpRM_R<Xi64, WriteIMul64Reg>, NF;
246
247  def IMUL16rr_NF_ND : IMulOpRR_R<Xi16, WriteIMul16Reg, 1>, EVEX_NF, PD;
248  def IMUL32rr_NF_ND : IMulOpRR_R<Xi32, WriteIMul32Reg, 1>, EVEX_NF;
249  def IMUL64rr_NF_ND : IMulOpRR_R<Xi64, WriteIMul64Reg, 1>, EVEX_NF;
250  def IMUL16rm_NF_ND : IMulOpRM_R<Xi16, WriteIMul16Reg, 1>, EVEX_NF, PD;
251  def IMUL32rm_NF_ND : IMulOpRM_R<Xi32, WriteIMul32Reg, 1>, EVEX_NF;
252  def IMUL64rm_NF_ND : IMulOpRM_R<Xi64, WriteIMul64Reg, 1>, EVEX_NF;
253
254  def IMUL16rr_EVEX : IMulOpRR_RF<Xi16, WriteIMul16Reg>, PL, PD;
255  def IMUL32rr_EVEX : IMulOpRR_RF<Xi32, WriteIMul32Reg>, PL;
256  def IMUL64rr_EVEX : IMulOpRR_RF<Xi64, WriteIMul64Reg>, PL;
257  def IMUL16rm_EVEX : IMulOpRM_RF<Xi16, WriteIMul16Reg>, PL, PD;
258  def IMUL32rm_EVEX : IMulOpRM_RF<Xi32, WriteIMul32Reg>, PL;
259  def IMUL64rm_EVEX : IMulOpRM_RF<Xi64, WriteIMul64Reg>, PL;
260}
261
262class IMulOpRI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
263  : BinOpRI8<0x6B, "imul", binop_ndd_args, t, MRMSrcReg,
264             (outs t.RegClass:$dst)> {
265  let SchedRW = [sched];
266}
267class IMulOpRI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
268  : BinOpRI<0x69, "imul", binop_ndd_args, t, MRMSrcReg,
269            (outs t.RegClass:$dst), []> {
270  let SchedRW = [sched];
271}
272class IMulOpRI_RF<X86TypeInfo t, X86FoldableSchedWrite sched>
273  : BinOpRI<0x69, "imul", binop_ndd_args, t, MRMSrcReg,
274            (outs t.RegClass:$dst),
275            [(set t.RegClass:$dst, EFLAGS, (X86smul_flag t.RegClass:$src1,
276             t.ImmNoSuOperator:$src2))]>, DefEFLAGS {
277  let SchedRW = [sched];
278}
279class IMulOpMI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
280  : BinOpMI8<"imul", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)> {
281  let Opcode = 0x6B;
282  let SchedRW = [sched.Folded];
283}
284class IMulOpMI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
285  : BinOpMI<0x69, "imul", binop_ndd_args, t, MRMSrcMem,
286            (outs t.RegClass:$dst), []> {
287  let SchedRW = [sched.Folded];
288}
289class IMulOpMI_RF<X86TypeInfo t, X86FoldableSchedWrite sched>
290  : BinOpMI<0x69, "imul", binop_ndd_args, t, MRMSrcMem,
291            (outs t.RegClass:$dst),
292            [(set t.RegClass:$dst, EFLAGS, (X86smul_flag (t.LoadNode addr:$src1),
293             t.ImmNoSuOperator:$src2))]>,
294    DefEFLAGS {
295  let SchedRW = [sched.Folded];
296}
297def IMUL16rri8 : IMulOpRI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, OpSize16;
298def IMUL32rri8 : IMulOpRI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, OpSize32;
299def IMUL64rri8 : IMulOpRI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS;
300def IMUL16rri  : IMulOpRI_RF<Xi16, WriteIMul16Imm>, OpSize16;
301def IMUL32rri  : IMulOpRI_RF<Xi32, WriteIMul32Imm>, OpSize32;
302def IMUL64rri32 : IMulOpRI_RF<Xi64, WriteIMul64Imm>;
303def IMUL16rmi8 : IMulOpMI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, OpSize16;
304def IMUL32rmi8 : IMulOpMI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, OpSize32;
305def IMUL64rmi8 : IMulOpMI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS;
306def IMUL16rmi  : IMulOpMI_RF<Xi16, WriteIMul16Imm>, OpSize16;
307def IMUL32rmi  : IMulOpMI_RF<Xi32, WriteIMul32Imm>, OpSize32;
308def IMUL64rmi32 : IMulOpMI_RF<Xi64, WriteIMul64Imm>;
309
310let Predicates = [In64BitMode] in {
311  def IMUL16rri8_NF : IMulOpRI8_R<Xi16, WriteIMul16Imm>, NF, PD;
312  def IMUL32rri8_NF : IMulOpRI8_R<Xi32, WriteIMul32Imm>, NF;
313  def IMUL64rri8_NF : IMulOpRI8_R<Xi64, WriteIMul64Imm>, NF;
314  def IMUL16rri_NF  : IMulOpRI_R<Xi16, WriteIMul16Imm>, NF, PD;
315  def IMUL32rri_NF  : IMulOpRI_R<Xi32, WriteIMul32Imm>, NF;
316  def IMUL64rri32_NF : IMulOpRI_R<Xi64, WriteIMul64Imm>, NF;
317  def IMUL16rmi8_NF : IMulOpMI8_R<Xi16, WriteIMul16Imm>, NF, PD;
318  def IMUL32rmi8_NF : IMulOpMI8_R<Xi32, WriteIMul32Imm>, NF;
319  def IMUL64rmi8_NF : IMulOpMI8_R<Xi64, WriteIMul64Imm>, NF;
320  def IMUL16rmi_NF  : IMulOpMI_R<Xi16, WriteIMul16Imm>, NF, PD;
321  def IMUL32rmi_NF  : IMulOpMI_R<Xi32, WriteIMul32Imm>, NF;
322  def IMUL64rmi32_NF : IMulOpMI_R<Xi64, WriteIMul64Imm>, NF;
323
324  def IMUL16rri8_EVEX : IMulOpRI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, PL, PD;
325  def IMUL32rri8_EVEX : IMulOpRI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, PL;
326  def IMUL64rri8_EVEX : IMulOpRI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS, PL;
327  def IMUL16rri_EVEX  : IMulOpRI_RF<Xi16, WriteIMul16Imm>, PL, PD;
328  def IMUL32rri_EVEX  : IMulOpRI_RF<Xi32, WriteIMul32Imm>, PL;
329  def IMUL64rri32_EVEX : IMulOpRI_RF<Xi64, WriteIMul64Imm>, PL;
330  def IMUL16rmi8_EVEX : IMulOpMI8_R<Xi16, WriteIMul16Imm>, DefEFLAGS, PL, PD;
331  def IMUL32rmi8_EVEX : IMulOpMI8_R<Xi32, WriteIMul32Imm>, DefEFLAGS, PL;
332  def IMUL64rmi8_EVEX : IMulOpMI8_R<Xi64, WriteIMul64Imm>, DefEFLAGS, PL;
333  def IMUL16rmi_EVEX  : IMulOpMI_RF<Xi16, WriteIMul16Imm>, PL, PD;
334  def IMUL32rmi_EVEX  : IMulOpMI_RF<Xi32, WriteIMul32Imm>, PL;
335  def IMUL64rmi32_EVEX : IMulOpMI_RF<Xi64, WriteIMul64Imm>, PL;
336}
337
338// IMULZU instructions
339class IMulZUOpRI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
340  : BinOpRI8<0x6B, "imulzu", binop_ndd_args, t, MRMSrcReg,
341             (outs t.RegClass:$dst)> {
342  let SchedRW = [sched];
343}
344class IMulZUOpRI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
345  : BinOpRI<0x69, "imulzu", binop_ndd_args, t, MRMSrcReg,
346            (outs t.RegClass:$dst), []> {
347  let SchedRW = [sched];
348}
349class IMulZUOpMI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
350  : BinOpMI8<"imulzu", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)> {
351  let Opcode = 0x6B;
352  let SchedRW = [sched.Folded];
353}
354class IMulZUOpMI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
355  : BinOpMI<0x69, "imulzu", binop_ndd_args, t, MRMSrcMem,
356            (outs t.RegClass:$dst), []> {
357  let SchedRW = [sched.Folded];
358}
359
360let Defs = [EFLAGS], Predicates = [HasEGPR, In64BitMode] in {
361  def IMULZU16rri8 : IMulZUOpRI8_R<Xi16, WriteIMul16Imm>, ZU, PD;
362  def IMULZU16rmi8 : IMulZUOpMI8_R<Xi16, WriteIMul16Imm>, ZU, PD;
363  def IMULZU16rri : IMulZUOpRI_R<Xi16, WriteIMul16Imm>, ZU, PD;
364  def IMULZU16rmi : IMulZUOpMI_R<Xi16, WriteIMul16Imm>, ZU, PD;
365  def IMULZU32rri8 : IMulZUOpRI8_R<Xi32, WriteIMul32Imm>, ZU;
366  def IMULZU32rmi8 : IMulZUOpMI8_R<Xi32, WriteIMul32Imm>, ZU;
367  def IMULZU32rri : IMulZUOpRI_R<Xi32, WriteIMul32Imm>, ZU;
368  def IMULZU32rmi : IMulZUOpMI_R<Xi32, WriteIMul32Imm>, ZU;
369  def IMULZU64rri8 : IMulZUOpRI8_R<Xi64, WriteIMul64Imm>, ZU;
370  def IMULZU64rmi8 : IMulZUOpMI8_R<Xi64, WriteIMul64Imm>, ZU;
371  def IMULZU64rri32 : IMulZUOpRI_R<Xi64, WriteIMul64Imm>, ZU;
372  def IMULZU64rmi32 : IMulZUOpMI_R<Xi64, WriteIMul64Imm>, ZU;
373}
374
375//===----------------------------------------------------------------------===//
376// INC and DEC Instructions
377//
378class IncOpR_RF<X86TypeInfo t, bit ndd = 0> : UnaryOpR_RF<0xFF, MRM0r, "inc", t, null_frag, ndd> {
379  let Pattern = [(set t.RegClass:$dst, EFLAGS,
380                 (X86add_flag_nocf t.RegClass:$src1, 1))];
381}
382class DecOpR_RF<X86TypeInfo t, bit ndd = 0> : UnaryOpR_RF<0xFF, MRM1r, "dec", t, null_frag, ndd> {
383  let Pattern = [(set t.RegClass:$dst, EFLAGS,
384                 (X86sub_flag_nocf t.RegClass:$src1, 1))];
385}
386class IncOpR_R<X86TypeInfo t, bit ndd = 0> : UnaryOpR_R<0xFF, MRM0r, "inc", t, null_frag, ndd>;
387class DecOpR_R<X86TypeInfo t, bit ndd = 0> : UnaryOpR_R<0xFF, MRM1r, "dec", t, null_frag, ndd>;
388class IncOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM0m, "inc", t, null_frag> {
389  let Pattern = [(store (add (t.LoadNode addr:$src1), 1), addr:$src1)];
390}
391class DecOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM1m, "dec", t, null_frag> {
392  let Pattern = [(store (add (t.LoadNode addr:$src1), -1), addr:$src1)];
393}
394class IncOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM0m, "inc", t, null_frag> {
395  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), 1))];
396}
397class DecOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM1m, "dec", t, null_frag> {
398  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), -1))];
399}
400class IncOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM0m, "inc", t, null_frag>;
401class DecOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM1m, "dec", t, null_frag>;
402class IncOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM0m, "inc", t, null_frag>;
403class DecOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM1m, "dec", t, null_frag>;
404
405// IncDec_Alt - Instructions like "inc reg" short forms.
406// Short forms only valid in 32-bit mode. Selected during MCInst lowering.
407class IncDec_Alt<bits<8> o, string m, X86TypeInfo t>
408  : UnaryOpR_RF<o, AddRegFrm, m, t, null_frag>, Requires<[Not64BitMode]>;
409
410let isConvertibleToThreeAddress = 1 in {
411  def INC16r_alt : IncDec_Alt<0x40, "inc", Xi16>, OpSize16;
412  def INC32r_alt : IncDec_Alt<0x40, "inc", Xi32>, OpSize32;
413  def DEC16r_alt : IncDec_Alt<0x48, "dec", Xi16>, OpSize16;
414  def DEC32r_alt : IncDec_Alt<0x48, "dec", Xi32>, OpSize32;
415  let Predicates = [NoNDD] in {
416    def INC8r  : IncOpR_RF<Xi8>;
417    def INC16r : IncOpR_RF<Xi16>, OpSize16;
418    def INC32r : IncOpR_RF<Xi32>, OpSize32;
419    def INC64r : IncOpR_RF<Xi64>;
420    def DEC8r  : DecOpR_RF<Xi8>;
421    def DEC16r : DecOpR_RF<Xi16>, OpSize16;
422    def DEC32r : DecOpR_RF<Xi32>, OpSize32;
423    def DEC64r : DecOpR_RF<Xi64>;
424  }
425  let Predicates = [HasNDD, In64BitMode] in {
426    def INC8r_ND  : IncOpR_RF<Xi8, 1>;
427    def INC16r_ND : IncOpR_RF<Xi16, 1>, PD;
428    def INC32r_ND : IncOpR_RF<Xi32, 1>;
429    def INC64r_ND : IncOpR_RF<Xi64, 1>;
430    def DEC8r_ND  : DecOpR_RF<Xi8, 1>;
431    def DEC16r_ND : DecOpR_RF<Xi16, 1>, PD;
432    def DEC32r_ND : DecOpR_RF<Xi32, 1>;
433    def DEC64r_ND : DecOpR_RF<Xi64, 1>;
434  }
435  let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
436    def INC8r_NF  : IncOpR_R<Xi8>, NF;
437    def INC16r_NF : IncOpR_R<Xi16>, NF, PD;
438    def INC32r_NF : IncOpR_R<Xi32>, NF;
439    def INC64r_NF : IncOpR_R<Xi64>, NF;
440    def DEC8r_NF  : DecOpR_R<Xi8>, NF;
441    def DEC16r_NF : DecOpR_R<Xi16>, NF, PD;
442    def DEC32r_NF : DecOpR_R<Xi32>, NF;
443    def DEC64r_NF : DecOpR_R<Xi64>, NF;
444    def INC8r_NF_ND  : IncOpR_R<Xi8, 1>, NF;
445    def INC16r_NF_ND : IncOpR_R<Xi16, 1>, NF, PD;
446    def INC32r_NF_ND : IncOpR_R<Xi32, 1>, NF;
447    def INC64r_NF_ND : IncOpR_R<Xi64, 1>, NF;
448    def DEC8r_NF_ND  : DecOpR_R<Xi8, 1>, NF;
449    def DEC16r_NF_ND : DecOpR_R<Xi16, 1>, NF, PD;
450    def DEC32r_NF_ND : DecOpR_R<Xi32, 1>, NF;
451    def DEC64r_NF_ND : DecOpR_R<Xi64, 1>, NF;
452    def INC8r_EVEX  : IncOpR_RF<Xi8>, PL;
453    def INC16r_EVEX : IncOpR_RF<Xi16>, PL, PD;
454    def INC32r_EVEX : IncOpR_RF<Xi32>, PL;
455    def INC64r_EVEX : IncOpR_RF<Xi64>, PL;
456    def DEC8r_EVEX  : DecOpR_RF<Xi8>, PL;
457    def DEC16r_EVEX : DecOpR_RF<Xi16>, PL, PD;
458    def DEC32r_EVEX : DecOpR_RF<Xi32>, PL;
459    def DEC64r_EVEX : DecOpR_RF<Xi64>, PL;
460  }
461}
462let Predicates = [UseIncDec] in {
463  def INC8m  : IncOpM_MF<Xi8>;
464  def INC16m : IncOpM_MF<Xi16>, OpSize16;
465  def INC32m : IncOpM_MF<Xi32>, OpSize32;
466  def DEC8m  : DecOpM_MF<Xi8>;
467  def DEC16m : DecOpM_MF<Xi16>, OpSize16;
468  def DEC32m : DecOpM_MF<Xi32>, OpSize32;
469}
470let Predicates = [UseIncDec, In64BitMode] in {
471  def INC64m : IncOpM_MF<Xi64>;
472  def DEC64m : DecOpM_MF<Xi64>;
473}
474let Predicates = [HasNDD, In64BitMode, UseIncDec] in {
475  def INC8m_ND  : IncOpM_RF<Xi8>;
476  def INC16m_ND : IncOpM_RF<Xi16>, PD;
477  def INC32m_ND : IncOpM_RF<Xi32>;
478  def DEC8m_ND  : DecOpM_RF<Xi8>;
479  def DEC16m_ND : DecOpM_RF<Xi16>, PD;
480  def DEC32m_ND : DecOpM_RF<Xi32>;
481  def INC64m_ND : IncOpM_RF<Xi64>;
482  def DEC64m_ND : DecOpM_RF<Xi64>;
483}
484let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
485  def INC8m_NF  : IncOpM_M<Xi8>, NF;
486  def INC16m_NF : IncOpM_M<Xi16>, NF, PD;
487  def INC32m_NF : IncOpM_M<Xi32>, NF;
488  def INC64m_NF : IncOpM_M<Xi64>, NF;
489  def DEC8m_NF  : DecOpM_M<Xi8>, NF;
490  def DEC16m_NF : DecOpM_M<Xi16>, NF, PD;
491  def DEC32m_NF : DecOpM_M<Xi32>, NF;
492  def DEC64m_NF : DecOpM_M<Xi64>, NF;
493  def INC8m_NF_ND  : IncOpM_R<Xi8>, NF;
494  def INC16m_NF_ND : IncOpM_R<Xi16>, NF, PD;
495  def INC32m_NF_ND : IncOpM_R<Xi32>, NF;
496  def INC64m_NF_ND : IncOpM_R<Xi64>, NF;
497  def DEC8m_NF_ND  : DecOpM_R<Xi8>, NF;
498  def DEC16m_NF_ND : DecOpM_R<Xi16>, NF, PD;
499  def DEC32m_NF_ND : DecOpM_R<Xi32>, NF;
500  def DEC64m_NF_ND : DecOpM_R<Xi64>, NF;
501  def INC8m_EVEX  : IncOpM_MF<Xi8>, PL;
502  def INC16m_EVEX : IncOpM_MF<Xi16>, PL, PD;
503  def INC32m_EVEX : IncOpM_MF<Xi32>, PL;
504  def INC64m_EVEX : IncOpM_MF<Xi64>, PL;
505  def DEC8m_EVEX  : DecOpM_MF<Xi8>, PL;
506  def DEC16m_EVEX : DecOpM_MF<Xi16>, PL, PD;
507  def DEC32m_EVEX : DecOpM_MF<Xi32>, PL;
508  def DEC64m_EVEX : DecOpM_MF<Xi64>, PL;
509}
510
511//===----------------------------------------------------------------------===//
512// NEG and NOT Instructions
513//
514class NegOpR_R<X86TypeInfo t, bit ndd = 0>
515  : UnaryOpR_R<0xF7, MRM3r, "neg", t, ineg, ndd>;
516class NegOpR_RF<X86TypeInfo t, bit ndd = 0>
517  : UnaryOpR_RF<0xF7, MRM3r, "neg", t, ineg, ndd>;
518class NegOpM_M<X86TypeInfo t> : UnaryOpM_M<0xF7, MRM3m, "neg", t, null_frag>;
519class NegOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xF7, MRM3m, "neg", t, ineg>;
520class NegOpM_R<X86TypeInfo t> : UnaryOpM_R<0xF7, MRM3m, "neg", t, null_frag>;
521class NegOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xF7, MRM3m, "neg", t, ineg>;
522
523class NotOpR_R<X86TypeInfo t, bit ndd = 0>
524  : UnaryOpR_R<0xF7, MRM2r, "not", t, not, ndd>;
525class NotOpM_M<X86TypeInfo t> : UnaryOpM_M<0xF7, MRM2m, "not", t, not>;
526class NotOpM_R<X86TypeInfo t> : UnaryOpM_R<0xF7, MRM2m, "not", t, not>;
527
528let Predicates = [NoNDD] in {
529def NEG8r  : NegOpR_RF<Xi8>;
530def NEG16r : NegOpR_RF<Xi16>, OpSize16;
531def NEG32r : NegOpR_RF<Xi32>, OpSize32;
532def NEG64r : NegOpR_RF<Xi64>;
533def NOT8r  : NotOpR_R<Xi8>;
534def NOT16r : NotOpR_R<Xi16>, OpSize16;
535def NOT32r : NotOpR_R<Xi32>, OpSize32;
536def NOT64r : NotOpR_R<Xi64>;
537}
538
539let Predicates = [HasNDD, In64BitMode] in {
540def NEG8r_ND  : NegOpR_RF<Xi8, 1>;
541def NEG16r_ND : NegOpR_RF<Xi16, 1>, PD;
542def NEG32r_ND : NegOpR_RF<Xi32, 1>;
543def NEG64r_ND : NegOpR_RF<Xi64, 1>;
544
545def NOT8r_ND  : NotOpR_R<Xi8, 1>;
546def NOT16r_ND : NotOpR_R<Xi16, 1>, PD;
547def NOT32r_ND : NotOpR_R<Xi32, 1>;
548def NOT64r_ND : NotOpR_R<Xi64, 1>;
549
550def NEG8r_NF_ND  : NegOpR_R<Xi8, 1>, EVEX_NF;
551def NEG16r_NF_ND : NegOpR_R<Xi16, 1>, EVEX_NF, PD;
552def NEG32r_NF_ND : NegOpR_R<Xi32, 1>, EVEX_NF;
553def NEG64r_NF_ND : NegOpR_R<Xi64, 1>, EVEX_NF;
554}
555
556def NEG8m  : NegOpM_MF<Xi8>;
557def NEG16m : NegOpM_MF<Xi16>, OpSize16;
558def NEG32m : NegOpM_MF<Xi32>, OpSize32;
559def NEG64m : NegOpM_MF<Xi64>, Requires<[In64BitMode]>;
560
561let Predicates = [HasNDD, In64BitMode] in {
562def NEG8m_ND  : NegOpM_RF<Xi8>;
563def NEG16m_ND : NegOpM_RF<Xi16>, PD;
564def NEG32m_ND : NegOpM_RF<Xi32>;
565def NEG64m_ND : NegOpM_RF<Xi64>;
566
567def NEG8m_NF_ND  : NegOpM_R<Xi8>, EVEX_NF;
568def NEG16m_NF_ND : NegOpM_R<Xi16>, EVEX_NF, PD;
569def NEG32m_NF_ND : NegOpM_R<Xi32>, EVEX_NF;
570def NEG64m_NF_ND : NegOpM_R<Xi64>, EVEX_NF;
571}
572
573def NOT8m  : NotOpM_M<Xi8>;
574def NOT16m : NotOpM_M<Xi16>, OpSize16;
575def NOT32m : NotOpM_M<Xi32>, OpSize32;
576def NOT64m : NotOpM_M<Xi64>, Requires<[In64BitMode]>;
577
578let Predicates = [HasNDD, In64BitMode] in {
579def NOT8m_ND  : NotOpM_R<Xi8>;
580def NOT16m_ND : NotOpM_R<Xi16>, PD;
581def NOT32m_ND : NotOpM_R<Xi32>;
582def NOT64m_ND : NotOpM_R<Xi64>;
583}
584
585let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
586def NEG8r_NF  : NegOpR_R<Xi8>, NF;
587def NEG16r_NF : NegOpR_R<Xi16>, NF, PD;
588def NEG32r_NF : NegOpR_R<Xi32>, NF;
589def NEG64r_NF : NegOpR_R<Xi64>, NF;
590def NEG8m_NF  : NegOpM_M<Xi8>, NF;
591def NEG16m_NF : NegOpM_M<Xi16>, NF, PD;
592def NEG32m_NF : NegOpM_M<Xi32>, NF;
593def NEG64m_NF : NegOpM_M<Xi64>, NF;
594
595def NEG8r_EVEX  : NegOpR_RF<Xi8>, PL;
596def NEG16r_EVEX : NegOpR_RF<Xi16>, PL, PD;
597def NEG32r_EVEX : NegOpR_RF<Xi32>, PL;
598def NEG64r_EVEX : NegOpR_RF<Xi64>, PL;
599
600def NOT8r_EVEX  : NotOpR_R<Xi8>, PL;
601def NOT16r_EVEX : NotOpR_R<Xi16>, PL, PD;
602def NOT32r_EVEX : NotOpR_R<Xi32>, PL;
603def NOT64r_EVEX : NotOpR_R<Xi64>, PL;
604
605def NEG8m_EVEX  : NegOpM_MF<Xi8>, PL;
606def NEG16m_EVEX : NegOpM_MF<Xi16>, PL, PD;
607def NEG32m_EVEX : NegOpM_MF<Xi32>, PL;
608def NEG64m_EVEX : NegOpM_MF<Xi64>, PL;
609
610def NOT8m_EVEX  : NotOpM_M<Xi8>, PL;
611def NOT16m_EVEX : NotOpM_M<Xi16>, PL, PD;
612def NOT32m_EVEX : NotOpM_M<Xi32>, PL;
613def NOT64m_EVEX : NotOpM_M<Xi64>, PL;
614}
615
616/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
617/// defined with "(set GPR:$dst, EFLAGS, (...".
618///
619/// It would be nice to get rid of the second and third argument here, but
620/// tblgen can't handle dependent type references aggressively enough: PR8330
621multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
622                         string mnemonic, Format RegMRM, Format MemMRM,
623                         SDNode opnodeflag, SDNode opnode,
624                         bit CommutableRR, bit ConvertibleToThreeAddress,
625                         bit ConvertibleToThreeAddressRR> {
626  let isCommutable = CommutableRR,
627      isConvertibleToThreeAddress = ConvertibleToThreeAddressRR in {
628    let Predicates = [NoNDD] in {
629      def 8rr  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
630      def 16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>, OpSize16;
631      def 32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>, OpSize32;
632      def 64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
633    }
634    let Predicates = [HasNDD, In64BitMode] in {
635      def 8rr_ND  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag, 1>;
636      def 16rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag, 1>, PD;
637      def 32rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag, 1>;
638      def 64rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag, 1>;
639      def 8rr_NF_ND  : BinOpRR_R<BaseOpc, mnemonic, Xi8, 1>, EVEX_NF;
640      def 16rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi16, 1>, EVEX_NF, PD;
641      def 32rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi32, 1>, EVEX_NF;
642      def 64rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi64, 1>, EVEX_NF;
643    }
644    let Predicates = [In64BitMode] in {
645      def 8rr_NF  : BinOpRR_R<BaseOpc, mnemonic, Xi8>, NF;
646      def 16rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi16>, NF, PD;
647      def 32rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi32>, NF;
648      def 64rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi64>, NF;
649      def 8rr_EVEX  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
650      def 16rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
651      def 32rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
652      def 64rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
653    }
654  }
655
656  def 8rr_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>;
657  def 16rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
658  def 32rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
659  def 64rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>;
660  let Predicates = [In64BitMode] in {
661    def 8rr_EVEX_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
662    def 16rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
663    def 32rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
664    def 64rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
665    def 8rr_ND_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
666    def 16rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
667    def 32rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
668    def 64rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
669    def 8rr_NF_REV  : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8>, NF;
670    def 16rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16>, NF, PD;
671    def 32rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32>, NF;
672    def 64rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64>, NF;
673    def 8rr_NF_ND_REV  : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
674    def 16rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
675    def 32rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
676    def 64rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
677  }
678
679  let Predicates = [NoNDD] in {
680    def 8rm   : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
681    def 16rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>, OpSize16;
682    def 32rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>, OpSize32;
683    def 64rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
684  }
685  let Predicates = [HasNDD, In64BitMode] in {
686    def 8rm_ND  : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag, 1>;
687    def 16rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag, 1>, PD;
688    def 32rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag, 1>;
689    def 64rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag, 1>;
690    def 8rm_NF_ND  : BinOpRM_R<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
691    def 16rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
692    def 32rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
693    def 64rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
694  }
695  let Predicates = [In64BitMode] in {
696    def 8rm_NF  : BinOpRM_R<BaseOpc2, mnemonic, Xi8>, NF;
697    def 16rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi16>, NF, PD;
698    def 32rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi32>, NF;
699    def 64rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi64>, NF;
700    def 8rm_EVEX  : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , null_frag>, PL;
701    def 16rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, null_frag>, PL, PD;
702    def 32rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, null_frag>, PL;
703    def 64rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, null_frag>, PL;
704  }
705
706  let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
707    let Predicates = [NoNDD] in {
708      // NOTE: These are order specific, we want the ri8 forms to be listed
709      // first so that they are slightly preferred to the ri forms.
710      def 16ri8 : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
711      def 32ri8 : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
712      def 64ri8 : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>;
713      def 8ri   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
714      def 16ri  : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM>, OpSize16;
715      def 32ri  : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM>, OpSize32;
716      def 64ri32: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM>;
717    }
718    let Predicates = [HasNDD, In64BitMode] in {
719      def 16ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
720      def 32ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
721      def 64ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
722      def 8ri_ND   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM, 1>;
723      def 16ri_ND  : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM, 1>, PD;
724      def 32ri_ND  : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM, 1>;
725      def 64ri32_ND: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM, 1>;
726      def 16ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
727      def 32ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
728      def 64ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
729      def 8ri_NF_ND  : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM, 1>, EVEX_NF;
730      def 16ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
731      def 32ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
732      def 64ri32_NF_ND : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
733    }
734    let Predicates = [In64BitMode] in {
735      def 16ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM>, NF, PD;
736      def 32ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM>, NF;
737      def 64ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM>, NF;
738      def 8ri_NF  : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM>, NF;
739      def 16ri_NF : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM>, NF, PD;
740      def 32ri_NF : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM>, NF;
741      def 64ri32_NF : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM>, NF;
742      def 16ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
743      def 32ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
744      def 64ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
745      def 8ri_EVEX   : BinOpRI_RF<0x80, mnemonic, Xi8 , null_frag, RegMRM>, PL;
746      def 16ri_EVEX  : BinOpRI_RF<0x81, mnemonic, Xi16, null_frag, RegMRM>, PL, PD;
747      def 32ri_EVEX  : BinOpRI_RF<0x81, mnemonic, Xi32, null_frag, RegMRM>, PL;
748      def 64ri32_EVEX: BinOpRI_RF<0x81, mnemonic, Xi64, null_frag, RegMRM>, PL;
749    }
750  }
751
752  def 8mr    : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , opnode>;
753  def 16mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
754  def 32mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
755  def 64mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi64, opnode>;
756  let Predicates = [HasNDD, In64BitMode] in {
757    defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
758    def 8mr_ND    : BinOpMR_RF<BaseOpc, mnemonic, Xi8 , node>;
759    def 16mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi16, node>, PD;
760    def 32mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi32, node>;
761    def 64mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi64, node>;
762    def 8mr_NF_ND    : BinOpMR_R<BaseOpc, mnemonic, Xi8>, EVEX_NF;
763    def 16mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi16>, EVEX_NF, PD;
764    def 32mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi32>, EVEX_NF;
765    def 64mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi64>, EVEX_NF;
766  }
767  let Predicates = [In64BitMode] in {
768    def 8mr_NF    : BinOpMR_M<BaseOpc, mnemonic, Xi8>, NF;
769    def 16mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi16>, NF, PD;
770    def 32mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi32>, NF;
771    def 64mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi64>, NF;
772    def 8mr_EVEX    : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
773    def 16mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
774    def 32mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
775    def 64mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
776  }
777
778  // NOTE: These are order specific, we want the mi8 forms to be listed
779  // first so that they are slightly preferred to the mi forms.
780  def 16mi8  : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, OpSize16;
781  def 32mi8  : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, OpSize32;
782  let Predicates = [In64BitMode] in
783    def 64mi8  : BinOpMI8_MF<mnemonic, Xi64, MemMRM>;
784  def 8mi    : BinOpMI_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
785  def 16mi   : BinOpMI_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
786  def 32mi   : BinOpMI_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
787  let Predicates = [In64BitMode] in
788    def 64mi32 : BinOpMI_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
789  let Predicates = [HasNDD, In64BitMode] in {
790    def 16mi8_ND  : BinOpMI8_RF<mnemonic, Xi16, MemMRM>, PD;
791    def 32mi8_ND  : BinOpMI8_RF<mnemonic, Xi32, MemMRM>;
792    def 64mi8_ND  : BinOpMI8_RF<mnemonic, Xi64, MemMRM>;
793    def 8mi_ND    : BinOpMI_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
794    def 16mi_ND   : BinOpMI_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
795    def 32mi_ND   : BinOpMI_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
796    def 64mi32_ND : BinOpMI_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
797    def 16mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi16, MemMRM>, NF, PD;
798    def 32mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi32, MemMRM>, NF;
799    def 64mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi64, MemMRM>, NF;
800    def 8mi_NF_ND    : BinOpMI_R<0x80, mnemonic, Xi8, MemMRM>, NF;
801    def 16mi_NF_ND   : BinOpMI_R<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
802    def 32mi_NF_ND   : BinOpMI_R<0x81, mnemonic, Xi32, MemMRM>, NF;
803    def 64mi32_NF_ND : BinOpMI_R<0x81, mnemonic, Xi64, MemMRM>, NF;
804  }
805  let Predicates = [In64BitMode] in {
806    def 16mi8_NF  : BinOpMI8_M<mnemonic, Xi16, MemMRM>, NF, PD;
807    def 32mi8_NF  : BinOpMI8_M<mnemonic, Xi32, MemMRM>, NF;
808    def 64mi8_NF  : BinOpMI8_M<mnemonic, Xi64, MemMRM>, NF;
809    def 8mi_NF    : BinOpMI_M<0x80, mnemonic, Xi8, MemMRM>, NF;
810    def 16mi_NF   : BinOpMI_M<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
811    def 32mi_NF   : BinOpMI_M<0x81, mnemonic, Xi32, MemMRM>, NF;
812    def 64mi32_NF : BinOpMI_M<0x81, mnemonic, Xi64, MemMRM>, NF;
813    def 16mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, PL, PD;
814    def 32mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, PL;
815    def 64mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi64, MemMRM>, PL;
816    def 8mi_EVEX    : BinOpMI_MF<0x80, mnemonic, Xi8 , null_frag, MemMRM>, PL;
817    def 16mi_EVEX   : BinOpMI_MF<0x81, mnemonic, Xi16, null_frag, MemMRM>, PL, PD;
818    def 32mi_EVEX   : BinOpMI_MF<0x81, mnemonic, Xi32, null_frag, MemMRM>, PL;
819    def 64mi32_EVEX : BinOpMI_MF<0x81, mnemonic, Xi64, null_frag, MemMRM>, PL;
820  }
821
822  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
823  // not in 64-bit mode.
824  let Predicates = [Not64BitMode] in {
825    def 8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
826    def 8mi8 : BinOpMI8_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
827  }
828
829  def 8i8 : BinOpAI_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
830  def 16i16 : BinOpAI_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
831  def 32i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
832  def 64i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
833}
834
835/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
836/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
837/// SBB.
838///
839/// It would be nice to get rid of the second and third argument here, but
840/// tblgen can't handle dependent type references aggressively enough: PR8330
841multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
842                          string mnemonic, Format RegMRM, Format MemMRM,
843                          SDNode opnode, bit CommutableRR,
844                           bit ConvertibleToThreeAddress> {
845  let isCommutable = CommutableRR in {
846    let Predicates = [NoNDD] in {
847      def 8rr  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , opnode>;
848      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
849        def 16rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
850        def 32rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
851        def 64rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, opnode>;
852      }
853    }
854    let Predicates = [HasNDD, In64BitMode] in {
855      def 8rr_ND  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , opnode, 1>;
856      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
857        def 16rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, opnode, 1>, PD;
858        def 32rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, opnode, 1>;
859        def 64rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, opnode, 1>;
860      }
861    }
862  } // isCommutable
863
864  let Predicates = [In64BitMode] in {
865    def 8rr_EVEX  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
866    def 16rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
867    def 32rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
868    def 64rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
869  }
870
871  def 8rr_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8>;
872  def 16rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
873  def 32rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
874  def 64rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64>;
875  let Predicates = [In64BitMode] in {
876    def 8rr_ND_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
877    def 16rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
878    def 32rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
879    def 64rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
880    def 8rr_EVEX_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
881    def 16rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
882    def 32rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
883    def 64rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
884  }
885
886  let Predicates = [NoNDD] in {
887    def 8rm   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode>;
888    def 16rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode>, OpSize16;
889    def 32rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode>, OpSize32;
890    def 64rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode>;
891  }
892  let Predicates = [HasNDD, In64BitMode] in {
893    def 8rm_ND   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode, 1>;
894    def 16rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode, 1>, PD;
895    def 32rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode, 1>;
896    def 64rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode, 1>;
897  }
898  let Predicates = [In64BitMode] in {
899    def 8rm_EVEX   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode>, PL;
900    def 16rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode>, PL, PD;
901    def 32rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode>, PL;
902    def 64rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode>, PL;
903  }
904
905  let Predicates = [NoNDD] in {
906    def 8ri   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
907    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
908      // NOTE: These are order specific, we want the ri8 forms to be listed
909      // first so that they are slightly preferred to the ri forms.
910      def 16ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
911      def 32ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
912      def 64ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM>;
913
914      def 16ri  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM>, OpSize16;
915      def 32ri  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM>, OpSize32;
916      def 64ri32: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM>;
917    }
918  }
919
920  let Predicates = [HasNDD, In64BitMode] in {
921    def 8ri_ND   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM, 1>;
922    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
923      def 16ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
924      def 32ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
925      def 64ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
926      def 16ri_ND  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM, 1>, PD;
927      def 32ri_ND  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM, 1>;
928      def 64ri32_ND: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM, 1>;
929    }
930  }
931  let Predicates = [In64BitMode] in {
932    def 8ri_EVEX   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM>, PL;
933    def 16ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
934    def 32ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
935    def 64ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
936    def 16ri_EVEX  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM>, PL, PD;
937    def 32ri_EVEX  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM>, PL;
938    def 64ri32_EVEX: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM>, PL;
939  }
940
941  def 8mr    : BinOpMRF_MF<BaseOpc, mnemonic, Xi8 , opnode>;
942  def 16mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
943  def 32mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
944  def 64mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi64, opnode>;
945  let Predicates = [HasNDD, In64BitMode] in {
946    defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
947    def 8mr_ND    : BinOpMRF_RF<BaseOpc, mnemonic, Xi8 , node>;
948    def 16mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi16, node>, PD;
949    def 32mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi32, node>;
950    def 64mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi64, node>;
951  }
952  let Predicates = [In64BitMode] in {
953    def 8mr_EVEX    : BinOpMRF_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
954    def 16mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
955    def 32mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
956    def 64mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
957  }
958
959  // NOTE: These are order specific, we want the mi8 forms to be listed
960  // first so that they are slightly preferred to the mi forms.
961  def 8mi    : BinOpMIF_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
962  def 16mi8  : BinOpMI8F_MF<mnemonic, Xi16, MemMRM>, OpSize16;
963  def 32mi8  : BinOpMI8F_MF<mnemonic, Xi32, MemMRM>, OpSize32;
964  let Predicates = [In64BitMode] in
965    def 64mi8  : BinOpMI8F_MF<mnemonic, Xi64, MemMRM>;
966  def 16mi   : BinOpMIF_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
967  def 32mi   : BinOpMIF_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
968  let Predicates = [In64BitMode] in
969    def 64mi32 : BinOpMIF_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
970
971  let Predicates = [HasNDD, In64BitMode] in {
972    def 8mi_ND    : BinOpMIF_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
973    def 16mi8_ND  : BinOpMI8F_RF<mnemonic, Xi16, MemMRM>, PD;
974    def 32mi8_ND  : BinOpMI8F_RF<mnemonic, Xi32, MemMRM>;
975    def 64mi8_ND  : BinOpMI8F_RF<mnemonic, Xi64, MemMRM>;
976    def 16mi_ND   : BinOpMIF_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
977    def 32mi_ND   : BinOpMIF_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
978    def 64mi32_ND : BinOpMIF_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
979  }
980  let Predicates = [In64BitMode] in {
981    def 8mi_EVEX    : BinOpMIF_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>, PL;
982    def 16mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi16, MemMRM>, PL, PD;
983    def 32mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi32, MemMRM>, PL;
984    def 64mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi64, MemMRM>, PL;
985    def 16mi_EVEX   : BinOpMIF_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, PL, PD;
986    def 32mi_EVEX   : BinOpMIF_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, PL;
987    def 64mi32_EVEX : BinOpMIF_MF<0x81, mnemonic, Xi64, opnode, MemMRM>, PL;
988  }
989
990  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
991  // not in 64-bit mode.
992  let Predicates = [Not64BitMode]  in {
993    def 8ri8 : BinOpRI8F_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
994    def 8mi8 : BinOpMI8F_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
995  }
996
997  def 8i8 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
998  def 16i16 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
999  def 32i32 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1000  def 64i32 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
1001}
1002
1003/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
1004/// defined with "(set EFLAGS, (...".  It would be really nice to find a way
1005/// to factor this with the other ArithBinOp_*.
1006///
1007multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1008                        string mnemonic, Format RegMRM, Format MemMRM,
1009                        SDNode opnode, bit CommutableRR,
1010                        bit ConvertibleToThreeAddress> {
1011  let isCommutable = CommutableRR in {
1012    def 8rr  : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1013    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1014      def 16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
1015      def 32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
1016      def 64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1017    } // isConvertibleToThreeAddress
1018  } // isCommutable
1019
1020  def 8rr_REV  : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>;
1021  def 16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
1022  def 32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
1023  def 64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>;
1024
1025  def 8rm   : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
1026  def 16rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>, OpSize16;
1027  def 32rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>, OpSize32;
1028  def 64rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
1029
1030  def 8ri   : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1031
1032  let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1033    // NOTE: These are order specific, we want the ri8 forms to be listed
1034    // first so that they are slightly preferred to the ri forms.
1035    def 16ri8 : BinOpRI8_F<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
1036    def 32ri8 : BinOpRI8_F<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
1037    def 64ri8 : BinOpRI8_F<0x83, mnemonic, Xi64, RegMRM>;
1038
1039    def 16ri  : BinOpRI_F<0x81, mnemonic, Xi16, opnode, RegMRM>, OpSize16;
1040    def 32ri  : BinOpRI_F<0x81, mnemonic, Xi32, opnode, RegMRM>, OpSize32;
1041    def 64ri32: BinOpRI_F<0x81, mnemonic, Xi64, opnode, RegMRM>;
1042  }
1043
1044  def 8mr    : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1045  def 16mr   : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
1046  def 32mr   : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
1047  def 64mr   : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
1048
1049  // NOTE: These are order specific, we want the mi8 forms to be listed
1050  // first so that they are slightly preferred to the mi forms.
1051  def 16mi8  : BinOpMI8_F<mnemonic, Xi16, MemMRM>, OpSize16;
1052  def 32mi8  : BinOpMI8_F<mnemonic, Xi32, MemMRM>, OpSize32;
1053  let Predicates = [In64BitMode] in
1054  def 64mi8  : BinOpMI8_F<mnemonic, Xi64, MemMRM>;
1055
1056  def 8mi    : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1057  def 16mi   : BinOpMI_F<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
1058  def 32mi   : BinOpMI_F<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
1059  let Predicates = [In64BitMode] in
1060    def 64mi32 : BinOpMI_F<0x81, mnemonic, Xi64, opnode, MemMRM>;
1061
1062  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1063  // not in 64-bit mode.
1064  let Predicates = [Not64BitMode] in {
1065    def 8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
1066    let mayLoad = 1 in
1067      def 8mi8 : BinOpMI8_F<mnemonic, Xi8, MemMRM>;
1068  }
1069
1070  def 8i8 : BinOpAI_F<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
1071  def 16i16 : BinOpAI_F<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1072  def 32i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1073  def 64i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
1074}
1075
1076
1077defm AND : ArithBinOp_RF<0x21, 0x23, 0x25, "and", MRM4r, MRM4m,
1078                         X86and_flag, and, 1, 0, 0>;
1079defm OR  : ArithBinOp_RF<0x09, 0x0B, 0x0D, "or", MRM1r, MRM1m,
1080                         X86or_flag, or, 1, 0, 0>;
1081defm XOR : ArithBinOp_RF<0x31, 0x33, 0x35, "xor", MRM6r, MRM6m,
1082                         X86xor_flag, xor, 1, 0, 0>;
1083defm ADD : ArithBinOp_RF<0x01, 0x03, 0x05, "add", MRM0r, MRM0m,
1084                         X86add_flag, add, 1, 1, 1>;
1085let isCompare = 1 in {
1086  defm SUB : ArithBinOp_RF<0x29, 0x2B, 0x2D, "sub", MRM5r, MRM5m,
1087                           X86sub_flag, sub, 0, 1, 0>;
1088}
1089
1090// Version of XOR8rr_NOREX that use GR8_NOREX. This is used by the handling of
1091// __builtin_parity where the last step xors an h-register with an l-register.
1092let isCodeGenOnly = 1, hasSideEffects = 0, Constraints = "$src1 = $dst",
1093    Defs = [EFLAGS], isCommutable = 1 in
1094  def XOR8rr_NOREX : I<0x30, MRMDestReg, (outs GR8_NOREX:$dst),
1095                       (ins GR8_NOREX:$src1, GR8_NOREX:$src2),
1096                       "xor{b}\t{$src2, $dst|$dst, $src2}", []>,
1097                       Sched<[WriteALU]>;
1098
1099// Arithmetic.
1100defm ADC : ArithBinOp_RFF<0x11, 0x13, 0x15, "adc", MRM2r, MRM2m, X86adc_flag,
1101                          1, 0>;
1102defm SBB : ArithBinOp_RFF<0x19, 0x1B, 0x1D, "sbb", MRM3r, MRM3m, X86sbb_flag,
1103                          0, 0>;
1104
1105let isCompare = 1 in {
1106  defm CMP : ArithBinOp_F<0x39, 0x3B, 0x3D, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
1107}
1108
1109// Patterns to recognize loads on the LHS of an ADC. We can't make X86adc_flag
1110// commutable since it has EFLAGs as an input.
1111let Predicates = [NoNDD] in {
1112  def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1113            (ADC8rm GR8:$src1, addr:$src2)>;
1114  def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1115            (ADC16rm GR16:$src1, addr:$src2)>;
1116  def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1117            (ADC32rm GR32:$src1, addr:$src2)>;
1118  def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1119            (ADC64rm GR64:$src1, addr:$src2)>;
1120}
1121let Predicates = [HasNDD] in {
1122  def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1123            (ADC8rm_ND GR8:$src1, addr:$src2)>;
1124  def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1125            (ADC16rm_ND GR16:$src1, addr:$src2)>;
1126  def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1127            (ADC32rm_ND GR32:$src1, addr:$src2)>;
1128  def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1129            (ADC64rm_ND GR64:$src1, addr:$src2)>;
1130}
1131
1132// Patterns to recognize RMW ADC with loads in operand 1.
1133def : Pat<(store (X86adc_flag GR8:$src, (loadi8 addr:$dst), EFLAGS),
1134                 addr:$dst),
1135          (ADC8mr addr:$dst, GR8:$src)>;
1136def : Pat<(store (X86adc_flag GR16:$src, (loadi16 addr:$dst), EFLAGS),
1137                 addr:$dst),
1138          (ADC16mr addr:$dst, GR16:$src)>;
1139def : Pat<(store (X86adc_flag GR32:$src, (loadi32 addr:$dst), EFLAGS),
1140                 addr:$dst),
1141          (ADC32mr addr:$dst, GR32:$src)>;
1142def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
1143                 addr:$dst),
1144          (ADC64mr addr:$dst, GR64:$src)>;
1145
1146// Patterns for basic arithmetic ops with relocImm for the immediate field.
1147multiclass ArithBinOp_RF_relocImm_Pats<SDNode OpNodeFlag, SDNode OpNode> {
1148  let Predicates = [NoNDD] in {
1149    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1150              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
1151    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1152              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
1153    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1154              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
1155    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1156              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1157
1158    def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst),
1159              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
1160    def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst),
1161              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
1162    def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst),
1163              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
1164    def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst),
1165              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
1166  }
1167  let Predicates = [HasNDD] in {
1168    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1169              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
1170    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1171              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
1172    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1173              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
1174    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1175              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1176
1177    def : Pat<(OpNode (load addr:$dst), relocImm8_su:$src),
1178              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
1179    def : Pat<(OpNode (load addr:$dst), relocImm16_su:$src),
1180              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
1181    def : Pat<(OpNode (load addr:$dst), relocImm32_su:$src),
1182              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
1183    def : Pat<(OpNode (load addr:$dst), i64relocImmSExt32_su:$src),
1184              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
1185  }
1186}
1187
1188multiclass ArithBinOp_RFF_relocImm_Pats<SDNode OpNodeFlag> {
1189  let Predicates = [NoNDD] in {
1190    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1191              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
1192    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
1193              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
1194    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
1195              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
1196    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
1197              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1198
1199    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst),
1200              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
1201    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst),
1202              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
1203    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst),
1204              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
1205    def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst),
1206              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
1207  }
1208  let Predicates = [HasNDD] in {
1209    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1210              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
1211    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
1212              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
1213    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
1214              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
1215    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
1216              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1217
1218    def : Pat<(OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS),
1219              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
1220    def : Pat<(OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS),
1221              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
1222    def : Pat<(OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS),
1223              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
1224    def : Pat<(OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS),
1225              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
1226  }
1227}
1228
1229multiclass ArithBinOp_F_relocImm_Pats<SDNode OpNodeFlag> {
1230  def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1231            (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
1232  def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1233            (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
1234  def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1235            (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
1236  def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1237            (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1238
1239  def : Pat<(OpNodeFlag (loadi8 addr:$src1), relocImm8_su:$src2),
1240            (!cast<Instruction>(NAME#"8mi") addr:$src1, relocImm8_su:$src2)>;
1241  def : Pat<(OpNodeFlag (loadi16 addr:$src1), relocImm16_su:$src2),
1242            (!cast<Instruction>(NAME#"16mi") addr:$src1, relocImm16_su:$src2)>;
1243  def : Pat<(OpNodeFlag (loadi32 addr:$src1), relocImm32_su:$src2),
1244            (!cast<Instruction>(NAME#"32mi") addr:$src1, relocImm32_su:$src2)>;
1245  def : Pat<(OpNodeFlag (loadi64 addr:$src1), i64relocImmSExt32_su:$src2),
1246            (!cast<Instruction>(NAME#"64mi32") addr:$src1, i64relocImmSExt32_su:$src2)>;
1247}
1248
1249defm AND : ArithBinOp_RF_relocImm_Pats<X86and_flag, and>;
1250defm OR  : ArithBinOp_RF_relocImm_Pats<X86or_flag, or>;
1251defm XOR : ArithBinOp_RF_relocImm_Pats<X86xor_flag, xor>;
1252defm ADD : ArithBinOp_RF_relocImm_Pats<X86add_flag, add>;
1253defm SUB : ArithBinOp_RF_relocImm_Pats<X86sub_flag, sub>;
1254
1255defm ADC : ArithBinOp_RFF_relocImm_Pats<X86adc_flag>;
1256defm SBB : ArithBinOp_RFF_relocImm_Pats<X86sbb_flag>;
1257
1258defm CMP : ArithBinOp_F_relocImm_Pats<X86cmp>;
1259
1260// ADC is commutable, but we can't indicate that to tablegen. So manually
1261// reverse the operands.
1262def : Pat<(X86adc_flag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1263          (ADC8ri relocImm8_su:$src2, GR8:$src1)>;
1264def : Pat<(X86adc_flag i16relocImmSExt8_su:$src2, GR16:$src1, EFLAGS),
1265          (ADC16ri8 GR16:$src1, i16relocImmSExt8_su:$src2)>;
1266def : Pat<(X86adc_flag relocImm16_su:$src2, GR16:$src1, EFLAGS),
1267          (ADC16ri GR16:$src1, relocImm16_su:$src2)>;
1268def : Pat<(X86adc_flag i32relocImmSExt8_su:$src2, GR32:$src1, EFLAGS),
1269          (ADC32ri8 GR32:$src1, i32relocImmSExt8_su:$src2)>;
1270def : Pat<(X86adc_flag relocImm32_su:$src2, GR32:$src1, EFLAGS),
1271          (ADC32ri GR32:$src1, relocImm32_su:$src2)>;
1272def : Pat<(X86adc_flag i64relocImmSExt8_su:$src2, GR64:$src1, EFLAGS),
1273          (ADC64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>;
1274def : Pat<(X86adc_flag i64relocImmSExt32_su:$src2, GR64:$src1, EFLAGS),
1275          (ADC64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
1276
1277def : Pat<(store (X86adc_flag relocImm8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1278          (ADC8mi addr:$dst, relocImm8_su:$src)>;
1279def : Pat<(store (X86adc_flag i16relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1280          (ADC16mi8 addr:$dst, i16relocImmSExt8_su:$src)>;
1281def : Pat<(store (X86adc_flag relocImm16_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1282          (ADC16mi addr:$dst, relocImm16_su:$src)>;
1283def : Pat<(store (X86adc_flag i32relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1284          (ADC32mi8 addr:$dst, i32relocImmSExt8_su:$src)>;
1285def : Pat<(store (X86adc_flag relocImm32_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1286          (ADC32mi addr:$dst, relocImm32_su:$src)>;
1287def : Pat<(store (X86adc_flag i64relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1288          (ADC64mi8 addr:$dst, i64relocImmSExt8_su:$src)>;
1289def : Pat<(store (X86adc_flag i64relocImmSExt32_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1290          (ADC64mi32 addr:$dst, i64relocImmSExt32_su:$src)>;
1291
1292//===----------------------------------------------------------------------===//
1293// Semantically, test instructions are similar like AND, except they don't
1294// generate a result.  From an encoding perspective, they are very different:
1295// they don't have all the usual imm8 and REV forms, and are encoded into a
1296// different space.
1297let isCompare = 1 in {
1298  let isCommutable = 1 in {
1299  // Avoid selecting these and instead use a test+and. Post processing will
1300  // combine them. This gives bunch of other patterns that start with
1301  // and a chance to match.
1302    def TEST8rr  : BinOpRR_F<0x84, "test", Xi8 , null_frag>;
1303    def TEST16rr : BinOpRR_F<0x85, "test", Xi16, null_frag>, OpSize16;
1304    def TEST32rr : BinOpRR_F<0x85, "test", Xi32, null_frag>, OpSize32;
1305    def TEST64rr : BinOpRR_F<0x85, "test", Xi64, null_frag>;
1306  } // isCommutable
1307
1308  def TEST8mr    : BinOpMR_F<0x84, "test", Xi8 , null_frag>;
1309  def TEST16mr   : BinOpMR_F<0x85, "test", Xi16, null_frag>, OpSize16;
1310  def TEST32mr   : BinOpMR_F<0x85, "test", Xi32, null_frag>, OpSize32;
1311  def TEST64mr   : BinOpMR_F<0x85, "test", Xi64, null_frag>;
1312
1313  def TEST8ri    : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1314  def TEST16ri   : BinOpRI_F<0xF7, "test", Xi16, X86testpat, MRM0r>, OpSize16;
1315  def TEST32ri   : BinOpRI_F<0xF7, "test", Xi32, X86testpat, MRM0r>, OpSize32;
1316  def TEST64ri32 : BinOpRI_F<0xF7, "test", Xi64, X86testpat, MRM0r>;
1317
1318  def TEST8mi    : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>;
1319  def TEST16mi   : BinOpMI_F<0xF7, "test", Xi16, X86testpat, MRM0m>, OpSize16;
1320  def TEST32mi   : BinOpMI_F<0xF7, "test", Xi32, X86testpat, MRM0m>, OpSize32;
1321
1322  let Predicates = [In64BitMode] in
1323    def TEST64mi32 : BinOpMI_F<0xF7, "test", Xi64, X86testpat, MRM0m>;
1324
1325  def TEST8i8 : BinOpAI_F<0xA8, "test", Xi8 , AL, "{$src, %al|al, $src}">;
1326  def TEST16i16 : BinOpAI_F<0xA9, "test", Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1327  def TEST32i32 : BinOpAI_F<0xA9, "test", Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1328  def TEST64i32 : BinOpAI_F<0xA9, "test", Xi64, RAX, "{$src, %rax|rax, $src}">;
1329} // isCompare
1330
1331// Patterns to match a relocImm into the immediate field.
1332def : Pat<(X86testpat GR8:$src1, relocImm8_su:$src2),
1333          (TEST8ri GR8:$src1, relocImm8_su:$src2)>;
1334def : Pat<(X86testpat GR16:$src1, relocImm16_su:$src2),
1335          (TEST16ri GR16:$src1, relocImm16_su:$src2)>;
1336def : Pat<(X86testpat GR32:$src1, relocImm32_su:$src2),
1337          (TEST32ri GR32:$src1, relocImm32_su:$src2)>;
1338def : Pat<(X86testpat GR64:$src1, i64relocImmSExt32_su:$src2),
1339          (TEST64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
1340
1341def : Pat<(X86testpat (loadi8 addr:$src1), relocImm8_su:$src2),
1342          (TEST8mi addr:$src1, relocImm8_su:$src2)>;
1343def : Pat<(X86testpat (loadi16 addr:$src1), relocImm16_su:$src2),
1344          (TEST16mi addr:$src1, relocImm16_su:$src2)>;
1345def : Pat<(X86testpat (loadi32 addr:$src1), relocImm32_su:$src2),
1346          (TEST32mi addr:$src1, relocImm32_su:$src2)>;
1347def : Pat<(X86testpat (loadi64 addr:$src1), i64relocImmSExt32_su:$src2),
1348          (TEST64mi32 addr:$src1, i64relocImmSExt32_su:$src2)>;
1349
1350//===----------------------------------------------------------------------===//
1351// ANDN Instruction
1352//
1353multiclass AndN<X86TypeInfo t, SDPatternOperator node, string suffix = ""> {
1354  defvar andn_rr_p =
1355    [(set t.RegClass:$dst, EFLAGS, (node (not t.RegClass:$src1),
1356     t.RegClass:$src2))];
1357  defvar andn_rm_p =
1358    [(set t.RegClass:$dst, EFLAGS, (node (not t.RegClass:$src1),
1359     (t.LoadNode addr:$src2)))];
1360  def rr#suffix : ITy<0xF2, MRMSrcReg, t, (outs t.RegClass:$dst),
1361                      (ins t.RegClass:$src1, t.RegClass:$src2), "andn",
1362                      binop_ndd_args, andn_rr_p>, VVVV, Sched<[WriteALU]>, T8;
1363  def rm#suffix : ITy<0xF2, MRMSrcMem, t, (outs t.RegClass:$dst),
1364                       (ins t.RegClass:$src1, t.MemOperand:$src2), "andn",
1365                       binop_ndd_args, andn_rm_p>, VVVV,
1366                       Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, T8;
1367}
1368
1369// Complexity is reduced to give and with immediate a chance to match first.
1370let AddedComplexity = -6 in {
1371defm ANDN32 : AndN<Xi32, X86and_flag>, VEX, Requires<[HasBMI, NoEGPR]>, DefEFLAGS;
1372defm ANDN64 : AndN<Xi64, X86and_flag>, VEX, Requires<[HasBMI, NoEGPR]>, DefEFLAGS;
1373defm ANDN32 : AndN<Xi32, X86and_flag, "_EVEX">, EVEX, Requires<[HasBMI, HasEGPR, In64BitMode]>, DefEFLAGS;
1374defm ANDN64 : AndN<Xi64, X86and_flag, "_EVEX">, EVEX, Requires<[HasBMI, HasEGPR, In64BitMode]>, DefEFLAGS;
1375defm ANDN32 : AndN<Xi32, null_frag, "_NF">, EVEX, EVEX_NF, Requires<[In64BitMode]>;
1376defm ANDN64 : AndN<Xi64, null_frag, "_NF">, EVEX, EVEX_NF, Requires<[In64BitMode]>;
1377}
1378
1379multiclass Andn_Pats<string suffix> {
1380  def : Pat<(and (not GR32:$src1), GR32:$src2),
1381            (!cast<Instruction>(ANDN32rr#suffix) GR32:$src1, GR32:$src2)>;
1382  def : Pat<(and (not GR64:$src1), GR64:$src2),
1383            (!cast<Instruction>(ANDN64rr#suffix) GR64:$src1, GR64:$src2)>;
1384  def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
1385            (!cast<Instruction>(ANDN32rm#suffix) GR32:$src1, addr:$src2)>;
1386  def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
1387            (!cast<Instruction>(ANDN64rm#suffix) GR64:$src1, addr:$src2)>;
1388}
1389
1390let Predicates = [HasBMI, NoEGPR], AddedComplexity = -6 in
1391  defm : Andn_Pats<"">;
1392
1393let Predicates = [HasBMI, HasEGPR], AddedComplexity = -6 in
1394  defm : Andn_Pats<"_EVEX">;
1395
1396//===----------------------------------------------------------------------===//
1397// MULX Instruction
1398//
1399multiclass MulX<X86TypeInfo t, X86FoldableSchedWrite sched> {
1400  defvar mulx_args = "{$src, $dst2, $dst1|$dst1, $dst2, $src}";
1401  defvar mulx_rm_sched =
1402    [WriteIMulHLd, sched.Folded,
1403     // Memory operand.
1404     ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
1405     // Implicit read of EDX/RDX
1406     sched.ReadAfterFold];
1407
1408  def rr : ITy<0xF6, MRMSrcReg, t, (outs t.RegClass:$dst1, t.RegClass:$dst2),
1409               (ins t.RegClass:$src), "mulx", mulx_args, []>, T8, XD, VEX,
1410           VVVV, Sched<[WriteIMulH, sched]>;
1411  let mayLoad = 1 in
1412    def rm : ITy<0xF6, MRMSrcMem, t, (outs t.RegClass:$dst1, t.RegClass:$dst2),
1413                 (ins t.MemOperand:$src), "mulx", mulx_args, []>, T8, XD, VEX,
1414                 VVVV, Sched<mulx_rm_sched>;
1415
1416  let Predicates = [In64BitMode] in {
1417    def rr_EVEX : ITy<0xF6, MRMSrcReg, t,
1418                      (outs t.RegClass:$dst1, t.RegClass:$dst2),
1419                      (ins t.RegClass:$src), "mulx", mulx_args, []>, T8, XD,
1420                  EVEX, VVVV, Sched<[WriteIMulH, sched]>;
1421    let mayLoad = 1 in
1422      def rm_EVEX : ITy<0xF6, MRMSrcMem, t,
1423                        (outs t.RegClass:$dst1, t.RegClass:$dst2),
1424                        (ins t.MemOperand:$src), "mulx", mulx_args, []>, T8, XD,
1425                    EVEX, VVVV, Sched<mulx_rm_sched>;
1426  }
1427  // Pseudo instructions to be used when the low result isn't used. The
1428  // instruction is defined to keep the high if both destinations are the same.
1429  def Hrr : PseudoI<(outs t.RegClass:$dst), (ins t.RegClass:$src), []>,
1430            Sched<[sched]>;
1431  let mayLoad = 1 in
1432  def Hrm : PseudoI<(outs t.RegClass:$dst), (ins t.MemOperand:$src), []>,
1433            Sched<[sched.Folded]>;
1434}
1435
1436let Uses = [EDX] in
1437  defm MULX32 : MulX<Xi32, WriteMULX32>;
1438
1439let Uses = [RDX] in
1440  defm MULX64 : MulX<Xi64, WriteMULX64>, REX_W;
1441
1442//===----------------------------------------------------------------------===//
1443// ADCX and ADOX Instructions
1444//
1445// We don't have patterns for these as there is no advantage over ADC for
1446// most code.
1447let Form = MRMSrcReg in {
1448  def ADCX32rr : BinOpRRF_RF<0xF6, "adcx", Xi32>, T8, PD;
1449  def ADCX64rr : BinOpRRF_RF<0xF6, "adcx", Xi64>, T8, PD;
1450  def ADOX32rr : BinOpRRF_RF<0xF6, "adox", Xi32>, T8, XS;
1451  def ADOX64rr : BinOpRRF_RF<0xF6, "adox", Xi64>, T8, XS;
1452  let Predicates =[In64BitMode] in {
1453    def ADCX32rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
1454    def ADCX64rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
1455    def ADOX32rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
1456    def ADOX64rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
1457    def ADCX32rr_ND : BinOpRRF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
1458    def ADCX64rr_ND : BinOpRRF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
1459    def ADOX32rr_ND : BinOpRRF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
1460    def ADOX64rr_ND : BinOpRRF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
1461  }
1462}
1463let Form = MRMSrcMem in {
1464  def ADCX32rm : BinOpRMF_RF<0xF6, "adcx", Xi32>, T8, PD;
1465  def ADCX64rm : BinOpRMF_RF<0xF6, "adcx", Xi64>, T8, PD;
1466  def ADOX32rm : BinOpRMF_RF<0xF6, "adox", Xi32>, T8, XS;
1467  def ADOX64rm : BinOpRMF_RF<0xF6, "adox", Xi64>, T8, XS;
1468  let Predicates =[In64BitMode] in {
1469    def ADCX32rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
1470    def ADCX64rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
1471    def ADOX32rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
1472    def ADOX64rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
1473    def ADCX32rm_ND : BinOpRMF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
1474    def ADCX64rm_ND : BinOpRMF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
1475    def ADOX32rm_ND : BinOpRMF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
1476    def ADOX64rm_ND : BinOpRMF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
1477  }
1478}
1479