xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86InstrArithmetic.td (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
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, (node AL, GR8:$src1)), (implicit EFLAGS)]>;
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, (node AL, (loadi8 addr:$src1))), (implicit EFLAGS)]>;
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                 (implicit EFLAGS)];
391}
392class DecOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM1m, "dec", t, null_frag> {
393  let Pattern = [(store (add (t.LoadNode addr:$src1), -1), addr:$src1),
394                 (implicit EFLAGS)];
395}
396class IncOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM0m, "inc", t, null_frag> {
397  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), 1))];
398}
399class DecOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM1m, "dec", t, null_frag> {
400  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), -1))];
401}
402class IncOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM0m, "inc", t, null_frag>;
403class DecOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM1m, "dec", t, null_frag>;
404class IncOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM0m, "inc", t, null_frag>;
405class DecOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM1m, "dec", t, null_frag>;
406
407// IncDec_Alt - Instructions like "inc reg" short forms.
408// Short forms only valid in 32-bit mode. Selected during MCInst lowering.
409class IncDec_Alt<bits<8> o, string m, X86TypeInfo t>
410  : UnaryOpR_RF<o, AddRegFrm, m, t, null_frag>, Requires<[Not64BitMode]>;
411
412let isConvertibleToThreeAddress = 1 in {
413  def INC16r_alt : IncDec_Alt<0x40, "inc", Xi16>, OpSize16;
414  def INC32r_alt : IncDec_Alt<0x40, "inc", Xi32>, OpSize32;
415  def DEC16r_alt : IncDec_Alt<0x48, "dec", Xi16>, OpSize16;
416  def DEC32r_alt : IncDec_Alt<0x48, "dec", Xi32>, OpSize32;
417  let Predicates = [NoNDD] in {
418    def INC8r  : IncOpR_RF<Xi8>;
419    def INC16r : IncOpR_RF<Xi16>, OpSize16;
420    def INC32r : IncOpR_RF<Xi32>, OpSize32;
421    def INC64r : IncOpR_RF<Xi64>;
422    def DEC8r  : DecOpR_RF<Xi8>;
423    def DEC16r : DecOpR_RF<Xi16>, OpSize16;
424    def DEC32r : DecOpR_RF<Xi32>, OpSize32;
425    def DEC64r : DecOpR_RF<Xi64>;
426  }
427  let Predicates = [HasNDD, In64BitMode] in {
428    def INC8r_ND  : IncOpR_RF<Xi8, 1>;
429    def INC16r_ND : IncOpR_RF<Xi16, 1>, PD;
430    def INC32r_ND : IncOpR_RF<Xi32, 1>;
431    def INC64r_ND : IncOpR_RF<Xi64, 1>;
432    def DEC8r_ND  : DecOpR_RF<Xi8, 1>;
433    def DEC16r_ND : DecOpR_RF<Xi16, 1>, PD;
434    def DEC32r_ND : DecOpR_RF<Xi32, 1>;
435    def DEC64r_ND : DecOpR_RF<Xi64, 1>;
436  }
437  let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
438    def INC8r_NF  : IncOpR_R<Xi8>, NF;
439    def INC16r_NF : IncOpR_R<Xi16>, NF, PD;
440    def INC32r_NF : IncOpR_R<Xi32>, NF;
441    def INC64r_NF : IncOpR_R<Xi64>, NF;
442    def DEC8r_NF  : DecOpR_R<Xi8>, NF;
443    def DEC16r_NF : DecOpR_R<Xi16>, NF, PD;
444    def DEC32r_NF : DecOpR_R<Xi32>, NF;
445    def DEC64r_NF : DecOpR_R<Xi64>, NF;
446    def INC8r_NF_ND  : IncOpR_R<Xi8, 1>, NF;
447    def INC16r_NF_ND : IncOpR_R<Xi16, 1>, NF, PD;
448    def INC32r_NF_ND : IncOpR_R<Xi32, 1>, NF;
449    def INC64r_NF_ND : IncOpR_R<Xi64, 1>, NF;
450    def DEC8r_NF_ND  : DecOpR_R<Xi8, 1>, NF;
451    def DEC16r_NF_ND : DecOpR_R<Xi16, 1>, NF, PD;
452    def DEC32r_NF_ND : DecOpR_R<Xi32, 1>, NF;
453    def DEC64r_NF_ND : DecOpR_R<Xi64, 1>, NF;
454    def INC8r_EVEX  : IncOpR_RF<Xi8>, PL;
455    def INC16r_EVEX : IncOpR_RF<Xi16>, PL, PD;
456    def INC32r_EVEX : IncOpR_RF<Xi32>, PL;
457    def INC64r_EVEX : IncOpR_RF<Xi64>, PL;
458    def DEC8r_EVEX  : DecOpR_RF<Xi8>, PL;
459    def DEC16r_EVEX : DecOpR_RF<Xi16>, PL, PD;
460    def DEC32r_EVEX : DecOpR_RF<Xi32>, PL;
461    def DEC64r_EVEX : DecOpR_RF<Xi64>, PL;
462  }
463}
464let Predicates = [UseIncDec] in {
465  def INC8m  : IncOpM_MF<Xi8>;
466  def INC16m : IncOpM_MF<Xi16>, OpSize16;
467  def INC32m : IncOpM_MF<Xi32>, OpSize32;
468  def DEC8m  : DecOpM_MF<Xi8>;
469  def DEC16m : DecOpM_MF<Xi16>, OpSize16;
470  def DEC32m : DecOpM_MF<Xi32>, OpSize32;
471}
472let Predicates = [UseIncDec, In64BitMode] in {
473  def INC64m : IncOpM_MF<Xi64>;
474  def DEC64m : DecOpM_MF<Xi64>;
475}
476let Predicates = [HasNDD, In64BitMode, UseIncDec] in {
477  def INC8m_ND  : IncOpM_RF<Xi8>;
478  def INC16m_ND : IncOpM_RF<Xi16>, PD;
479  def INC32m_ND : IncOpM_RF<Xi32>;
480  def DEC8m_ND  : DecOpM_RF<Xi8>;
481  def DEC16m_ND : DecOpM_RF<Xi16>, PD;
482  def DEC32m_ND : DecOpM_RF<Xi32>;
483  def INC64m_ND : IncOpM_RF<Xi64>;
484  def DEC64m_ND : DecOpM_RF<Xi64>;
485}
486let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
487  def INC8m_NF  : IncOpM_M<Xi8>, NF;
488  def INC16m_NF : IncOpM_M<Xi16>, NF, PD;
489  def INC32m_NF : IncOpM_M<Xi32>, NF;
490  def INC64m_NF : IncOpM_M<Xi64>, NF;
491  def DEC8m_NF  : DecOpM_M<Xi8>, NF;
492  def DEC16m_NF : DecOpM_M<Xi16>, NF, PD;
493  def DEC32m_NF : DecOpM_M<Xi32>, NF;
494  def DEC64m_NF : DecOpM_M<Xi64>, NF;
495  def INC8m_NF_ND  : IncOpM_R<Xi8>, NF;
496  def INC16m_NF_ND : IncOpM_R<Xi16>, NF, PD;
497  def INC32m_NF_ND : IncOpM_R<Xi32>, NF;
498  def INC64m_NF_ND : IncOpM_R<Xi64>, NF;
499  def DEC8m_NF_ND  : DecOpM_R<Xi8>, NF;
500  def DEC16m_NF_ND : DecOpM_R<Xi16>, NF, PD;
501  def DEC32m_NF_ND : DecOpM_R<Xi32>, NF;
502  def DEC64m_NF_ND : DecOpM_R<Xi64>, NF;
503  def INC8m_EVEX  : IncOpM_MF<Xi8>, PL;
504  def INC16m_EVEX : IncOpM_MF<Xi16>, PL, PD;
505  def INC32m_EVEX : IncOpM_MF<Xi32>, PL;
506  def INC64m_EVEX : IncOpM_MF<Xi64>, PL;
507  def DEC8m_EVEX  : DecOpM_MF<Xi8>, PL;
508  def DEC16m_EVEX : DecOpM_MF<Xi16>, PL, PD;
509  def DEC32m_EVEX : DecOpM_MF<Xi32>, PL;
510  def DEC64m_EVEX : DecOpM_MF<Xi64>, PL;
511}
512
513//===----------------------------------------------------------------------===//
514// NEG and NOT Instructions
515//
516class NegOpR_R<X86TypeInfo t, bit ndd = 0>
517  : UnaryOpR_R<0xF7, MRM3r, "neg", t, ineg, ndd>;
518class NegOpR_RF<X86TypeInfo t, bit ndd = 0>
519  : UnaryOpR_RF<0xF7, MRM3r, "neg", t, ineg, ndd>;
520class NegOpM_M<X86TypeInfo t> : UnaryOpM_M<0xF7, MRM3m, "neg", t, null_frag>;
521class NegOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xF7, MRM3m, "neg", t, ineg>;
522class NegOpM_R<X86TypeInfo t> : UnaryOpM_R<0xF7, MRM3m, "neg", t, null_frag>;
523class NegOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xF7, MRM3m, "neg", t, ineg>;
524
525class NotOpR_R<X86TypeInfo t, bit ndd = 0>
526  : UnaryOpR_R<0xF7, MRM2r, "not", t, not, ndd>;
527class NotOpM_M<X86TypeInfo t> : UnaryOpM_M<0xF7, MRM2m, "not", t, not>;
528class NotOpM_R<X86TypeInfo t> : UnaryOpM_R<0xF7, MRM2m, "not", t, not>;
529
530let Predicates = [NoNDD] in {
531def NEG8r  : NegOpR_RF<Xi8>;
532def NEG16r : NegOpR_RF<Xi16>, OpSize16;
533def NEG32r : NegOpR_RF<Xi32>, OpSize32;
534def NEG64r : NegOpR_RF<Xi64>;
535def NOT8r  : NotOpR_R<Xi8>;
536def NOT16r : NotOpR_R<Xi16>, OpSize16;
537def NOT32r : NotOpR_R<Xi32>, OpSize32;
538def NOT64r : NotOpR_R<Xi64>;
539}
540
541let Predicates = [HasNDD, In64BitMode] in {
542def NEG8r_ND  : NegOpR_RF<Xi8, 1>;
543def NEG16r_ND : NegOpR_RF<Xi16, 1>, PD;
544def NEG32r_ND : NegOpR_RF<Xi32, 1>;
545def NEG64r_ND : NegOpR_RF<Xi64, 1>;
546
547def NOT8r_ND  : NotOpR_R<Xi8, 1>;
548def NOT16r_ND : NotOpR_R<Xi16, 1>, PD;
549def NOT32r_ND : NotOpR_R<Xi32, 1>;
550def NOT64r_ND : NotOpR_R<Xi64, 1>;
551
552def NEG8r_NF_ND  : NegOpR_R<Xi8, 1>, EVEX_NF;
553def NEG16r_NF_ND : NegOpR_R<Xi16, 1>, EVEX_NF, PD;
554def NEG32r_NF_ND : NegOpR_R<Xi32, 1>, EVEX_NF;
555def NEG64r_NF_ND : NegOpR_R<Xi64, 1>, EVEX_NF;
556}
557
558def NEG8m  : NegOpM_MF<Xi8>;
559def NEG16m : NegOpM_MF<Xi16>, OpSize16;
560def NEG32m : NegOpM_MF<Xi32>, OpSize32;
561def NEG64m : NegOpM_MF<Xi64>, Requires<[In64BitMode]>;
562
563let Predicates = [HasNDD, In64BitMode] in {
564def NEG8m_ND  : NegOpM_RF<Xi8>;
565def NEG16m_ND : NegOpM_RF<Xi16>, PD;
566def NEG32m_ND : NegOpM_RF<Xi32>;
567def NEG64m_ND : NegOpM_RF<Xi64>;
568
569def NEG8m_NF_ND  : NegOpM_R<Xi8>, EVEX_NF;
570def NEG16m_NF_ND : NegOpM_R<Xi16>, EVEX_NF, PD;
571def NEG32m_NF_ND : NegOpM_R<Xi32>, EVEX_NF;
572def NEG64m_NF_ND : NegOpM_R<Xi64>, EVEX_NF;
573}
574
575def NOT8m  : NotOpM_M<Xi8>;
576def NOT16m : NotOpM_M<Xi16>, OpSize16;
577def NOT32m : NotOpM_M<Xi32>, OpSize32;
578def NOT64m : NotOpM_M<Xi64>, Requires<[In64BitMode]>;
579
580let Predicates = [HasNDD, In64BitMode] in {
581def NOT8m_ND  : NotOpM_R<Xi8>;
582def NOT16m_ND : NotOpM_R<Xi16>, PD;
583def NOT32m_ND : NotOpM_R<Xi32>;
584def NOT64m_ND : NotOpM_R<Xi64>;
585}
586
587let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
588def NEG8r_NF  : NegOpR_R<Xi8>, NF;
589def NEG16r_NF : NegOpR_R<Xi16>, NF, PD;
590def NEG32r_NF : NegOpR_R<Xi32>, NF;
591def NEG64r_NF : NegOpR_R<Xi64>, NF;
592def NEG8m_NF  : NegOpM_M<Xi8>, NF;
593def NEG16m_NF : NegOpM_M<Xi16>, NF, PD;
594def NEG32m_NF : NegOpM_M<Xi32>, NF;
595def NEG64m_NF : NegOpM_M<Xi64>, NF;
596
597def NEG8r_EVEX  : NegOpR_RF<Xi8>, PL;
598def NEG16r_EVEX : NegOpR_RF<Xi16>, PL, PD;
599def NEG32r_EVEX : NegOpR_RF<Xi32>, PL;
600def NEG64r_EVEX : NegOpR_RF<Xi64>, PL;
601
602def NOT8r_EVEX  : NotOpR_R<Xi8>, PL;
603def NOT16r_EVEX : NotOpR_R<Xi16>, PL, PD;
604def NOT32r_EVEX : NotOpR_R<Xi32>, PL;
605def NOT64r_EVEX : NotOpR_R<Xi64>, PL;
606
607def NEG8m_EVEX  : NegOpM_MF<Xi8>, PL;
608def NEG16m_EVEX : NegOpM_MF<Xi16>, PL, PD;
609def NEG32m_EVEX : NegOpM_MF<Xi32>, PL;
610def NEG64m_EVEX : NegOpM_MF<Xi64>, PL;
611
612def NOT8m_EVEX  : NotOpM_M<Xi8>, PL;
613def NOT16m_EVEX : NotOpM_M<Xi16>, PL, PD;
614def NOT32m_EVEX : NotOpM_M<Xi32>, PL;
615def NOT64m_EVEX : NotOpM_M<Xi64>, PL;
616}
617
618/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
619/// defined with "(set GPR:$dst, EFLAGS, (...".
620///
621/// It would be nice to get rid of the second and third argument here, but
622/// tblgen can't handle dependent type references aggressively enough: PR8330
623multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
624                         string mnemonic, Format RegMRM, Format MemMRM,
625                         SDNode opnodeflag, SDNode opnode,
626                         bit CommutableRR, bit ConvertibleToThreeAddress,
627                         bit ConvertibleToThreeAddressRR> {
628  let isCommutable = CommutableRR,
629      isConvertibleToThreeAddress = ConvertibleToThreeAddressRR in {
630    let Predicates = [NoNDD] in {
631      def 8rr  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
632      def 16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>, OpSize16;
633      def 32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>, OpSize32;
634      def 64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
635    }
636    let Predicates = [HasNDD, In64BitMode] in {
637      def 8rr_ND  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag, 1>;
638      def 16rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag, 1>, PD;
639      def 32rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag, 1>;
640      def 64rr_ND : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag, 1>;
641      def 8rr_NF_ND  : BinOpRR_R<BaseOpc, mnemonic, Xi8, 1>, EVEX_NF;
642      def 16rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi16, 1>, EVEX_NF, PD;
643      def 32rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi32, 1>, EVEX_NF;
644      def 64rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi64, 1>, EVEX_NF;
645    }
646    let Predicates = [In64BitMode] in {
647      def 8rr_NF  : BinOpRR_R<BaseOpc, mnemonic, Xi8>, NF;
648      def 16rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi16>, NF, PD;
649      def 32rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi32>, NF;
650      def 64rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi64>, NF;
651      def 8rr_EVEX  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
652      def 16rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
653      def 32rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
654      def 64rr_EVEX : BinOpRR_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
655    }
656  }
657
658  def 8rr_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>;
659  def 16rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
660  def 32rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
661  def 64rr_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>;
662  let Predicates = [In64BitMode] in {
663    def 8rr_EVEX_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
664    def 16rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
665    def 32rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
666    def 64rr_EVEX_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
667    def 8rr_ND_REV  : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
668    def 16rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
669    def 32rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
670    def 64rr_ND_REV : BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
671    def 8rr_NF_REV  : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8>, NF;
672    def 16rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16>, NF, PD;
673    def 32rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32>, NF;
674    def 64rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64>, NF;
675    def 8rr_NF_ND_REV  : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
676    def 16rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
677    def 32rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
678    def 64rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
679  }
680
681  let Predicates = [NoNDD] in {
682    def 8rm   : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
683    def 16rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>, OpSize16;
684    def 32rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>, OpSize32;
685    def 64rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
686  }
687  let Predicates = [HasNDD, In64BitMode] in {
688    def 8rm_ND  : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag, 1>;
689    def 16rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag, 1>, PD;
690    def 32rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag, 1>;
691    def 64rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag, 1>;
692    def 8rm_NF_ND  : BinOpRM_R<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
693    def 16rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
694    def 32rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
695    def 64rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
696  }
697  let Predicates = [In64BitMode] in {
698    def 8rm_NF  : BinOpRM_R<BaseOpc2, mnemonic, Xi8>, NF;
699    def 16rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi16>, NF, PD;
700    def 32rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi32>, NF;
701    def 64rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi64>, NF;
702    def 8rm_EVEX  : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , null_frag>, PL;
703    def 16rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, null_frag>, PL, PD;
704    def 32rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, null_frag>, PL;
705    def 64rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, null_frag>, PL;
706  }
707
708  let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
709    let Predicates = [NoNDD] in {
710      // NOTE: These are order specific, we want the ri8 forms to be listed
711      // first so that they are slightly preferred to the ri forms.
712      def 16ri8 : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
713      def 32ri8 : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
714      def 64ri8 : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>;
715      def 8ri   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
716      def 16ri  : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM>, OpSize16;
717      def 32ri  : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM>, OpSize32;
718      def 64ri32: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM>;
719    }
720    let Predicates = [HasNDD, In64BitMode] in {
721      def 16ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
722      def 32ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
723      def 64ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
724      def 8ri_ND   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM, 1>;
725      def 16ri_ND  : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM, 1>, PD;
726      def 32ri_ND  : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM, 1>;
727      def 64ri32_ND: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM, 1>;
728      def 16ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
729      def 32ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
730      def 64ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
731      def 8ri_NF_ND  : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM, 1>, EVEX_NF;
732      def 16ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
733      def 32ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
734      def 64ri32_NF_ND : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
735    }
736    let Predicates = [In64BitMode] in {
737      def 16ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM>, NF, PD;
738      def 32ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM>, NF;
739      def 64ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM>, NF;
740      def 8ri_NF  : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM>, NF;
741      def 16ri_NF : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM>, NF, PD;
742      def 32ri_NF : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM>, NF;
743      def 64ri32_NF : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM>, NF;
744      def 16ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
745      def 32ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
746      def 64ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
747      def 8ri_EVEX   : BinOpRI_RF<0x80, mnemonic, Xi8 , null_frag, RegMRM>, PL;
748      def 16ri_EVEX  : BinOpRI_RF<0x81, mnemonic, Xi16, null_frag, RegMRM>, PL, PD;
749      def 32ri_EVEX  : BinOpRI_RF<0x81, mnemonic, Xi32, null_frag, RegMRM>, PL;
750      def 64ri32_EVEX: BinOpRI_RF<0x81, mnemonic, Xi64, null_frag, RegMRM>, PL;
751    }
752  }
753
754  def 8mr    : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , opnode>;
755  def 16mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
756  def 32mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
757  def 64mr   : BinOpMR_MF<BaseOpc, mnemonic, Xi64, opnode>;
758  let Predicates = [HasNDD, In64BitMode] in {
759    defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
760    def 8mr_ND    : BinOpMR_RF<BaseOpc, mnemonic, Xi8 , node>;
761    def 16mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi16, node>, PD;
762    def 32mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi32, node>;
763    def 64mr_ND   : BinOpMR_RF<BaseOpc, mnemonic, Xi64, node>;
764    def 8mr_NF_ND    : BinOpMR_R<BaseOpc, mnemonic, Xi8>, EVEX_NF;
765    def 16mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi16>, EVEX_NF, PD;
766    def 32mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi32>, EVEX_NF;
767    def 64mr_NF_ND   : BinOpMR_R<BaseOpc, mnemonic, Xi64>, EVEX_NF;
768  }
769  let Predicates = [In64BitMode] in {
770    def 8mr_NF    : BinOpMR_M<BaseOpc, mnemonic, Xi8>, NF;
771    def 16mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi16>, NF, PD;
772    def 32mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi32>, NF;
773    def 64mr_NF   : BinOpMR_M<BaseOpc, mnemonic, Xi64>, NF;
774    def 8mr_EVEX    : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
775    def 16mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
776    def 32mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
777    def 64mr_EVEX   : BinOpMR_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
778  }
779
780  // NOTE: These are order specific, we want the mi8 forms to be listed
781  // first so that they are slightly preferred to the mi forms.
782  def 16mi8  : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, OpSize16;
783  def 32mi8  : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, OpSize32;
784  let Predicates = [In64BitMode] in
785    def 64mi8  : BinOpMI8_MF<mnemonic, Xi64, MemMRM>;
786  def 8mi    : BinOpMI_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
787  def 16mi   : BinOpMI_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
788  def 32mi   : BinOpMI_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
789  let Predicates = [In64BitMode] in
790    def 64mi32 : BinOpMI_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
791  let Predicates = [HasNDD, In64BitMode] in {
792    def 16mi8_ND  : BinOpMI8_RF<mnemonic, Xi16, MemMRM>, PD;
793    def 32mi8_ND  : BinOpMI8_RF<mnemonic, Xi32, MemMRM>;
794    def 64mi8_ND  : BinOpMI8_RF<mnemonic, Xi64, MemMRM>;
795    def 8mi_ND    : BinOpMI_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
796    def 16mi_ND   : BinOpMI_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
797    def 32mi_ND   : BinOpMI_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
798    def 64mi32_ND : BinOpMI_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
799    def 16mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi16, MemMRM>, NF, PD;
800    def 32mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi32, MemMRM>, NF;
801    def 64mi8_NF_ND  : BinOpMI8_R<mnemonic, Xi64, MemMRM>, NF;
802    def 8mi_NF_ND    : BinOpMI_R<0x80, mnemonic, Xi8, MemMRM>, NF;
803    def 16mi_NF_ND   : BinOpMI_R<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
804    def 32mi_NF_ND   : BinOpMI_R<0x81, mnemonic, Xi32, MemMRM>, NF;
805    def 64mi32_NF_ND : BinOpMI_R<0x81, mnemonic, Xi64, MemMRM>, NF;
806  }
807  let Predicates = [In64BitMode] in {
808    def 16mi8_NF  : BinOpMI8_M<mnemonic, Xi16, MemMRM>, NF, PD;
809    def 32mi8_NF  : BinOpMI8_M<mnemonic, Xi32, MemMRM>, NF;
810    def 64mi8_NF  : BinOpMI8_M<mnemonic, Xi64, MemMRM>, NF;
811    def 8mi_NF    : BinOpMI_M<0x80, mnemonic, Xi8, MemMRM>, NF;
812    def 16mi_NF   : BinOpMI_M<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
813    def 32mi_NF   : BinOpMI_M<0x81, mnemonic, Xi32, MemMRM>, NF;
814    def 64mi32_NF : BinOpMI_M<0x81, mnemonic, Xi64, MemMRM>, NF;
815    def 16mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, PL, PD;
816    def 32mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, PL;
817    def 64mi8_EVEX  : BinOpMI8_MF<mnemonic, Xi64, MemMRM>, PL;
818    def 8mi_EVEX    : BinOpMI_MF<0x80, mnemonic, Xi8 , null_frag, MemMRM>, PL;
819    def 16mi_EVEX   : BinOpMI_MF<0x81, mnemonic, Xi16, null_frag, MemMRM>, PL, PD;
820    def 32mi_EVEX   : BinOpMI_MF<0x81, mnemonic, Xi32, null_frag, MemMRM>, PL;
821    def 64mi32_EVEX : BinOpMI_MF<0x81, mnemonic, Xi64, null_frag, MemMRM>, PL;
822  }
823
824  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
825  // not in 64-bit mode.
826  let Predicates = [Not64BitMode] in {
827    def 8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
828    def 8mi8 : BinOpMI8_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
829  }
830
831  def 8i8 : BinOpAI_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
832  def 16i16 : BinOpAI_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
833  def 32i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
834  def 64i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
835}
836
837/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
838/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
839/// SBB.
840///
841/// It would be nice to get rid of the second and third argument here, but
842/// tblgen can't handle dependent type references aggressively enough: PR8330
843multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
844                          string mnemonic, Format RegMRM, Format MemMRM,
845                          SDNode opnode, bit CommutableRR,
846                           bit ConvertibleToThreeAddress> {
847  let isCommutable = CommutableRR in {
848    let Predicates = [NoNDD] in {
849      def 8rr  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , opnode>;
850      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
851        def 16rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
852        def 32rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
853        def 64rr : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, opnode>;
854      }
855    }
856    let Predicates = [HasNDD, In64BitMode] in {
857      def 8rr_ND  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , opnode, 1>;
858      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
859        def 16rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, opnode, 1>, PD;
860        def 32rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, opnode, 1>;
861        def 64rr_ND : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, opnode, 1>;
862      }
863    }
864  } // isCommutable
865
866  let Predicates = [In64BitMode] in {
867    def 8rr_EVEX  : BinOpRRF_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
868    def 16rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
869    def 32rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
870    def 64rr_EVEX : BinOpRRF_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
871  }
872
873  def 8rr_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8>;
874  def 16rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
875  def 32rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
876  def 64rr_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64>;
877  let Predicates = [In64BitMode] in {
878    def 8rr_ND_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
879    def 16rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
880    def 32rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
881    def 64rr_ND_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
882    def 8rr_EVEX_REV  : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
883    def 16rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
884    def 32rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
885    def 64rr_EVEX_REV : BinOpRRF_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
886  }
887
888  let Predicates = [NoNDD] in {
889    def 8rm   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode>;
890    def 16rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode>, OpSize16;
891    def 32rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode>, OpSize32;
892    def 64rm  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode>;
893  }
894  let Predicates = [HasNDD, In64BitMode] in {
895    def 8rm_ND   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode, 1>;
896    def 16rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode, 1>, PD;
897    def 32rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode, 1>;
898    def 64rm_ND  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode, 1>;
899  }
900  let Predicates = [In64BitMode] in {
901    def 8rm_EVEX   : BinOpRMF_RF<BaseOpc2, mnemonic, Xi8 , opnode>, PL;
902    def 16rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi16, opnode>, PL, PD;
903    def 32rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi32, opnode>, PL;
904    def 64rm_EVEX  : BinOpRMF_RF<BaseOpc2, mnemonic, Xi64, opnode>, PL;
905  }
906
907  let Predicates = [NoNDD] in {
908    def 8ri   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
909    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
910      // NOTE: These are order specific, we want the ri8 forms to be listed
911      // first so that they are slightly preferred to the ri forms.
912      def 16ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
913      def 32ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
914      def 64ri8 : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM>;
915
916      def 16ri  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM>, OpSize16;
917      def 32ri  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM>, OpSize32;
918      def 64ri32: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM>;
919    }
920  }
921
922  let Predicates = [HasNDD, In64BitMode] in {
923    def 8ri_ND   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM, 1>;
924    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
925      def 16ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
926      def 32ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
927      def 64ri8_ND : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
928      def 16ri_ND  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM, 1>, PD;
929      def 32ri_ND  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM, 1>;
930      def 64ri32_ND: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM, 1>;
931    }
932  }
933  let Predicates = [In64BitMode] in {
934    def 8ri_EVEX   : BinOpRIF_RF<0x80, mnemonic, Xi8 , opnode, RegMRM>, PL;
935    def 16ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
936    def 32ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
937    def 64ri8_EVEX : BinOpRI8F_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
938    def 16ri_EVEX  : BinOpRIF_RF<0x81, mnemonic, Xi16, opnode, RegMRM>, PL, PD;
939    def 32ri_EVEX  : BinOpRIF_RF<0x81, mnemonic, Xi32, opnode, RegMRM>, PL;
940    def 64ri32_EVEX: BinOpRIF_RF<0x81, mnemonic, Xi64, opnode, RegMRM>, PL;
941  }
942
943  def 8mr    : BinOpMRF_MF<BaseOpc, mnemonic, Xi8 , opnode>;
944  def 16mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
945  def 32mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
946  def 64mr   : BinOpMRF_MF<BaseOpc, mnemonic, Xi64, opnode>;
947  let Predicates = [HasNDD, In64BitMode] in {
948    defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
949    def 8mr_ND    : BinOpMRF_RF<BaseOpc, mnemonic, Xi8 , node>;
950    def 16mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi16, node>, PD;
951    def 32mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi32, node>;
952    def 64mr_ND   : BinOpMRF_RF<BaseOpc, mnemonic, Xi64, node>;
953  }
954  let Predicates = [In64BitMode] in {
955    def 8mr_EVEX    : BinOpMRF_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
956    def 16mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
957    def 32mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
958    def 64mr_EVEX   : BinOpMRF_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
959  }
960
961  // NOTE: These are order specific, we want the mi8 forms to be listed
962  // first so that they are slightly preferred to the mi forms.
963  def 8mi    : BinOpMIF_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
964  def 16mi8  : BinOpMI8F_MF<mnemonic, Xi16, MemMRM>, OpSize16;
965  def 32mi8  : BinOpMI8F_MF<mnemonic, Xi32, MemMRM>, OpSize32;
966  let Predicates = [In64BitMode] in
967    def 64mi8  : BinOpMI8F_MF<mnemonic, Xi64, MemMRM>;
968  def 16mi   : BinOpMIF_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
969  def 32mi   : BinOpMIF_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
970  let Predicates = [In64BitMode] in
971    def 64mi32 : BinOpMIF_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
972
973  let Predicates = [HasNDD, In64BitMode] in {
974    def 8mi_ND    : BinOpMIF_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
975    def 16mi8_ND  : BinOpMI8F_RF<mnemonic, Xi16, MemMRM>, PD;
976    def 32mi8_ND  : BinOpMI8F_RF<mnemonic, Xi32, MemMRM>;
977    def 64mi8_ND  : BinOpMI8F_RF<mnemonic, Xi64, MemMRM>;
978    def 16mi_ND   : BinOpMIF_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
979    def 32mi_ND   : BinOpMIF_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
980    def 64mi32_ND : BinOpMIF_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
981  }
982  let Predicates = [In64BitMode] in {
983    def 8mi_EVEX    : BinOpMIF_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>, PL;
984    def 16mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi16, MemMRM>, PL, PD;
985    def 32mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi32, MemMRM>, PL;
986    def 64mi8_EVEX  : BinOpMI8F_MF<mnemonic, Xi64, MemMRM>, PL;
987    def 16mi_EVEX   : BinOpMIF_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, PL, PD;
988    def 32mi_EVEX   : BinOpMIF_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, PL;
989    def 64mi32_EVEX : BinOpMIF_MF<0x81, mnemonic, Xi64, opnode, MemMRM>, PL;
990  }
991
992  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
993  // not in 64-bit mode.
994  let Predicates = [Not64BitMode]  in {
995    def 8ri8 : BinOpRI8F_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
996    def 8mi8 : BinOpMI8F_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
997  }
998
999  def 8i8 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
1000  def 16i16 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1001  def 32i32 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1002  def 64i32 : BinOpAIF_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
1003}
1004
1005/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
1006/// defined with "(set EFLAGS, (...".  It would be really nice to find a way
1007/// to factor this with the other ArithBinOp_*.
1008///
1009multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1010                        string mnemonic, Format RegMRM, Format MemMRM,
1011                        SDNode opnode, bit CommutableRR,
1012                        bit ConvertibleToThreeAddress> {
1013  let isCommutable = CommutableRR in {
1014    def 8rr  : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1015    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1016      def 16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
1017      def 32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
1018      def 64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1019    } // isConvertibleToThreeAddress
1020  } // isCommutable
1021
1022  def 8rr_REV  : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>;
1023  def 16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
1024  def 32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
1025  def 64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>;
1026
1027  def 8rm   : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
1028  def 16rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>, OpSize16;
1029  def 32rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>, OpSize32;
1030  def 64rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
1031
1032  def 8ri   : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1033
1034  let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1035    // NOTE: These are order specific, we want the ri8 forms to be listed
1036    // first so that they are slightly preferred to the ri forms.
1037    def 16ri8 : BinOpRI8_F<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
1038    def 32ri8 : BinOpRI8_F<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
1039    def 64ri8 : BinOpRI8_F<0x83, mnemonic, Xi64, RegMRM>;
1040
1041    def 16ri  : BinOpRI_F<0x81, mnemonic, Xi16, opnode, RegMRM>, OpSize16;
1042    def 32ri  : BinOpRI_F<0x81, mnemonic, Xi32, opnode, RegMRM>, OpSize32;
1043    def 64ri32: BinOpRI_F<0x81, mnemonic, Xi64, opnode, RegMRM>;
1044  }
1045
1046  def 8mr    : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1047  def 16mr   : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
1048  def 32mr   : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
1049  def 64mr   : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
1050
1051  // NOTE: These are order specific, we want the mi8 forms to be listed
1052  // first so that they are slightly preferred to the mi forms.
1053  def 16mi8  : BinOpMI8_F<mnemonic, Xi16, MemMRM>, OpSize16;
1054  def 32mi8  : BinOpMI8_F<mnemonic, Xi32, MemMRM>, OpSize32;
1055  let Predicates = [In64BitMode] in
1056  def 64mi8  : BinOpMI8_F<mnemonic, Xi64, MemMRM>;
1057
1058  def 8mi    : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1059  def 16mi   : BinOpMI_F<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
1060  def 32mi   : BinOpMI_F<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
1061  let Predicates = [In64BitMode] in
1062    def 64mi32 : BinOpMI_F<0x81, mnemonic, Xi64, opnode, MemMRM>;
1063
1064  // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1065  // not in 64-bit mode.
1066  let Predicates = [Not64BitMode] in {
1067    def 8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
1068    let mayLoad = 1 in
1069      def 8mi8 : BinOpMI8_F<mnemonic, Xi8, MemMRM>;
1070  }
1071
1072  def 8i8 : BinOpAI_F<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
1073  def 16i16 : BinOpAI_F<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1074  def 32i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1075  def 64i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
1076}
1077
1078
1079defm AND : ArithBinOp_RF<0x21, 0x23, 0x25, "and", MRM4r, MRM4m,
1080                         X86and_flag, and, 1, 0, 0>;
1081defm OR  : ArithBinOp_RF<0x09, 0x0B, 0x0D, "or", MRM1r, MRM1m,
1082                         X86or_flag, or, 1, 0, 0>;
1083defm XOR : ArithBinOp_RF<0x31, 0x33, 0x35, "xor", MRM6r, MRM6m,
1084                         X86xor_flag, xor, 1, 0, 0>;
1085defm ADD : ArithBinOp_RF<0x01, 0x03, 0x05, "add", MRM0r, MRM0m,
1086                         X86add_flag, add, 1, 1, 1>;
1087let isCompare = 1 in {
1088  defm SUB : ArithBinOp_RF<0x29, 0x2B, 0x2D, "sub", MRM5r, MRM5m,
1089                           X86sub_flag, sub, 0, 1, 0>;
1090}
1091
1092// Version of XOR8rr_NOREX that use GR8_NOREX. This is used by the handling of
1093// __builtin_parity where the last step xors an h-register with an l-register.
1094let isCodeGenOnly = 1, hasSideEffects = 0, Constraints = "$src1 = $dst",
1095    Defs = [EFLAGS], isCommutable = 1 in
1096  def XOR8rr_NOREX : I<0x30, MRMDestReg, (outs GR8_NOREX:$dst),
1097                       (ins GR8_NOREX:$src1, GR8_NOREX:$src2),
1098                       "xor{b}\t{$src2, $dst|$dst, $src2}", []>,
1099                       Sched<[WriteALU]>;
1100
1101// Arithmetic.
1102defm ADC : ArithBinOp_RFF<0x11, 0x13, 0x15, "adc", MRM2r, MRM2m, X86adc_flag,
1103                          1, 0>;
1104defm SBB : ArithBinOp_RFF<0x19, 0x1B, 0x1D, "sbb", MRM3r, MRM3m, X86sbb_flag,
1105                          0, 0>;
1106
1107let isCompare = 1 in {
1108  defm CMP : ArithBinOp_F<0x39, 0x3B, 0x3D, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
1109}
1110
1111// Patterns to recognize loads on the LHS of an ADC. We can't make X86adc_flag
1112// commutable since it has EFLAGs as an input.
1113let Predicates = [NoNDD] in {
1114  def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1115            (ADC8rm GR8:$src1, addr:$src2)>;
1116  def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1117            (ADC16rm GR16:$src1, addr:$src2)>;
1118  def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1119            (ADC32rm GR32:$src1, addr:$src2)>;
1120  def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1121            (ADC64rm GR64:$src1, addr:$src2)>;
1122}
1123let Predicates = [HasNDD] in {
1124  def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1125            (ADC8rm_ND GR8:$src1, addr:$src2)>;
1126  def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1127            (ADC16rm_ND GR16:$src1, addr:$src2)>;
1128  def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1129            (ADC32rm_ND GR32:$src1, addr:$src2)>;
1130  def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1131            (ADC64rm_ND GR64:$src1, addr:$src2)>;
1132}
1133
1134// Patterns to recognize RMW ADC with loads in operand 1.
1135def : Pat<(store (X86adc_flag GR8:$src, (loadi8 addr:$dst), EFLAGS),
1136                 addr:$dst),
1137          (ADC8mr addr:$dst, GR8:$src)>;
1138def : Pat<(store (X86adc_flag GR16:$src, (loadi16 addr:$dst), EFLAGS),
1139                 addr:$dst),
1140          (ADC16mr addr:$dst, GR16:$src)>;
1141def : Pat<(store (X86adc_flag GR32:$src, (loadi32 addr:$dst), EFLAGS),
1142                 addr:$dst),
1143          (ADC32mr addr:$dst, GR32:$src)>;
1144def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
1145                 addr:$dst),
1146          (ADC64mr addr:$dst, GR64:$src)>;
1147
1148// Patterns for basic arithmetic ops with relocImm for the immediate field.
1149multiclass ArithBinOp_RF_relocImm_Pats<SDNode OpNodeFlag, SDNode OpNode> {
1150  let Predicates = [NoNDD] in {
1151    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1152              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
1153    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1154              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
1155    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1156              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
1157    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1158              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1159
1160    def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst),
1161              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
1162    def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst),
1163              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
1164    def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst),
1165              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
1166    def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst),
1167              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
1168  }
1169  let Predicates = [HasNDD] in {
1170    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1171              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
1172    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1173              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
1174    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1175              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
1176    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1177              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1178
1179    def : Pat<(OpNode (load addr:$dst), relocImm8_su:$src),
1180              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
1181    def : Pat<(OpNode (load addr:$dst), relocImm16_su:$src),
1182              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
1183    def : Pat<(OpNode (load addr:$dst), relocImm32_su:$src),
1184              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
1185    def : Pat<(OpNode (load addr:$dst), i64relocImmSExt32_su:$src),
1186              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
1187  }
1188}
1189
1190multiclass ArithBinOp_RFF_relocImm_Pats<SDNode OpNodeFlag> {
1191  let Predicates = [NoNDD] in {
1192    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1193              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
1194    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
1195              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
1196    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
1197              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
1198    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
1199              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1200
1201    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst),
1202              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
1203    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst),
1204              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
1205    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst),
1206              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
1207    def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst),
1208              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
1209  }
1210  let Predicates = [HasNDD] in {
1211    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1212              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
1213    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
1214              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
1215    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
1216              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
1217    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
1218              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1219
1220    def : Pat<(OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS),
1221              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
1222    def : Pat<(OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS),
1223              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
1224    def : Pat<(OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS),
1225              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
1226    def : Pat<(OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS),
1227              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
1228  }
1229}
1230
1231multiclass ArithBinOp_F_relocImm_Pats<SDNode OpNodeFlag> {
1232  def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
1233            (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
1234  def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
1235            (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
1236  def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
1237            (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
1238  def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
1239            (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
1240
1241  def : Pat<(OpNodeFlag (loadi8 addr:$src1), relocImm8_su:$src2),
1242            (!cast<Instruction>(NAME#"8mi") addr:$src1, relocImm8_su:$src2)>;
1243  def : Pat<(OpNodeFlag (loadi16 addr:$src1), relocImm16_su:$src2),
1244            (!cast<Instruction>(NAME#"16mi") addr:$src1, relocImm16_su:$src2)>;
1245  def : Pat<(OpNodeFlag (loadi32 addr:$src1), relocImm32_su:$src2),
1246            (!cast<Instruction>(NAME#"32mi") addr:$src1, relocImm32_su:$src2)>;
1247  def : Pat<(OpNodeFlag (loadi64 addr:$src1), i64relocImmSExt32_su:$src2),
1248            (!cast<Instruction>(NAME#"64mi32") addr:$src1, i64relocImmSExt32_su:$src2)>;
1249}
1250
1251defm AND : ArithBinOp_RF_relocImm_Pats<X86and_flag, and>;
1252defm OR  : ArithBinOp_RF_relocImm_Pats<X86or_flag, or>;
1253defm XOR : ArithBinOp_RF_relocImm_Pats<X86xor_flag, xor>;
1254defm ADD : ArithBinOp_RF_relocImm_Pats<X86add_flag, add>;
1255defm SUB : ArithBinOp_RF_relocImm_Pats<X86sub_flag, sub>;
1256
1257defm ADC : ArithBinOp_RFF_relocImm_Pats<X86adc_flag>;
1258defm SBB : ArithBinOp_RFF_relocImm_Pats<X86sbb_flag>;
1259
1260defm CMP : ArithBinOp_F_relocImm_Pats<X86cmp>;
1261
1262// ADC is commutable, but we can't indicate that to tablegen. So manually
1263// reverse the operands.
1264def : Pat<(X86adc_flag GR8:$src1, relocImm8_su:$src2, EFLAGS),
1265          (ADC8ri relocImm8_su:$src2, GR8:$src1)>;
1266def : Pat<(X86adc_flag i16relocImmSExt8_su:$src2, GR16:$src1, EFLAGS),
1267          (ADC16ri8 GR16:$src1, i16relocImmSExt8_su:$src2)>;
1268def : Pat<(X86adc_flag relocImm16_su:$src2, GR16:$src1, EFLAGS),
1269          (ADC16ri GR16:$src1, relocImm16_su:$src2)>;
1270def : Pat<(X86adc_flag i32relocImmSExt8_su:$src2, GR32:$src1, EFLAGS),
1271          (ADC32ri8 GR32:$src1, i32relocImmSExt8_su:$src2)>;
1272def : Pat<(X86adc_flag relocImm32_su:$src2, GR32:$src1, EFLAGS),
1273          (ADC32ri GR32:$src1, relocImm32_su:$src2)>;
1274def : Pat<(X86adc_flag i64relocImmSExt8_su:$src2, GR64:$src1, EFLAGS),
1275          (ADC64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>;
1276def : Pat<(X86adc_flag i64relocImmSExt32_su:$src2, GR64:$src1, EFLAGS),
1277          (ADC64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
1278
1279def : Pat<(store (X86adc_flag relocImm8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1280          (ADC8mi addr:$dst, relocImm8_su:$src)>;
1281def : Pat<(store (X86adc_flag i16relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1282          (ADC16mi8 addr:$dst, i16relocImmSExt8_su:$src)>;
1283def : Pat<(store (X86adc_flag relocImm16_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1284          (ADC16mi addr:$dst, relocImm16_su:$src)>;
1285def : Pat<(store (X86adc_flag i32relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1286          (ADC32mi8 addr:$dst, i32relocImmSExt8_su:$src)>;
1287def : Pat<(store (X86adc_flag relocImm32_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1288          (ADC32mi addr:$dst, relocImm32_su:$src)>;
1289def : Pat<(store (X86adc_flag i64relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1290          (ADC64mi8 addr:$dst, i64relocImmSExt8_su:$src)>;
1291def : Pat<(store (X86adc_flag i64relocImmSExt32_su:$src, (load addr:$dst), EFLAGS), addr:$dst),
1292          (ADC64mi32 addr:$dst, i64relocImmSExt32_su:$src)>;
1293
1294//===----------------------------------------------------------------------===//
1295// Semantically, test instructions are similar like AND, except they don't
1296// generate a result.  From an encoding perspective, they are very different:
1297// they don't have all the usual imm8 and REV forms, and are encoded into a
1298// different space.
1299let isCompare = 1 in {
1300  let isCommutable = 1 in {
1301  // Avoid selecting these and instead use a test+and. Post processing will
1302  // combine them. This gives bunch of other patterns that start with
1303  // and a chance to match.
1304    def TEST8rr  : BinOpRR_F<0x84, "test", Xi8 , null_frag>;
1305    def TEST16rr : BinOpRR_F<0x85, "test", Xi16, null_frag>, OpSize16;
1306    def TEST32rr : BinOpRR_F<0x85, "test", Xi32, null_frag>, OpSize32;
1307    def TEST64rr : BinOpRR_F<0x85, "test", Xi64, null_frag>;
1308  } // isCommutable
1309
1310  def TEST8mr    : BinOpMR_F<0x84, "test", Xi8 , null_frag>;
1311  def TEST16mr   : BinOpMR_F<0x85, "test", Xi16, null_frag>, OpSize16;
1312  def TEST32mr   : BinOpMR_F<0x85, "test", Xi32, null_frag>, OpSize32;
1313  def TEST64mr   : BinOpMR_F<0x85, "test", Xi64, null_frag>;
1314
1315  def TEST8ri    : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1316  def TEST16ri   : BinOpRI_F<0xF7, "test", Xi16, X86testpat, MRM0r>, OpSize16;
1317  def TEST32ri   : BinOpRI_F<0xF7, "test", Xi32, X86testpat, MRM0r>, OpSize32;
1318  def TEST64ri32 : BinOpRI_F<0xF7, "test", Xi64, X86testpat, MRM0r>;
1319
1320  def TEST8mi    : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>;
1321  def TEST16mi   : BinOpMI_F<0xF7, "test", Xi16, X86testpat, MRM0m>, OpSize16;
1322  def TEST32mi   : BinOpMI_F<0xF7, "test", Xi32, X86testpat, MRM0m>, OpSize32;
1323
1324  let Predicates = [In64BitMode] in
1325    def TEST64mi32 : BinOpMI_F<0xF7, "test", Xi64, X86testpat, MRM0m>;
1326
1327  def TEST8i8 : BinOpAI_F<0xA8, "test", Xi8 , AL, "{$src, %al|al, $src}">;
1328  def TEST16i16 : BinOpAI_F<0xA9, "test", Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
1329  def TEST32i32 : BinOpAI_F<0xA9, "test", Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
1330  def TEST64i32 : BinOpAI_F<0xA9, "test", Xi64, RAX, "{$src, %rax|rax, $src}">;
1331} // isCompare
1332
1333// Patterns to match a relocImm into the immediate field.
1334def : Pat<(X86testpat GR8:$src1, relocImm8_su:$src2),
1335          (TEST8ri GR8:$src1, relocImm8_su:$src2)>;
1336def : Pat<(X86testpat GR16:$src1, relocImm16_su:$src2),
1337          (TEST16ri GR16:$src1, relocImm16_su:$src2)>;
1338def : Pat<(X86testpat GR32:$src1, relocImm32_su:$src2),
1339          (TEST32ri GR32:$src1, relocImm32_su:$src2)>;
1340def : Pat<(X86testpat GR64:$src1, i64relocImmSExt32_su:$src2),
1341          (TEST64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
1342
1343def : Pat<(X86testpat (loadi8 addr:$src1), relocImm8_su:$src2),
1344          (TEST8mi addr:$src1, relocImm8_su:$src2)>;
1345def : Pat<(X86testpat (loadi16 addr:$src1), relocImm16_su:$src2),
1346          (TEST16mi addr:$src1, relocImm16_su:$src2)>;
1347def : Pat<(X86testpat (loadi32 addr:$src1), relocImm32_su:$src2),
1348          (TEST32mi addr:$src1, relocImm32_su:$src2)>;
1349def : Pat<(X86testpat (loadi64 addr:$src1), i64relocImmSExt32_su:$src2),
1350          (TEST64mi32 addr:$src1, i64relocImmSExt32_su:$src2)>;
1351
1352//===----------------------------------------------------------------------===//
1353// ANDN Instruction
1354//
1355multiclass AndN<X86TypeInfo t, SDPatternOperator node, string suffix = ""> {
1356  defvar andn_rr_p =
1357    [(set t.RegClass:$dst, EFLAGS, (node (not t.RegClass:$src1),
1358     t.RegClass:$src2))];
1359  defvar andn_rm_p =
1360    [(set t.RegClass:$dst, EFLAGS, (node (not t.RegClass:$src1),
1361     (t.LoadNode addr:$src2)))];
1362  def rr#suffix : ITy<0xF2, MRMSrcReg, t, (outs t.RegClass:$dst),
1363                      (ins t.RegClass:$src1, t.RegClass:$src2), "andn",
1364                      binop_ndd_args, andn_rr_p>, VVVV, Sched<[WriteALU]>, T8;
1365  def rm#suffix : ITy<0xF2, MRMSrcMem, t, (outs t.RegClass:$dst),
1366                       (ins t.RegClass:$src1, t.MemOperand:$src2), "andn",
1367                       binop_ndd_args, andn_rm_p>, VVVV,
1368                       Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>, T8;
1369}
1370
1371// Complexity is reduced to give and with immediate a chance to match first.
1372let AddedComplexity = -6 in {
1373defm ANDN32 : AndN<Xi32, X86and_flag>, VEX, Requires<[HasBMI, NoEGPR]>, DefEFLAGS;
1374defm ANDN64 : AndN<Xi64, X86and_flag>, VEX, Requires<[HasBMI, NoEGPR]>, DefEFLAGS;
1375defm ANDN32 : AndN<Xi32, X86and_flag, "_EVEX">, EVEX, Requires<[HasBMI, HasEGPR, In64BitMode]>, DefEFLAGS;
1376defm ANDN64 : AndN<Xi64, X86and_flag, "_EVEX">, EVEX, Requires<[HasBMI, HasEGPR, In64BitMode]>, DefEFLAGS;
1377defm ANDN32 : AndN<Xi32, null_frag, "_NF">, EVEX, EVEX_NF, Requires<[In64BitMode]>;
1378defm ANDN64 : AndN<Xi64, null_frag, "_NF">, EVEX, EVEX_NF, Requires<[In64BitMode]>;
1379}
1380
1381multiclass Andn_Pats<string suffix> {
1382  def : Pat<(and (not GR32:$src1), GR32:$src2),
1383            (!cast<Instruction>(ANDN32rr#suffix) GR32:$src1, GR32:$src2)>;
1384  def : Pat<(and (not GR64:$src1), GR64:$src2),
1385            (!cast<Instruction>(ANDN64rr#suffix) GR64:$src1, GR64:$src2)>;
1386  def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
1387            (!cast<Instruction>(ANDN32rm#suffix) GR32:$src1, addr:$src2)>;
1388  def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
1389            (!cast<Instruction>(ANDN64rm#suffix) GR64:$src1, addr:$src2)>;
1390}
1391
1392let Predicates = [HasBMI, NoEGPR], AddedComplexity = -6 in
1393  defm : Andn_Pats<"">;
1394
1395let Predicates = [HasBMI, HasEGPR], AddedComplexity = -6 in
1396  defm : Andn_Pats<"_EVEX">;
1397
1398//===----------------------------------------------------------------------===//
1399// MULX Instruction
1400//
1401multiclass MulX<X86TypeInfo t, X86FoldableSchedWrite sched> {
1402  defvar mulx_args = "{$src, $dst2, $dst1|$dst1, $dst2, $src}";
1403  defvar mulx_rm_sched =
1404    [WriteIMulHLd, sched.Folded,
1405     // Memory operand.
1406     ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
1407     // Implicit read of EDX/RDX
1408     sched.ReadAfterFold];
1409
1410  def rr : ITy<0xF6, MRMSrcReg, t, (outs t.RegClass:$dst1, t.RegClass:$dst2),
1411               (ins t.RegClass:$src), "mulx", mulx_args, []>, T8, XD, VEX,
1412           VVVV, Sched<[WriteIMulH, sched]>;
1413  let mayLoad = 1 in
1414    def rm : ITy<0xF6, MRMSrcMem, t, (outs t.RegClass:$dst1, t.RegClass:$dst2),
1415                 (ins t.MemOperand:$src), "mulx", mulx_args, []>, T8, XD, VEX,
1416                 VVVV, Sched<mulx_rm_sched>;
1417
1418  let Predicates = [In64BitMode] in {
1419    def rr_EVEX : ITy<0xF6, MRMSrcReg, t,
1420                      (outs t.RegClass:$dst1, t.RegClass:$dst2),
1421                      (ins t.RegClass:$src), "mulx", mulx_args, []>, T8, XD,
1422                  EVEX, VVVV, Sched<[WriteIMulH, sched]>;
1423    let mayLoad = 1 in
1424      def rm_EVEX : ITy<0xF6, MRMSrcMem, t,
1425                        (outs t.RegClass:$dst1, t.RegClass:$dst2),
1426                        (ins t.MemOperand:$src), "mulx", mulx_args, []>, T8, XD,
1427                    EVEX, VVVV, Sched<mulx_rm_sched>;
1428  }
1429  // Pseudo instructions to be used when the low result isn't used. The
1430  // instruction is defined to keep the high if both destinations are the same.
1431  def Hrr : PseudoI<(outs t.RegClass:$dst), (ins t.RegClass:$src), []>,
1432            Sched<[sched]>;
1433  let mayLoad = 1 in
1434  def Hrm : PseudoI<(outs t.RegClass:$dst), (ins t.MemOperand:$src), []>,
1435            Sched<[sched.Folded]>;
1436}
1437
1438let Uses = [EDX] in
1439  defm MULX32 : MulX<Xi32, WriteMULX32>;
1440
1441let Uses = [RDX] in
1442  defm MULX64 : MulX<Xi64, WriteMULX64>, REX_W;
1443
1444//===----------------------------------------------------------------------===//
1445// ADCX and ADOX Instructions
1446//
1447// We don't have patterns for these as there is no advantage over ADC for
1448// most code.
1449let Form = MRMSrcReg in {
1450  def ADCX32rr : BinOpRRF_RF<0xF6, "adcx", Xi32>, T8, PD;
1451  def ADCX64rr : BinOpRRF_RF<0xF6, "adcx", Xi64>, T8, PD;
1452  def ADOX32rr : BinOpRRF_RF<0xF6, "adox", Xi32>, T8, XS;
1453  def ADOX64rr : BinOpRRF_RF<0xF6, "adox", Xi64>, T8, XS;
1454  let Predicates =[In64BitMode] in {
1455    def ADCX32rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
1456    def ADCX64rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
1457    def ADOX32rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
1458    def ADOX64rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
1459    def ADCX32rr_ND : BinOpRRF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
1460    def ADCX64rr_ND : BinOpRRF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
1461    def ADOX32rr_ND : BinOpRRF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
1462    def ADOX64rr_ND : BinOpRRF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
1463  }
1464}
1465let Form = MRMSrcMem in {
1466  def ADCX32rm : BinOpRMF_RF<0xF6, "adcx", Xi32>, T8, PD;
1467  def ADCX64rm : BinOpRMF_RF<0xF6, "adcx", Xi64>, T8, PD;
1468  def ADOX32rm : BinOpRMF_RF<0xF6, "adox", Xi32>, T8, XS;
1469  def ADOX64rm : BinOpRMF_RF<0xF6, "adox", Xi64>, T8, XS;
1470  let Predicates =[In64BitMode] in {
1471    def ADCX32rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
1472    def ADCX64rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
1473    def ADOX32rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
1474    def ADOX64rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
1475    def ADCX32rm_ND : BinOpRMF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
1476    def ADCX64rm_ND : BinOpRMF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
1477    def ADOX32rm_ND : BinOpRMF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
1478    def ADOX64rm_ND : BinOpRMF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
1479  }
1480}
1481