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