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