//
// Extra precision multiplication
-let Defs = [AL,AH], Uses = [AL] in
+let Defs = [AL,AH,EFLAGS], Uses = [AL] in
def MUL8r : I<0xF6, MRM4r, (outs), (ins GR8:$src), "mul{b}\t$src",
// FIXME: Used for 8-bit mul, ignore result upper 8 bits.
// This probably ought to be moved to a def : Pat<> if the
// syntax can be accepted.
[(set AL, (mul AL, GR8:$src))]>; // AL,AH = AL*GR8
-let Defs = [AX,DX], Uses = [AX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX] in
def MUL16r : I<0xF7, MRM4r, (outs), (ins GR16:$src), "mul{w}\t$src", []>,
OpSize; // AX,DX = AX*GR16
-let Defs = [EAX,EDX], Uses = [EAX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src), "mul{l}\t$src", []>;
// EAX,EDX = EAX*GR32
-let Defs = [AL,AH], Uses = [AL] in
+let Defs = [AL,AH,EFLAGS], Uses = [AL] in
def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$src),
"mul{b}\t$src",
// FIXME: Used for 8-bit mul, ignore result upper 8 bits.
// This probably ought to be moved to a def : Pat<> if the
// syntax can be accepted.
[(set AL, (mul AL, (loadi8 addr:$src)))]>; // AL,AH = AL*[mem8]
-let Defs = [AX,DX], Uses = [AX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX] in
def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src),
"mul{w}\t$src", []>, OpSize; // AX,DX = AX*[mem16]
-let Defs = [EAX,EDX], Uses = [EAX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src),
"mul{l}\t$src", []>; // EAX,EDX = EAX*[mem32]
-let Defs = [AL,AH], Uses = [AL] in
+let Defs = [AL,AH,EFLAGS], Uses = [AL] in
def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>;
// AL,AH = AL*GR8
-let Defs = [AX,DX], Uses = [AX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX] in
def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", []>,
OpSize; // AX,DX = AX*GR16
-let Defs = [EAX,EDX], Uses = [EAX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in
def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>;
// EAX,EDX = EAX*GR32
-let Defs = [AL,AH], Uses = [AL] in
+let Defs = [AL,AH,EFLAGS], Uses = [AL] in
def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src),
"imul{b}\t$src", []>; // AL,AH = AL*[mem8]
-let Defs = [AX,DX], Uses = [AX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX] in
def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src),
"imul{w}\t$src", []>, OpSize; // AX,DX = AX*[mem16]
let Defs = [EAX,EDX], Uses = [EAX] in
"imul{l}\t$src", []>; // EAX,EDX = EAX*[mem32]
// unsigned division/remainder
-let Defs = [AX], Uses = [AL,AH] in
+let Defs = [AX,EFLAGS], Uses = [AL,AH] in
def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH
"div{b}\t$src", []>;
-let Defs = [AX,DX], Uses = [AX,DX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX
"div{w}\t$src", []>, OpSize;
-let Defs = [EAX,EDX], Uses = [EAX,EDX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX
"div{l}\t$src", []>;
-let Defs = [AX], Uses = [AL,AH] in
+let Defs = [AX,EFLAGS], Uses = [AL,AH] in
def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH
"div{b}\t$src", []>;
-let Defs = [AX,DX], Uses = [AX,DX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX
"div{w}\t$src", []>, OpSize;
-let Defs = [EAX,EDX], Uses = [EAX,EDX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX
"div{l}\t$src", []>;
// Signed division/remainder.
-let Defs = [AX], Uses = [AL,AH] in
+let Defs = [AX,EFLAGS], Uses = [AL,AH] in
def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH
"idiv{b}\t$src", []>;
-let Defs = [AX,DX], Uses = [AX,DX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX
"idiv{w}\t$src", []>, OpSize;
-let Defs = [EAX,EDX], Uses = [EAX,EDX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX
"idiv{l}\t$src", []>;
-let Defs = [AX], Uses = [AL,AH] in
+let Defs = [AX,EFLAGS], Uses = [AL,AH] in
def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH
"idiv{b}\t$src", []>;
-let Defs = [AX,DX], Uses = [AX,DX] in
+let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX
"idiv{w}\t$src", []>, OpSize;
-let Defs = [EAX,EDX], Uses = [EAX,EDX] in
+let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX
"idiv{l}\t$src", []>;
// unary instructions
let CodeSize = 2 in {
+let Defs = [EFLAGS] in {
def NEG8r : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src), "neg{b}\t$dst",
[(set GR8:$dst, (ineg GR8:$src))]>;
def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src), "neg{w}\t$dst",
[(store (ineg (loadi32 addr:$dst)), addr:$dst)]>;
}
+} // Defs = [EFLAGS]
def NOT8r : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src), "not{b}\t$dst",
[(set GR8:$dst, (not GR8:$src))]>;
} // CodeSize
// TODO: inc/dec is slow for P4, but fast for Pentium-M.
+let Defs = [EFLAGS] in {
let CodeSize = 2 in
def INC8r : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src), "inc{b}\t$dst",
[(set GR8:$dst, (add GR8:$src, 1))]>;
def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst",
[(store (add (loadi32 addr:$dst), -1), addr:$dst)]>;
}
+} // Defs = [EFLAGS]
// Logical operators...
+let Defs = [EFLAGS] in {
let isCommutable = 1 in { // X = AND Y, Z --> X = AND Z, Y
def AND8rr : I<0x20, MRMDestReg,
(outs GR8 :$dst), (ins GR8 :$src1, GR8 :$src2),
"xor{l}\t{$src, $dst|$dst, $src}",
[(store (xor (load addr:$dst), i32immSExt8:$src), addr:$dst)]>;
}
+} // Defs = [EFLAGS]
// Shift instructions
+let Defs = [EFLAGS] in {
let Uses = [CL] in {
def SHL8rCL : I<0xD2, MRM4r, (outs GR8 :$dst), (ins GR8 :$src),
"shl{b}\t{%cl, $dst|$dst, %CL}",
(i8 imm:$src3)), addr:$dst)]>,
TB, OpSize;
}
+} // Defs = [EFLAGS]
// Arithmetic.
+let Defs = [EFLAGS] in {
let isCommutable = 1 in { // X = ADD Y, Z --> X = ADD Z, Y
def ADD8rr : I<0x00, MRMDestReg, (outs GR8 :$dst),
(ins GR8 :$src1, GR8 :$src2),
def ADD16mr : I<0x01, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2),
"add{w}\t{$src2, $dst|$dst, $src2}",
[(store (add (load addr:$dst), GR16:$src2), addr:$dst)]>,
- OpSize;
+ OpSize;
def ADD32mr : I<0x01, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
"add{l}\t{$src2, $dst|$dst, $src2}",
[(store (add (load addr:$dst), GR32:$src2), addr:$dst)]>;
def ADD16mi : Ii16<0x81, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src2),
"add{w}\t{$src2, $dst|$dst, $src2}",
[(store (add (loadi16 addr:$dst), imm:$src2), addr:$dst)]>,
- OpSize;
+ OpSize;
def ADD32mi : Ii32<0x81, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src2),
"add{l}\t{$src2, $dst|$dst, $src2}",
[(store (add (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
def ADD16mi8 : Ii8<0x83, MRM0m, (outs), (ins i16mem:$dst, i16i8imm :$src2),
"add{w}\t{$src2, $dst|$dst, $src2}",
[(store (add (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>,
- OpSize;
+ OpSize;
def ADD32mi8 : Ii8<0x83, MRM0m, (outs), (ins i32mem:$dst, i32i8imm :$src2),
"add{l}\t{$src2, $dst|$dst, $src2}",
[(store (add (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
def SUB16ri8 : Ii8<0x83, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
"sub{w}\t{$src2, $dst|$dst, $src2}",
[(set GR16:$dst, (sub GR16:$src1, i16immSExt8:$src2))]>,
- OpSize;
+ OpSize;
def SUB32ri8 : Ii8<0x83, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
"sub{l}\t{$src2, $dst|$dst, $src2}",
[(set GR32:$dst, (sub GR32:$src1, i32immSExt8:$src2))]>;
def SUB16mr : I<0x29, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2),
"sub{w}\t{$src2, $dst|$dst, $src2}",
[(store (sub (load addr:$dst), GR16:$src2), addr:$dst)]>,
- OpSize;
+ OpSize;
def SUB32mr : I<0x29, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
"sub{l}\t{$src2, $dst|$dst, $src2}",
[(store (sub (load addr:$dst), GR32:$src2), addr:$dst)]>;
def SUB16mi : Ii16<0x81, MRM5m, (outs), (ins i16mem:$dst, i16imm:$src2),
"sub{w}\t{$src2, $dst|$dst, $src2}",
[(store (sub (loadi16 addr:$dst), imm:$src2), addr:$dst)]>,
- OpSize;
+ OpSize;
def SUB32mi : Ii32<0x81, MRM5m, (outs), (ins i32mem:$dst, i32imm:$src2),
"sub{l}\t{$src2, $dst|$dst, $src2}",
[(store (sub (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
def SUB16mi8 : Ii8<0x83, MRM5m, (outs), (ins i16mem:$dst, i16i8imm :$src2),
"sub{w}\t{$src2, $dst|$dst, $src2}",
[(store (sub (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>,
- OpSize;
+ OpSize;
def SUB32mi8 : Ii8<0x83, MRM5m, (outs), (ins i32mem:$dst, i32i8imm :$src2),
"sub{l}\t{$src2, $dst|$dst, $src2}",
[(store (sub (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
def SBB32rr : I<0x19, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
"sbb{l}\t{$src2, $dst|$dst, $src2}",
- [(set GR32:$dst, (sube GR32:$src1, GR32:$src2))]>;
+ [(set GR32:$dst, (sube GR32:$src1, GR32:$src2))]>;
let isTwoAddress = 0 in {
def SBB32mr : I<0x19, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
[(store (sube (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
def SBB32mi8 : Ii8<0x83, MRM3m, (outs), (ins i32mem:$dst, i32i8imm :$src2),
"sbb{l}\t{$src2, $dst|$dst, $src2}",
- [(store (sube (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
+ [(store (sube (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
}
def SBB32rm : I<0x1B, MRMSrcMem, (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
"sbb{l}\t{$src2, $dst|$dst, $src2}",
def SBB32ri8 : Ii8<0x83, MRM3r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
"sbb{l}\t{$src2, $dst|$dst, $src2}",
[(set GR32:$dst, (sube GR32:$src1, i32immSExt8:$src2))]>;
+} // Defs = [EFLAGS]
+let Defs = [EFLAGS] in {
let isCommutable = 1 in { // X = IMUL Y, Z --> X = IMUL Z, Y
def IMUL16rr : I<0xAF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
"imul{w}\t{$src2, $dst|$dst, $src2}",
def IMUL32rm : I<0xAF, MRMSrcMem, (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
"imul{l}\t{$src2, $dst|$dst, $src2}",
[(set GR32:$dst, (mul GR32:$src1, (load addr:$src2)))]>, TB;
-
+} // Defs = [EFLAGS]
} // end Two Address instructions
// Suprisingly enough, these are not two address instructions!
+let Defs = [EFLAGS] in {
def IMUL16rri : Ii16<0x69, MRMSrcReg, // GR16 = GR16*I16
(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
"imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
(outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2),
"imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
[(set GR32:$dst, (mul (load addr:$src1), i32immSExt8:$src2))]>;
+} // Defs = [EFLAGS]
//===----------------------------------------------------------------------===//
// Test instructions are just like AND, except they don't generate a result.
//
+ let Defs = [EFLAGS] in {
let isCommutable = 1 in { // TEST X, Y --> TEST Y, X
def TEST8rr : I<0x84, MRMDestReg, (outs), (ins GR8:$src1, GR8:$src2),
"test{b}\t{$src2, $src1|$src1, $src2}",
(outs), (ins i32mem:$src1, i32imm:$src2),
"test{l}\t{$src2, $src1|$src1, $src2}",
[(X86cmp (and (loadi32 addr:$src1), imm:$src2), 0)]>;
+} // Defs = [EFLAGS]
// Condition code ops, incl. set if equal/not equal/...
-let Uses = [AH] in
+let Defs = [EFLAGS], Uses = [AH] in
def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", []>; // flags = AH
-let Defs = [AH] in
+let Defs = [AH], Uses = [EFLAGS] in
def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>; // AH = flags
def SETEr : I<0x94, MRM0r,
TB; // [mem8] = not parity
// Integer comparisons
+let Defs = [EFLAGS] in {
def CMP8rr : I<0x38, MRMDestReg,
(outs), (ins GR8 :$src1, GR8 :$src2),
"cmp{b}\t{$src2, $src1|$src1, $src2}",
(outs), (ins GR32:$src1, i32i8imm:$src2),
"cmp{l}\t{$src2, $src1|$src1, $src2}",
[(X86cmp GR32:$src1, i32immSExt8:$src2)]>;
+} // Defs = [EFLAGS]
// Sign/Zero extenders
def MOVSX16rr8 : I<0xBE, MRMSrcReg, (outs GR16:$dst), (ins GR8 :$src),
// Alias instructions that map movr0 to xor.
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
-let isReMaterializable = 1 in {
+let Defs = [EFLAGS], isReMaterializable = 1 in {
def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins),
"xor{b}\t$dst, $dst",
[(set GR8:$dst, 0)]>;
// Arithmetic Instructions...
//
+let Defs = [EFLAGS] in {
let isTwoAddress = 1 in {
let isConvertibleToThreeAddress = 1 in {
let isCommutable = 1 in
def SBB64mi8 : RIi8<0x83, MRM3m, (outs), (ins i64mem:$dst, i64i8imm :$src2),
"sbb{q}\t{$src2, $dst|$dst, $src2}",
[(store (sube (load addr:$dst), i64immSExt8:$src2), addr:$dst)]>;
+} // Defs = [EFLAGS]
// Unsigned multiplication
-let Defs = [RAX,RDX], Uses = [RAX] in {
+let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in {
def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src),
"mul{q}\t$src", []>; // RAX,RDX = RAX*GR64
def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src),
"imul{q}\t$src", []>; // RAX,RDX = RAX*[mem64]
}
+let Defs = [EFLAGS] in {
let isTwoAddress = 1 in {
let isCommutable = 1 in
def IMUL64rr : RI<0xAF, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
(outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2),
"imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
[(set GR64:$dst, (mul (load addr:$src1), i64immSExt8:$src2))]>;
+} // Defs = [EFLAGS]
// Unsigned division / remainder
-let Defs = [RAX,RDX], Uses = [RAX,RDX] in {
+let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in {
def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src), // RDX:RAX/r64 = RAX,RDX
"div{q}\t$src", []>;
def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64] = RAX,RDX
}
// Unary instructions
-let CodeSize = 2 in {
+let Defs = [EFLAGS], CodeSize = 2 in {
let isTwoAddress = 1 in
def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src), "neg{q}\t$dst",
[(set GR64:$dst, (ineg GR64:$src))]>;
[(set GR32:$dst, (add GR32:$src, -1))]>,
Requires<[In64BitMode]>;
} // isConvertibleToThreeAddress
-} // CodeSize
+} // Defs = [EFLAGS], CodeSize
+let Defs = [EFLAGS] in {
// Shift instructions
let isTwoAddress = 1 in {
let Uses = [CL] in
(outs), (ins i64mem:$dst, GR64:$src2, i8imm:$src3),
"shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", []>,
TB;
+} // Defs = [EFLAGS]
//===----------------------------------------------------------------------===//
// Logical Instructions...
def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst",
[(store (not (loadi64 addr:$dst)), addr:$dst)]>;
+let Defs = [EFLAGS] in {
let isTwoAddress = 1 in {
let isCommutable = 1 in
def AND64rr : RI<0x21, MRMDestReg,
def XOR64mi8 : RIi8<0x83, MRM6m, (outs), (ins i64mem:$dst, i64i8imm :$src),
"xor{q}\t{$src, $dst|$dst, $src}",
[(store (xor (load addr:$dst), i64immSExt8:$src), addr:$dst)]>;
+} // Defs = [EFLAGS]
//===----------------------------------------------------------------------===//
// Comparison Instructions...
//
// Integer comparison
+let Defs = [EFLAGS] in {
let isCommutable = 1 in
def TEST64rr : RI<0x85, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2),
"test{q}\t{$src2, $src1|$src1, $src2}",
def CMP64ri8 : RIi8<0x83, MRM7r, (outs), (ins GR64:$src1, i64i8imm:$src2),
"cmp{q}\t{$src2, $src1|$src1, $src2}",
[(X86cmp GR64:$src1, i64immSExt8:$src2)]>;
+} // Defs = [EFLAGS]
// Conditional moves
let isTwoAddress = 1 in {
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
// FIXME: AddedComplexity gives MOV64r0 a higher priority than MOV64ri32. Remove
// when we have a better way to specify isel priority.
-let AddedComplexity = 1, isReMaterializable = 1 in
+let Defs = [EFLAGS], AddedComplexity = 1, isReMaterializable = 1 in
def MOV64r0 : RI<0x31, MRMInitReg, (outs GR64:$dst), (ins),
"xor{q}\t$dst, $dst",
[(set GR64:$dst, 0)]>;