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