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 neverHasSideEffects = 1 in
19 def LEA16r : I<0x8D, MRMSrcMem,
20 (outs GR16:$dst), (ins i32mem:$src),
21 "lea{w}\t{$src|$dst}, {$dst|$src}", [], IIC_LEA_16>, OpSize;
22 let isReMaterializable = 1 in
23 def LEA32r : I<0x8D, MRMSrcMem,
24 (outs GR32:$dst), (ins i32mem:$src),
25 "lea{l}\t{$src|$dst}, {$dst|$src}",
26 [(set GR32:$dst, lea32addr:$src)], IIC_LEA>,
27 OpSize16, 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)], IIC_LEA>,
33 OpSize16, 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)], IIC_LEA>;
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<SchedWrite SW> : Sched<[SW,
51 ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
52 // Register reads (implicit or explicit).
53 ReadAfterLd, ReadAfterLd]>;
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)], IIC_MUL8>, Sched<[WriteIMul]>;
68 let Defs = [AX,DX,EFLAGS], Uses = [AX], neverHasSideEffects = 1 in
69 def MUL16r : I<0xF7, MRM4r, (outs), (ins GR16:$src),
71 [], IIC_MUL16_REG>, OpSize, Sched<[WriteIMul]>;
73 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], neverHasSideEffects = 1 in
74 def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src),
76 [/*(set EAX, EDX, EFLAGS, (X86umul_flag EAX, GR32:$src))*/],
77 IIC_MUL32_REG>, OpSize16, Sched<[WriteIMul]>;
79 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], neverHasSideEffects = 1 in
80 def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src),
82 [/*(set RAX, RDX, EFLAGS, (X86umul_flag RAX, GR64:$src))*/],
83 IIC_MUL64>, Sched<[WriteIMul]>;
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)], IIC_MUL8>, SchedLoadReg<WriteIMulLd>;
94 let mayLoad = 1, neverHasSideEffects = 1 in {
95 let Defs = [AX,DX,EFLAGS], Uses = [AX] in
96 def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src),
98 [], IIC_MUL16_MEM>, OpSize, SchedLoadReg<WriteIMulLd>;
99 // EAX,EDX = EAX*[mem32]
100 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
101 def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src),
103 [], IIC_MUL32_MEM>, OpSize16, SchedLoadReg<WriteIMulLd>;
104 // RAX,RDX = RAX*[mem64]
105 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
106 def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src),
107 "mul{q}\t$src", [], IIC_MUL64>, SchedLoadReg<WriteIMulLd>;
110 let neverHasSideEffects = 1 in {
112 let Defs = [AL,EFLAGS,AX], Uses = [AL] in
113 def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", [],
114 IIC_IMUL8>, Sched<[WriteIMul]>;
116 let Defs = [AX,DX,EFLAGS], Uses = [AX] in
117 def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", [],
118 IIC_IMUL16_RR>, OpSize, Sched<[WriteIMul]>;
119 // EAX,EDX = EAX*GR32
120 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
121 def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", [],
122 IIC_IMUL32_RR>, OpSize16, Sched<[WriteIMul]>;
123 // RAX,RDX = RAX*GR64
124 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
125 def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), "imul{q}\t$src", [],
126 IIC_IMUL64_RR>, Sched<[WriteIMul]>;
130 let Defs = [AL,EFLAGS,AX], Uses = [AL] in
131 def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src),
132 "imul{b}\t$src", [], IIC_IMUL8>, SchedLoadReg<WriteIMulLd>;
133 // AX,DX = AX*[mem16]
134 let Defs = [AX,DX,EFLAGS], Uses = [AX] in
135 def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src),
136 "imul{w}\t$src", [], IIC_IMUL16_MEM>, OpSize,
137 SchedLoadReg<WriteIMulLd>;
138 // EAX,EDX = EAX*[mem32]
139 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
140 def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src),
141 "imul{l}\t$src", [], IIC_IMUL32_MEM>, OpSize16,
142 SchedLoadReg<WriteIMulLd>;
143 // RAX,RDX = RAX*[mem64]
144 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in
145 def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src),
146 "imul{q}\t$src", [], IIC_IMUL64>, SchedLoadReg<WriteIMulLd>;
148 } // neverHasSideEffects
151 let Defs = [EFLAGS] in {
152 let Constraints = "$src1 = $dst" in {
154 let isCommutable = 1, SchedRW = [WriteIMul] in {
155 // X = IMUL Y, Z --> X = IMUL Z, Y
156 // Register-Register Signed Integer Multiply
157 def IMUL16rr : I<0xAF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src1,GR16:$src2),
158 "imul{w}\t{$src2, $dst|$dst, $src2}",
159 [(set GR16:$dst, EFLAGS,
160 (X86smul_flag GR16:$src1, GR16:$src2))], IIC_IMUL16_RR>,
162 def IMUL32rr : I<0xAF, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src1,GR32:$src2),
163 "imul{l}\t{$src2, $dst|$dst, $src2}",
164 [(set GR32:$dst, EFLAGS,
165 (X86smul_flag GR32:$src1, GR32:$src2))], IIC_IMUL32_RR>,
167 def IMUL64rr : RI<0xAF, MRMSrcReg, (outs GR64:$dst),
168 (ins GR64:$src1, GR64:$src2),
169 "imul{q}\t{$src2, $dst|$dst, $src2}",
170 [(set GR64:$dst, EFLAGS,
171 (X86smul_flag GR64:$src1, GR64:$src2))], IIC_IMUL64_RR>,
173 } // isCommutable, SchedRW
175 // Register-Memory Signed Integer Multiply
176 let SchedRW = [WriteIMulLd, ReadAfterLd] in {
177 def IMUL16rm : I<0xAF, MRMSrcMem, (outs GR16:$dst),
178 (ins GR16:$src1, i16mem:$src2),
179 "imul{w}\t{$src2, $dst|$dst, $src2}",
180 [(set GR16:$dst, EFLAGS,
181 (X86smul_flag GR16:$src1, (load addr:$src2)))],
184 def IMUL32rm : I<0xAF, MRMSrcMem, (outs GR32:$dst),
185 (ins GR32:$src1, i32mem:$src2),
186 "imul{l}\t{$src2, $dst|$dst, $src2}",
187 [(set GR32:$dst, EFLAGS,
188 (X86smul_flag GR32:$src1, (load addr:$src2)))],
191 def IMUL64rm : RI<0xAF, MRMSrcMem, (outs GR64:$dst),
192 (ins GR64:$src1, i64mem:$src2),
193 "imul{q}\t{$src2, $dst|$dst, $src2}",
194 [(set GR64:$dst, EFLAGS,
195 (X86smul_flag GR64:$src1, (load addr:$src2)))],
199 } // Constraints = "$src1 = $dst"
203 // Surprisingly enough, these are not two address instructions!
204 let Defs = [EFLAGS] in {
205 let SchedRW = [WriteIMul] in {
206 // Register-Integer Signed Integer Multiply
207 def 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 IIC_IMUL16_RRI>, OpSize;
213 def IMUL16rri8 : Ii8<0x6B, MRMSrcReg, // GR16 = GR16*I8
214 (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
215 "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
216 [(set GR16:$dst, EFLAGS,
217 (X86smul_flag GR16:$src1, i16immSExt8:$src2))],
220 def IMUL32rri : Ii32<0x69, MRMSrcReg, // GR32 = GR32*I32
221 (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
222 "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
223 [(set GR32:$dst, EFLAGS,
224 (X86smul_flag GR32:$src1, imm:$src2))],
225 IIC_IMUL32_RRI>, OpSize16;
226 def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, // GR32 = GR32*I8
227 (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
228 "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
229 [(set GR32:$dst, EFLAGS,
230 (X86smul_flag GR32:$src1, i32immSExt8:$src2))],
231 IIC_IMUL32_RRI>, OpSize16;
232 def IMUL64rri32 : RIi32<0x69, MRMSrcReg, // GR64 = GR64*I32
233 (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
234 "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
235 [(set GR64:$dst, EFLAGS,
236 (X86smul_flag GR64:$src1, i64immSExt32:$src2))],
238 def IMUL64rri8 : RIi8<0x6B, MRMSrcReg, // GR64 = GR64*I8
239 (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
240 "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
241 [(set GR64:$dst, EFLAGS,
242 (X86smul_flag GR64:$src1, i64immSExt8:$src2))],
246 // Memory-Integer Signed Integer Multiply
247 let SchedRW = [WriteIMulLd] in {
248 def IMUL16rmi : Ii16<0x69, MRMSrcMem, // GR16 = [mem16]*I16
249 (outs GR16:$dst), (ins i16mem:$src1, i16imm:$src2),
250 "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
251 [(set GR16:$dst, EFLAGS,
252 (X86smul_flag (load addr:$src1), imm:$src2))],
255 def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem, // GR16 = [mem16]*I8
256 (outs GR16:$dst), (ins i16mem:$src1, i16i8imm :$src2),
257 "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
258 [(set GR16:$dst, EFLAGS,
259 (X86smul_flag (load addr:$src1),
260 i16immSExt8:$src2))], IIC_IMUL16_RMI>,
262 def IMUL32rmi : Ii32<0x69, MRMSrcMem, // GR32 = [mem32]*I32
263 (outs GR32:$dst), (ins i32mem:$src1, i32imm:$src2),
264 "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
265 [(set GR32:$dst, EFLAGS,
266 (X86smul_flag (load addr:$src1), imm:$src2))],
267 IIC_IMUL32_RMI>, OpSize16;
268 def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8
269 (outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2),
270 "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
271 [(set GR32:$dst, EFLAGS,
272 (X86smul_flag (load addr:$src1),
273 i32immSExt8:$src2))],
274 IIC_IMUL32_RMI>, OpSize16;
275 def IMUL64rmi32 : RIi32<0x69, MRMSrcMem, // GR64 = [mem64]*I32
276 (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2),
277 "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
278 [(set GR64:$dst, EFLAGS,
279 (X86smul_flag (load addr:$src1),
280 i64immSExt32:$src2))],
282 def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem, // GR64 = [mem64]*I8
283 (outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2),
284 "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
285 [(set GR64:$dst, EFLAGS,
286 (X86smul_flag (load addr:$src1),
287 i64immSExt8:$src2))],
295 // unsigned division/remainder
296 let hasSideEffects = 1 in { // so that we don't speculatively execute
297 let SchedRW = [WriteIDiv] in {
298 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
299 def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH
300 "div{b}\t$src", [], IIC_DIV8_REG>;
301 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
302 def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX
303 "div{w}\t$src", [], IIC_DIV16>, OpSize;
304 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
305 def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX
306 "div{l}\t$src", [], IIC_DIV32>, OpSize16;
307 // RDX:RAX/r64 = RAX,RDX
308 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
309 def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src),
310 "div{q}\t$src", [], IIC_DIV64>;
314 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
315 def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH
316 "div{b}\t$src", [], IIC_DIV8_MEM>,
317 SchedLoadReg<WriteIDivLd>;
318 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
319 def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX
320 "div{w}\t$src", [], IIC_DIV16>, OpSize,
321 SchedLoadReg<WriteIDivLd>;
322 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX
323 def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src),
324 "div{l}\t$src", [], IIC_DIV32>,
325 SchedLoadReg<WriteIDivLd>, OpSize16;
326 // RDX:RAX/[mem64] = RAX,RDX
327 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
328 def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src),
329 "div{q}\t$src", [], IIC_DIV64>,
330 SchedLoadReg<WriteIDivLd>;
333 // Signed division/remainder.
334 let SchedRW = [WriteIDiv] in {
335 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
336 def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH
337 "idiv{b}\t$src", [], IIC_IDIV8>;
338 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
339 def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX
340 "idiv{w}\t$src", [], IIC_IDIV16>, OpSize;
341 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
342 def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX
343 "idiv{l}\t$src", [], IIC_IDIV32>, OpSize16;
344 // RDX:RAX/r64 = RAX,RDX
345 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
346 def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src),
347 "idiv{q}\t$src", [], IIC_IDIV64>;
351 let Defs = [AL,AH,EFLAGS], Uses = [AX] in
352 def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH
353 "idiv{b}\t$src", [], IIC_IDIV8>,
354 SchedLoadReg<WriteIDivLd>;
355 let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
356 def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX
357 "idiv{w}\t$src", [], IIC_IDIV16>, OpSize,
358 SchedLoadReg<WriteIDivLd>;
359 let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in // EDX:EAX/[mem32] = EAX,EDX
360 def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src),
361 "idiv{l}\t$src", [], IIC_IDIV32>, OpSize16,
362 SchedLoadReg<WriteIDivLd>;
363 let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in // RDX:RAX/[mem64] = RAX,RDX
364 def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src),
365 "idiv{q}\t$src", [], IIC_IDIV64>,
366 SchedLoadReg<WriteIDivLd>;
368 } // hasSideEffects = 0
370 //===----------------------------------------------------------------------===//
371 // Two address Instructions.
374 // unary instructions
375 let CodeSize = 2 in {
376 let Defs = [EFLAGS] in {
377 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
378 def NEG8r : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src1),
380 [(set GR8:$dst, (ineg GR8:$src1)),
381 (implicit EFLAGS)], IIC_UNARY_REG>;
382 def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src1),
384 [(set GR16:$dst, (ineg GR16:$src1)),
385 (implicit EFLAGS)], IIC_UNARY_REG>, OpSize;
386 def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src1),
388 [(set GR32:$dst, (ineg GR32:$src1)),
389 (implicit EFLAGS)], IIC_UNARY_REG>, OpSize16;
390 def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src1), "neg{q}\t$dst",
391 [(set GR64:$dst, (ineg GR64:$src1)),
392 (implicit EFLAGS)], IIC_UNARY_REG>;
393 } // Constraints = "$src1 = $dst", SchedRW
395 // Read-modify-write negate.
396 let SchedRW = [WriteALULd, WriteRMW] in {
397 def NEG8m : I<0xF6, MRM3m, (outs), (ins i8mem :$dst),
399 [(store (ineg (loadi8 addr:$dst)), addr:$dst),
400 (implicit EFLAGS)], IIC_UNARY_MEM>;
401 def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst),
403 [(store (ineg (loadi16 addr:$dst)), addr:$dst),
404 (implicit EFLAGS)], IIC_UNARY_MEM>, OpSize;
405 def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst),
407 [(store (ineg (loadi32 addr:$dst)), addr:$dst),
408 (implicit EFLAGS)], IIC_UNARY_MEM>, OpSize16;
409 def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst",
410 [(store (ineg (loadi64 addr:$dst)), addr:$dst),
411 (implicit EFLAGS)], IIC_UNARY_MEM>;
416 // Note: NOT does not set EFLAGS!
418 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
419 // Match xor -1 to not. Favors these over a move imm + xor to save code size.
420 let AddedComplexity = 15 in {
421 def NOT8r : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src1),
423 [(set GR8:$dst, (not GR8:$src1))], IIC_UNARY_REG>;
424 def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src1),
426 [(set GR16:$dst, (not GR16:$src1))], IIC_UNARY_REG>, OpSize;
427 def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src1),
429 [(set GR32:$dst, (not GR32:$src1))], IIC_UNARY_REG>, OpSize16;
430 def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src1), "not{q}\t$dst",
431 [(set GR64:$dst, (not GR64:$src1))], IIC_UNARY_REG>;
433 } // Constraints = "$src1 = $dst", SchedRW
435 let SchedRW = [WriteALULd, WriteRMW] in {
436 def NOT8m : I<0xF6, MRM2m, (outs), (ins i8mem :$dst),
438 [(store (not (loadi8 addr:$dst)), addr:$dst)], IIC_UNARY_MEM>;
439 def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst),
441 [(store (not (loadi16 addr:$dst)), addr:$dst)], IIC_UNARY_MEM>,
443 def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst),
445 [(store (not (loadi32 addr:$dst)), addr:$dst)], IIC_UNARY_MEM>,
447 def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst",
448 [(store (not (loadi64 addr:$dst)), addr:$dst)], IIC_UNARY_MEM>;
452 // TODO: inc/dec is slow for P4, but fast for Pentium-M.
453 let Defs = [EFLAGS] in {
454 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
456 def INC8r : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1),
458 [(set GR8:$dst, EFLAGS, (X86inc_flag GR8:$src1))],
461 let isConvertibleToThreeAddress = 1, CodeSize = 1 in { // Can xform into LEA.
462 def INC16r : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
464 [(set GR16:$dst, EFLAGS, (X86inc_flag GR16:$src1))], IIC_UNARY_REG>,
465 OpSize, Requires<[Not64BitMode]>;
466 def INC32r : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
468 [(set GR32:$dst, EFLAGS, (X86inc_flag GR32:$src1))],
470 OpSize16, Requires<[Not64BitMode]>;
471 def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src1), "inc{q}\t$dst",
472 [(set GR64:$dst, EFLAGS, (X86inc_flag GR64:$src1))],
474 } // isConvertibleToThreeAddress = 1, CodeSize = 1
477 // In 64-bit mode, single byte INC and DEC cannot be encoded.
478 let isConvertibleToThreeAddress = 1, CodeSize = 2 in {
479 // Can transform into LEA.
480 def INC64_16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
482 [(set GR16:$dst, EFLAGS, (X86inc_flag GR16:$src1))],
484 OpSize, Requires<[In64BitMode]>;
485 def INC64_32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
487 [(set GR32:$dst, EFLAGS, (X86inc_flag GR32:$src1))],
489 OpSize16, Requires<[In64BitMode]>;
490 def DEC64_16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src1),
492 [(set GR16:$dst, EFLAGS, (X86dec_flag GR16:$src1))],
494 OpSize, Requires<[In64BitMode]>;
495 def DEC64_32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src1),
497 [(set GR32:$dst, EFLAGS, (X86dec_flag GR32:$src1))],
499 OpSize16, Requires<[In64BitMode]>;
500 } // isConvertibleToThreeAddress = 1, CodeSize = 2
502 let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0,
504 def INC32_16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
505 "inc{w}\t$dst", [], IIC_UNARY_REG>,
506 OpSize, Requires<[Not64BitMode]>;
507 def INC32_32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
508 "inc{l}\t$dst", [], IIC_UNARY_REG>,
509 OpSize16, Requires<[Not64BitMode]>;
510 def DEC32_16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src1),
511 "dec{w}\t$dst", [], IIC_UNARY_REG>,
512 OpSize, Requires<[Not64BitMode]>;
513 def DEC32_32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src1),
514 "dec{l}\t$dst", [], IIC_UNARY_REG>,
515 OpSize16, Requires<[Not64BitMode]>;
516 } // isCodeGenOnly = 1, ForceDisassemble = 1, HasSideEffects = 0, CodeSize = 2
518 } // Constraints = "$src1 = $dst", SchedRW
520 let CodeSize = 2, SchedRW = [WriteALULd, WriteRMW] in {
521 def INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst",
522 [(store (add (loadi8 addr:$dst), 1), addr:$dst),
523 (implicit EFLAGS)], IIC_UNARY_MEM>;
524 def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst",
525 [(store (add (loadi16 addr:$dst), 1), addr:$dst),
526 (implicit EFLAGS)], IIC_UNARY_MEM>,
527 OpSize, Requires<[Not64BitMode]>;
528 def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst",
529 [(store (add (loadi32 addr:$dst), 1), addr:$dst),
530 (implicit EFLAGS)], IIC_UNARY_MEM>,
531 OpSize16, Requires<[Not64BitMode]>;
532 def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst",
533 [(store (add (loadi64 addr:$dst), 1), addr:$dst),
534 (implicit EFLAGS)], IIC_UNARY_MEM>;
536 // These are duplicates of their 32-bit counterparts. Only needed so X86 knows
537 // how to unfold them.
538 // FIXME: What is this for??
539 def INC64_16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst",
540 [(store (add (loadi16 addr:$dst), 1), addr:$dst),
541 (implicit EFLAGS)], IIC_UNARY_MEM>,
542 OpSize, Requires<[In64BitMode]>;
543 def INC64_32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst",
544 [(store (add (loadi32 addr:$dst), 1), addr:$dst),
545 (implicit EFLAGS)], IIC_UNARY_MEM>,
546 OpSize16, Requires<[In64BitMode]>;
547 def DEC64_16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst",
548 [(store (add (loadi16 addr:$dst), -1), addr:$dst),
549 (implicit EFLAGS)], IIC_UNARY_MEM>,
550 OpSize, Requires<[In64BitMode]>;
551 def DEC64_32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst",
552 [(store (add (loadi32 addr:$dst), -1), addr:$dst),
553 (implicit EFLAGS)], IIC_UNARY_MEM>,
554 OpSize16, Requires<[In64BitMode]>;
555 } // CodeSize = 2, SchedRW
557 let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in {
559 def DEC8r : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1),
561 [(set GR8:$dst, EFLAGS, (X86dec_flag GR8:$src1))],
563 let isConvertibleToThreeAddress = 1, CodeSize = 1 in { // Can xform into LEA.
564 def DEC16r : I<0x48, AddRegFrm, (outs GR16:$dst), (ins GR16:$src1),
566 [(set GR16:$dst, EFLAGS, (X86dec_flag GR16:$src1))],
568 OpSize, Requires<[Not64BitMode]>;
569 def DEC32r : I<0x48, AddRegFrm, (outs GR32:$dst), (ins GR32:$src1),
571 [(set GR32:$dst, EFLAGS, (X86dec_flag GR32:$src1))],
573 OpSize16, Requires<[Not64BitMode]>;
574 def DEC64r : RI<0xFF, MRM1r, (outs GR64:$dst), (ins GR64:$src1), "dec{q}\t$dst",
575 [(set GR64:$dst, EFLAGS, (X86dec_flag GR64:$src1))],
578 } // Constraints = "$src1 = $dst", SchedRW
581 let CodeSize = 2, SchedRW = [WriteALULd, WriteRMW] in {
582 def DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), "dec{b}\t$dst",
583 [(store (add (loadi8 addr:$dst), -1), addr:$dst),
584 (implicit EFLAGS)], IIC_UNARY_MEM>;
585 def DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst",
586 [(store (add (loadi16 addr:$dst), -1), addr:$dst),
587 (implicit EFLAGS)], IIC_UNARY_MEM>,
588 OpSize, Requires<[Not64BitMode]>;
589 def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst",
590 [(store (add (loadi32 addr:$dst), -1), addr:$dst),
591 (implicit EFLAGS)], IIC_UNARY_MEM>,
592 OpSize16, Requires<[Not64BitMode]>;
593 def DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), "dec{q}\t$dst",
594 [(store (add (loadi64 addr:$dst), -1), addr:$dst),
595 (implicit EFLAGS)], IIC_UNARY_MEM>;
596 } // CodeSize = 2, SchedRW
599 /// X86TypeInfo - This is a bunch of information that describes relevant X86
600 /// information about value types. For example, it can tell you what the
601 /// register class and preferred load to use.
602 class X86TypeInfo<ValueType vt, string instrsuffix, RegisterClass regclass,
603 PatFrag loadnode, X86MemOperand memoperand, ImmType immkind,
604 Operand immoperand, SDPatternOperator immoperator,
605 Operand imm8operand, SDPatternOperator imm8operator,
606 bit hasOddOpcode, bit hasOpSizePrefix, bit hasOpSize16Prefix,
607 bit hasREX_WPrefix> {
608 /// VT - This is the value type itself.
611 /// InstrSuffix - This is the suffix used on instructions with this type. For
612 /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q".
613 string InstrSuffix = instrsuffix;
615 /// RegClass - This is the register class associated with this type. For
616 /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64.
617 RegisterClass RegClass = regclass;
619 /// LoadNode - This is the load node associated with this type. For
620 /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64.
621 PatFrag LoadNode = loadnode;
623 /// MemOperand - This is the memory operand associated with this type. For
624 /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem.
625 X86MemOperand MemOperand = memoperand;
627 /// ImmEncoding - This is the encoding of an immediate of this type. For
628 /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32
629 /// since the immediate fields of i64 instructions is a 32-bit sign extended
631 ImmType ImmEncoding = immkind;
633 /// ImmOperand - This is the operand kind of an immediate of this type. For
634 /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 ->
635 /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign
637 Operand ImmOperand = immoperand;
639 /// ImmOperator - This is the operator that should be used to match an
640 /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32).
641 SDPatternOperator ImmOperator = immoperator;
643 /// Imm8Operand - This is the operand kind to use for an imm8 of this type.
644 /// For example, i8 -> <invalid>, i16 -> i16i8imm, i32 -> i32i8imm. This is
645 /// only used for instructions that have a sign-extended imm8 field form.
646 Operand Imm8Operand = imm8operand;
648 /// Imm8Operator - This is the operator that should be used to match an 8-bit
649 /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8).
650 SDPatternOperator Imm8Operator = imm8operator;
652 /// HasOddOpcode - This bit is true if the instruction should have an odd (as
653 /// opposed to even) opcode. Operations on i8 are usually even, operations on
654 /// other datatypes are odd.
655 bit HasOddOpcode = hasOddOpcode;
657 /// HasOpSizePrefix - This bit is set to true if the instruction should have
658 /// the 0x66 operand size prefix in 32-bit or 64-bit modes. This is set for
660 bit HasOpSizePrefix = hasOpSizePrefix;
662 /// HasOpSizePrefix - This bit is set to true if the instruction should have
663 /// the 0x66 operand size prefix in 16-bit mode. This is set for i32 types.
664 bit HasOpSize16Prefix = hasOpSize16Prefix;
666 /// HasREX_WPrefix - This bit is set to true if the instruction should have
667 /// the 0x40 REX prefix. This is set for i64 types.
668 bit HasREX_WPrefix = hasREX_WPrefix;
671 def invalid_node : SDNode<"<<invalid_node>>", SDTIntLeaf,[],"<<invalid_node>>">;
674 def Xi8 : X86TypeInfo<i8 , "b", GR8 , loadi8 , i8mem ,
675 Imm8 , i8imm , imm, i8imm , invalid_node,
677 def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem,
678 Imm16, i16imm, imm, i16i8imm, i16immSExt8,
680 def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem,
681 Imm32, i32imm, imm, i32i8imm, i32immSExt8,
683 def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem,
684 Imm32, i64i32imm, i64immSExt32, i64i8imm, i64immSExt8,
687 /// ITy - This instruction base class takes the type info for the instruction.
689 /// 1. Concatenates together the instruction mnemonic with the appropriate
690 /// suffix letter, a tab, and the arguments.
691 /// 2. Infers whether the instruction should have a 0x66 prefix byte.
692 /// 3. Infers whether the instruction should have a 0x40 REX_W prefix.
693 /// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations)
694 /// or 1 (for i16,i32,i64 operations).
695 class ITy<bits<8> opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins,
696 string mnemonic, string args, list<dag> pattern,
697 InstrItinClass itin = IIC_BIN_NONMEM>
698 : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4},
699 opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode },
701 !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern,
704 // Infer instruction prefixes from type info.
705 let hasOpSizePrefix = typeinfo.HasOpSizePrefix;
706 let hasOpSize16Prefix = typeinfo.HasOpSize16Prefix;
707 let hasREX_WPrefix = typeinfo.HasREX_WPrefix;
710 // BinOpRR - Instructions like "add reg, reg, reg".
711 class BinOpRR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
712 dag outlist, list<dag> pattern, InstrItinClass itin,
713 Format f = MRMDestReg>
714 : ITy<opcode, f, typeinfo, outlist,
715 (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
716 mnemonic, "{$src2, $src1|$src1, $src2}", pattern, itin>,
719 // BinOpRR_R - Instructions like "add reg, reg, reg", where the pattern has
720 // just a regclass (no eflags) as a result.
721 class BinOpRR_R<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
723 : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
724 [(set typeinfo.RegClass:$dst,
725 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))],
728 // BinOpRR_F - Instructions like "cmp reg, Reg", where the pattern has
729 // just a EFLAGS as a result.
730 class BinOpRR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
731 SDPatternOperator opnode, Format f = MRMDestReg>
732 : BinOpRR<opcode, mnemonic, typeinfo, (outs),
734 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))],
737 // BinOpRR_RF - Instructions like "add reg, reg, reg", where the pattern has
738 // both a regclass and EFLAGS as a result.
739 class BinOpRR_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
741 : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
742 [(set typeinfo.RegClass:$dst, EFLAGS,
743 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))],
746 // BinOpRR_RFF - Instructions like "adc reg, reg, reg", where the pattern has
747 // both a regclass and EFLAGS as a result, and has EFLAGS as input.
748 class BinOpRR_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
750 : BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
751 [(set typeinfo.RegClass:$dst, EFLAGS,
752 (opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2,
753 EFLAGS))], IIC_BIN_CARRY_NONMEM>;
755 // BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding).
756 class BinOpRR_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
757 InstrItinClass itin = IIC_BIN_NONMEM>
758 : ITy<opcode, MRMSrcReg, typeinfo,
759 (outs typeinfo.RegClass:$dst),
760 (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
761 mnemonic, "{$src2, $dst|$dst, $src2}", [], itin>,
763 // The disassembler should know about this, but not the asmparser.
764 let isCodeGenOnly = 1;
765 let ForceDisassemble = 1;
766 let hasSideEffects = 0;
769 // BinOpRR_RDD_Rev - Instructions like "adc reg, reg, reg" (reversed encoding).
770 class BinOpRR_RFF_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
771 : BinOpRR_Rev<opcode, mnemonic, typeinfo, IIC_BIN_CARRY_NONMEM>;
773 // BinOpRR_F_Rev - Instructions like "cmp reg, reg" (reversed encoding).
774 class BinOpRR_F_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
775 : ITy<opcode, MRMSrcReg, typeinfo, (outs),
776 (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
777 mnemonic, "{$src2, $src1|$src1, $src2}", [], IIC_BIN_NONMEM>,
779 // The disassembler should know about this, but not the asmparser.
780 let isCodeGenOnly = 1;
781 let ForceDisassemble = 1;
782 let hasSideEffects = 0;
785 // BinOpRM - Instructions like "add reg, reg, [mem]".
786 class BinOpRM<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
787 dag outlist, list<dag> pattern,
788 InstrItinClass itin = IIC_BIN_MEM>
789 : ITy<opcode, MRMSrcMem, typeinfo, outlist,
790 (ins typeinfo.RegClass:$src1, typeinfo.MemOperand:$src2),
791 mnemonic, "{$src2, $src1|$src1, $src2}", pattern, itin>,
792 Sched<[WriteALULd, ReadAfterLd]>;
794 // BinOpRM_R - Instructions like "add reg, reg, [mem]".
795 class BinOpRM_R<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
797 : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
798 [(set typeinfo.RegClass:$dst,
799 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
801 // BinOpRM_F - Instructions like "cmp reg, [mem]".
802 class BinOpRM_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
803 SDPatternOperator opnode>
804 : BinOpRM<opcode, mnemonic, typeinfo, (outs),
806 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
808 // BinOpRM_RF - Instructions like "add reg, reg, [mem]".
809 class BinOpRM_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
811 : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
812 [(set typeinfo.RegClass:$dst, EFLAGS,
813 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
815 // BinOpRM_RFF - Instructions like "adc reg, reg, [mem]".
816 class BinOpRM_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
818 : BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
819 [(set typeinfo.RegClass:$dst, EFLAGS,
820 (opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2),
821 EFLAGS))], IIC_BIN_CARRY_MEM>;
823 // BinOpRI - Instructions like "add reg, reg, imm".
824 class BinOpRI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
825 Format f, dag outlist, list<dag> pattern,
826 InstrItinClass itin = IIC_BIN_NONMEM>
827 : ITy<opcode, f, typeinfo, outlist,
828 (ins typeinfo.RegClass:$src1, typeinfo.ImmOperand:$src2),
829 mnemonic, "{$src2, $src1|$src1, $src2}", pattern, itin>,
831 let ImmT = typeinfo.ImmEncoding;
834 // BinOpRI_R - Instructions like "add reg, reg, imm".
835 class BinOpRI_R<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
836 SDNode opnode, Format f>
837 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
838 [(set typeinfo.RegClass:$dst,
839 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
841 // BinOpRI_F - Instructions like "cmp reg, imm".
842 class BinOpRI_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
843 SDPatternOperator opnode, Format f>
844 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs),
846 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
848 // BinOpRI_RF - Instructions like "add reg, reg, imm".
849 class BinOpRI_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
850 SDNode opnode, Format f>
851 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
852 [(set typeinfo.RegClass:$dst, EFLAGS,
853 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
854 // BinOpRI_RFF - Instructions like "adc reg, reg, imm".
855 class BinOpRI_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
856 SDNode opnode, Format f>
857 : BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
858 [(set typeinfo.RegClass:$dst, EFLAGS,
859 (opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2,
860 EFLAGS))], IIC_BIN_CARRY_NONMEM>;
862 // BinOpRI8 - Instructions like "add reg, reg, imm8".
863 class BinOpRI8<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
864 Format f, dag outlist, list<dag> pattern,
865 InstrItinClass itin = IIC_BIN_NONMEM>
866 : ITy<opcode, f, typeinfo, outlist,
867 (ins typeinfo.RegClass:$src1, typeinfo.Imm8Operand:$src2),
868 mnemonic, "{$src2, $src1|$src1, $src2}", pattern, itin>,
870 let ImmT = Imm8; // Always 8-bit immediate.
873 // BinOpRI8_R - Instructions like "add reg, reg, imm8".
874 class BinOpRI8_R<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
875 SDNode opnode, Format f>
876 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
877 [(set typeinfo.RegClass:$dst,
878 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
880 // BinOpRI8_F - Instructions like "cmp reg, imm8".
881 class BinOpRI8_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
882 SDNode opnode, Format f>
883 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs),
885 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
887 // BinOpRI8_RF - Instructions like "add reg, reg, imm8".
888 class BinOpRI8_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
889 SDNode opnode, Format f>
890 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
891 [(set typeinfo.RegClass:$dst, EFLAGS,
892 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
894 // BinOpRI8_RFF - Instructions like "adc reg, reg, imm8".
895 class BinOpRI8_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
896 SDNode opnode, Format f>
897 : BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
898 [(set typeinfo.RegClass:$dst, EFLAGS,
899 (opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2,
900 EFLAGS))], IIC_BIN_CARRY_NONMEM>;
902 // BinOpMR - Instructions like "add [mem], reg".
903 class BinOpMR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
904 list<dag> pattern, InstrItinClass itin = IIC_BIN_MEM>
905 : ITy<opcode, MRMDestMem, typeinfo,
906 (outs), (ins typeinfo.MemOperand:$dst, typeinfo.RegClass:$src),
907 mnemonic, "{$src, $dst|$dst, $src}", pattern, itin>,
908 Sched<[WriteALULd, WriteRMW]>;
910 // BinOpMR_RMW - Instructions like "add [mem], reg".
911 class BinOpMR_RMW<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
913 : BinOpMR<opcode, mnemonic, typeinfo,
914 [(store (opnode (load addr:$dst), typeinfo.RegClass:$src), addr:$dst),
917 // BinOpMR_RMW_FF - Instructions like "adc [mem], reg".
918 class BinOpMR_RMW_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
920 : BinOpMR<opcode, mnemonic, typeinfo,
921 [(store (opnode (load addr:$dst), typeinfo.RegClass:$src, EFLAGS),
923 (implicit EFLAGS)], IIC_BIN_CARRY_MEM>;
925 // BinOpMR_F - Instructions like "cmp [mem], reg".
926 class BinOpMR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
928 : BinOpMR<opcode, mnemonic, typeinfo,
929 [(set EFLAGS, (opnode (load addr:$dst), typeinfo.RegClass:$src))]>;
931 // BinOpMI - Instructions like "add [mem], imm".
932 class BinOpMI<string mnemonic, X86TypeInfo typeinfo,
933 Format f, list<dag> pattern, bits<8> opcode = 0x80,
934 InstrItinClass itin = IIC_BIN_MEM>
935 : ITy<opcode, f, typeinfo,
936 (outs), (ins typeinfo.MemOperand:$dst, typeinfo.ImmOperand:$src),
937 mnemonic, "{$src, $dst|$dst, $src}", pattern, itin>,
938 Sched<[WriteALULd, WriteRMW]> {
939 let ImmT = typeinfo.ImmEncoding;
942 // BinOpMI_RMW - Instructions like "add [mem], imm".
943 class BinOpMI_RMW<string mnemonic, X86TypeInfo typeinfo,
944 SDNode opnode, Format f>
945 : BinOpMI<mnemonic, typeinfo, f,
946 [(store (opnode (typeinfo.VT (load addr:$dst)),
947 typeinfo.ImmOperator:$src), addr:$dst),
949 // BinOpMI_RMW_FF - Instructions like "adc [mem], imm".
950 class BinOpMI_RMW_FF<string mnemonic, X86TypeInfo typeinfo,
951 SDNode opnode, Format f>
952 : BinOpMI<mnemonic, typeinfo, f,
953 [(store (opnode (typeinfo.VT (load addr:$dst)),
954 typeinfo.ImmOperator:$src, EFLAGS), addr:$dst),
955 (implicit EFLAGS)], 0x80, IIC_BIN_CARRY_MEM>;
957 // BinOpMI_F - Instructions like "cmp [mem], imm".
958 class BinOpMI_F<string mnemonic, X86TypeInfo typeinfo,
959 SDPatternOperator opnode, Format f, bits<8> opcode = 0x80>
960 : BinOpMI<mnemonic, typeinfo, f,
961 [(set EFLAGS, (opnode (typeinfo.VT (load addr:$dst)),
962 typeinfo.ImmOperator:$src))],
965 // BinOpMI8 - Instructions like "add [mem], imm8".
966 class BinOpMI8<string mnemonic, X86TypeInfo typeinfo,
967 Format f, list<dag> pattern,
968 InstrItinClass itin = IIC_BIN_MEM>
969 : ITy<0x82, f, typeinfo,
970 (outs), (ins typeinfo.MemOperand:$dst, typeinfo.Imm8Operand:$src),
971 mnemonic, "{$src, $dst|$dst, $src}", pattern, itin>,
972 Sched<[WriteALULd, WriteRMW]> {
973 let ImmT = Imm8; // Always 8-bit immediate.
976 // BinOpMI8_RMW - Instructions like "add [mem], imm8".
977 class BinOpMI8_RMW<string mnemonic, X86TypeInfo typeinfo,
978 SDNode opnode, Format f>
979 : BinOpMI8<mnemonic, typeinfo, f,
980 [(store (opnode (load addr:$dst),
981 typeinfo.Imm8Operator:$src), addr:$dst),
984 // BinOpMI8_RMW_FF - Instructions like "adc [mem], imm8".
985 class BinOpMI8_RMW_FF<string mnemonic, X86TypeInfo typeinfo,
986 SDNode opnode, Format f>
987 : BinOpMI8<mnemonic, typeinfo, f,
988 [(store (opnode (load addr:$dst),
989 typeinfo.Imm8Operator:$src, EFLAGS), addr:$dst),
990 (implicit EFLAGS)], IIC_BIN_CARRY_MEM>;
992 // BinOpMI8_F - Instructions like "cmp [mem], imm8".
993 class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
994 SDNode opnode, Format f>
995 : BinOpMI8<mnemonic, typeinfo, f,
996 [(set EFLAGS, (opnode (load addr:$dst),
997 typeinfo.Imm8Operator:$src))]>;
999 // BinOpAI - Instructions like "add %eax, %eax, imm", that imp-def EFLAGS.
1000 class BinOpAI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
1001 Register areg, string operands,
1002 InstrItinClass itin = IIC_BIN_NONMEM>
1003 : ITy<opcode, RawFrm, typeinfo,
1004 (outs), (ins typeinfo.ImmOperand:$src),
1005 mnemonic, operands, [], itin>, Sched<[WriteALU]> {
1006 let ImmT = typeinfo.ImmEncoding;
1008 let Defs = [areg, EFLAGS];
1009 let hasSideEffects = 0;
1012 // BinOpAI_FF - Instructions like "adc %eax, %eax, imm", that implicitly define
1014 class BinOpAI_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
1015 Register areg, string operands>
1016 : BinOpAI<opcode, mnemonic, typeinfo, areg, operands,
1017 IIC_BIN_CARRY_NONMEM> {
1018 let Uses = [areg, EFLAGS];
1021 /// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
1022 /// defined with "(set GPR:$dst, EFLAGS, (...".
1024 /// It would be nice to get rid of the second and third argument here, but
1025 /// tblgen can't handle dependent type references aggressively enough: PR8330
1026 multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1027 string mnemonic, Format RegMRM, Format MemMRM,
1028 SDNode opnodeflag, SDNode opnode,
1029 bit CommutableRR, bit ConvertibleToThreeAddress> {
1030 let Defs = [EFLAGS] in {
1031 let Constraints = "$src1 = $dst" in {
1032 let isCommutable = CommutableRR,
1033 isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1034 def NAME#8rr : BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
1035 def NAME#16rr : BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>;
1036 def NAME#32rr : BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>;
1037 def NAME#64rr : BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
1040 def NAME#8rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>;
1041 def NAME#16rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi16>;
1042 def NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>;
1043 def NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>;
1045 def NAME#8rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
1046 def NAME#16rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>;
1047 def NAME#32rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>;
1048 def NAME#64rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
1050 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1051 // NOTE: These are order specific, we want the ri8 forms to be listed
1052 // first so that they are slightly preferred to the ri forms.
1053 def NAME#16ri8 : BinOpRI8_RF<0x82, mnemonic, Xi16, opnodeflag, RegMRM>;
1054 def NAME#32ri8 : BinOpRI8_RF<0x82, mnemonic, Xi32, opnodeflag, RegMRM>;
1055 def NAME#64ri8 : BinOpRI8_RF<0x82, mnemonic, Xi64, opnodeflag, RegMRM>;
1057 def NAME#8ri : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
1058 def NAME#16ri : BinOpRI_RF<0x80, mnemonic, Xi16, opnodeflag, RegMRM>;
1059 def NAME#32ri : BinOpRI_RF<0x80, mnemonic, Xi32, opnodeflag, RegMRM>;
1060 def NAME#64ri32: BinOpRI_RF<0x80, mnemonic, Xi64, opnodeflag, RegMRM>;
1062 } // Constraints = "$src1 = $dst"
1064 def NAME#8mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi8 , opnode>;
1065 def NAME#16mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi16, opnode>;
1066 def NAME#32mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi32, opnode>;
1067 def NAME#64mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi64, opnode>;
1069 // NOTE: These are order specific, we want the mi8 forms to be listed
1070 // first so that they are slightly preferred to the mi forms.
1071 def NAME#16mi8 : BinOpMI8_RMW<mnemonic, Xi16, opnode, MemMRM>;
1072 def NAME#32mi8 : BinOpMI8_RMW<mnemonic, Xi32, opnode, MemMRM>;
1073 def NAME#64mi8 : BinOpMI8_RMW<mnemonic, Xi64, opnode, MemMRM>;
1075 def NAME#8mi : BinOpMI_RMW<mnemonic, Xi8 , opnode, MemMRM>;
1076 def NAME#16mi : BinOpMI_RMW<mnemonic, Xi16, opnode, MemMRM>;
1077 def NAME#32mi : BinOpMI_RMW<mnemonic, Xi32, opnode, MemMRM>;
1078 def NAME#64mi32 : BinOpMI_RMW<mnemonic, Xi64, opnode, MemMRM>;
1079 } // Defs = [EFLAGS]
1081 def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
1082 "{$src, %al|al, $src}">;
1083 def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
1084 "{$src, %ax|ax, $src}">;
1085 def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
1086 "{$src, %eax|eax, $src}">;
1087 def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
1088 "{$src, %rax|rax, $src}">;
1091 /// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
1092 /// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
1095 /// It would be nice to get rid of the second and third argument here, but
1096 /// tblgen can't handle dependent type references aggressively enough: PR8330
1097 multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1098 string mnemonic, Format RegMRM, Format MemMRM,
1099 SDNode opnode, bit CommutableRR,
1100 bit ConvertibleToThreeAddress> {
1101 let Uses = [EFLAGS], Defs = [EFLAGS] in {
1102 let Constraints = "$src1 = $dst" in {
1103 let isCommutable = CommutableRR,
1104 isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1105 def NAME#8rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi8 , opnode>;
1106 def NAME#16rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi16, opnode>;
1107 def NAME#32rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi32, opnode>;
1108 def NAME#64rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi64, opnode>;
1111 def NAME#8rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi8>;
1112 def NAME#16rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi16>;
1113 def NAME#32rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi32>;
1114 def NAME#64rr_REV : BinOpRR_RFF_Rev<BaseOpc2, mnemonic, Xi64>;
1116 def NAME#8rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi8 , opnode>;
1117 def NAME#16rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi16, opnode>;
1118 def NAME#32rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi32, opnode>;
1119 def NAME#64rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi64, opnode>;
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_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>;
1125 def NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>;
1126 def NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>;
1128 def NAME#8ri : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1129 def NAME#16ri : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>;
1130 def NAME#32ri : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>;
1131 def NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>;
1133 } // Constraints = "$src1 = $dst"
1135 def NAME#8mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi8 , opnode>;
1136 def NAME#16mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi16, opnode>;
1137 def NAME#32mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi32, opnode>;
1138 def NAME#64mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi64, opnode>;
1140 // NOTE: These are order specific, we want the mi8 forms to be listed
1141 // first so that they are slightly preferred to the mi forms.
1142 def NAME#16mi8 : BinOpMI8_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
1143 def NAME#32mi8 : BinOpMI8_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
1144 def NAME#64mi8 : BinOpMI8_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
1146 def NAME#8mi : BinOpMI_RMW_FF<mnemonic, Xi8 , opnode, MemMRM>;
1147 def NAME#16mi : BinOpMI_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
1148 def NAME#32mi : BinOpMI_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
1149 def NAME#64mi32 : BinOpMI_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
1150 } // Uses = [EFLAGS], Defs = [EFLAGS]
1152 def NAME#8i8 : BinOpAI_FF<BaseOpc4, mnemonic, Xi8 , AL,
1153 "{$src, %al|al, $src}">;
1154 def NAME#16i16 : BinOpAI_FF<BaseOpc4, mnemonic, Xi16, AX,
1155 "{$src, %ax|ax, $src}">;
1156 def NAME#32i32 : BinOpAI_FF<BaseOpc4, mnemonic, Xi32, EAX,
1157 "{$src, %eax|eax, $src}">;
1158 def NAME#64i32 : BinOpAI_FF<BaseOpc4, mnemonic, Xi64, RAX,
1159 "{$src, %rax|rax, $src}">;
1162 /// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
1163 /// defined with "(set EFLAGS, (...". It would be really nice to find a way
1164 /// to factor this with the other ArithBinOp_*.
1166 multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
1167 string mnemonic, Format RegMRM, Format MemMRM,
1169 bit CommutableRR, bit ConvertibleToThreeAddress> {
1170 let Defs = [EFLAGS] in {
1171 let isCommutable = CommutableRR,
1172 isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1173 def NAME#8rr : BinOpRR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1174 def NAME#16rr : BinOpRR_F<BaseOpc, mnemonic, Xi16, opnode>;
1175 def NAME#32rr : BinOpRR_F<BaseOpc, mnemonic, Xi32, opnode>;
1176 def NAME#64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
1179 def NAME#8rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>;
1180 def NAME#16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>;
1181 def NAME#32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>;
1182 def NAME#64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>;
1184 def NAME#8rm : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
1185 def NAME#16rm : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>;
1186 def NAME#32rm : BinOpRM_F<BaseOpc2, mnemonic, Xi32, opnode>;
1187 def NAME#64rm : BinOpRM_F<BaseOpc2, mnemonic, Xi64, opnode>;
1189 let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
1190 // NOTE: These are order specific, we want the ri8 forms to be listed
1191 // first so that they are slightly preferred to the ri forms.
1192 def NAME#16ri8 : BinOpRI8_F<0x82, mnemonic, Xi16, opnode, RegMRM>;
1193 def NAME#32ri8 : BinOpRI8_F<0x82, mnemonic, Xi32, opnode, RegMRM>;
1194 def NAME#64ri8 : BinOpRI8_F<0x82, mnemonic, Xi64, opnode, RegMRM>;
1196 def NAME#8ri : BinOpRI_F<0x80, mnemonic, Xi8 , opnode, RegMRM>;
1197 def NAME#16ri : BinOpRI_F<0x80, mnemonic, Xi16, opnode, RegMRM>;
1198 def NAME#32ri : BinOpRI_F<0x80, mnemonic, Xi32, opnode, RegMRM>;
1199 def NAME#64ri32: BinOpRI_F<0x80, mnemonic, Xi64, opnode, RegMRM>;
1202 def NAME#8mr : BinOpMR_F<BaseOpc, mnemonic, Xi8 , opnode>;
1203 def NAME#16mr : BinOpMR_F<BaseOpc, mnemonic, Xi16, opnode>;
1204 def NAME#32mr : BinOpMR_F<BaseOpc, mnemonic, Xi32, opnode>;
1205 def NAME#64mr : BinOpMR_F<BaseOpc, mnemonic, Xi64, opnode>;
1207 // NOTE: These are order specific, we want the mi8 forms to be listed
1208 // first so that they are slightly preferred to the mi forms.
1209 def NAME#16mi8 : BinOpMI8_F<mnemonic, Xi16, opnode, MemMRM>;
1210 def NAME#32mi8 : BinOpMI8_F<mnemonic, Xi32, opnode, MemMRM>;
1211 def NAME#64mi8 : BinOpMI8_F<mnemonic, Xi64, opnode, MemMRM>;
1213 def NAME#8mi : BinOpMI_F<mnemonic, Xi8 , opnode, MemMRM>;
1214 def NAME#16mi : BinOpMI_F<mnemonic, Xi16, opnode, MemMRM>;
1215 def NAME#32mi : BinOpMI_F<mnemonic, Xi32, opnode, MemMRM>;
1216 def NAME#64mi32 : BinOpMI_F<mnemonic, Xi64, opnode, MemMRM>;
1217 } // Defs = [EFLAGS]
1219 def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
1220 "{$src, %al|al, $src}">;
1221 def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
1222 "{$src, %ax|ax, $src}">;
1223 def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
1224 "{$src, %eax|eax, $src}">;
1225 def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
1226 "{$src, %rax|rax, $src}">;
1230 defm AND : ArithBinOp_RF<0x20, 0x22, 0x24, "and", MRM4r, MRM4m,
1231 X86and_flag, and, 1, 0>;
1232 defm OR : ArithBinOp_RF<0x08, 0x0A, 0x0C, "or", MRM1r, MRM1m,
1233 X86or_flag, or, 1, 0>;
1234 defm XOR : ArithBinOp_RF<0x30, 0x32, 0x34, "xor", MRM6r, MRM6m,
1235 X86xor_flag, xor, 1, 0>;
1236 defm ADD : ArithBinOp_RF<0x00, 0x02, 0x04, "add", MRM0r, MRM0m,
1237 X86add_flag, add, 1, 1>;
1238 let isCompare = 1 in {
1239 defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m,
1240 X86sub_flag, sub, 0, 0>;
1244 defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
1246 defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
1249 let isCompare = 1 in {
1250 defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
1254 //===----------------------------------------------------------------------===//
1255 // Semantically, test instructions are similar like AND, except they don't
1256 // generate a result. From an encoding perspective, they are very different:
1257 // they don't have all the usual imm8 and REV forms, and are encoded into a
1259 def X86testpat : PatFrag<(ops node:$lhs, node:$rhs),
1260 (X86cmp (and_su node:$lhs, node:$rhs), 0)>;
1262 let isCompare = 1 in {
1263 let Defs = [EFLAGS] in {
1264 let isCommutable = 1 in {
1265 def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat, MRMSrcReg>;
1266 def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat, MRMSrcReg>;
1267 def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat, MRMSrcReg>;
1268 def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat, MRMSrcReg>;
1271 def TEST8rm : BinOpRM_F<0x84, "test", Xi8 , X86testpat>;
1272 def TEST16rm : BinOpRM_F<0x84, "test", Xi16, X86testpat>;
1273 def TEST32rm : BinOpRM_F<0x84, "test", Xi32, X86testpat>;
1274 def TEST64rm : BinOpRM_F<0x84, "test", Xi64, X86testpat>;
1276 def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
1277 def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>;
1278 def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>;
1279 def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>;
1281 def TEST8mi : BinOpMI_F<"test", Xi8 , X86testpat, MRM0m, 0xF6>;
1282 def TEST16mi : BinOpMI_F<"test", Xi16, X86testpat, MRM0m, 0xF6>;
1283 def TEST32mi : BinOpMI_F<"test", Xi32, X86testpat, MRM0m, 0xF6>;
1284 def TEST64mi32 : BinOpMI_F<"test", Xi64, X86testpat, MRM0m, 0xF6>;
1286 // When testing the result of EXTRACT_SUBREG sub_8bit_hi, make sure the
1287 // register class is constrained to GR8_NOREX.
1289 def TEST8ri_NOREX : I<0, Pseudo, (outs), (ins GR8_NOREX:$src, i8imm:$mask),
1290 "", [], IIC_BIN_NONMEM>, Sched<[WriteALU]>;
1291 } // Defs = [EFLAGS]
1293 def TEST8i8 : BinOpAI<0xA8, "test", Xi8 , AL,
1294 "{$src, %al|al, $src}">;
1295 def TEST16i16 : BinOpAI<0xA8, "test", Xi16, AX,
1296 "{$src, %ax|ax, $src}">;
1297 def TEST32i32 : BinOpAI<0xA8, "test", Xi32, EAX,
1298 "{$src, %eax|eax, $src}">;
1299 def TEST64i32 : BinOpAI<0xA8, "test", Xi64, RAX,
1300 "{$src, %rax|rax, $src}">;
1303 //===----------------------------------------------------------------------===//
1306 multiclass bmi_andn<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
1308 def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
1309 !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1310 [(set RC:$dst, EFLAGS, (X86and_flag (not RC:$src1), RC:$src2))],
1311 IIC_BIN_NONMEM>, Sched<[WriteALU]>;
1312 def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
1313 !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
1314 [(set RC:$dst, EFLAGS,
1315 (X86and_flag (not RC:$src1), (ld_frag addr:$src2)))], IIC_BIN_MEM>,
1316 Sched<[WriteALULd, ReadAfterLd]>;
1319 let Predicates = [HasBMI], Defs = [EFLAGS] in {
1320 defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8, VEX_4V;
1321 defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8, VEX_4V, VEX_W;
1324 let Predicates = [HasBMI] in {
1325 def : Pat<(and (not GR32:$src1), GR32:$src2),
1326 (ANDN32rr GR32:$src1, GR32:$src2)>;
1327 def : Pat<(and (not GR64:$src1), GR64:$src2),
1328 (ANDN64rr GR64:$src1, GR64:$src2)>;
1329 def : Pat<(and (not GR32:$src1), (loadi32 addr:$src2)),
1330 (ANDN32rm GR32:$src1, addr:$src2)>;
1331 def : Pat<(and (not GR64:$src1), (loadi64 addr:$src2)),
1332 (ANDN64rm GR64:$src1, addr:$src2)>;
1335 //===----------------------------------------------------------------------===//
1338 multiclass bmi_mulx<string mnemonic, RegisterClass RC, X86MemOperand x86memop> {
1339 let neverHasSideEffects = 1 in {
1340 let isCommutable = 1 in
1341 def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src),
1342 !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1343 [], IIC_MUL8>, T8XD, VEX_4V, Sched<[WriteIMul, WriteIMulH]>;
1346 def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src),
1347 !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"),
1348 [], IIC_MUL8>, T8XD, VEX_4V, Sched<[WriteIMulLd, WriteIMulH]>;
1352 let Predicates = [HasBMI2] in {
1354 defm MULX32 : bmi_mulx<"mulx{l}", GR32, i32mem>;
1356 defm MULX64 : bmi_mulx<"mulx{q}", GR64, i64mem>, VEX_W;
1359 //===----------------------------------------------------------------------===//
1362 let hasSideEffects = 0, Predicates = [HasADX], Defs = [EFLAGS] in {
1363 let SchedRW = [WriteALU] in {
1364 def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
1365 "adcx{l}\t{$src, $dst|$dst, $src}",
1366 [], IIC_BIN_NONMEM>, T8PD;
1368 def ADCX64rr : I<0xF6, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
1369 "adcx{q}\t{$src, $dst|$dst, $src}",
1370 [], IIC_BIN_NONMEM>, T8PD, REX_W, Requires<[In64BitMode]>;
1373 let mayLoad = 1, SchedRW = [WriteALULd] in {
1374 def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
1375 "adcx{l}\t{$src, $dst|$dst, $src}",
1376 [], IIC_BIN_MEM>, T8PD;
1378 def ADCX64rm : I<0xF6, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
1379 "adcx{q}\t{$src, $dst|$dst, $src}",
1380 [], IIC_BIN_MEM>, T8PD, REX_W, Requires<[In64BitMode]>;
1384 //===----------------------------------------------------------------------===//
1387 let hasSideEffects = 0, Predicates = [HasADX], Defs = [EFLAGS] in {
1388 let SchedRW = [WriteALU] in {
1389 def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
1390 "adox{l}\t{$src, $dst|$dst, $src}",
1391 [], IIC_BIN_NONMEM>, T8XS;
1393 def ADOX64rr : I<0xF6, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
1394 "adox{q}\t{$src, $dst|$dst, $src}",
1395 [], IIC_BIN_NONMEM>, T8XS, REX_W, Requires<[In64BitMode]>;
1398 let mayLoad = 1, SchedRW = [WriteALULd] in {
1399 def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
1400 "adox{l}\t{$src, $dst|$dst, $src}",
1401 [], IIC_BIN_MEM>, T8XS;
1403 def ADOX64rm : I<0xF6, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
1404 "adox{q}\t{$src, $dst|$dst, $src}",
1405 [], IIC_BIN_MEM>, T8XS, REX_W, Requires<[In64BitMode]>;