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// NOTE: These are order specific, we want the ri8 forms to be listed
198// first so that they are slightly preferred to the ri forms.
199
200// Register-Integer Signed Integer Multiply
201def IMUL16rri8 : Ii8<0x6B, MRMSrcReg,                       // GR16 = GR16*I8
202                     (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
203                     "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
204                     [(set GR16:$dst, EFLAGS,
205                           (X86smul_flag GR16:$src1, i16immSExt8:$src2))]>,
206                     Sched<[WriteIMul16Imm]>, OpSize16;
207def IMUL16rri  : Ii16<0x69, MRMSrcReg,                      // GR16 = GR16*I16
208                      (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
209                      "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
210                      [(set GR16:$dst, EFLAGS,
211                            (X86smul_flag GR16:$src1, imm:$src2))]>,
212                      Sched<[WriteIMul16Imm]>, OpSize16;
213def IMUL32rri  : Ii32<0x69, MRMSrcReg,                      // GR32 = GR32*I32
214                      (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
215                      "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
216                      [(set GR32:$dst, EFLAGS,
217                            (X86smul_flag GR32:$src1, imm:$src2))]>,
218                      Sched<[WriteIMul32Imm]>, OpSize32;
219def IMUL32rri8 : Ii8<0x6B, MRMSrcReg,                       // GR32 = GR32*I8
220                     (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
221                     "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
222                     [(set GR32:$dst, EFLAGS,
223                           (X86smul_flag GR32:$src1, i32immSExt8:$src2))]>,
224                     Sched<[WriteIMul32Imm]>, OpSize32;
225def IMUL64rri8 : RIi8<0x6B, MRMSrcReg,                      // GR64 = GR64*I8
226                      (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
227                      "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
228                      [(set GR64:$dst, EFLAGS,
229                            (X86smul_flag GR64:$src1, i64immSExt8:$src2))]>,
230                      Sched<[WriteIMul64Imm]>;
231def IMUL64rri32 : RIi32S<0x69, MRMSrcReg,                    // GR64 = GR64*I32
232                         (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
233                         "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
234                         [(set GR64:$dst, EFLAGS,
235                             (X86smul_flag GR64:$src1, i64immSExt32:$src2))]>,
236                         Sched<[WriteIMul64Imm]>;
237
238// Memory-Integer Signed Integer Multiply
239def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem,                       // GR16 = [mem16]*I8
240                     (outs GR16:$dst), (ins i16mem:$src1, i16i8imm :$src2),
241                     "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
242                     [(set GR16:$dst, EFLAGS,
243                           (X86smul_flag (loadi16 addr:$src1),
244                                         i16immSExt8:$src2))]>,
245                     Sched<[WriteIMul16Imm.Folded]>, OpSize16;
246def IMUL16rmi  : Ii16<0x69, MRMSrcMem,                     // GR16 = [mem16]*I16
247                      (outs GR16:$dst), (ins i16mem:$src1, i16imm:$src2),
248                      "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
249                      [(set GR16:$dst, EFLAGS,
250                            (X86smul_flag (loadi16 addr:$src1), imm:$src2))]>,
251                      Sched<[WriteIMul16Imm.Folded]>, OpSize16;
252def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem,                       // GR32 = [mem32]*I8
253                     (outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2),
254                     "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
255                     [(set GR32:$dst, EFLAGS,
256                           (X86smul_flag (loadi32 addr:$src1),
257                                         i32immSExt8:$src2))]>,
258                     Sched<[WriteIMul32Imm.Folded]>, OpSize32;
259def IMUL32rmi  : Ii32<0x69, MRMSrcMem,                     // GR32 = [mem32]*I32
260                      (outs GR32:$dst), (ins i32mem:$src1, i32imm:$src2),
261                      "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
262                      [(set GR32:$dst, EFLAGS,
263                            (X86smul_flag (loadi32 addr:$src1), imm:$src2))]>,
264                      Sched<[WriteIMul32Imm.Folded]>, OpSize32;
265def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem,                      // GR64 = [mem64]*I8
266                      (outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2),
267                      "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
268                      [(set GR64:$dst, EFLAGS,
269                            (X86smul_flag (loadi64 addr:$src1),
270                                          i64immSExt8:$src2))]>,
271                      Sched<[WriteIMul64Imm.Folded]>;
272def IMUL64rmi32 : RIi32S<0x69, MRMSrcMem,                   // GR64 = [mem64]*I32
273                         (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2),
274                         "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
275                         [(set GR64:$dst, EFLAGS,
276                              (X86smul_flag (loadi64 addr:$src1),
277                                            i64immSExt32:$src2))]>,
278                         Sched<[WriteIMul64Imm.Folded]>;
279} // Defs = [EFLAGS]
280
281// unsigned division/remainder
282let hasSideEffects = 1 in { // so that we don't speculatively execute
283let Defs = [AL,AH,EFLAGS], Uses = [AX] in
284def DIV8r  : I<0xF6, MRM6r, (outs),  (ins GR8:$src),    // AX/r8 = AL,AH
285               "div{b}\t$src", []>, Sched<[WriteDiv8]>;
286let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
287def DIV16r : I<0xF7, MRM6r, (outs),  (ins GR16:$src),   // DX:AX/r16 = AX,DX
288               "div{w}\t$src", []>, Sched<[WriteDiv16]>, OpSize16;
289let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
290def DIV32r : I<0xF7, MRM6r, (outs),  (ins GR32:$src),   // EDX:EAX/r32 = EAX,EDX
291               "div{l}\t$src", []>, Sched<[WriteDiv32]>, OpSize32;
292// RDX:RAX/r64 = RAX,RDX
293let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
294def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src),
295                "div{q}\t$src", []>, Sched<[WriteDiv64]>;
296
297let mayLoad = 1 in {
298let Defs = [AL,AH,EFLAGS], Uses = [AX] in
299def DIV8m  : I<0xF6, MRM6m, (outs), (ins i8mem:$src),   // AX/[mem8] = AL,AH
300               "div{b}\t$src", []>, SchedLoadReg<WriteDiv8>;
301let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
302def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src),  // DX:AX/[mem16] = AX,DX
303               "div{w}\t$src", []>, OpSize16, SchedLoadReg<WriteDiv16>;
304let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in    // EDX:EAX/[mem32] = EAX,EDX
305def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src),
306               "div{l}\t$src", []>, SchedLoadReg<WriteDiv32>, OpSize32;
307// RDX:RAX/[mem64] = RAX,RDX
308let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
309def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src),
310                "div{q}\t$src", []>, SchedLoadReg<WriteDiv64>,
311                Requires<[In64BitMode]>;
312}
313
314// Signed division/remainder.
315let Defs = [AL,AH,EFLAGS], Uses = [AX] in
316def IDIV8r : I<0xF6, MRM7r, (outs),  (ins GR8:$src),    // AX/r8 = AL,AH
317               "idiv{b}\t$src", []>, Sched<[WriteIDiv8]>;
318let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
319def IDIV16r: I<0xF7, MRM7r, (outs),  (ins GR16:$src),   // DX:AX/r16 = AX,DX
320               "idiv{w}\t$src", []>, Sched<[WriteIDiv16]>, OpSize16;
321let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
322def IDIV32r: I<0xF7, MRM7r, (outs),  (ins GR32:$src),   // EDX:EAX/r32 = EAX,EDX
323               "idiv{l}\t$src", []>, Sched<[WriteIDiv32]>, OpSize32;
324// RDX:RAX/r64 = RAX,RDX
325let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
326def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src),
327                "idiv{q}\t$src", []>, Sched<[WriteIDiv64]>;
328
329let mayLoad = 1 in {
330let Defs = [AL,AH,EFLAGS], Uses = [AX] in
331def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src),   // AX/[mem8] = AL,AH
332               "idiv{b}\t$src", []>, SchedLoadReg<WriteIDiv8>;
333let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
334def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src),  // DX:AX/[mem16] = AX,DX
335               "idiv{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIDiv16>;
336let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in    // EDX:EAX/[mem32] = EAX,EDX
337def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src),
338               "idiv{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIDiv32>;
339let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in // RDX:RAX/[mem64] = RAX,RDX
340def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src),
341                "idiv{q}\t$src", []>, SchedLoadReg<WriteIDiv64>,
342                Requires<[In64BitMode]>;
343}
344} // hasSideEffects = 0
345
346//===----------------------------------------------------------------------===//
347//  Two address Instructions.
348//
349
350// unary instructions
351let CodeSize = 2 in {
352let Defs = [EFLAGS] in {
353let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
354def NEG8r  : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src1),
355               "neg{b}\t$dst",
356               [(set GR8:$dst, (ineg GR8:$src1)),
357                (implicit EFLAGS)]>;
358def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src1),
359               "neg{w}\t$dst",
360               [(set GR16:$dst, (ineg GR16:$src1)),
361                (implicit EFLAGS)]>, OpSize16;
362def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src1),
363               "neg{l}\t$dst",
364               [(set GR32:$dst, (ineg GR32:$src1)),
365                (implicit EFLAGS)]>, OpSize32;
366def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src1), "neg{q}\t$dst",
367                [(set GR64:$dst, (ineg GR64:$src1)),
368                 (implicit EFLAGS)]>;
369} // Constraints = "$src1 = $dst", SchedRW
370
371// Read-modify-write negate.
372let SchedRW = [WriteALURMW] in {
373def NEG8m  : I<0xF6, MRM3m, (outs), (ins i8mem :$dst),
374               "neg{b}\t$dst",
375               [(store (ineg (loadi8 addr:$dst)), addr:$dst),
376                (implicit EFLAGS)]>;
377def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst),
378               "neg{w}\t$dst",
379               [(store (ineg (loadi16 addr:$dst)), addr:$dst),
380                (implicit EFLAGS)]>, OpSize16;
381def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst),
382               "neg{l}\t$dst",
383               [(store (ineg (loadi32 addr:$dst)), addr:$dst),
384                (implicit EFLAGS)]>, OpSize32;
385def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst",
386                [(store (ineg (loadi64 addr:$dst)), addr:$dst),
387                 (implicit EFLAGS)]>,
388                Requires<[In64BitMode]>;
389} // SchedRW
390} // Defs = [EFLAGS]
391
392
393// Note: NOT does not set EFLAGS!
394
395let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
396def NOT8r  : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src1),
397               "not{b}\t$dst",
398               [(set GR8:$dst, (not GR8:$src1))]>;
399def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src1),
400               "not{w}\t$dst",
401               [(set GR16:$dst, (not GR16:$src1))]>, OpSize16;
402def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src1),
403               "not{l}\t$dst",
404               [(set GR32:$dst, (not GR32:$src1))]>, OpSize32;
405def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src1), "not{q}\t$dst",
406                [(set GR64:$dst, (not GR64:$src1))]>;
407} // Constraints = "$src1 = $dst", SchedRW
408
409let SchedRW = [WriteALURMW] in {
410def NOT8m  : I<0xF6, MRM2m, (outs), (ins i8mem :$dst),
411               "not{b}\t$dst",
412               [(store (not (loadi8 addr:$dst)), addr:$dst)]>;
413def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst),
414               "not{w}\t$dst",
415               [(store (not (loadi16 addr:$dst)), addr:$dst)]>,
416               OpSize16;
417def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst),
418               "not{l}\t$dst",
419               [(store (not (loadi32 addr:$dst)), addr:$dst)]>,
420               OpSize32;
421def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst",
422                [(store (not (loadi64 addr:$dst)), addr:$dst)]>,
423                Requires<[In64BitMode]>;
424} // SchedRW
425} // CodeSize
426
427def X86add_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs),
428                               (X86add_flag node:$lhs, node:$rhs), [{
429  return hasNoCarryFlagUses(SDValue(N, 1));
430}]>;
431
432def X86sub_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs),
433                               (X86sub_flag node:$lhs, node:$rhs), [{
434  // Only use DEC if the result is used.
435  return !SDValue(N, 0).use_empty() && hasNoCarryFlagUses(SDValue(N, 1));
436}]>;
437
438// TODO: inc/dec is slow for P4, but fast for Pentium-M.
439let Defs = [EFLAGS] in {
440let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
441let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA.
442def INC8r  : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1),
443               "inc{b}\t$dst",
444               [(set GR8:$dst, EFLAGS, (X86add_flag_nocf GR8:$src1, 1))]>;
445def INC16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
446               "inc{w}\t$dst",
447               [(set GR16:$dst, EFLAGS, (X86add_flag_nocf GR16:$src1, 1))]>,
448               OpSize16;
449def INC32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
450               "inc{l}\t$dst",
451               [(set GR32:$dst, EFLAGS, (X86add_flag_nocf GR32:$src1, 1))]>,
452               OpSize32;
453def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src1), "inc{q}\t$dst",
454                [(set GR64:$dst, EFLAGS, (X86add_flag_nocf GR64:$src1, 1))]>;
455} // isConvertibleToThreeAddress = 1, CodeSize = 2
456
457// Short forms only valid in 32-bit mode. Selected during MCInst lowering.
458let CodeSize = 1, hasSideEffects = 0 in {
459def INC16r_alt : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
460                   "inc{w}\t$dst", []>,
461                 OpSize16, Requires<[Not64BitMode]>;
462def INC32r_alt : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
463                   "inc{l}\t$dst", []>,
464                 OpSize32, Requires<[Not64BitMode]>;
465} // CodeSize = 1, hasSideEffects = 0
466} // Constraints = "$src1 = $dst", SchedRW
467
468let CodeSize = 2, SchedRW = [WriteALURMW] in {
469let Predicates = [UseIncDec] in {
470  def INC8m  : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst",
471               [(store (add (loadi8 addr:$dst), 1), addr:$dst),
472                (implicit EFLAGS)]>;
473  def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst",
474               [(store (add (loadi16 addr:$dst), 1), addr:$dst),
475                (implicit EFLAGS)]>, OpSize16;
476  def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst",
477               [(store (add (loadi32 addr:$dst), 1), addr:$dst),
478                (implicit EFLAGS)]>, OpSize32;
479} // Predicates
480let Predicates = [UseIncDec, In64BitMode] in {
481  def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst",
482                  [(store (add (loadi64 addr:$dst), 1), addr:$dst),
483                   (implicit EFLAGS)]>;
484} // Predicates
485} // CodeSize = 2, SchedRW
486
487let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
488let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA.
489def DEC8r  : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1),
490               "dec{b}\t$dst",
491               [(set GR8:$dst, EFLAGS, (X86sub_flag_nocf GR8:$src1, 1))]>;
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, relocImm8_su, i8imm, invalid_node,
609                       0, OpSizeFixed, 0>;
610def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem,
611                       Imm16, i16imm, relocImm16_su, i16i8imm, i16immSExt8_su,
612                       1, OpSize16, 0>;
613def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem,
614                       Imm32, i32imm, relocImm32_su, i32i8imm, i32immSExt8_su,
615                       1, OpSize32, 0>;
616def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem,
617                       Imm32S, i64i32imm, i64relocImmSExt32_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                         bit ConvertibleToThreeAddressRR> {
929  let Defs = [EFLAGS] in {
930    let Constraints = "$src1 = $dst" in {
931      let isCommutable = CommutableRR in {
932        let isConvertibleToThreeAddress = ConvertibleToThreeAddressRR in {
933          def NAME#8rr  : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
934          def NAME#16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>;
935          def NAME#32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>;
936          def NAME#64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
937        } // isConvertibleToThreeAddress
938      } // isCommutable
939
940      def NAME#8rr_REV  : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
941      def NAME#16rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
942      def NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
943      def NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
944
945      def NAME#8rm   : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
946      def NAME#16rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>;
947      def NAME#32rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>;
948      def NAME#64rm  : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
949
950      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
951        def NAME#8ri   : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
952
953        // NOTE: These are order specific, we want the ri8 forms to be listed
954        // first so that they are slightly preferred to the ri forms.
955        def NAME#16ri8 : BinOpRI8_RF<0x82, mnemonic, Xi16, opnodeflag, RegMRM>;
956        def NAME#32ri8 : BinOpRI8_RF<0x82, mnemonic, Xi32, opnodeflag, RegMRM>;
957        def NAME#64ri8 : BinOpRI8_RF<0x82, mnemonic, Xi64, opnodeflag, RegMRM>;
958
959        def NAME#16ri  : BinOpRI_RF<0x80, mnemonic, Xi16, opnodeflag, RegMRM>;
960        def NAME#32ri  : BinOpRI_RF<0x80, mnemonic, Xi32, opnodeflag, RegMRM>;
961        def NAME#64ri32: BinOpRI_RF<0x80, mnemonic, Xi64, opnodeflag, RegMRM>;
962      }
963    } // Constraints = "$src1 = $dst"
964
965    let mayLoad = 1, mayStore = 1 in {
966      def NAME#8mr    : BinOpMR_RMW<BaseOpc, mnemonic, Xi8 , opnode>;
967      def NAME#16mr   : BinOpMR_RMW<BaseOpc, mnemonic, Xi16, opnode>;
968      def NAME#32mr   : BinOpMR_RMW<BaseOpc, mnemonic, Xi32, opnode>;
969      def NAME#64mr   : BinOpMR_RMW<BaseOpc, mnemonic, Xi64, opnode>;
970    }
971
972    // NOTE: These are order specific, we want the mi8 forms to be listed
973    // first so that they are slightly preferred to the mi forms.
974    def NAME#16mi8  : BinOpMI8_RMW<mnemonic, Xi16, opnode, MemMRM>;
975    def NAME#32mi8  : BinOpMI8_RMW<mnemonic, Xi32, opnode, MemMRM>;
976    let Predicates = [In64BitMode] in
977    def NAME#64mi8  : BinOpMI8_RMW<mnemonic, Xi64, opnode, MemMRM>;
978
979    def NAME#8mi    : BinOpMI_RMW<0x80, mnemonic, Xi8 , opnode, MemMRM>;
980    def NAME#16mi   : BinOpMI_RMW<0x80, mnemonic, Xi16, opnode, MemMRM>;
981    def NAME#32mi   : BinOpMI_RMW<0x80, mnemonic, Xi32, opnode, MemMRM>;
982    let Predicates = [In64BitMode] in
983    def NAME#64mi32 : BinOpMI_RMW<0x80, mnemonic, Xi64, opnode, MemMRM>;
984
985    // These are for the disassembler since 0x82 opcode behaves like 0x80, but
986    // not in 64-bit mode.
987    let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
988        hasSideEffects = 0 in {
989      let Constraints = "$src1 = $dst" in
990        def NAME#8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, null_frag, RegMRM>;
991      let mayLoad = 1, mayStore = 1 in
992        def NAME#8mi8 : BinOpMI8_RMW<mnemonic, Xi8, null_frag, MemMRM>;
993    }
994  } // Defs = [EFLAGS]
995
996  def NAME#8i8   : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
997                           "{$src, %al|al, $src}">;
998  def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
999                           "{$src, %ax|ax, $src}">;
1000  def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
1001                           "{$src, %eax|eax, $src}">;
1002  def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
1003                           "{$src, %rax|rax, $src}">;
1004}
1005
1006/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
1007/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
1008/// SBB.
1009///
1010/// It would be nice to get rid of the second and third argument here, but
1011/// tblgen can't handle dependent type references aggressively enough: PR8330
1012multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1013                          string mnemonic, Format RegMRM, Format MemMRM,
1014                          SDNode opnode, bit CommutableRR,
1015                           bit ConvertibleToThreeAddress> {
1016  let Uses = [EFLAGS], Defs = [EFLAGS] in {
1017    let Constraints = "$src1 = $dst" in {
1018      let isCommutable = CommutableRR in {
1019        def NAME#8rr  : BinOpRR_RFF<BaseOpc, mnemonic, Xi8 , opnode>;
1020        let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1021          def NAME#16rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi16, opnode>;
1022          def NAME#32rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi32, opnode>;
1023          def NAME#64rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi64, opnode>;
1024        } // isConvertibleToThreeAddress
1025      } // isCommutable
1026
1027      def NAME#8rr_REV  : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
1028      def NAME#16rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
1029      def NAME#32rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
1030      def NAME#64rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
1031
1032      def NAME#8rm   : BinOpRM_RFF<BaseOpc2, mnemonic, Xi8 , opnode>;
1033      def NAME#16rm  : BinOpRM_RFF<BaseOpc2, mnemonic, Xi16, opnode>;
1034      def NAME#32rm  : BinOpRM_RFF<BaseOpc2, mnemonic, Xi32, opnode>;
1035      def NAME#64rm  : BinOpRM_RFF<BaseOpc2, mnemonic, Xi64, opnode>;
1036
1037      def NAME#8ri   : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1038
1039      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1040        // NOTE: These are order specific, we want the ri8 forms to be listed
1041        // first so that they are slightly preferred to the ri forms.
1042        def NAME#16ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>;
1043        def NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>;
1044        def NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>;
1045
1046        def NAME#16ri  : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>;
1047        def NAME#32ri  : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>;
1048        def NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>;
1049      }
1050    } // Constraints = "$src1 = $dst"
1051
1052    def NAME#8mr    : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi8 , opnode>;
1053    def NAME#16mr   : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi16, opnode>;
1054    def NAME#32mr   : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi32, opnode>;
1055    def NAME#64mr   : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi64, opnode>;
1056
1057    // NOTE: These are order specific, we want the mi8 forms to be listed
1058    // first so that they are slightly preferred to the mi forms.
1059    def NAME#16mi8  : BinOpMI8_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
1060    def NAME#32mi8  : BinOpMI8_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
1061    let Predicates = [In64BitMode] in
1062    def NAME#64mi8  : BinOpMI8_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
1063
1064    def NAME#8mi    : BinOpMI_RMW_FF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1065    def NAME#16mi   : BinOpMI_RMW_FF<0x80, mnemonic, Xi16, opnode, MemMRM>;
1066    def NAME#32mi   : BinOpMI_RMW_FF<0x80, mnemonic, Xi32, opnode, MemMRM>;
1067    let Predicates = [In64BitMode] in
1068    def NAME#64mi32 : BinOpMI_RMW_FF<0x80, mnemonic, Xi64, opnode, MemMRM>;
1069
1070    // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1071    // not in 64-bit mode.
1072    let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
1073        hasSideEffects = 0 in {
1074      let Constraints = "$src1 = $dst" in
1075        def NAME#8ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi8, null_frag, RegMRM>;
1076      let mayLoad = 1, mayStore = 1 in
1077        def NAME#8mi8 : BinOpMI8_RMW_FF<mnemonic, Xi8, null_frag, MemMRM>;
1078    }
1079  } // Uses = [EFLAGS], Defs = [EFLAGS]
1080
1081  def NAME#8i8   : BinOpAI_RFF<BaseOpc4, mnemonic, Xi8 , AL,
1082                               "{$src, %al|al, $src}">;
1083  def NAME#16i16 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi16, AX,
1084                               "{$src, %ax|ax, $src}">;
1085  def NAME#32i32 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi32, EAX,
1086                               "{$src, %eax|eax, $src}">;
1087  def NAME#64i32 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi64, RAX,
1088                               "{$src, %rax|rax, $src}">;
1089}
1090
1091/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
1092/// defined with "(set EFLAGS, (...".  It would be really nice to find a way
1093/// to factor this with the other ArithBinOp_*.
1094///
1095multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1096                        string mnemonic, Format RegMRM, Format MemMRM,
1097                        SDNode opnode,
1098                        bit CommutableRR, bit ConvertibleToThreeAddress> {
1099  let Defs = [EFLAGS] in {
1100    let isCommutable = CommutableRR in {
1101      def NAME#8rr  : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1102      let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1103        def NAME#16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>;
1104        def NAME#32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>;
1105        def NAME#64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1106      }
1107    } // isCommutable
1108
1109    def NAME#8rr_REV  : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
1110    def NAME#16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
1111    def NAME#32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
1112    def NAME#64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
1113
1114    def NAME#8rm   : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
1115    def NAME#16rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>;
1116    def NAME#32rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>;
1117    def NAME#64rm  : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
1118
1119    def NAME#8ri   : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1120
1121    let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1122      // NOTE: These are order specific, we want the ri8 forms to be listed
1123      // first so that they are slightly preferred to the ri forms.
1124      def NAME#16ri8 : BinOpRI8_F<0x82, mnemonic, Xi16, opnode, RegMRM>;
1125      def NAME#32ri8 : BinOpRI8_F<0x82, mnemonic, Xi32, opnode, RegMRM>;
1126      def NAME#64ri8 : BinOpRI8_F<0x82, mnemonic, Xi64, opnode, RegMRM>;
1127
1128      def NAME#16ri  : BinOpRI_F<0x80, mnemonic, Xi16, opnode, RegMRM>;
1129      def NAME#32ri  : BinOpRI_F<0x80, mnemonic, Xi32, opnode, RegMRM>;
1130      def NAME#64ri32: BinOpRI_F<0x80, mnemonic, Xi64, opnode, RegMRM>;
1131    }
1132
1133    def NAME#8mr    : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1134    def NAME#16mr   : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>;
1135    def NAME#32mr   : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>;
1136    def NAME#64mr   : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
1137
1138    // NOTE: These are order specific, we want the mi8 forms to be listed
1139    // first so that they are slightly preferred to the mi forms.
1140    def NAME#16mi8  : BinOpMI8_F<mnemonic, Xi16, opnode, MemMRM>;
1141    def NAME#32mi8  : BinOpMI8_F<mnemonic, Xi32, opnode, MemMRM>;
1142    let Predicates = [In64BitMode] in
1143    def NAME#64mi8  : BinOpMI8_F<mnemonic, Xi64, opnode, MemMRM>;
1144
1145    def NAME#8mi    : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1146    def NAME#16mi   : BinOpMI_F<0x80, mnemonic, Xi16, opnode, MemMRM>;
1147    def NAME#32mi   : BinOpMI_F<0x80, mnemonic, Xi32, opnode, MemMRM>;
1148    let Predicates = [In64BitMode] in
1149    def NAME#64mi32 : BinOpMI_F<0x80, mnemonic, Xi64, opnode, MemMRM>;
1150
1151    // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1152    // not in 64-bit mode.
1153    let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
1154        hasSideEffects = 0 in {
1155      def NAME#8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, null_frag, RegMRM>;
1156      let mayLoad = 1 in
1157        def NAME#8mi8 : BinOpMI8_F<mnemonic, Xi8, null_frag, MemMRM>;
1158    }
1159  } // Defs = [EFLAGS]
1160
1161  def NAME#8i8   : BinOpAI_F<BaseOpc4, mnemonic, Xi8 , AL,
1162                             "{$src, %al|al, $src}">;
1163  def NAME#16i16 : BinOpAI_F<BaseOpc4, mnemonic, Xi16, AX,
1164                             "{$src, %ax|ax, $src}">;
1165  def NAME#32i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi32, EAX,
1166                             "{$src, %eax|eax, $src}">;
1167  def NAME#64i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi64, RAX,
1168                             "{$src, %rax|rax, $src}">;
1169}
1170
1171
1172defm AND : ArithBinOp_RF<0x20, 0x22, 0x24, "and", MRM4r, MRM4m,
1173                         X86and_flag, and, 1, 0, 0>;
1174defm OR  : ArithBinOp_RF<0x08, 0x0A, 0x0C, "or", MRM1r, MRM1m,
1175                         X86or_flag, or, 1, 0, 0>;
1176defm XOR : ArithBinOp_RF<0x30, 0x32, 0x34, "xor", MRM6r, MRM6m,
1177                         X86xor_flag, xor, 1, 0, 0>;
1178defm ADD : ArithBinOp_RF<0x00, 0x02, 0x04, "add", MRM0r, MRM0m,
1179                         X86add_flag, add, 1, 1, 1>;
1180let isCompare = 1 in {
1181defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m,
1182                         X86sub_flag, sub, 0, 1, 0>;
1183}
1184
1185// Arithmetic.
1186defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
1187                          1, 0>;
1188defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
1189                          0, 0>;
1190
1191let isCompare = 1 in {
1192defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
1193}
1194
1195// Patterns to recognize loads on the LHS of an ADC. We can't make X86adc_flag
1196// commutable since it has EFLAGs as an input.
1197def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1198          (ADC8rm GR8:$src1, addr:$src2)>;
1199def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1200          (ADC16rm GR16:$src1, addr:$src2)>;
1201def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1202          (ADC32rm GR32:$src1, addr:$src2)>;
1203def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1204          (ADC64rm GR64:$src1, addr:$src2)>;
1205
1206// Patterns to recognize RMW ADC with loads in operand 1.
1207def : Pat<(store (X86adc_flag GR8:$src, (loadi8 addr:$dst), EFLAGS),
1208                 addr:$dst),
1209          (ADC8mr addr:$dst, GR8:$src)>;
1210def : Pat<(store (X86adc_flag GR16:$src, (loadi16 addr:$dst), EFLAGS),
1211                 addr:$dst),
1212          (ADC16mr addr:$dst, GR16:$src)>;
1213def : Pat<(store (X86adc_flag GR32:$src, (loadi32 addr:$dst), EFLAGS),
1214                 addr:$dst),
1215          (ADC32mr addr:$dst, GR32:$src)>;
1216def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
1217                 addr:$dst),
1218          (ADC64mr addr:$dst, GR64:$src)>;
1219
1220//===----------------------------------------------------------------------===//
1221// Semantically, test instructions are similar like AND, except they don't
1222// generate a result.  From an encoding perspective, they are very different:
1223// they don't have all the usual imm8 and REV forms, and are encoded into a
1224// different space.
1225def X86testpat : PatFrag<(ops node:$lhs, node:$rhs),
1226                         (X86cmp (and_su node:$lhs, node:$rhs), 0)>;
1227
1228let isCompare = 1 in {
1229  let Defs = [EFLAGS] in {
1230    let isCommutable = 1 in {
1231      // Avoid selecting these and instead use a test+and. Post processing will
1232      // combine them. This gives bunch of other patterns that start with
1233      // and a chance to match.
1234      def TEST8rr  : BinOpRR_F<0x84, "test", Xi8 , null_frag>;
1235      def TEST16rr : BinOpRR_F<0x84, "test", Xi16, null_frag>;
1236      def TEST32rr : BinOpRR_F<0x84, "test", Xi32, null_frag>;
1237      def TEST64rr : BinOpRR_F<0x84, "test", Xi64, null_frag>;
1238    } // isCommutable
1239
1240    let hasSideEffects = 0, mayLoad = 1 in {
1241    def TEST8mr    : BinOpMR_F<0x84, "test", Xi8 , null_frag>;
1242    def TEST16mr   : BinOpMR_F<0x84, "test", Xi16, null_frag>;
1243    def TEST32mr   : BinOpMR_F<0x84, "test", Xi32, null_frag>;
1244    def TEST64mr   : BinOpMR_F<0x84, "test", Xi64, null_frag>;
1245    }
1246
1247    def TEST8ri    : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1248    def TEST16ri   : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>;
1249    def TEST32ri   : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>;
1250    let Predicates = [In64BitMode] in
1251    def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>;
1252
1253    def TEST8mi    : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>;
1254    def TEST16mi   : BinOpMI_F<0xF6, "test", Xi16, X86testpat, MRM0m>;
1255    def TEST32mi   : BinOpMI_F<0xF6, "test", Xi32, X86testpat, MRM0m>;
1256    let Predicates = [In64BitMode] in
1257    def TEST64mi32 : BinOpMI_F<0xF6, "test", Xi64, X86testpat, MRM0m>;
1258  } // Defs = [EFLAGS]
1259
1260  def TEST8i8    : BinOpAI_F<0xA8, "test", Xi8 , AL,
1261                             "{$src, %al|al, $src}">;
1262  def TEST16i16  : BinOpAI_F<0xA8, "test", Xi16, AX,
1263                             "{$src, %ax|ax, $src}">;
1264  def TEST32i32  : BinOpAI_F<0xA8, "test", Xi32, EAX,
1265                             "{$src, %eax|eax, $src}">;
1266  def TEST64i32  : BinOpAI_F<0xA8, "test", Xi64, RAX,
1267                             "{$src, %rax|rax, $src}">;
1268} // isCompare
1269
1270//===----------------------------------------------------------------------===//
1271// ANDN Instruction
1272//
1273multiclass bmi_andn<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1274                    PatFrag ld_frag, X86FoldableSchedWrite sched> {
1275  def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
1276            !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1277            [(set RC:$dst, EFLAGS, (X86and_flag (not RC:$src1), RC:$src2))]>,
1278            Sched<[sched]>;
1279  def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
1280            !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1281            [(set RC:$dst, EFLAGS,
1282             (X86and_flag (not RC:$src1), (ld_frag addr:$src2)))]>,
1283           Sched<[sched.Folded, sched.ReadAfterFold]>;
1284}
1285
1286// Complexity is reduced to give and with immediate a chance to match first.
1287let Predicates = [HasBMI], Defs = [EFLAGS], AddedComplexity = -6 in {
1288  defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32, WriteALU>, T8PS, VEX_4V;
1289  defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64, WriteALU>, T8PS, VEX_4V, VEX_W;
1290}
1291
1292let Predicates = [HasBMI], AddedComplexity = -6 in {
1293  def : Pat<(and (not GR32:$src1), GR32:$src2),
1294            (ANDN32rr GR32:$src1, GR32:$src2)>;
1295  def : Pat<(and (not GR64:$src1), GR64:$src2),
1296            (ANDN64rr GR64:$src1, GR64:$src2)>;
1297  def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
1298            (ANDN32rm GR32:$src1, addr:$src2)>;
1299  def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
1300            (ANDN64rm GR64:$src1, addr:$src2)>;
1301}
1302
1303//===----------------------------------------------------------------------===//
1304// MULX Instruction
1305//
1306multiclass bmi_mulx<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1307                    X86FoldableSchedWrite sched> {
1308let hasSideEffects = 0 in {
1309  let isCommutable = 1 in
1310  def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src),
1311             !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1312             []>, T8XD, VEX_4V, Sched<[sched, WriteIMulH]>;
1313
1314  let mayLoad = 1 in
1315  def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src),
1316             !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1317             []>, T8XD, VEX_4V, Sched<[sched.Folded, WriteIMulH]>;
1318}
1319}
1320
1321let Predicates = [HasBMI2] in {
1322  let Uses = [EDX] in
1323    defm MULX32 : bmi_mulx<"mulx{l}", GR32, i32mem, WriteIMul32>;
1324  let Uses = [RDX] in
1325    defm MULX64 : bmi_mulx<"mulx{q}", GR64, i64mem, WriteIMul64>, VEX_W;
1326}
1327
1328//===----------------------------------------------------------------------===//
1329// ADCX and ADOX Instructions
1330//
1331// We don't have patterns for these as there is no advantage over ADC for
1332// most code.
1333let Predicates = [HasADX], Defs = [EFLAGS], Uses = [EFLAGS],
1334    Constraints = "$src1 = $dst", hasSideEffects = 0 in {
1335  let SchedRW = [WriteADC], isCommutable = 1 in {
1336  def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst),
1337                   (ins GR32:$src1, GR32:$src2),
1338                   "adcx{l}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1339  def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst),
1340                    (ins GR64:$src1, GR64:$src2),
1341                    "adcx{q}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1342
1343  def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst),
1344                   (ins GR32:$src1, GR32:$src2),
1345                   "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1346
1347  def ADOX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst),
1348                    (ins GR64:$src1, GR64:$src2),
1349                    "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1350  } // SchedRW
1351
1352  let mayLoad = 1, SchedRW = [WriteADC.Folded, WriteADC.ReadAfterFold] in {
1353  def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst),
1354                   (ins GR32:$src1, i32mem:$src2),
1355                   "adcx{l}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1356
1357  def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst),
1358                    (ins GR64:$src1, i64mem:$src2),
1359                    "adcx{q}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1360
1361  def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst),
1362                   (ins GR32:$src1, i32mem:$src2),
1363                   "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1364
1365  def ADOX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst),
1366                    (ins GR64:$src1, i64mem:$src2),
1367                    "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1368  } // mayLoad, SchedRW
1369}
1370