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//===----------------------------------------------------------------------===//
41//  Fixed-Register Multiplication and Division Instructions.
42//
43
44// SchedModel info for instruction that loads one value and gets the second
45// (and possibly third) value from a register.
46// This is used for instructions that put the memory operands before other
47// uses.
48class SchedLoadReg<X86FoldableSchedWrite Sched> : Sched<[Sched.Folded,
49  // Memory operand.
50  ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
51  // Register reads (implicit or explicit).
52  Sched.ReadAfterFold, Sched.ReadAfterFold]>;
53
54// Extra precision multiplication
55
56// AL is really implied by AX, but the registers in Defs must match the
57// SDNode results (i8, i32).
58// AL,AH = AL*GR8
59let Defs = [AL,EFLAGS,AX], Uses = [AL] in
60def MUL8r  : I<0xF6, MRM4r, (outs),  (ins GR8:$src), "mul{b}\t$src",
61               // FIXME: Used for 8-bit mul, ignore result upper 8 bits.
62               // This probably ought to be moved to a def : Pat<> if the
63               // syntax can be accepted.
64               [(set AL, (mul AL, GR8:$src)),
65                (implicit EFLAGS)]>, Sched<[WriteIMul8]>;
66// AX,DX = AX*GR16
67let Defs = [AX,DX,EFLAGS], Uses = [AX], hasSideEffects = 0 in
68def MUL16r : I<0xF7, MRM4r, (outs),  (ins GR16:$src),
69               "mul{w}\t$src",
70               []>, OpSize16, Sched<[WriteIMul16]>;
71// EAX,EDX = EAX*GR32
72let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], hasSideEffects = 0 in
73def MUL32r : I<0xF7, MRM4r, (outs),  (ins GR32:$src),
74               "mul{l}\t$src",
75               [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/]>,
76               OpSize32, Sched<[WriteIMul32]>;
77// RAX,RDX = RAX*GR64
78let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], hasSideEffects = 0 in
79def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src),
80                "mul{q}\t$src",
81                [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/]>,
82                Sched<[WriteIMul64]>;
83// AL,AH = AL*[mem8]
84let Defs = [AL,EFLAGS,AX], Uses = [AL] in
85def MUL8m  : I<0xF6, MRM4m, (outs), (ins i8mem :$src),
86               "mul{b}\t$src",
87               // FIXME: Used for 8-bit mul, ignore result upper 8 bits.
88               // This probably ought to be moved to a def : Pat<> if the
89               // syntax can be accepted.
90               [(set AL, (mul AL, (loadi8 addr:$src))),
91                (implicit EFLAGS)]>, SchedLoadReg<WriteIMul8>;
92// AX,DX = AX*[mem16]
93let mayLoad = 1, hasSideEffects = 0 in {
94let Defs = [AX,DX,EFLAGS], Uses = [AX] in
95def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src),
96               "mul{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIMul16>;
97// EAX,EDX = EAX*[mem32]
98let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
99def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src),
100              "mul{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIMul32>;
101// RAX,RDX = RAX*[mem64]
102let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
103def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src),
104                "mul{q}\t$src", []>, SchedLoadReg<WriteIMul64>,
105                Requires<[In64BitMode]>;
106}
107
108let hasSideEffects = 0 in {
109// AL,AH = AL*GR8
110let Defs = [AL,EFLAGS,AX], Uses = [AL] in
111def IMUL8r  : I<0xF6, MRM5r, (outs),  (ins GR8:$src), "imul{b}\t$src", []>,
112                Sched<[WriteIMul8]>;
113// AX,DX = AX*GR16
114let Defs = [AX,DX,EFLAGS], Uses = [AX] in
115def IMUL16r : I<0xF7, MRM5r, (outs),  (ins GR16:$src), "imul{w}\t$src", []>,
116                OpSize16, Sched<[WriteIMul16]>;
117// EAX,EDX = EAX*GR32
118let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
119def IMUL32r : I<0xF7, MRM5r, (outs),  (ins GR32:$src), "imul{l}\t$src", []>,
120                OpSize32, Sched<[WriteIMul32]>;
121// RAX,RDX = RAX*GR64
122let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
123def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), "imul{q}\t$src", []>,
124                 Sched<[WriteIMul64]>;
125
126let mayLoad = 1 in {
127// AL,AH = AL*[mem8]
128let Defs = [AL,EFLAGS,AX], Uses = [AL] in
129def IMUL8m  : I<0xF6, MRM5m, (outs), (ins i8mem :$src),
130                "imul{b}\t$src", []>, SchedLoadReg<WriteIMul8>;
131// AX,DX = AX*[mem16]
132let Defs = [AX,DX,EFLAGS], Uses = [AX] in
133def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src),
134                "imul{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIMul16>;
135// EAX,EDX = EAX*[mem32]
136let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
137def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src),
138                "imul{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIMul32>;
139// RAX,RDX = RAX*[mem64]
140let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
141def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src),
142                 "imul{q}\t$src", []>, SchedLoadReg<WriteIMul64>,
143                 Requires<[In64BitMode]>;
144}
145} // hasSideEffects
146
147
148let Defs = [EFLAGS] in {
149let Constraints = "$src1 = $dst" in {
150
151let isCommutable = 1 in {
152// X = IMUL Y, Z --> X = IMUL Z, Y
153// Register-Register Signed Integer Multiply
154def IMUL16rr : I<0xAF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src1,GR16:$src2),
155                 "imul{w}\t{$src2, $dst|$dst, $src2}",
156                 [(set GR16:$dst, EFLAGS,
157                       (X86smul_flag GR16:$src1, GR16:$src2))]>,
158                 Sched<[WriteIMul16Reg]>, TB, OpSize16;
159def IMUL32rr : I<0xAF, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src1,GR32:$src2),
160                 "imul{l}\t{$src2, $dst|$dst, $src2}",
161                 [(set GR32:$dst, EFLAGS,
162                       (X86smul_flag GR32:$src1, GR32:$src2))]>,
163                 Sched<[WriteIMul32Reg]>, TB, OpSize32;
164def IMUL64rr : RI<0xAF, MRMSrcReg, (outs GR64:$dst),
165                                   (ins GR64:$src1, GR64:$src2),
166                  "imul{q}\t{$src2, $dst|$dst, $src2}",
167                  [(set GR64:$dst, EFLAGS,
168                        (X86smul_flag GR64:$src1, GR64:$src2))]>,
169                  Sched<[WriteIMul64Reg]>, TB;
170} // isCommutable
171
172// Register-Memory Signed Integer Multiply
173def IMUL16rm : I<0xAF, MRMSrcMem, (outs GR16:$dst),
174                                  (ins GR16:$src1, i16mem:$src2),
175                 "imul{w}\t{$src2, $dst|$dst, $src2}",
176                 [(set GR16:$dst, EFLAGS,
177                       (X86smul_flag GR16:$src1, (loadi16 addr:$src2)))]>,
178                 Sched<[WriteIMul16Reg.Folded, WriteIMul16Reg.ReadAfterFold]>, TB, OpSize16;
179def IMUL32rm : I<0xAF, MRMSrcMem, (outs GR32:$dst),
180                 (ins GR32:$src1, i32mem:$src2),
181                 "imul{l}\t{$src2, $dst|$dst, $src2}",
182                 [(set GR32:$dst, EFLAGS,
183                       (X86smul_flag GR32:$src1, (loadi32 addr:$src2)))]>,
184                 Sched<[WriteIMul32Reg.Folded, WriteIMul32Reg.ReadAfterFold]>, TB, OpSize32;
185def IMUL64rm : RI<0xAF, MRMSrcMem, (outs GR64:$dst),
186                                   (ins GR64:$src1, i64mem:$src2),
187                  "imul{q}\t{$src2, $dst|$dst, $src2}",
188                  [(set GR64:$dst, EFLAGS,
189                        (X86smul_flag GR64:$src1, (loadi64 addr:$src2)))]>,
190                  Sched<[WriteIMul64Reg.Folded, WriteIMul32Reg.ReadAfterFold]>, TB;
191} // Constraints = "$src1 = $dst"
192
193} // Defs = [EFLAGS]
194
195// Surprisingly enough, these are not two address instructions!
196let Defs = [EFLAGS] in {
197// Register-Integer Signed Integer Multiply
198def IMUL16rri  : Ii16<0x69, MRMSrcReg,                      // GR16 = GR16*I16
199                      (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
200                      "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
201                      [(set GR16:$dst, EFLAGS,
202                            (X86smul_flag GR16:$src1, imm:$src2))]>,
203                      Sched<[WriteIMul16Imm]>, OpSize16;
204def IMUL16rri8 : Ii8<0x6B, MRMSrcReg,                       // GR16 = GR16*I8
205                     (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
206                     "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
207                     [(set GR16:$dst, EFLAGS,
208                           (X86smul_flag GR16:$src1, i16immSExt8:$src2))]>,
209                     Sched<[WriteIMul16Imm]>, OpSize16;
210def IMUL32rri  : Ii32<0x69, MRMSrcReg,                      // GR32 = GR32*I32
211                      (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
212                      "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
213                      [(set GR32:$dst, EFLAGS,
214                            (X86smul_flag GR32:$src1, imm:$src2))]>,
215                      Sched<[WriteIMul32Imm]>, OpSize32;
216def IMUL32rri8 : Ii8<0x6B, MRMSrcReg,                       // GR32 = GR32*I8
217                     (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
218                     "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
219                     [(set GR32:$dst, EFLAGS,
220                           (X86smul_flag GR32:$src1, i32immSExt8:$src2))]>,
221                     Sched<[WriteIMul32Imm]>, OpSize32;
222def IMUL64rri32 : RIi32S<0x69, MRMSrcReg,                    // GR64 = GR64*I32
223                         (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
224                         "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
225                         [(set GR64:$dst, EFLAGS,
226                             (X86smul_flag GR64:$src1, i64immSExt32:$src2))]>,
227                         Sched<[WriteIMul64Imm]>;
228def IMUL64rri8 : RIi8<0x6B, MRMSrcReg,                      // GR64 = GR64*I8
229                      (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
230                      "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
231                      [(set GR64:$dst, EFLAGS,
232                            (X86smul_flag GR64:$src1, i64immSExt8:$src2))]>,
233                      Sched<[WriteIMul64Imm]>;
234
235// Memory-Integer Signed Integer Multiply
236def IMUL16rmi  : Ii16<0x69, MRMSrcMem,                     // GR16 = [mem16]*I16
237                      (outs GR16:$dst), (ins i16mem:$src1, i16imm:$src2),
238                      "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
239                      [(set GR16:$dst, EFLAGS,
240                            (X86smul_flag (loadi16 addr:$src1), imm:$src2))]>,
241                      Sched<[WriteIMul16Imm.Folded]>, OpSize16;
242def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem,                       // GR16 = [mem16]*I8
243                     (outs GR16:$dst), (ins i16mem:$src1, i16i8imm :$src2),
244                     "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
245                     [(set GR16:$dst, EFLAGS,
246                           (X86smul_flag (loadi16 addr:$src1),
247                                         i16immSExt8:$src2))]>,
248                     Sched<[WriteIMul16Imm.Folded]>, OpSize16;
249def IMUL32rmi  : Ii32<0x69, MRMSrcMem,                     // GR32 = [mem32]*I32
250                      (outs GR32:$dst), (ins i32mem:$src1, i32imm:$src2),
251                      "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
252                      [(set GR32:$dst, EFLAGS,
253                            (X86smul_flag (loadi32 addr:$src1), imm:$src2))]>,
254                      Sched<[WriteIMul32Imm.Folded]>, OpSize32;
255def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem,                       // GR32 = [mem32]*I8
256                     (outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2),
257                     "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
258                     [(set GR32:$dst, EFLAGS,
259                           (X86smul_flag (loadi32 addr:$src1),
260                                         i32immSExt8:$src2))]>,
261                     Sched<[WriteIMul32Imm.Folded]>, OpSize32;
262def IMUL64rmi32 : RIi32S<0x69, MRMSrcMem,                   // GR64 = [mem64]*I32
263                         (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2),
264                         "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
265                         [(set GR64:$dst, EFLAGS,
266                              (X86smul_flag (loadi64 addr:$src1),
267                                            i64immSExt32:$src2))]>,
268                         Sched<[WriteIMul64Imm.Folded]>;
269def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem,                      // GR64 = [mem64]*I8
270                      (outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2),
271                      "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
272                      [(set GR64:$dst, EFLAGS,
273                            (X86smul_flag (loadi64 addr:$src1),
274                                          i64immSExt8:$src2))]>,
275                      Sched<[WriteIMul64Imm.Folded]>;
276} // Defs = [EFLAGS]
277
278// unsigned division/remainder
279let hasSideEffects = 1 in { // so that we don't speculatively execute
280let Defs = [AL,AH,EFLAGS], Uses = [AX] in
281def DIV8r  : I<0xF6, MRM6r, (outs),  (ins GR8:$src),    // AX/r8 = AL,AH
282               "div{b}\t$src", []>, Sched<[WriteDiv8]>;
283let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
284def DIV16r : I<0xF7, MRM6r, (outs),  (ins GR16:$src),   // DX:AX/r16 = AX,DX
285               "div{w}\t$src", []>, Sched<[WriteDiv16]>, OpSize16;
286let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
287def DIV32r : I<0xF7, MRM6r, (outs),  (ins GR32:$src),   // EDX:EAX/r32 = EAX,EDX
288               "div{l}\t$src", []>, Sched<[WriteDiv32]>, OpSize32;
289// RDX:RAX/r64 = RAX,RDX
290let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
291def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src),
292                "div{q}\t$src", []>, Sched<[WriteDiv64]>;
293
294let mayLoad = 1 in {
295let Defs = [AL,AH,EFLAGS], Uses = [AX] in
296def DIV8m  : I<0xF6, MRM6m, (outs), (ins i8mem:$src),   // AX/[mem8] = AL,AH
297               "div{b}\t$src", []>, SchedLoadReg<WriteDiv8>;
298let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
299def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src),  // DX:AX/[mem16] = AX,DX
300               "div{w}\t$src", []>, OpSize16, SchedLoadReg<WriteDiv16>;
301let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in    // EDX:EAX/[mem32] = EAX,EDX
302def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src),
303               "div{l}\t$src", []>, SchedLoadReg<WriteDiv32>, OpSize32;
304// RDX:RAX/[mem64] = RAX,RDX
305let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
306def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src),
307                "div{q}\t$src", []>, SchedLoadReg<WriteDiv64>,
308                Requires<[In64BitMode]>;
309}
310
311// Signed division/remainder.
312let Defs = [AL,AH,EFLAGS], Uses = [AX] in
313def IDIV8r : I<0xF6, MRM7r, (outs),  (ins GR8:$src),    // AX/r8 = AL,AH
314               "idiv{b}\t$src", []>, Sched<[WriteIDiv8]>;
315let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
316def IDIV16r: I<0xF7, MRM7r, (outs),  (ins GR16:$src),   // DX:AX/r16 = AX,DX
317               "idiv{w}\t$src", []>, Sched<[WriteIDiv16]>, OpSize16;
318let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
319def IDIV32r: I<0xF7, MRM7r, (outs),  (ins GR32:$src),   // EDX:EAX/r32 = EAX,EDX
320               "idiv{l}\t$src", []>, Sched<[WriteIDiv32]>, OpSize32;
321// RDX:RAX/r64 = RAX,RDX
322let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
323def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src),
324                "idiv{q}\t$src", []>, Sched<[WriteIDiv64]>;
325
326let mayLoad = 1 in {
327let Defs = [AL,AH,EFLAGS], Uses = [AX] in
328def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src),   // AX/[mem8] = AL,AH
329               "idiv{b}\t$src", []>, SchedLoadReg<WriteIDiv8>;
330let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
331def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src),  // DX:AX/[mem16] = AX,DX
332               "idiv{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIDiv16>;
333let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in    // EDX:EAX/[mem32] = EAX,EDX
334def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src),
335               "idiv{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIDiv32>;
336let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in // RDX:RAX/[mem64] = RAX,RDX
337def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src),
338                "idiv{q}\t$src", []>, SchedLoadReg<WriteIDiv64>,
339                Requires<[In64BitMode]>;
340}
341} // hasSideEffects = 0
342
343//===----------------------------------------------------------------------===//
344//  Two address Instructions.
345//
346
347// unary instructions
348let CodeSize = 2 in {
349let Defs = [EFLAGS] in {
350let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
351def NEG8r  : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src1),
352               "neg{b}\t$dst",
353               [(set GR8:$dst, (ineg GR8:$src1)),
354                (implicit EFLAGS)]>;
355def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src1),
356               "neg{w}\t$dst",
357               [(set GR16:$dst, (ineg GR16:$src1)),
358                (implicit EFLAGS)]>, OpSize16;
359def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src1),
360               "neg{l}\t$dst",
361               [(set GR32:$dst, (ineg GR32:$src1)),
362                (implicit EFLAGS)]>, OpSize32;
363def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src1), "neg{q}\t$dst",
364                [(set GR64:$dst, (ineg GR64:$src1)),
365                 (implicit EFLAGS)]>;
366} // Constraints = "$src1 = $dst", SchedRW
367
368// Read-modify-write negate.
369let SchedRW = [WriteALURMW] in {
370def NEG8m  : I<0xF6, MRM3m, (outs), (ins i8mem :$dst),
371               "neg{b}\t$dst",
372               [(store (ineg (loadi8 addr:$dst)), addr:$dst),
373                (implicit EFLAGS)]>;
374def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst),
375               "neg{w}\t$dst",
376               [(store (ineg (loadi16 addr:$dst)), addr:$dst),
377                (implicit EFLAGS)]>, OpSize16;
378def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst),
379               "neg{l}\t$dst",
380               [(store (ineg (loadi32 addr:$dst)), addr:$dst),
381                (implicit EFLAGS)]>, OpSize32;
382def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst",
383                [(store (ineg (loadi64 addr:$dst)), addr:$dst),
384                 (implicit EFLAGS)]>,
385                Requires<[In64BitMode]>;
386} // SchedRW
387} // Defs = [EFLAGS]
388
389
390// Note: NOT does not set EFLAGS!
391
392let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
393def NOT8r  : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src1),
394               "not{b}\t$dst",
395               [(set GR8:$dst, (not GR8:$src1))]>;
396def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src1),
397               "not{w}\t$dst",
398               [(set GR16:$dst, (not GR16:$src1))]>, OpSize16;
399def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src1),
400               "not{l}\t$dst",
401               [(set GR32:$dst, (not GR32:$src1))]>, OpSize32;
402def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src1), "not{q}\t$dst",
403                [(set GR64:$dst, (not GR64:$src1))]>;
404} // Constraints = "$src1 = $dst", SchedRW
405
406let SchedRW = [WriteALURMW] in {
407def NOT8m  : I<0xF6, MRM2m, (outs), (ins i8mem :$dst),
408               "not{b}\t$dst",
409               [(store (not (loadi8 addr:$dst)), addr:$dst)]>;
410def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst),
411               "not{w}\t$dst",
412               [(store (not (loadi16 addr:$dst)), addr:$dst)]>,
413               OpSize16;
414def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst),
415               "not{l}\t$dst",
416               [(store (not (loadi32 addr:$dst)), addr:$dst)]>,
417               OpSize32;
418def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst",
419                [(store (not (loadi64 addr:$dst)), addr:$dst)]>,
420                Requires<[In64BitMode]>;
421} // SchedRW
422} // CodeSize
423
424def X86add_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs),
425                               (X86add_flag node:$lhs, node:$rhs), [{
426  return hasNoCarryFlagUses(SDValue(N, 1));
427}]>;
428
429def X86sub_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs),
430                               (X86sub_flag node:$lhs, node:$rhs), [{
431  // Only use DEC if the result is used.
432  return !SDValue(N, 0).use_empty() && hasNoCarryFlagUses(SDValue(N, 1));
433}]>;
434
435// TODO: inc/dec is slow for P4, but fast for Pentium-M.
436let Defs = [EFLAGS] in {
437let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
438let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA.
439def INC8r  : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1),
440               "inc{b}\t$dst",
441               [(set GR8:$dst, EFLAGS, (X86add_flag_nocf GR8:$src1, 1))]>;
442def INC16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
443               "inc{w}\t$dst",
444               [(set GR16:$dst, EFLAGS, (X86add_flag_nocf GR16:$src1, 1))]>,
445               OpSize16;
446def INC32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
447               "inc{l}\t$dst",
448               [(set GR32:$dst, EFLAGS, (X86add_flag_nocf GR32:$src1, 1))]>,
449               OpSize32;
450def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src1), "inc{q}\t$dst",
451                [(set GR64:$dst, EFLAGS, (X86add_flag_nocf GR64:$src1, 1))]>;
452} // isConvertibleToThreeAddress = 1, CodeSize = 2
453
454// Short forms only valid in 32-bit mode. Selected during MCInst lowering.
455let CodeSize = 1, hasSideEffects = 0 in {
456def INC16r_alt : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
457                   "inc{w}\t$dst", []>,
458                 OpSize16, Requires<[Not64BitMode]>;
459def INC32r_alt : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
460                   "inc{l}\t$dst", []>,
461                 OpSize32, Requires<[Not64BitMode]>;
462} // CodeSize = 1, hasSideEffects = 0
463} // Constraints = "$src1 = $dst", SchedRW
464
465let CodeSize = 2, SchedRW = [WriteALURMW] in {
466let Predicates = [UseIncDec] in {
467  def INC8m  : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst",
468               [(store (add (loadi8 addr:$dst), 1), addr:$dst),
469                (implicit EFLAGS)]>;
470  def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst",
471               [(store (add (loadi16 addr:$dst), 1), addr:$dst),
472                (implicit EFLAGS)]>, OpSize16;
473  def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst",
474               [(store (add (loadi32 addr:$dst), 1), addr:$dst),
475                (implicit EFLAGS)]>, OpSize32;
476} // Predicates
477let Predicates = [UseIncDec, In64BitMode] in {
478  def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst",
479                  [(store (add (loadi64 addr:$dst), 1), addr:$dst),
480                   (implicit EFLAGS)]>;
481} // Predicates
482} // CodeSize = 2, SchedRW
483
484let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
485let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA.
486def DEC8r  : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1),
487               "dec{b}\t$dst",
488               [(set GR8:$dst, EFLAGS, (X86sub_flag_nocf GR8:$src1, 1))]>;
489def DEC16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src1),
490               "dec{w}\t$dst",
491               [(set GR16:$dst, EFLAGS, (X86sub_flag_nocf GR16:$src1, 1))]>,
492               OpSize16;
493def DEC32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src1),
494               "dec{l}\t$dst",
495               [(set GR32:$dst, EFLAGS, (X86sub_flag_nocf GR32:$src1, 1))]>,
496               OpSize32;
497def DEC64r : RI<0xFF, MRM1r, (outs GR64:$dst), (ins GR64:$src1), "dec{q}\t$dst",
498                [(set GR64:$dst, EFLAGS, (X86sub_flag_nocf GR64:$src1, 1))]>;
499} // isConvertibleToThreeAddress = 1, CodeSize = 2
500
501// Short forms only valid in 32-bit mode. Selected during MCInst lowering.
502let CodeSize = 1, hasSideEffects = 0 in {
503def DEC16r_alt : I<0x48, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
504                   "dec{w}\t$dst", []>,
505                 OpSize16, Requires<[Not64BitMode]>;
506def DEC32r_alt : I<0x48, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
507                   "dec{l}\t$dst", []>,
508                 OpSize32, Requires<[Not64BitMode]>;
509} // CodeSize = 1, hasSideEffects = 0
510} // Constraints = "$src1 = $dst", SchedRW
511
512
513let CodeSize = 2, SchedRW = [WriteALURMW] in {
514let Predicates = [UseIncDec] in {
515  def DEC8m  : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), "dec{b}\t$dst",
516               [(store (add (loadi8 addr:$dst), -1), addr:$dst),
517                (implicit EFLAGS)]>;
518  def DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst",
519               [(store (add (loadi16 addr:$dst), -1), addr:$dst),
520                (implicit EFLAGS)]>, OpSize16;
521  def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst",
522               [(store (add (loadi32 addr:$dst), -1), addr:$dst),
523                (implicit EFLAGS)]>, OpSize32;
524} // Predicates
525let Predicates = [UseIncDec, In64BitMode] in {
526  def DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), "dec{q}\t$dst",
527                  [(store (add (loadi64 addr:$dst), -1), addr:$dst),
528                   (implicit EFLAGS)]>;
529} // Predicates
530} // CodeSize = 2, SchedRW
531} // Defs = [EFLAGS]
532
533/// X86TypeInfo - This is a bunch of information that describes relevant X86
534/// information about value types.  For example, it can tell you what the
535/// register class and preferred load to use.
536class X86TypeInfo<ValueType vt, string instrsuffix, RegisterClass regclass,
537                  PatFrag loadnode, X86MemOperand memoperand, ImmType immkind,
538                  Operand immoperand, SDPatternOperator immoperator,
539                  Operand imm8operand, SDPatternOperator imm8operator,
540                  bit hasOddOpcode, OperandSize opSize,
541                  bit hasREX_WPrefix> {
542  /// VT - This is the value type itself.
543  ValueType VT = vt;
544
545  /// InstrSuffix - This is the suffix used on instructions with this type.  For
546  /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q".
547  string InstrSuffix = instrsuffix;
548
549  /// RegClass - This is the register class associated with this type.  For
550  /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64.
551  RegisterClass RegClass = regclass;
552
553  /// LoadNode - This is the load node associated with this type.  For
554  /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64.
555  PatFrag LoadNode = loadnode;
556
557  /// MemOperand - This is the memory operand associated with this type.  For
558  /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem.
559  X86MemOperand MemOperand = memoperand;
560
561  /// ImmEncoding - This is the encoding of an immediate of this type.  For
562  /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32.  Note that i64 -> Imm32
563  /// since the immediate fields of i64 instructions is a 32-bit sign extended
564  /// value.
565  ImmType ImmEncoding = immkind;
566
567  /// ImmOperand - This is the operand kind of an immediate of this type.  For
568  /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm.  Note that i64 ->
569  /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign
570  /// extended value.
571  Operand ImmOperand = immoperand;
572
573  /// ImmOperator - This is the operator that should be used to match an
574  /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32).
575  SDPatternOperator ImmOperator = immoperator;
576
577  /// Imm8Operand - This is the operand kind to use for an imm8 of this type.
578  /// For example, i8 -> <invalid>, i16 -> i16i8imm, i32 -> i32i8imm.  This is
579  /// only used for instructions that have a sign-extended imm8 field form.
580  Operand Imm8Operand = imm8operand;
581
582  /// Imm8Operator - This is the operator that should be used to match an 8-bit
583  /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8).
584  SDPatternOperator Imm8Operator = imm8operator;
585
586  /// HasOddOpcode - This bit is true if the instruction should have an odd (as
587  /// opposed to even) opcode.  Operations on i8 are usually even, operations on
588  /// other datatypes are odd.
589  bit HasOddOpcode = hasOddOpcode;
590
591  /// OpSize - Selects whether the instruction needs a 0x66 prefix based on
592  /// 16-bit vs 32-bit mode. i8/i64 set this to OpSizeFixed. i16 sets this
593  /// to Opsize16. i32 sets this to OpSize32.
594  OperandSize OpSize = opSize;
595
596  /// HasREX_WPrefix - This bit is set to true if the instruction should have
597  /// the 0x40 REX prefix.  This is set for i64 types.
598  bit HasREX_WPrefix = hasREX_WPrefix;
599}
600
601def invalid_node : SDNode<"<<invalid_node>>", SDTIntLeaf,[],"<<invalid_node>>">;
602
603
604def Xi8  : X86TypeInfo<i8, "b", GR8, loadi8, i8mem,
605                       Imm8, i8imm, relocImm8_su, i8imm, invalid_node,
606                       0, OpSizeFixed, 0>;
607def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem,
608                       Imm16, i16imm, relocImm16_su, i16i8imm, i16immSExt8_su,
609                       1, OpSize16, 0>;
610def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem,
611                       Imm32, i32imm, relocImm32_su, i32i8imm, i32immSExt8_su,
612                       1, OpSize32, 0>;
613def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem,
614                       Imm32S, i64i32imm, i64relocImmSExt32_su, i64i8imm, i64immSExt8_su,
615                       1, OpSizeFixed, 1>;
616
617/// ITy - This instruction base class takes the type info for the instruction.
618/// Using this, it:
619/// 1. Concatenates together the instruction mnemonic with the appropriate
620///    suffix letter, a tab, and the arguments.
621/// 2. Infers whether the instruction should have a 0x66 prefix byte.
622/// 3. Infers whether the instruction should have a 0x40 REX_W prefix.
623/// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations)
624///    or 1 (for i16,i32,i64 operations).
625class ITy<bits<8> opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins,
626          string mnemonic, string args, list<dag> pattern>
627  : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4},
628       opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode },
629      f, outs, ins,
630      !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern> {
631
632  // Infer instruction prefixes from type info.
633  let OpSize = typeinfo.OpSize;
634  let hasREX_WPrefix  = typeinfo.HasREX_WPrefix;
635}
636
637// BinOpRR - Instructions like "add reg, reg, reg".
638class BinOpRR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
639              dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
640  : ITy<opcode, MRMDestReg, typeinfo, outlist,
641        (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
642        mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
643    Sched<[sched]>;
644
645// BinOpRR_F - Instructions like "cmp reg, Reg", where the pattern has
646// just a EFLAGS as a result.
647class BinOpRR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
648                SDPatternOperator opnode>
649  : BinOpRR<opcode, mnemonic, typeinfo, (outs), WriteALU,
650            [(set EFLAGS,
651                  (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
652
653// BinOpRR_RF - Instructions like "add reg, reg, reg", where the pattern has
654// both a regclass and EFLAGS as a result.
655class BinOpRR_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
656                 SDNode opnode>
657  : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteALU,
658            [(set typeinfo.RegClass:$dst, EFLAGS,
659                  (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
660
661// BinOpRR_RFF - Instructions like "adc reg, reg, reg", where the pattern has
662// both a regclass and EFLAGS as a result, and has EFLAGS as input.
663class BinOpRR_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
664                  SDNode opnode>
665  : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteADC,
666            [(set typeinfo.RegClass:$dst, EFLAGS,
667                  (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2,
668                          EFLAGS))]>;
669
670// BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding).
671class BinOpRR_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
672                  X86FoldableSchedWrite sched = WriteALU>
673  : ITy<opcode, MRMSrcReg, typeinfo,
674        (outs typeinfo.RegClass:$dst),
675        (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
676        mnemonic, "{$src2, $dst|$dst, $src2}", []>,
677    Sched<[sched]> {
678  // The disassembler should know about this, but not the asmparser.
679  let isCodeGenOnly = 1;
680  let ForceDisassemble = 1;
681  let hasSideEffects = 0;
682}
683
684// BinOpRR_RDD_Rev - Instructions like "adc reg, reg, reg" (reversed encoding).
685class BinOpRR_RFF_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
686  : BinOpRR_Rev<opcode, mnemonic, typeinfo, WriteADC>;
687
688// BinOpRR_F_Rev - Instructions like "cmp reg, reg" (reversed encoding).
689class BinOpRR_F_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
690  : ITy<opcode, MRMSrcReg, typeinfo, (outs),
691        (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
692        mnemonic, "{$src2, $src1|$src1, $src2}", []>,
693    Sched<[WriteALU]> {
694  // The disassembler should know about this, but not the asmparser.
695  let isCodeGenOnly = 1;
696  let ForceDisassemble = 1;
697  let hasSideEffects = 0;
698}
699
700// BinOpRM - Instructions like "add reg, reg, [mem]".
701class BinOpRM<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
702              dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
703  : ITy<opcode, MRMSrcMem, typeinfo, outlist,
704        (ins typeinfo.RegClass:$src1, typeinfo.MemOperand:$src2),
705        mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
706    Sched<[sched.Folded, sched.ReadAfterFold]>;
707
708// BinOpRM_F - Instructions like "cmp reg, [mem]".
709class BinOpRM_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
710                SDNode opnode>
711  : BinOpRM<opcode, mnemonic, typeinfo, (outs), WriteALU,
712            [(set EFLAGS,
713            (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
714
715// BinOpRM_RF - Instructions like "add reg, reg, [mem]".
716class BinOpRM_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
717                 SDNode opnode>
718  : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteALU,
719            [(set typeinfo.RegClass:$dst, EFLAGS,
720            (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
721
722// BinOpRM_RFF - Instructions like "adc reg, reg, [mem]".
723class BinOpRM_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
724                 SDNode opnode>
725  : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteADC,
726            [(set typeinfo.RegClass:$dst, EFLAGS,
727            (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2),
728                    EFLAGS))]>;
729
730// BinOpRI - Instructions like "add reg, reg, imm".
731class BinOpRI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
732              Format f, dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
733  : ITy<opcode, f, typeinfo, outlist,
734        (ins typeinfo.RegClass:$src1, typeinfo.ImmOperand:$src2),
735        mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
736    Sched<[sched]> {
737  let ImmT = typeinfo.ImmEncoding;
738}
739
740// BinOpRI_F - Instructions like "cmp reg, imm".
741class BinOpRI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
742                SDPatternOperator opnode, Format f>
743  : BinOpRI<opcode, mnemonic, typeinfo, f, (outs), WriteALU,
744            [(set EFLAGS,
745                (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
746
747// BinOpRI_RF - Instructions like "add reg, reg, imm".
748class BinOpRI_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
749                 SDNode opnode, Format f>
750  : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteALU,
751            [(set typeinfo.RegClass:$dst, EFLAGS,
752                (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
753// BinOpRI_RFF - Instructions like "adc reg, reg, imm".
754class BinOpRI_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
755                 SDNode opnode, Format f>
756  : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteADC,
757            [(set typeinfo.RegClass:$dst, EFLAGS,
758                (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2,
759                        EFLAGS))]>;
760
761// BinOpRI8 - Instructions like "add reg, reg, imm8".
762class BinOpRI8<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
763               Format f, dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
764  : ITy<opcode, f, typeinfo, outlist,
765        (ins typeinfo.RegClass:$src1, typeinfo.Imm8Operand:$src2),
766        mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
767    Sched<[sched]> {
768  let ImmT = Imm8; // Always 8-bit immediate.
769}
770
771// BinOpRI8_F - Instructions like "cmp reg, imm8".
772class BinOpRI8_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
773                  SDPatternOperator opnode, Format f>
774  : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs), WriteALU,
775             [(set EFLAGS,
776               (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
777
778// BinOpRI8_RF - Instructions like "add reg, reg, imm8".
779class BinOpRI8_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
780                  SDPatternOperator opnode, Format f>
781  : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteALU,
782             [(set typeinfo.RegClass:$dst, EFLAGS,
783               (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
784
785// BinOpRI8_RFF - Instructions like "adc reg, reg, imm8".
786class BinOpRI8_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
787                   SDPatternOperator opnode, Format f>
788  : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteADC,
789             [(set typeinfo.RegClass:$dst, EFLAGS,
790               (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2,
791                       EFLAGS))]>;
792
793// BinOpMR - Instructions like "add [mem], reg".
794class BinOpMR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
795              list<dag> pattern>
796  : ITy<opcode, MRMDestMem, typeinfo,
797        (outs), (ins typeinfo.MemOperand:$dst, typeinfo.RegClass:$src),
798        mnemonic, "{$src, $dst|$dst, $src}", pattern>;
799
800// BinOpMR_RMW - Instructions like "add [mem], reg".
801class BinOpMR_RMW<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
802                  SDNode opnode>
803  : BinOpMR<opcode, mnemonic, typeinfo,
804          [(store (opnode (load addr:$dst), typeinfo.RegClass:$src), addr:$dst),
805           (implicit EFLAGS)]>, Sched<[WriteALURMW]>;
806
807// BinOpMR_RMW_FF - Instructions like "adc [mem], reg".
808class BinOpMR_RMW_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
809                    SDNode opnode>
810  : BinOpMR<opcode, mnemonic, typeinfo,
811            [(store (opnode (load addr:$dst), typeinfo.RegClass:$src, EFLAGS),
812                    addr:$dst),
813             (implicit EFLAGS)]>, Sched<[WriteADCRMW]>;
814
815// BinOpMR_F - Instructions like "cmp [mem], reg".
816class BinOpMR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
817                SDPatternOperator opnode>
818  : BinOpMR<opcode, mnemonic, typeinfo,
819            [(set EFLAGS, (opnode (typeinfo.LoadNode addr:$dst),
820                                   typeinfo.RegClass:$src))]>,
821            Sched<[WriteALU.Folded, ReadDefault, ReadDefault, ReadDefault,
822                   ReadDefault, ReadDefault, WriteALU.ReadAfterFold]>;
823
824// BinOpMI - Instructions like "add [mem], imm".
825class BinOpMI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
826              Format f, list<dag> pattern>
827  : ITy<opcode, f, typeinfo,
828        (outs), (ins typeinfo.MemOperand:$dst, typeinfo.ImmOperand:$src),
829        mnemonic, "{$src, $dst|$dst, $src}", pattern> {
830  let ImmT = typeinfo.ImmEncoding;
831}
832
833// BinOpMI_RMW - Instructions like "add [mem], imm".
834class BinOpMI_RMW<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
835                  SDNode opnode, Format f>
836  : BinOpMI<opcode, mnemonic, typeinfo, f,
837            [(store (opnode (typeinfo.VT (load addr:$dst)),
838                            typeinfo.ImmOperator:$src), addr:$dst),
839             (implicit EFLAGS)]>, Sched<[WriteALURMW]>;
840// BinOpMI_RMW_FF - Instructions like "adc [mem], imm".
841class BinOpMI_RMW_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
842                     SDNode opnode, Format f>
843  : BinOpMI<opcode, mnemonic, typeinfo, f,
844            [(store (opnode (typeinfo.VT (load addr:$dst)),
845                             typeinfo.ImmOperator:$src, EFLAGS), addr:$dst),
846             (implicit EFLAGS)]>, Sched<[WriteADCRMW]>;
847
848// BinOpMI_F - Instructions like "cmp [mem], imm".
849class BinOpMI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
850                SDPatternOperator opnode, Format f>
851  : BinOpMI<opcode, mnemonic, typeinfo, f,
852            [(set EFLAGS, (opnode (typeinfo.LoadNode addr:$dst),
853                                  typeinfo.ImmOperator:$src))]>,
854            Sched<[WriteALU.Folded]>;
855
856// BinOpMI8 - Instructions like "add [mem], imm8".
857class BinOpMI8<string mnemonic, X86TypeInfo typeinfo,
858               Format f, list<dag> pattern>
859  : ITy<0x82, f, typeinfo,
860        (outs), (ins typeinfo.MemOperand:$dst, typeinfo.Imm8Operand:$src),
861        mnemonic, "{$src, $dst|$dst, $src}", pattern> {
862  let ImmT = Imm8; // Always 8-bit immediate.
863}
864
865// BinOpMI8_RMW - Instructions like "add [mem], imm8".
866class BinOpMI8_RMW<string mnemonic, X86TypeInfo typeinfo,
867                   SDPatternOperator opnode, Format f>
868  : BinOpMI8<mnemonic, typeinfo, f,
869             [(store (opnode (load addr:$dst),
870                             typeinfo.Imm8Operator:$src), addr:$dst),
871              (implicit EFLAGS)]>, Sched<[WriteALURMW]>;
872
873// BinOpMI8_RMW_FF - Instructions like "adc [mem], imm8".
874class BinOpMI8_RMW_FF<string mnemonic, X86TypeInfo typeinfo,
875                      SDPatternOperator opnode, Format f>
876  : BinOpMI8<mnemonic, typeinfo, f,
877             [(store (opnode (load addr:$dst),
878                             typeinfo.Imm8Operator:$src, EFLAGS), addr:$dst),
879              (implicit EFLAGS)]>, Sched<[WriteADCRMW]>;
880
881// BinOpMI8_F - Instructions like "cmp [mem], imm8".
882class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
883                 SDPatternOperator opnode, Format f>
884  : BinOpMI8<mnemonic, typeinfo, f,
885             [(set EFLAGS, (opnode (typeinfo.LoadNode addr:$dst),
886                                    typeinfo.Imm8Operator:$src))]>,
887             Sched<[WriteALU.Folded]>;
888
889// BinOpAI - Instructions like "add %eax, %eax, imm", that imp-def EFLAGS.
890class BinOpAI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
891              Register areg, string operands, X86FoldableSchedWrite sched = WriteALU>
892  : ITy<opcode, RawFrm, typeinfo,
893        (outs), (ins typeinfo.ImmOperand:$src),
894        mnemonic, operands, []>, Sched<[sched]> {
895  let ImmT = typeinfo.ImmEncoding;
896  let Uses = [areg];
897  let Defs = [areg, EFLAGS];
898  let hasSideEffects = 0;
899}
900
901// BinOpAI_RFF - Instructions like "adc %eax, %eax, imm", that implicitly define
902// and use EFLAGS.
903class BinOpAI_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
904                  Register areg, string operands>
905  : BinOpAI<opcode, mnemonic, typeinfo, areg, operands, WriteADC> {
906  let Uses = [areg, EFLAGS];
907}
908
909// BinOpAI_F - Instructions like "cmp %eax, %eax, imm", that imp-def EFLAGS.
910class BinOpAI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
911                Register areg, string operands>
912  : BinOpAI<opcode, mnemonic, typeinfo, areg, operands> {
913  let Defs = [EFLAGS];
914}
915
916/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
917/// defined with "(set GPR:$dst, EFLAGS, (...".
918///
919/// It would be nice to get rid of the second and third argument here, but
920/// tblgen can't handle dependent type references aggressively enough: PR8330
921multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
922                         string mnemonic, Format RegMRM, Format MemMRM,
923                         SDNode opnodeflag, SDNode opnode,
924                         bit CommutableRR, bit ConvertibleToThreeAddress> {
925  let Defs = [EFLAGS] in {
926    let Constraints = "$src1 = $dst" in {
927      let isCommutable = CommutableRR in {
928        let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
929          def NAME#8rr  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
930          def NAME#16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>;
931          def NAME#32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>;
932          def NAME#64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
933        } // isConvertibleToThreeAddress
934      } // isCommutable
935
936      def NAME#8rr_REV  : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
937      def NAME#16rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
938      def NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
939      def NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
940
941      def NAME#8rm   : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
942      def NAME#16rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>;
943      def NAME#32rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>;
944      def NAME#64rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
945
946      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
947        def NAME#8ri   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
948
949        // NOTE: These are order specific, we want the ri8 forms to be listed
950        // first so that they are slightly preferred to the ri forms.
951        def NAME#16ri8 : BinOpRI8_RF<0x82, mnemonic, Xi16, opnodeflag, RegMRM>;
952        def NAME#32ri8 : BinOpRI8_RF<0x82, mnemonic, Xi32, opnodeflag, RegMRM>;
953        def NAME#64ri8 : BinOpRI8_RF<0x82, mnemonic, Xi64, opnodeflag, RegMRM>;
954
955        def NAME#16ri  : BinOpRI_RF<0x80, mnemonic, Xi16, opnodeflag, RegMRM>;
956        def NAME#32ri  : BinOpRI_RF<0x80, mnemonic, Xi32, opnodeflag, RegMRM>;
957        def NAME#64ri32: BinOpRI_RF<0x80, mnemonic, Xi64, opnodeflag, RegMRM>;
958      }
959    } // Constraints = "$src1 = $dst"
960
961    let mayLoad = 1, mayStore = 1 in {
962      def NAME#8mr    : BinOpMR_RMW<BaseOpc, mnemonic, Xi8 , opnode>;
963      def NAME#16mr   : BinOpMR_RMW<BaseOpc, mnemonic, Xi16, opnode>;
964      def NAME#32mr   : BinOpMR_RMW<BaseOpc, mnemonic, Xi32, opnode>;
965      def NAME#64mr   : BinOpMR_RMW<BaseOpc, mnemonic, Xi64, opnode>;
966    }
967
968    // NOTE: These are order specific, we want the mi8 forms to be listed
969    // first so that they are slightly preferred to the mi forms.
970    def NAME#16mi8  : BinOpMI8_RMW<mnemonic, Xi16, opnode, MemMRM>;
971    def NAME#32mi8  : BinOpMI8_RMW<mnemonic, Xi32, opnode, MemMRM>;
972    let Predicates = [In64BitMode] in
973    def NAME#64mi8  : BinOpMI8_RMW<mnemonic, Xi64, opnode, MemMRM>;
974
975    def NAME#8mi    : BinOpMI_RMW<0x80, mnemonic, Xi8 , opnode, MemMRM>;
976    def NAME#16mi   : BinOpMI_RMW<0x80, mnemonic, Xi16, opnode, MemMRM>;
977    def NAME#32mi   : BinOpMI_RMW<0x80, mnemonic, Xi32, opnode, MemMRM>;
978    let Predicates = [In64BitMode] in
979    def NAME#64mi32 : BinOpMI_RMW<0x80, mnemonic, Xi64, opnode, MemMRM>;
980
981    // These are for the disassembler since 0x82 opcode behaves like 0x80, but
982    // not in 64-bit mode.
983    let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
984        hasSideEffects = 0 in {
985      let Constraints = "$src1 = $dst" in
986        def NAME#8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, null_frag, RegMRM>;
987      let mayLoad = 1, mayStore = 1 in
988        def NAME#8mi8 : BinOpMI8_RMW<mnemonic, Xi8, null_frag, MemMRM>;
989    }
990  } // Defs = [EFLAGS]
991
992  def NAME#8i8   : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
993                           "{$src, %al|al, $src}">;
994  def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
995                           "{$src, %ax|ax, $src}">;
996  def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
997                           "{$src, %eax|eax, $src}">;
998  def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
999                           "{$src, %rax|rax, $src}">;
1000}
1001
1002/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
1003/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
1004/// SBB.
1005///
1006/// It would be nice to get rid of the second and third argument here, but
1007/// tblgen can't handle dependent type references aggressively enough: PR8330
1008multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1009                          string mnemonic, Format RegMRM, Format MemMRM,
1010                          SDNode opnode, bit CommutableRR,
1011                           bit ConvertibleToThreeAddress> {
1012  let Uses = [EFLAGS], Defs = [EFLAGS] in {
1013    let Constraints = "$src1 = $dst" in {
1014      let isCommutable = CommutableRR in {
1015        def NAME#8rr  : BinOpRR_RFF<BaseOpc, mnemonic, Xi8 , opnode>;
1016        let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1017          def NAME#16rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi16, opnode>;
1018          def NAME#32rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi32, opnode>;
1019          def NAME#64rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi64, opnode>;
1020        } // isConvertibleToThreeAddress
1021      } // isCommutable
1022
1023      def NAME#8rr_REV  : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
1024      def NAME#16rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
1025      def NAME#32rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
1026      def NAME#64rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
1027
1028      def NAME#8rm   : BinOpRM_RFF<BaseOpc2, mnemonic, Xi8 , opnode>;
1029      def NAME#16rm  : BinOpRM_RFF<BaseOpc2, mnemonic, Xi16, opnode>;
1030      def NAME#32rm  : BinOpRM_RFF<BaseOpc2, mnemonic, Xi32, opnode>;
1031      def NAME#64rm  : BinOpRM_RFF<BaseOpc2, mnemonic, Xi64, opnode>;
1032
1033      def NAME#8ri   : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1034
1035      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1036        // NOTE: These are order specific, we want the ri8 forms to be listed
1037        // first so that they are slightly preferred to the ri forms.
1038        def NAME#16ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>;
1039        def NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>;
1040        def NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>;
1041
1042        def NAME#16ri  : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>;
1043        def NAME#32ri  : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>;
1044        def NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>;
1045      }
1046    } // Constraints = "$src1 = $dst"
1047
1048    def NAME#8mr    : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi8 , opnode>;
1049    def NAME#16mr   : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi16, opnode>;
1050    def NAME#32mr   : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi32, opnode>;
1051    def NAME#64mr   : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi64, opnode>;
1052
1053    // NOTE: These are order specific, we want the mi8 forms to be listed
1054    // first so that they are slightly preferred to the mi forms.
1055    def NAME#16mi8  : BinOpMI8_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
1056    def NAME#32mi8  : BinOpMI8_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
1057    let Predicates = [In64BitMode] in
1058    def NAME#64mi8  : BinOpMI8_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
1059
1060    def NAME#8mi    : BinOpMI_RMW_FF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1061    def NAME#16mi   : BinOpMI_RMW_FF<0x80, mnemonic, Xi16, opnode, MemMRM>;
1062    def NAME#32mi   : BinOpMI_RMW_FF<0x80, mnemonic, Xi32, opnode, MemMRM>;
1063    let Predicates = [In64BitMode] in
1064    def NAME#64mi32 : BinOpMI_RMW_FF<0x80, mnemonic, Xi64, opnode, MemMRM>;
1065
1066    // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1067    // not in 64-bit mode.
1068    let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
1069        hasSideEffects = 0 in {
1070      let Constraints = "$src1 = $dst" in
1071        def NAME#8ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi8, null_frag, RegMRM>;
1072      let mayLoad = 1, mayStore = 1 in
1073        def NAME#8mi8 : BinOpMI8_RMW_FF<mnemonic, Xi8, null_frag, MemMRM>;
1074    }
1075  } // Uses = [EFLAGS], Defs = [EFLAGS]
1076
1077  def NAME#8i8   : BinOpAI_RFF<BaseOpc4, mnemonic, Xi8 , AL,
1078                               "{$src, %al|al, $src}">;
1079  def NAME#16i16 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi16, AX,
1080                               "{$src, %ax|ax, $src}">;
1081  def NAME#32i32 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi32, EAX,
1082                               "{$src, %eax|eax, $src}">;
1083  def NAME#64i32 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi64, RAX,
1084                               "{$src, %rax|rax, $src}">;
1085}
1086
1087/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
1088/// defined with "(set EFLAGS, (...".  It would be really nice to find a way
1089/// to factor this with the other ArithBinOp_*.
1090///
1091multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1092                        string mnemonic, Format RegMRM, Format MemMRM,
1093                        SDNode opnode,
1094                        bit CommutableRR, bit ConvertibleToThreeAddress> {
1095  let Defs = [EFLAGS] in {
1096    let isCommutable = CommutableRR in {
1097      def NAME#8rr  : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1098      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1099        def NAME#16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>;
1100        def NAME#32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>;
1101        def NAME#64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1102      }
1103    } // isCommutable
1104
1105    def NAME#8rr_REV  : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
1106    def NAME#16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
1107    def NAME#32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
1108    def NAME#64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
1109
1110    def NAME#8rm   : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
1111    def NAME#16rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>;
1112    def NAME#32rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>;
1113    def NAME#64rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
1114
1115    def NAME#8ri   : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1116
1117    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1118      // NOTE: These are order specific, we want the ri8 forms to be listed
1119      // first so that they are slightly preferred to the ri forms.
1120      def NAME#16ri8 : BinOpRI8_F<0x82, mnemonic, Xi16, opnode, RegMRM>;
1121      def NAME#32ri8 : BinOpRI8_F<0x82, mnemonic, Xi32, opnode, RegMRM>;
1122      def NAME#64ri8 : BinOpRI8_F<0x82, mnemonic, Xi64, opnode, RegMRM>;
1123
1124      def NAME#16ri  : BinOpRI_F<0x80, mnemonic, Xi16, opnode, RegMRM>;
1125      def NAME#32ri  : BinOpRI_F<0x80, mnemonic, Xi32, opnode, RegMRM>;
1126      def NAME#64ri32: BinOpRI_F<0x80, mnemonic, Xi64, opnode, RegMRM>;
1127    }
1128
1129    def NAME#8mr    : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1130    def NAME#16mr   : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>;
1131    def NAME#32mr   : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>;
1132    def NAME#64mr   : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
1133
1134    // NOTE: These are order specific, we want the mi8 forms to be listed
1135    // first so that they are slightly preferred to the mi forms.
1136    def NAME#16mi8  : BinOpMI8_F<mnemonic, Xi16, opnode, MemMRM>;
1137    def NAME#32mi8  : BinOpMI8_F<mnemonic, Xi32, opnode, MemMRM>;
1138    let Predicates = [In64BitMode] in
1139    def NAME#64mi8  : BinOpMI8_F<mnemonic, Xi64, opnode, MemMRM>;
1140
1141    def NAME#8mi    : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1142    def NAME#16mi   : BinOpMI_F<0x80, mnemonic, Xi16, opnode, MemMRM>;
1143    def NAME#32mi   : BinOpMI_F<0x80, mnemonic, Xi32, opnode, MemMRM>;
1144    let Predicates = [In64BitMode] in
1145    def NAME#64mi32 : BinOpMI_F<0x80, mnemonic, Xi64, opnode, MemMRM>;
1146
1147    // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1148    // not in 64-bit mode.
1149    let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
1150        hasSideEffects = 0 in {
1151      def NAME#8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, null_frag, RegMRM>;
1152      let mayLoad = 1 in
1153        def NAME#8mi8 : BinOpMI8_F<mnemonic, Xi8, null_frag, MemMRM>;
1154    }
1155  } // Defs = [EFLAGS]
1156
1157  def NAME#8i8   : BinOpAI_F<BaseOpc4, mnemonic, Xi8 , AL,
1158                             "{$src, %al|al, $src}">;
1159  def NAME#16i16 : BinOpAI_F<BaseOpc4, mnemonic, Xi16, AX,
1160                             "{$src, %ax|ax, $src}">;
1161  def NAME#32i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi32, EAX,
1162                             "{$src, %eax|eax, $src}">;
1163  def NAME#64i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi64, RAX,
1164                             "{$src, %rax|rax, $src}">;
1165}
1166
1167
1168defm AND : ArithBinOp_RF<0x20, 0x22, 0x24, "and", MRM4r, MRM4m,
1169                         X86and_flag, and, 1, 0>;
1170defm OR  : ArithBinOp_RF<0x08, 0x0A, 0x0C, "or", MRM1r, MRM1m,
1171                         X86or_flag, or, 1, 0>;
1172defm XOR : ArithBinOp_RF<0x30, 0x32, 0x34, "xor", MRM6r, MRM6m,
1173                         X86xor_flag, xor, 1, 0>;
1174defm ADD : ArithBinOp_RF<0x00, 0x02, 0x04, "add", MRM0r, MRM0m,
1175                         X86add_flag, add, 1, 1>;
1176let isCompare = 1 in {
1177defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m,
1178                         X86sub_flag, sub, 0, 0>;
1179}
1180
1181// Arithmetic.
1182defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
1183                          1, 0>;
1184defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
1185                          0, 0>;
1186
1187let isCompare = 1 in {
1188defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
1189}
1190
1191// Patterns to recognize loads on the LHS of an ADC. We can't make X86adc_flag
1192// commutable since it has EFLAGs as an input.
1193def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1194          (ADC8rm GR8:$src1, addr:$src2)>;
1195def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1196          (ADC16rm GR16:$src1, addr:$src2)>;
1197def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1198          (ADC32rm GR32:$src1, addr:$src2)>;
1199def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1200          (ADC64rm GR64:$src1, addr:$src2)>;
1201
1202// Patterns to recognize RMW ADC with loads in operand 1.
1203def : Pat<(store (X86adc_flag GR8:$src, (loadi8 addr:$dst), EFLAGS),
1204                 addr:$dst),
1205          (ADC8mr addr:$dst, GR8:$src)>;
1206def : Pat<(store (X86adc_flag GR16:$src, (loadi16 addr:$dst), EFLAGS),
1207                 addr:$dst),
1208          (ADC16mr addr:$dst, GR16:$src)>;
1209def : Pat<(store (X86adc_flag GR32:$src, (loadi32 addr:$dst), EFLAGS),
1210                 addr:$dst),
1211          (ADC32mr addr:$dst, GR32:$src)>;
1212def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
1213                 addr:$dst),
1214          (ADC64mr addr:$dst, GR64:$src)>;
1215
1216//===----------------------------------------------------------------------===//
1217// Semantically, test instructions are similar like AND, except they don't
1218// generate a result.  From an encoding perspective, they are very different:
1219// they don't have all the usual imm8 and REV forms, and are encoded into a
1220// different space.
1221def X86testpat : PatFrag<(ops node:$lhs, node:$rhs),
1222                         (X86cmp (and_su node:$lhs, node:$rhs), 0)>;
1223
1224let isCompare = 1 in {
1225  let Defs = [EFLAGS] in {
1226    let isCommutable = 1 in {
1227      // Avoid selecting these and instead use a test+and. Post processing will
1228      // combine them. This gives bunch of other patterns that start with
1229      // and a chance to match.
1230      def TEST8rr  : BinOpRR_F<0x84, "test", Xi8 , null_frag>;
1231      def TEST16rr : BinOpRR_F<0x84, "test", Xi16, null_frag>;
1232      def TEST32rr : BinOpRR_F<0x84, "test", Xi32, null_frag>;
1233      def TEST64rr : BinOpRR_F<0x84, "test", Xi64, null_frag>;
1234    } // isCommutable
1235
1236    let hasSideEffects = 0, mayLoad = 1 in {
1237    def TEST8mr    : BinOpMR_F<0x84, "test", Xi8 , null_frag>;
1238    def TEST16mr   : BinOpMR_F<0x84, "test", Xi16, null_frag>;
1239    def TEST32mr   : BinOpMR_F<0x84, "test", Xi32, null_frag>;
1240    def TEST64mr   : BinOpMR_F<0x84, "test", Xi64, null_frag>;
1241    }
1242
1243    def TEST8ri    : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1244    def TEST16ri   : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>;
1245    def TEST32ri   : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>;
1246    let Predicates = [In64BitMode] in
1247    def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>;
1248
1249    def TEST8mi    : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>;
1250    def TEST16mi   : BinOpMI_F<0xF6, "test", Xi16, X86testpat, MRM0m>;
1251    def TEST32mi   : BinOpMI_F<0xF6, "test", Xi32, X86testpat, MRM0m>;
1252    let Predicates = [In64BitMode] in
1253    def TEST64mi32 : BinOpMI_F<0xF6, "test", Xi64, X86testpat, MRM0m>;
1254  } // Defs = [EFLAGS]
1255
1256  def TEST8i8    : BinOpAI_F<0xA8, "test", Xi8 , AL,
1257                             "{$src, %al|al, $src}">;
1258  def TEST16i16  : BinOpAI_F<0xA8, "test", Xi16, AX,
1259                             "{$src, %ax|ax, $src}">;
1260  def TEST32i32  : BinOpAI_F<0xA8, "test", Xi32, EAX,
1261                             "{$src, %eax|eax, $src}">;
1262  def TEST64i32  : BinOpAI_F<0xA8, "test", Xi64, RAX,
1263                             "{$src, %rax|rax, $src}">;
1264} // isCompare
1265
1266//===----------------------------------------------------------------------===//
1267// ANDN Instruction
1268//
1269multiclass bmi_andn<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1270                    PatFrag ld_frag> {
1271  def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
1272            !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1273            [(set RC:$dst, EFLAGS, (X86and_flag (not RC:$src1), RC:$src2))]>,
1274            Sched<[WriteALU]>;
1275  def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
1276            !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1277            [(set RC:$dst, EFLAGS,
1278             (X86and_flag (not RC:$src1), (ld_frag addr:$src2)))]>,
1279           Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>;
1280}
1281
1282// Complexity is reduced to give and with immediate a chance to match first.
1283let Predicates = [HasBMI], Defs = [EFLAGS], AddedComplexity = -6 in {
1284  defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8PS, VEX_4V;
1285  defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8PS, VEX_4V, VEX_W;
1286}
1287
1288let Predicates = [HasBMI], AddedComplexity = -6 in {
1289  def : Pat<(and (not GR32:$src1), GR32:$src2),
1290            (ANDN32rr GR32:$src1, GR32:$src2)>;
1291  def : Pat<(and (not GR64:$src1), GR64:$src2),
1292            (ANDN64rr GR64:$src1, GR64:$src2)>;
1293  def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
1294            (ANDN32rm GR32:$src1, addr:$src2)>;
1295  def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
1296            (ANDN64rm GR64:$src1, addr:$src2)>;
1297}
1298
1299//===----------------------------------------------------------------------===//
1300// MULX Instruction
1301//
1302multiclass bmi_mulx<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1303                    X86FoldableSchedWrite sched> {
1304let hasSideEffects = 0 in {
1305  let isCommutable = 1 in
1306  def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src),
1307             !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1308             []>, T8XD, VEX_4V, Sched<[sched, WriteIMulH]>;
1309
1310  let mayLoad = 1 in
1311  def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src),
1312             !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1313             []>, T8XD, VEX_4V, Sched<[sched.Folded, WriteIMulH]>;
1314}
1315}
1316
1317let Predicates = [HasBMI2] in {
1318  let Uses = [EDX] in
1319    defm MULX32 : bmi_mulx<"mulx{l}", GR32, i32mem, WriteIMul32>;
1320  let Uses = [RDX] in
1321    defm MULX64 : bmi_mulx<"mulx{q}", GR64, i64mem, WriteIMul64>, VEX_W;
1322}
1323
1324//===----------------------------------------------------------------------===//
1325// ADCX and ADOX Instructions
1326//
1327// We don't have patterns for these as there is no advantage over ADC for
1328// most code.
1329let Predicates = [HasADX], Defs = [EFLAGS], Uses = [EFLAGS],
1330    Constraints = "$src1 = $dst", hasSideEffects = 0 in {
1331  let SchedRW = [WriteADC], isCommutable = 1 in {
1332  def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst),
1333                   (ins GR32:$src1, GR32:$src2),
1334                   "adcx{l}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1335  def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst),
1336                    (ins GR64:$src1, GR64:$src2),
1337                    "adcx{q}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1338
1339  def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst),
1340                   (ins GR32:$src1, GR32:$src2),
1341                   "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1342
1343  def ADOX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst),
1344                    (ins GR64:$src1, GR64:$src2),
1345                    "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1346  } // SchedRW
1347
1348  let mayLoad = 1, SchedRW = [WriteADC.Folded, WriteADC.ReadAfterFold] in {
1349  def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst),
1350                   (ins GR32:$src1, i32mem:$src2),
1351                   "adcx{l}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1352
1353  def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst),
1354                    (ins GR64:$src1, i64mem:$src2),
1355                    "adcx{q}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1356
1357  def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst),
1358                   (ins GR32:$src1, i32mem:$src2),
1359                   "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1360
1361  def ADOX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst),
1362                    (ins GR64:$src1, i64mem:$src2),
1363                    "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1364  } // mayLoad, SchedRW
1365}
1366