1 //===-- X86InstrArithmetic.td - Integer Arithmetic Instrs --*- tablegen -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file describes the integer arithmetic instructions in the X86
13 //===----------------------------------------------------------------------===//
15 //===----------------------------------------------------------------------===//
16 // LEA - Load Effective Address
17 let SchedRW = [WriteLEA] in {
18 let hasSideEffects = 0 in
19 def LEA16r : I<0x8D, MRMSrcMem,
20 (outs GR16:$dst), (ins anymem:$src),
21 "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize16;
22 let isReMaterializable = 1 in
23 def 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]>;
29 def 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]>;
35 let isReMaterializable = 1 in
36 def LEA64r : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src),
37 "lea{q}\t{$src|$dst}, {$dst|$src}",
38 [(set GR64:$dst, lea64addr:$src)]>;
41 //===----------------------------------------------------------------------===//
42 // Fixed-Register Multiplication and Division Instructions.
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
49 class SchedLoadReg<X86FoldableSchedWrite Sched> : Sched<[Sched.Folded,
51 ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
52 // Register reads (implicit or explicit).
53 Sched.ReadAfterFold, Sched.ReadAfterFold]>;
55 // Extra precision multiplication
57 // AL is really implied by AX, but the registers in Defs must match the
58 // SDNode results (i8, i32).
60 let Defs = [AL,EFLAGS,AX], Uses = [AL] in
61 def 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]>;
68 let Defs = [AX,DX,EFLAGS], Uses = [AX], hasSideEffects = 0 in
69 def MUL16r : I<0xF7, MRM4r, (outs), (ins GR16:$src),
71 []>, OpSize16, Sched<[WriteIMul16]>;
73 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], hasSideEffects = 0 in
74 def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src),
76 [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/]>,
77 OpSize32, Sched<[WriteIMul32]>;
79 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], hasSideEffects = 0 in
80 def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src),
82 [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/]>,
85 let Defs = [AL,EFLAGS,AX], Uses = [AL] in
86 def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$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>;
94 let mayLoad = 1, hasSideEffects = 0 in {
95 let Defs = [AX,DX,EFLAGS], Uses = [AX] in
96 def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src),
97 "mul{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIMul16>;
98 // EAX,EDX = EAX*[mem32]
99 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
100 def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src),
101 "mul{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIMul32>;
102 // RAX,RDX = RAX*[mem64]
103 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
104 def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src),
105 "mul{q}\t$src", []>, SchedLoadReg<WriteIMul64>,
106 Requires<[In64BitMode]>;
109 let hasSideEffects = 0 in {
111 let Defs = [AL,EFLAGS,AX], Uses = [AL] in
112 def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>,
115 let Defs = [AX,DX,EFLAGS], Uses = [AX] in
116 def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", []>,
117 OpSize16, Sched<[WriteIMul16]>;
118 // EAX,EDX = EAX*GR32
119 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
120 def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>,
121 OpSize32, Sched<[WriteIMul32]>;
122 // RAX,RDX = RAX*GR64
123 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
124 def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), "imul{q}\t$src", []>,
125 Sched<[WriteIMul64]>;
129 let Defs = [AL,EFLAGS,AX], Uses = [AL] in
130 def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src),
131 "imul{b}\t$src", []>, SchedLoadReg<WriteIMul8>;
132 // AX,DX = AX*[mem16]
133 let Defs = [AX,DX,EFLAGS], Uses = [AX] in
134 def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src),
135 "imul{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIMul16>;
136 // EAX,EDX = EAX*[mem32]
137 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
138 def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src),
139 "imul{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIMul32>;
140 // RAX,RDX = RAX*[mem64]
141 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
142 def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src),
143 "imul{q}\t$src", []>, SchedLoadReg<WriteIMul64>,
144 Requires<[In64BitMode]>;
149 let Defs = [EFLAGS] in {
150 let Constraints = "$src1 = $dst" in {
152 let isCommutable = 1 in {
153 // X = IMUL Y, Z --> X = IMUL Z, Y
154 // Register-Register Signed Integer Multiply
155 def 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;
160 def 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;
165 def 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;
173 // Register-Memory Signed Integer Multiply
174 def 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;
180 def 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;
186 def 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"
196 // Surprisingly enough, these are not two address instructions!
197 let Defs = [EFLAGS] in {
198 // Register-Integer Signed Integer Multiply
199 def 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;
205 def 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;
211 def 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;
217 def 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;
223 def 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]>;
229 def 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]>;
236 // Memory-Integer Signed Integer Multiply
237 def 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;
243 def 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;
250 def 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;
256 def 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;
263 def 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]>;
270 def 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]>;
279 // unsigned division/remainder
280 let hasSideEffects = 1 in { // so that we don't speculatively execute
281 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
282 def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH
283 "div{b}\t$src", []>, Sched<[WriteDiv8]>;
284 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
285 def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX
286 "div{w}\t$src", []>, Sched<[WriteDiv16]>, OpSize16;
287 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
288 def 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
291 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
292 def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src),
293 "div{q}\t$src", []>, Sched<[WriteDiv64]>;
296 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
297 def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH
298 "div{b}\t$src", []>, SchedLoadReg<WriteDiv8>;
299 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
300 def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX
301 "div{w}\t$src", []>, OpSize16, SchedLoadReg<WriteDiv16>;
302 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX
303 def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src),
304 "div{l}\t$src", []>, SchedLoadReg<WriteDiv32>, OpSize32;
305 // RDX:RAX/[mem64] = RAX,RDX
306 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
307 def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src),
308 "div{q}\t$src", []>, SchedLoadReg<WriteDiv64>,
309 Requires<[In64BitMode]>;
312 // Signed division/remainder.
313 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
314 def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH
315 "idiv{b}\t$src", []>, Sched<[WriteIDiv8]>;
316 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
317 def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX
318 "idiv{w}\t$src", []>, Sched<[WriteIDiv16]>, OpSize16;
319 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
320 def 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
323 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
324 def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src),
325 "idiv{q}\t$src", []>, Sched<[WriteIDiv64]>;
328 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
329 def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH
330 "idiv{b}\t$src", []>, SchedLoadReg<WriteIDiv8>;
331 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
332 def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX
333 "idiv{w}\t$src", []>, OpSize16, SchedLoadReg<WriteIDiv16>;
334 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX
335 def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src),
336 "idiv{l}\t$src", []>, OpSize32, SchedLoadReg<WriteIDiv32>;
337 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in // RDX:RAX/[mem64] = RAX,RDX
338 def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src),
339 "idiv{q}\t$src", []>, SchedLoadReg<WriteIDiv64>,
340 Requires<[In64BitMode]>;
342 } // hasSideEffects = 0
344 //===----------------------------------------------------------------------===//
345 // Two address Instructions.
348 // unary instructions
349 let CodeSize = 2 in {
350 let Defs = [EFLAGS] in {
351 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
352 def NEG8r : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src1),
354 [(set GR8:$dst, (ineg GR8:$src1)),
356 def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src1),
358 [(set GR16:$dst, (ineg GR16:$src1)),
359 (implicit EFLAGS)]>, OpSize16;
360 def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src1),
362 [(set GR32:$dst, (ineg GR32:$src1)),
363 (implicit EFLAGS)]>, OpSize32;
364 def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src1), "neg{q}\t$dst",
365 [(set GR64:$dst, (ineg GR64:$src1)),
367 } // Constraints = "$src1 = $dst", SchedRW
369 // Read-modify-write negate.
370 let SchedRW = [WriteALURMW] in {
371 def NEG8m : I<0xF6, MRM3m, (outs), (ins i8mem :$dst),
373 [(store (ineg (loadi8 addr:$dst)), addr:$dst),
375 def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst),
377 [(store (ineg (loadi16 addr:$dst)), addr:$dst),
378 (implicit EFLAGS)]>, OpSize16;
379 def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst),
381 [(store (ineg (loadi32 addr:$dst)), addr:$dst),
382 (implicit EFLAGS)]>, OpSize32;
383 def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst",
384 [(store (ineg (loadi64 addr:$dst)), addr:$dst),
386 Requires<[In64BitMode]>;
391 // Note: NOT does not set EFLAGS!
393 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
394 def NOT8r : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src1),
396 [(set GR8:$dst, (not GR8:$src1))]>;
397 def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src1),
399 [(set GR16:$dst, (not GR16:$src1))]>, OpSize16;
400 def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src1),
402 [(set GR32:$dst, (not GR32:$src1))]>, OpSize32;
403 def 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
407 let SchedRW = [WriteALURMW] in {
408 def NOT8m : I<0xF6, MRM2m, (outs), (ins i8mem :$dst),
410 [(store (not (loadi8 addr:$dst)), addr:$dst)]>;
411 def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst),
413 [(store (not (loadi16 addr:$dst)), addr:$dst)]>,
415 def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst),
417 [(store (not (loadi32 addr:$dst)), addr:$dst)]>,
419 def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst",
420 [(store (not (loadi64 addr:$dst)), addr:$dst)]>,
421 Requires<[In64BitMode]>;
425 // TODO: inc/dec is slow for P4, but fast for Pentium-M.
426 let Defs = [EFLAGS] in {
427 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
429 def INC8r : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1),
431 [(set GR8:$dst, EFLAGS, (X86inc_flag GR8:$src1))]>;
432 let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA.
433 def INC16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
435 [(set GR16:$dst, EFLAGS, (X86inc_flag GR16:$src1))]>, OpSize16;
436 def INC32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
438 [(set GR32:$dst, EFLAGS, (X86inc_flag GR32:$src1))]>, OpSize32;
439 def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src1), "inc{q}\t$dst",
440 [(set GR64:$dst, EFLAGS, (X86inc_flag GR64:$src1))]>;
441 } // isConvertibleToThreeAddress = 1, CodeSize = 2
443 // Short forms only valid in 32-bit mode. Selected during MCInst lowering.
444 let CodeSize = 1, hasSideEffects = 0 in {
445 def INC16r_alt : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
447 OpSize16, Requires<[Not64BitMode]>;
448 def INC32r_alt : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
450 OpSize32, Requires<[Not64BitMode]>;
451 } // CodeSize = 1, hasSideEffects = 0
452 } // Constraints = "$src1 = $dst", SchedRW
454 let CodeSize = 2, SchedRW = [WriteALURMW] in {
455 let Predicates = [UseIncDec] in {
456 def INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst",
457 [(store (add (loadi8 addr:$dst), 1), addr:$dst),
459 def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst",
460 [(store (add (loadi16 addr:$dst), 1), addr:$dst),
461 (implicit EFLAGS)]>, OpSize16;
462 def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst",
463 [(store (add (loadi32 addr:$dst), 1), addr:$dst),
464 (implicit EFLAGS)]>, OpSize32;
466 let Predicates = [UseIncDec, In64BitMode] in {
467 def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst",
468 [(store (add (loadi64 addr:$dst), 1), addr:$dst),
471 } // CodeSize = 2, SchedRW
473 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
475 def DEC8r : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1),
477 [(set GR8:$dst, EFLAGS, (X86dec_flag GR8:$src1))]>;
478 let isConvertibleToThreeAddress = 1, CodeSize = 2 in { // Can xform into LEA.
479 def DEC16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src1),
481 [(set GR16:$dst, EFLAGS, (X86dec_flag GR16:$src1))]>, OpSize16;
482 def DEC32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src1),
484 [(set GR32:$dst, EFLAGS, (X86dec_flag GR32:$src1))]>, OpSize32;
485 def DEC64r : RI<0xFF, MRM1r, (outs GR64:$dst), (ins GR64:$src1), "dec{q}\t$dst",
486 [(set GR64:$dst, EFLAGS, (X86dec_flag GR64:$src1))]>;
487 } // isConvertibleToThreeAddress = 1, CodeSize = 2
489 // Short forms only valid in 32-bit mode. Selected during MCInst lowering.
490 let CodeSize = 1, hasSideEffects = 0 in {
491 def DEC16r_alt : I<0x48, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
493 OpSize16, Requires<[Not64BitMode]>;
494 def DEC32r_alt : I<0x48, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
496 OpSize32, Requires<[Not64BitMode]>;
497 } // CodeSize = 1, hasSideEffects = 0
498 } // Constraints = "$src1 = $dst", SchedRW
501 let CodeSize = 2, SchedRW = [WriteALURMW] in {
502 let Predicates = [UseIncDec] in {
503 def DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), "dec{b}\t$dst",
504 [(store (add (loadi8 addr:$dst), -1), addr:$dst),
506 def DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst",
507 [(store (add (loadi16 addr:$dst), -1), addr:$dst),
508 (implicit EFLAGS)]>, OpSize16;
509 def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst",
510 [(store (add (loadi32 addr:$dst), -1), addr:$dst),
511 (implicit EFLAGS)]>, OpSize32;
513 let Predicates = [UseIncDec, In64BitMode] in {
514 def DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), "dec{q}\t$dst",
515 [(store (add (loadi64 addr:$dst), -1), addr:$dst),
518 } // CodeSize = 2, SchedRW
521 /// X86TypeInfo - This is a bunch of information that describes relevant X86
522 /// information about value types. For example, it can tell you what the
523 /// register class and preferred load to use.
524 class X86TypeInfo<ValueType vt, string instrsuffix, RegisterClass regclass,
525 PatFrag loadnode, X86MemOperand memoperand, ImmType immkind,
526 Operand immoperand, SDPatternOperator immoperator,
527 Operand imm8operand, SDPatternOperator imm8operator,
528 bit hasOddOpcode, OperandSize opSize,
529 bit hasREX_WPrefix> {
530 /// VT - This is the value type itself.
533 /// InstrSuffix - This is the suffix used on instructions with this type. For
534 /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q".
535 string InstrSuffix = instrsuffix;
537 /// RegClass - This is the register class associated with this type. For
538 /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64.
539 RegisterClass RegClass = regclass;
541 /// LoadNode - This is the load node associated with this type. For
542 /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64.
543 PatFrag LoadNode = loadnode;
545 /// MemOperand - This is the memory operand associated with this type. For
546 /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem.
547 X86MemOperand MemOperand = memoperand;
549 /// ImmEncoding - This is the encoding of an immediate of this type. For
550 /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32
551 /// since the immediate fields of i64 instructions is a 32-bit sign extended
553 ImmType ImmEncoding = immkind;
555 /// ImmOperand - This is the operand kind of an immediate of this type. For
556 /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 ->
557 /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign
559 Operand ImmOperand = immoperand;
561 /// ImmOperator - This is the operator that should be used to match an
562 /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32).
563 SDPatternOperator ImmOperator = immoperator;
565 /// Imm8Operand - This is the operand kind to use for an imm8 of this type.
566 /// For example, i8 -> <invalid>, i16 -> i16i8imm, i32 -> i32i8imm. This is
567 /// only used for instructions that have a sign-extended imm8 field form.
568 Operand Imm8Operand = imm8operand;
570 /// Imm8Operator - This is the operator that should be used to match an 8-bit
571 /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8).
572 SDPatternOperator Imm8Operator = imm8operator;
574 /// HasOddOpcode - This bit is true if the instruction should have an odd (as
575 /// opposed to even) opcode. Operations on i8 are usually even, operations on
576 /// other datatypes are odd.
577 bit HasOddOpcode = hasOddOpcode;
579 /// OpSize - Selects whether the instruction needs a 0x66 prefix based on
580 /// 16-bit vs 32-bit mode. i8/i64 set this to OpSizeFixed. i16 sets this
581 /// to Opsize16. i32 sets this to OpSize32.
582 OperandSize OpSize = opSize;
584 /// HasREX_WPrefix - This bit is set to true if the instruction should have
585 /// the 0x40 REX prefix. This is set for i64 types.
586 bit HasREX_WPrefix = hasREX_WPrefix;
589 def invalid_node : SDNode<"<<invalid_node>>", SDTIntLeaf,[],"<<invalid_node>>">;
592 def Xi8 : X86TypeInfo<i8, "b", GR8, loadi8, i8mem,
593 Imm8, i8imm, imm8_su, i8imm, invalid_node,
595 def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem,
596 Imm16, i16imm, imm16_su, i16i8imm, i16immSExt8_su,
598 def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem,
599 Imm32, i32imm, imm32_su, i32i8imm, i32immSExt8_su,
601 def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem,
602 Imm32S, i64i32imm, i64immSExt32_su, i64i8imm, i64immSExt8_su,
605 /// ITy - This instruction base class takes the type info for the instruction.
607 /// 1. Concatenates together the instruction mnemonic with the appropriate
608 /// suffix letter, a tab, and the arguments.
609 /// 2. Infers whether the instruction should have a 0x66 prefix byte.
610 /// 3. Infers whether the instruction should have a 0x40 REX_W prefix.
611 /// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations)
612 /// or 1 (for i16,i32,i64 operations).
613 class ITy<bits<8> opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins,
614 string mnemonic, string args, list<dag> pattern>
615 : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4},
616 opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode },
618 !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern> {
620 // Infer instruction prefixes from type info.
621 let OpSize = typeinfo.OpSize;
622 let hasREX_WPrefix = typeinfo.HasREX_WPrefix;
625 // BinOpRR - Instructions like "add reg, reg, reg".
626 class BinOpRR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
627 dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
628 : ITy<opcode, MRMDestReg, typeinfo, outlist,
629 (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
630 mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
633 // BinOpRR_F - Instructions like "cmp reg, Reg", where the pattern has
634 // just a EFLAGS as a result.
635 class BinOpRR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
636 SDPatternOperator opnode>
637 : BinOpRR<opcode, mnemonic, typeinfo, (outs), WriteALU,
639 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
641 // BinOpRR_RF - Instructions like "add reg, reg, reg", where the pattern has
642 // both a regclass and EFLAGS as a result.
643 class BinOpRR_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
645 : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteALU,
646 [(set typeinfo.RegClass:$dst, EFLAGS,
647 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
649 // BinOpRR_RFF - Instructions like "adc reg, reg, reg", where the pattern has
650 // both a regclass and EFLAGS as a result, and has EFLAGS as input.
651 class BinOpRR_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
653 : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteADC,
654 [(set typeinfo.RegClass:$dst, EFLAGS,
655 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2,
658 // BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding).
659 class BinOpRR_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
660 X86FoldableSchedWrite sched = WriteALU>
661 : ITy<opcode, MRMSrcReg, typeinfo,
662 (outs typeinfo.RegClass:$dst),
663 (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
664 mnemonic, "{$src2, $dst|$dst, $src2}", []>,
666 // The disassembler should know about this, but not the asmparser.
667 let isCodeGenOnly = 1;
668 let ForceDisassemble = 1;
669 let hasSideEffects = 0;
672 // BinOpRR_RDD_Rev - Instructions like "adc reg, reg, reg" (reversed encoding).
673 class BinOpRR_RFF_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
674 : BinOpRR_Rev<opcode, mnemonic, typeinfo, WriteADC>;
676 // BinOpRR_F_Rev - Instructions like "cmp reg, reg" (reversed encoding).
677 class BinOpRR_F_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
678 : ITy<opcode, MRMSrcReg, typeinfo, (outs),
679 (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
680 mnemonic, "{$src2, $src1|$src1, $src2}", []>,
682 // The disassembler should know about this, but not the asmparser.
683 let isCodeGenOnly = 1;
684 let ForceDisassemble = 1;
685 let hasSideEffects = 0;
688 // BinOpRM - Instructions like "add reg, reg, [mem]".
689 class BinOpRM<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
690 dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
691 : ITy<opcode, MRMSrcMem, typeinfo, outlist,
692 (ins typeinfo.RegClass:$src1, typeinfo.MemOperand:$src2),
693 mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
694 Sched<[sched.Folded, sched.ReadAfterFold]>;
696 // BinOpRM_F - Instructions like "cmp reg, [mem]".
697 class BinOpRM_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
699 : BinOpRM<opcode, mnemonic, typeinfo, (outs), WriteALU,
701 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
703 // BinOpRM_RF - Instructions like "add reg, reg, [mem]".
704 class BinOpRM_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
706 : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteALU,
707 [(set typeinfo.RegClass:$dst, EFLAGS,
708 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
710 // BinOpRM_RFF - Instructions like "adc reg, reg, [mem]".
711 class BinOpRM_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
713 : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst), WriteADC,
714 [(set typeinfo.RegClass:$dst, EFLAGS,
715 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2),
718 // BinOpRI - Instructions like "add reg, reg, imm".
719 class BinOpRI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
720 Format f, dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
721 : ITy<opcode, f, typeinfo, outlist,
722 (ins typeinfo.RegClass:$src1, typeinfo.ImmOperand:$src2),
723 mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
725 let ImmT = typeinfo.ImmEncoding;
728 // BinOpRI_F - Instructions like "cmp reg, imm".
729 class BinOpRI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
730 SDPatternOperator opnode, Format f>
731 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs), WriteALU,
733 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
735 // BinOpRI_RF - Instructions like "add reg, reg, imm".
736 class BinOpRI_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
737 SDNode opnode, Format f>
738 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteALU,
739 [(set typeinfo.RegClass:$dst, EFLAGS,
740 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
741 // BinOpRI_RFF - Instructions like "adc reg, reg, imm".
742 class BinOpRI_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
743 SDNode opnode, Format f>
744 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteADC,
745 [(set typeinfo.RegClass:$dst, EFLAGS,
746 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2,
749 // BinOpRI8 - Instructions like "add reg, reg, imm8".
750 class BinOpRI8<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
751 Format f, dag outlist, X86FoldableSchedWrite sched, list<dag> pattern>
752 : ITy<opcode, f, typeinfo, outlist,
753 (ins typeinfo.RegClass:$src1, typeinfo.Imm8Operand:$src2),
754 mnemonic, "{$src2, $src1|$src1, $src2}", pattern>,
756 let ImmT = Imm8; // Always 8-bit immediate.
759 // BinOpRI8_F - Instructions like "cmp reg, imm8".
760 class BinOpRI8_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
761 SDPatternOperator opnode, Format f>
762 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs), WriteALU,
764 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
766 // BinOpRI8_RF - Instructions like "add reg, reg, imm8".
767 class BinOpRI8_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
768 SDPatternOperator opnode, Format f>
769 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteALU,
770 [(set typeinfo.RegClass:$dst, EFLAGS,
771 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
773 // BinOpRI8_RFF - Instructions like "adc reg, reg, imm8".
774 class BinOpRI8_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
775 SDPatternOperator opnode, Format f>
776 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst), WriteADC,
777 [(set typeinfo.RegClass:$dst, EFLAGS,
778 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2,
781 // BinOpMR - Instructions like "add [mem], reg".
782 class BinOpMR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
784 : ITy<opcode, MRMDestMem, typeinfo,
785 (outs), (ins typeinfo.MemOperand:$dst, typeinfo.RegClass:$src),
786 mnemonic, "{$src, $dst|$dst, $src}", pattern>;
788 // BinOpMR_RMW - Instructions like "add [mem], reg".
789 class BinOpMR_RMW<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
791 : BinOpMR<opcode, mnemonic, typeinfo,
792 [(store (opnode (load addr:$dst), typeinfo.RegClass:$src), addr:$dst),
793 (implicit EFLAGS)]>, Sched<[WriteALURMW]>;
795 // BinOpMR_RMW_FF - Instructions like "adc [mem], reg".
796 class BinOpMR_RMW_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
798 : BinOpMR<opcode, mnemonic, typeinfo,
799 [(store (opnode (load addr:$dst), typeinfo.RegClass:$src, EFLAGS),
801 (implicit EFLAGS)]>, Sched<[WriteADCRMW]>;
803 // BinOpMR_F - Instructions like "cmp [mem], reg".
804 class BinOpMR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
805 SDPatternOperator opnode>
806 : BinOpMR<opcode, mnemonic, typeinfo,
807 [(set EFLAGS, (opnode (typeinfo.LoadNode addr:$dst),
808 typeinfo.RegClass:$src))]>,
809 Sched<[WriteALU.Folded, ReadDefault, ReadDefault, ReadDefault,
810 ReadDefault, ReadDefault, WriteALU.ReadAfterFold]>;
812 // BinOpMI - Instructions like "add [mem], imm".
813 class BinOpMI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
814 Format f, list<dag> pattern>
815 : ITy<opcode, f, typeinfo,
816 (outs), (ins typeinfo.MemOperand:$dst, typeinfo.ImmOperand:$src),
817 mnemonic, "{$src, $dst|$dst, $src}", pattern> {
818 let ImmT = typeinfo.ImmEncoding;
821 // BinOpMI_RMW - Instructions like "add [mem], imm".
822 class BinOpMI_RMW<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
823 SDNode opnode, Format f>
824 : BinOpMI<opcode, mnemonic, typeinfo, f,
825 [(store (opnode (typeinfo.VT (load addr:$dst)),
826 typeinfo.ImmOperator:$src), addr:$dst),
827 (implicit EFLAGS)]>, Sched<[WriteALURMW]>;
828 // BinOpMI_RMW_FF - Instructions like "adc [mem], imm".
829 class BinOpMI_RMW_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
830 SDNode opnode, Format f>
831 : BinOpMI<opcode, mnemonic, typeinfo, f,
832 [(store (opnode (typeinfo.VT (load addr:$dst)),
833 typeinfo.ImmOperator:$src, EFLAGS), addr:$dst),
834 (implicit EFLAGS)]>, Sched<[WriteADCRMW]>;
836 // BinOpMI_F - Instructions like "cmp [mem], imm".
837 class BinOpMI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
838 SDPatternOperator opnode, Format f>
839 : BinOpMI<opcode, mnemonic, typeinfo, f,
840 [(set EFLAGS, (opnode (typeinfo.LoadNode addr:$dst),
841 typeinfo.ImmOperator:$src))]>,
842 Sched<[WriteALU.Folded]>;
844 // BinOpMI8 - Instructions like "add [mem], imm8".
845 class BinOpMI8<string mnemonic, X86TypeInfo typeinfo,
846 Format f, list<dag> pattern>
847 : ITy<0x82, f, typeinfo,
848 (outs), (ins typeinfo.MemOperand:$dst, typeinfo.Imm8Operand:$src),
849 mnemonic, "{$src, $dst|$dst, $src}", pattern> {
850 let ImmT = Imm8; // Always 8-bit immediate.
853 // BinOpMI8_RMW - Instructions like "add [mem], imm8".
854 class BinOpMI8_RMW<string mnemonic, X86TypeInfo typeinfo,
855 SDPatternOperator opnode, Format f>
856 : BinOpMI8<mnemonic, typeinfo, f,
857 [(store (opnode (load addr:$dst),
858 typeinfo.Imm8Operator:$src), addr:$dst),
859 (implicit EFLAGS)]>, Sched<[WriteALURMW]>;
861 // BinOpMI8_RMW_FF - Instructions like "adc [mem], imm8".
862 class BinOpMI8_RMW_FF<string mnemonic, X86TypeInfo typeinfo,
863 SDPatternOperator opnode, Format f>
864 : BinOpMI8<mnemonic, typeinfo, f,
865 [(store (opnode (load addr:$dst),
866 typeinfo.Imm8Operator:$src, EFLAGS), addr:$dst),
867 (implicit EFLAGS)]>, Sched<[WriteADCRMW]>;
869 // BinOpMI8_F - Instructions like "cmp [mem], imm8".
870 class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
871 SDPatternOperator opnode, Format f>
872 : BinOpMI8<mnemonic, typeinfo, f,
873 [(set EFLAGS, (opnode (typeinfo.LoadNode addr:$dst),
874 typeinfo.Imm8Operator:$src))]>,
875 Sched<[WriteALU.Folded]>;
877 // BinOpAI - Instructions like "add %eax, %eax, imm", that imp-def EFLAGS.
878 class BinOpAI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
879 Register areg, string operands, X86FoldableSchedWrite sched = WriteALU>
880 : ITy<opcode, RawFrm, typeinfo,
881 (outs), (ins typeinfo.ImmOperand:$src),
882 mnemonic, operands, []>, Sched<[sched]> {
883 let ImmT = typeinfo.ImmEncoding;
885 let Defs = [areg, EFLAGS];
886 let hasSideEffects = 0;
889 // BinOpAI_RFF - Instructions like "adc %eax, %eax, imm", that implicitly define
891 class BinOpAI_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
892 Register areg, string operands>
893 : BinOpAI<opcode, mnemonic, typeinfo, areg, operands, WriteADC> {
894 let Uses = [areg, EFLAGS];
897 // BinOpAI_F - Instructions like "cmp %eax, %eax, imm", that imp-def EFLAGS.
898 class BinOpAI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
899 Register areg, string operands>
900 : BinOpAI<opcode, mnemonic, typeinfo, areg, operands> {
904 /// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
905 /// defined with "(set GPR:$dst, EFLAGS, (...".
907 /// It would be nice to get rid of the second and third argument here, but
908 /// tblgen can't handle dependent type references aggressively enough: PR8330
909 multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
910 string mnemonic, Format RegMRM, Format MemMRM,
911 SDNode opnodeflag, SDNode opnode,
912 bit CommutableRR, bit ConvertibleToThreeAddress> {
913 let Defs = [EFLAGS] in {
914 let Constraints = "$src1 = $dst" in {
915 let isCommutable = CommutableRR in {
916 def NAME#8rr : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
917 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
918 def NAME#16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>;
919 def NAME#32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>;
920 def NAME#64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
921 } // isConvertibleToThreeAddress
924 def NAME#8rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
925 def NAME#16rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
926 def NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
927 def NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
929 def NAME#8rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
930 def NAME#16rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>;
931 def NAME#32rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>;
932 def NAME#64rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
934 def NAME#8ri : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
936 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
937 // NOTE: These are order specific, we want the ri8 forms to be listed
938 // first so that they are slightly preferred to the ri forms.
939 def NAME#16ri8 : BinOpRI8_RF<0x82, mnemonic, Xi16, opnodeflag, RegMRM>;
940 def NAME#32ri8 : BinOpRI8_RF<0x82, mnemonic, Xi32, opnodeflag, RegMRM>;
941 def NAME#64ri8 : BinOpRI8_RF<0x82, mnemonic, Xi64, opnodeflag, RegMRM>;
943 def NAME#16ri : BinOpRI_RF<0x80, mnemonic, Xi16, opnodeflag, RegMRM>;
944 def NAME#32ri : BinOpRI_RF<0x80, mnemonic, Xi32, opnodeflag, RegMRM>;
945 def NAME#64ri32: BinOpRI_RF<0x80, mnemonic, Xi64, opnodeflag, RegMRM>;
947 } // Constraints = "$src1 = $dst"
949 let mayLoad = 1, mayStore = 1 in {
950 def NAME#8mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi8 , opnode>;
951 def NAME#16mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi16, opnode>;
952 def NAME#32mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi32, opnode>;
953 def NAME#64mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi64, opnode>;
956 // NOTE: These are order specific, we want the mi8 forms to be listed
957 // first so that they are slightly preferred to the mi forms.
958 def NAME#16mi8 : BinOpMI8_RMW<mnemonic, Xi16, opnode, MemMRM>;
959 def NAME#32mi8 : BinOpMI8_RMW<mnemonic, Xi32, opnode, MemMRM>;
960 let Predicates = [In64BitMode] in
961 def NAME#64mi8 : BinOpMI8_RMW<mnemonic, Xi64, opnode, MemMRM>;
963 def NAME#8mi : BinOpMI_RMW<0x80, mnemonic, Xi8 , opnode, MemMRM>;
964 def NAME#16mi : BinOpMI_RMW<0x80, mnemonic, Xi16, opnode, MemMRM>;
965 def NAME#32mi : BinOpMI_RMW<0x80, mnemonic, Xi32, opnode, MemMRM>;
966 let Predicates = [In64BitMode] in
967 def NAME#64mi32 : BinOpMI_RMW<0x80, mnemonic, Xi64, opnode, MemMRM>;
969 // These are for the disassembler since 0x82 opcode behaves like 0x80, but
970 // not in 64-bit mode.
971 let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
972 hasSideEffects = 0 in {
973 let Constraints = "$src1 = $dst" in
974 def NAME#8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, null_frag, RegMRM>;
975 let mayLoad = 1, mayStore = 1 in
976 def NAME#8mi8 : BinOpMI8_RMW<mnemonic, Xi8, null_frag, MemMRM>;
980 def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
981 "{$src, %al|al, $src}">;
982 def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
983 "{$src, %ax|ax, $src}">;
984 def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
985 "{$src, %eax|eax, $src}">;
986 def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
987 "{$src, %rax|rax, $src}">;
990 /// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
991 /// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
994 /// It would be nice to get rid of the second and third argument here, but
995 /// tblgen can't handle dependent type references aggressively enough: PR8330
996 multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
997 string mnemonic, Format RegMRM, Format MemMRM,
998 SDNode opnode, bit CommutableRR,
999 bit ConvertibleToThreeAddress> {
1000 let Uses = [EFLAGS], Defs = [EFLAGS] in {
1001 let Constraints = "$src1 = $dst" in {
1002 let isCommutable = CommutableRR in {
1003 def NAME#8rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi8 , opnode>;
1004 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1005 def NAME#16rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi16, opnode>;
1006 def NAME#32rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi32, opnode>;
1007 def NAME#64rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi64, opnode>;
1008 } // isConvertibleToThreeAddress
1011 def NAME#8rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
1012 def NAME#16rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
1013 def NAME#32rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
1014 def NAME#64rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
1016 def NAME#8rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi8 , opnode>;
1017 def NAME#16rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi16, opnode>;
1018 def NAME#32rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi32, opnode>;
1019 def NAME#64rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi64, opnode>;
1021 def NAME#8ri : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1023 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1024 // NOTE: These are order specific, we want the ri8 forms to be listed
1025 // first so that they are slightly preferred to the ri forms.
1026 def NAME#16ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>;
1027 def NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>;
1028 def NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>;
1030 def NAME#16ri : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>;
1031 def NAME#32ri : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>;
1032 def NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>;
1034 } // Constraints = "$src1 = $dst"
1036 def NAME#8mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi8 , opnode>;
1037 def NAME#16mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi16, opnode>;
1038 def NAME#32mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi32, opnode>;
1039 def NAME#64mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi64, opnode>;
1041 // NOTE: These are order specific, we want the mi8 forms to be listed
1042 // first so that they are slightly preferred to the mi forms.
1043 def NAME#16mi8 : BinOpMI8_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
1044 def NAME#32mi8 : BinOpMI8_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
1045 let Predicates = [In64BitMode] in
1046 def NAME#64mi8 : BinOpMI8_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
1048 def NAME#8mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1049 def NAME#16mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi16, opnode, MemMRM>;
1050 def NAME#32mi : BinOpMI_RMW_FF<0x80, mnemonic, Xi32, opnode, MemMRM>;
1051 let Predicates = [In64BitMode] in
1052 def NAME#64mi32 : BinOpMI_RMW_FF<0x80, mnemonic, Xi64, opnode, MemMRM>;
1054 // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1055 // not in 64-bit mode.
1056 let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
1057 hasSideEffects = 0 in {
1058 let Constraints = "$src1 = $dst" in
1059 def NAME#8ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi8, null_frag, RegMRM>;
1060 let mayLoad = 1, mayStore = 1 in
1061 def NAME#8mi8 : BinOpMI8_RMW_FF<mnemonic, Xi8, null_frag, MemMRM>;
1063 } // Uses = [EFLAGS], Defs = [EFLAGS]
1065 def NAME#8i8 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi8 , AL,
1066 "{$src, %al|al, $src}">;
1067 def NAME#16i16 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi16, AX,
1068 "{$src, %ax|ax, $src}">;
1069 def NAME#32i32 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi32, EAX,
1070 "{$src, %eax|eax, $src}">;
1071 def NAME#64i32 : BinOpAI_RFF<BaseOpc4, mnemonic, Xi64, RAX,
1072 "{$src, %rax|rax, $src}">;
1075 /// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
1076 /// defined with "(set EFLAGS, (...". It would be really nice to find a way
1077 /// to factor this with the other ArithBinOp_*.
1079 multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1080 string mnemonic, Format RegMRM, Format MemMRM,
1082 bit CommutableRR, bit ConvertibleToThreeAddress> {
1083 let Defs = [EFLAGS] in {
1084 let isCommutable = CommutableRR in {
1085 def NAME#8rr : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1086 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1087 def NAME#16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>;
1088 def NAME#32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>;
1089 def NAME#64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1093 def NAME#8rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>, FoldGenData<NAME#8rr>;
1094 def NAME#16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>, FoldGenData<NAME#16rr>;
1095 def NAME#32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>, FoldGenData<NAME#32rr>;
1096 def NAME#64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>, FoldGenData<NAME#64rr>;
1098 def NAME#8rm : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
1099 def NAME#16rm : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>;
1100 def NAME#32rm : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>;
1101 def NAME#64rm : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
1103 def NAME#8ri : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1105 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1106 // NOTE: These are order specific, we want the ri8 forms to be listed
1107 // first so that they are slightly preferred to the ri forms.
1108 def NAME#16ri8 : BinOpRI8_F<0x82, mnemonic, Xi16, opnode, RegMRM>;
1109 def NAME#32ri8 : BinOpRI8_F<0x82, mnemonic, Xi32, opnode, RegMRM>;
1110 def NAME#64ri8 : BinOpRI8_F<0x82, mnemonic, Xi64, opnode, RegMRM>;
1112 def NAME#16ri : BinOpRI_F<0x80, mnemonic, Xi16, opnode, RegMRM>;
1113 def NAME#32ri : BinOpRI_F<0x80, mnemonic, Xi32, opnode, RegMRM>;
1114 def NAME#64ri32: BinOpRI_F<0x80, mnemonic, Xi64, opnode, RegMRM>;
1117 def NAME#8mr : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1118 def NAME#16mr : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>;
1119 def NAME#32mr : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>;
1120 def NAME#64mr : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
1122 // NOTE: These are order specific, we want the mi8 forms to be listed
1123 // first so that they are slightly preferred to the mi forms.
1124 def NAME#16mi8 : BinOpMI8_F<mnemonic, Xi16, opnode, MemMRM>;
1125 def NAME#32mi8 : BinOpMI8_F<mnemonic, Xi32, opnode, MemMRM>;
1126 let Predicates = [In64BitMode] in
1127 def NAME#64mi8 : BinOpMI8_F<mnemonic, Xi64, opnode, MemMRM>;
1129 def NAME#8mi : BinOpMI_F<0x80, mnemonic, Xi8 , opnode, MemMRM>;
1130 def NAME#16mi : BinOpMI_F<0x80, mnemonic, Xi16, opnode, MemMRM>;
1131 def NAME#32mi : BinOpMI_F<0x80, mnemonic, Xi32, opnode, MemMRM>;
1132 let Predicates = [In64BitMode] in
1133 def NAME#64mi32 : BinOpMI_F<0x80, mnemonic, Xi64, opnode, MemMRM>;
1135 // These are for the disassembler since 0x82 opcode behaves like 0x80, but
1136 // not in 64-bit mode.
1137 let Predicates = [Not64BitMode], isCodeGenOnly = 1, ForceDisassemble = 1,
1138 hasSideEffects = 0 in {
1139 def NAME#8ri8 : BinOpRI8_F<0x82, mnemonic, Xi8, null_frag, RegMRM>;
1141 def NAME#8mi8 : BinOpMI8_F<mnemonic, Xi8, null_frag, MemMRM>;
1143 } // Defs = [EFLAGS]
1145 def NAME#8i8 : BinOpAI_F<BaseOpc4, mnemonic, Xi8 , AL,
1146 "{$src, %al|al, $src}">;
1147 def NAME#16i16 : BinOpAI_F<BaseOpc4, mnemonic, Xi16, AX,
1148 "{$src, %ax|ax, $src}">;
1149 def NAME#32i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi32, EAX,
1150 "{$src, %eax|eax, $src}">;
1151 def NAME#64i32 : BinOpAI_F<BaseOpc4, mnemonic, Xi64, RAX,
1152 "{$src, %rax|rax, $src}">;
1156 defm AND : ArithBinOp_RF<0x20, 0x22, 0x24, "and", MRM4r, MRM4m,
1157 X86and_flag, and, 1, 0>;
1158 defm OR : ArithBinOp_RF<0x08, 0x0A, 0x0C, "or", MRM1r, MRM1m,
1159 X86or_flag, or, 1, 0>;
1160 defm XOR : ArithBinOp_RF<0x30, 0x32, 0x34, "xor", MRM6r, MRM6m,
1161 X86xor_flag, xor, 1, 0>;
1162 defm ADD : ArithBinOp_RF<0x00, 0x02, 0x04, "add", MRM0r, MRM0m,
1163 X86add_flag, add, 1, 1>;
1164 let isCompare = 1 in {
1165 defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m,
1166 X86sub_flag, sub, 0, 0>;
1170 defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
1172 defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
1175 let isCompare = 1 in {
1176 defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
1179 // Patterns to recognize loads on the LHS of an ADC. We can't make X86adc_flag
1180 // commutable since it has EFLAGs as an input.
1181 def : Pat<(X86adc_flag (loadi8 addr:$src2), GR8:$src1, EFLAGS),
1182 (ADC8rm GR8:$src1, addr:$src2)>;
1183 def : Pat<(X86adc_flag (loadi16 addr:$src2), GR16:$src1, EFLAGS),
1184 (ADC16rm GR16:$src1, addr:$src2)>;
1185 def : Pat<(X86adc_flag (loadi32 addr:$src2), GR32:$src1, EFLAGS),
1186 (ADC32rm GR32:$src1, addr:$src2)>;
1187 def : Pat<(X86adc_flag (loadi64 addr:$src2), GR64:$src1, EFLAGS),
1188 (ADC64rm GR64:$src1, addr:$src2)>;
1190 // Patterns to recognize RMW ADC with loads in operand 1.
1191 def : Pat<(store (X86adc_flag GR8:$src, (loadi8 addr:$dst), EFLAGS),
1193 (ADC8mr addr:$dst, GR8:$src)>;
1194 def : Pat<(store (X86adc_flag GR16:$src, (loadi16 addr:$dst), EFLAGS),
1196 (ADC16mr addr:$dst, GR16:$src)>;
1197 def : Pat<(store (X86adc_flag GR32:$src, (loadi32 addr:$dst), EFLAGS),
1199 (ADC32mr addr:$dst, GR32:$src)>;
1200 def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
1202 (ADC64mr addr:$dst, GR64:$src)>;
1204 //===----------------------------------------------------------------------===//
1205 // Semantically, test instructions are similar like AND, except they don't
1206 // generate a result. From an encoding perspective, they are very different:
1207 // they don't have all the usual imm8 and REV forms, and are encoded into a
1209 def X86testpat : PatFrag<(ops node:$lhs, node:$rhs),
1210 (X86cmp (and_su node:$lhs, node:$rhs), 0)>;
1212 let isCompare = 1 in {
1213 let Defs = [EFLAGS] in {
1214 let isCommutable = 1 in {
1215 def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat>;
1216 def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat>;
1217 def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat>;
1218 def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat>;
1221 def TEST8mr : BinOpMR_F<0x84, "test", Xi8 , X86testpat>;
1222 def TEST16mr : BinOpMR_F<0x84, "test", Xi16, X86testpat>;
1223 def TEST32mr : BinOpMR_F<0x84, "test", Xi32, X86testpat>;
1224 def TEST64mr : BinOpMR_F<0x84, "test", Xi64, X86testpat>;
1226 def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1227 def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>;
1228 def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>;
1229 let Predicates = [In64BitMode] in
1230 def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>;
1232 def TEST8mi : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>;
1233 def TEST16mi : BinOpMI_F<0xF6, "test", Xi16, X86testpat, MRM0m>;
1234 def TEST32mi : BinOpMI_F<0xF6, "test", Xi32, X86testpat, MRM0m>;
1235 let Predicates = [In64BitMode] in
1236 def TEST64mi32 : BinOpMI_F<0xF6, "test", Xi64, X86testpat, MRM0m>;
1237 } // Defs = [EFLAGS]
1239 def TEST8i8 : BinOpAI_F<0xA8, "test", Xi8 , AL,
1240 "{$src, %al|al, $src}">;
1241 def TEST16i16 : BinOpAI_F<0xA8, "test", Xi16, AX,
1242 "{$src, %ax|ax, $src}">;
1243 def TEST32i32 : BinOpAI_F<0xA8, "test", Xi32, EAX,
1244 "{$src, %eax|eax, $src}">;
1245 def TEST64i32 : BinOpAI_F<0xA8, "test", Xi64, RAX,
1246 "{$src, %rax|rax, $src}">;
1249 //===----------------------------------------------------------------------===//
1252 multiclass bmi_andn<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1254 def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
1255 !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1256 [(set RC:$dst, EFLAGS, (X86and_flag (not RC:$src1), RC:$src2))]>,
1258 def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
1259 !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1260 [(set RC:$dst, EFLAGS,
1261 (X86and_flag (not RC:$src1), (ld_frag addr:$src2)))]>,
1262 Sched<[WriteALU.Folded, WriteALU.ReadAfterFold]>;
1265 // Complexity is reduced to give and with immediate a chance to match first.
1266 let Predicates = [HasBMI], Defs = [EFLAGS], AddedComplexity = -6 in {
1267 defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8PS, VEX_4V;
1268 defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8PS, VEX_4V, VEX_W;
1271 let Predicates = [HasBMI], AddedComplexity = -6 in {
1272 def : Pat<(and (not GR32:$src1), GR32:$src2),
1273 (ANDN32rr GR32:$src1, GR32:$src2)>;
1274 def : Pat<(and (not GR64:$src1), GR64:$src2),
1275 (ANDN64rr GR64:$src1, GR64:$src2)>;
1276 def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
1277 (ANDN32rm GR32:$src1, addr:$src2)>;
1278 def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
1279 (ANDN64rm GR64:$src1, addr:$src2)>;
1282 //===----------------------------------------------------------------------===//
1285 multiclass bmi_mulx<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1286 X86FoldableSchedWrite sched> {
1287 let hasSideEffects = 0 in {
1288 let isCommutable = 1 in
1289 def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src),
1290 !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1291 []>, T8XD, VEX_4V, Sched<[sched, WriteIMulH]>;
1294 def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src),
1295 !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1296 []>, T8XD, VEX_4V, Sched<[sched.Folded, WriteIMulH]>;
1300 let Predicates = [HasBMI2] in {
1302 defm MULX32 : bmi_mulx<"mulx{l}", GR32, i32mem, WriteIMul32>;
1304 defm MULX64 : bmi_mulx<"mulx{q}", GR64, i64mem, WriteIMul64>, VEX_W;
1307 //===----------------------------------------------------------------------===//
1308 // ADCX and ADOX Instructions
1310 // We don't have patterns for these as there is no advantage over ADC for
1312 let Predicates = [HasADX], Defs = [EFLAGS], Uses = [EFLAGS],
1313 Constraints = "$src1 = $dst", hasSideEffects = 0 in {
1314 let SchedRW = [WriteADC], isCommutable = 1 in {
1315 def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst),
1316 (ins GR32:$src1, GR32:$src2),
1317 "adcx{l}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1318 def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst),
1319 (ins GR64:$src1, GR64:$src2),
1320 "adcx{q}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1322 def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst),
1323 (ins GR32:$src1, GR32:$src2),
1324 "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1326 def ADOX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst),
1327 (ins GR64:$src1, GR64:$src2),
1328 "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1331 let mayLoad = 1, SchedRW = [WriteADC.Folded, WriteADC.ReadAfterFold] in {
1332 def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst),
1333 (ins GR32:$src1, i32mem:$src2),
1334 "adcx{l}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1336 def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst),
1337 (ins GR64:$src1, i64mem:$src2),
1338 "adcx{q}\t{$src2, $dst|$dst, $src2}", []>, T8PD;
1340 def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst),
1341 (ins GR32:$src1, i32mem:$src2),
1342 "adox{l}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1344 def ADOX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst),
1345 (ins GR64:$src1, i64mem:$src2),
1346 "adox{q}\t{$src2, $dst|$dst, $src2}", []>, T8XS;
1347 } // mayLoad, SchedRW