mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
Add implicit def of EFLAGS on those instructions that may modify flags.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41962 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f82e1e66ce
commit
24f2ea3971
@ -488,7 +488,7 @@ def UCOM_Fpr80 : FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP,
|
||||
def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP,
|
||||
[(X86cmp RFP80:$lhs, RFP80:$rhs)]>; // CC = ST(0) cmp ST(i)
|
||||
|
||||
let Uses = [ST0] in {
|
||||
let Defs = [EFLAGS], Uses = [ST0] in {
|
||||
def UCOM_Fr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i)
|
||||
(outs), (ins RST:$reg),
|
||||
"fucom\t$reg">, DD;
|
||||
|
@ -182,7 +182,7 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
break;
|
||||
}
|
||||
case X86::SHL64ri: {
|
||||
assert(MI->getNumOperands() == 3 && "Unknown shift instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown shift instruction!");
|
||||
// NOTE: LEA doesn't produce flags like shift does, but LLVM never uses
|
||||
// the flags produced by a shift yet, so this is safe.
|
||||
unsigned Dest = MI->getOperand(0).getReg();
|
||||
@ -195,7 +195,7 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
break;
|
||||
}
|
||||
case X86::SHL32ri: {
|
||||
assert(MI->getNumOperands() == 3 && "Unknown shift instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown shift instruction!");
|
||||
// NOTE: LEA doesn't produce flags like shift does, but LLVM never uses
|
||||
// the flags produced by a shift yet, so this is safe.
|
||||
unsigned Dest = MI->getOperand(0).getReg();
|
||||
@ -210,7 +210,7 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
break;
|
||||
}
|
||||
case X86::SHL16ri: {
|
||||
assert(MI->getNumOperands() == 3 && "Unknown shift instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown shift instruction!");
|
||||
// NOTE: LEA doesn't produce flags like shift does, but LLVM never uses
|
||||
// the flags produced by a shift yet, so this is safe.
|
||||
unsigned Dest = MI->getOperand(0).getReg();
|
||||
@ -259,40 +259,40 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
switch (MI->getOpcode()) {
|
||||
case X86::INC32r:
|
||||
case X86::INC64_32r:
|
||||
assert(MI->getNumOperands() == 2 && "Unknown inc instruction!");
|
||||
assert(MI->getNumOperands() >= 2 && "Unknown inc instruction!");
|
||||
NewMI = addRegOffset(BuildMI(get(X86::LEA32r), Dest), Src, 1);
|
||||
break;
|
||||
case X86::INC16r:
|
||||
case X86::INC64_16r:
|
||||
if (DisableLEA16) return 0;
|
||||
assert(MI->getNumOperands() == 2 && "Unknown inc instruction!");
|
||||
assert(MI->getNumOperands() >= 2 && "Unknown inc instruction!");
|
||||
NewMI = addRegOffset(BuildMI(get(X86::LEA16r), Dest), Src, 1);
|
||||
break;
|
||||
case X86::DEC32r:
|
||||
case X86::DEC64_32r:
|
||||
assert(MI->getNumOperands() == 2 && "Unknown dec instruction!");
|
||||
assert(MI->getNumOperands() >= 2 && "Unknown dec instruction!");
|
||||
NewMI = addRegOffset(BuildMI(get(X86::LEA32r), Dest), Src, -1);
|
||||
break;
|
||||
case X86::DEC16r:
|
||||
case X86::DEC64_16r:
|
||||
if (DisableLEA16) return 0;
|
||||
assert(MI->getNumOperands() == 2 && "Unknown dec instruction!");
|
||||
assert(MI->getNumOperands() >= 2 && "Unknown dec instruction!");
|
||||
NewMI = addRegOffset(BuildMI(get(X86::LEA16r), Dest), Src, -1);
|
||||
break;
|
||||
case X86::ADD32rr:
|
||||
assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");
|
||||
NewMI = addRegReg(BuildMI(get(X86::LEA32r), Dest), Src,
|
||||
MI->getOperand(2).getReg());
|
||||
break;
|
||||
case X86::ADD16rr:
|
||||
if (DisableLEA16) return 0;
|
||||
assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");
|
||||
NewMI = addRegReg(BuildMI(get(X86::LEA16r), Dest), Src,
|
||||
MI->getOperand(2).getReg());
|
||||
break;
|
||||
case X86::ADD32ri:
|
||||
case X86::ADD32ri8:
|
||||
assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");
|
||||
if (MI->getOperand(2).isImmediate())
|
||||
NewMI = addRegOffset(BuildMI(get(X86::LEA32r), Dest), Src,
|
||||
MI->getOperand(2).getImmedValue());
|
||||
@ -300,7 +300,7 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
case X86::ADD16ri:
|
||||
case X86::ADD16ri8:
|
||||
if (DisableLEA16) return 0;
|
||||
assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
|
||||
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");
|
||||
if (MI->getOperand(2).isImmediate())
|
||||
NewMI = addRegOffset(BuildMI(get(X86::LEA16r), Dest), Src,
|
||||
MI->getOperand(2).getImmedValue());
|
||||
@ -308,7 +308,7 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
case X86::SHL16ri:
|
||||
if (DisableLEA16) return 0;
|
||||
case X86::SHL32ri:
|
||||
assert(MI->getNumOperands() == 3 && MI->getOperand(2).isImmediate() &&
|
||||
assert(MI->getNumOperands() >= 3 && MI->getOperand(2).isImmediate() &&
|
||||
"Unknown shl instruction!");
|
||||
unsigned ShAmt = MI->getOperand(2).getImmedValue();
|
||||
if (ShAmt == 1 || ShAmt == 2 || ShAmt == 3) {
|
||||
|
@ -547,45 +547,45 @@ def MOV32mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src),
|
||||
//
|
||||
|
||||
// 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
|
||||
@ -593,42 +593,42 @@ def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src),
|
||||
"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", []>;
|
||||
|
||||
@ -992,6 +992,7 @@ def CMOVNP32rm : I<0x4B, MRMSrcMem, // if !parity, GR32 = [mem32]
|
||||
|
||||
// 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",
|
||||
@ -1007,6 +1008,7 @@ let isTwoAddress = 0 in {
|
||||
[(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))]>;
|
||||
@ -1025,6 +1027,7 @@ let isTwoAddress = 0 in {
|
||||
} // 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))]>;
|
||||
@ -1063,8 +1066,10 @@ let isTwoAddress = 0, CodeSize = 2 in {
|
||||
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),
|
||||
@ -1307,8 +1312,10 @@ let isTwoAddress = 0 in {
|
||||
"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}",
|
||||
@ -1750,9 +1757,11 @@ let isTwoAddress = 0 in {
|
||||
(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),
|
||||
@ -1812,7 +1821,7 @@ let isTwoAddress = 0 in {
|
||||
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)]>;
|
||||
@ -1822,14 +1831,14 @@ let isTwoAddress = 0 in {
|
||||
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)]>;
|
||||
@ -1893,7 +1902,7 @@ def SUB32ri : Ii32<0x81, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2
|
||||
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))]>;
|
||||
@ -1904,7 +1913,7 @@ let isTwoAddress = 0 in {
|
||||
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)]>;
|
||||
@ -1914,14 +1923,14 @@ let isTwoAddress = 0 in {
|
||||
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)]>;
|
||||
@ -1929,7 +1938,7 @@ let isTwoAddress = 0 in {
|
||||
|
||||
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),
|
||||
@ -1943,7 +1952,7 @@ let isTwoAddress = 0 in {
|
||||
[(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}",
|
||||
@ -1954,7 +1963,9 @@ def SBB32ri : Ii32<0x81, MRM3r, (outs GR32:$dst), (ins GR32:$src1, i32imm:$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}",
|
||||
@ -1970,10 +1981,11 @@ def IMUL16rm : I<0xAF, MRMSrcMem, (outs GR16:$dst), (ins GR16:$src1, i16mem:$src
|
||||
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}",
|
||||
@ -2010,10 +2022,12 @@ def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8
|
||||
(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}",
|
||||
@ -2063,12 +2077,13 @@ def TEST32mi : Ii32<0xF7, MRM0m, // flags = [mem32] & imm32
|
||||
(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,
|
||||
@ -2215,6 +2230,7 @@ def SETNPm : I<0x9B, MRM0m,
|
||||
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}",
|
||||
@ -2291,6 +2307,7 @@ def CMP32ri8 : Ii8<0x83, MRM7r,
|
||||
(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),
|
||||
@ -2352,7 +2369,7 @@ def CDQ : I<0x99, RawFrm, (outs), (ins),
|
||||
|
||||
// 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)]>;
|
||||
|
@ -360,12 +360,14 @@ let isTwoAddress = 1 in {
|
||||
"cmp${cc}ss\t{$src, $dst|$dst, $src}", []>;
|
||||
}
|
||||
|
||||
let Defs = [EFLAGS] in {
|
||||
def UCOMISSrr: PSI<0x2E, MRMSrcReg, (outs), (ins FR32:$src1, FR32:$src2),
|
||||
"ucomiss\t{$src2, $src1|$src1, $src2}",
|
||||
[(X86cmp FR32:$src1, FR32:$src2)]>;
|
||||
def UCOMISSrm: PSI<0x2E, MRMSrcMem, (outs), (ins FR32:$src1, f32mem:$src2),
|
||||
"ucomiss\t{$src2, $src1|$src1, $src2}",
|
||||
[(X86cmp FR32:$src1, (loadf32 addr:$src2))]>;
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
// Aliases to match intrinsics which expect XMM operand(s).
|
||||
let isTwoAddress = 1 in {
|
||||
@ -381,6 +383,7 @@ let isTwoAddress = 1 in {
|
||||
(load addr:$src), imm:$cc))]>;
|
||||
}
|
||||
|
||||
let Defs = [EFLAGS] in {
|
||||
def Int_UCOMISSrr: PSI<0x2E, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2),
|
||||
"ucomiss\t{$src2, $src1|$src1, $src2}",
|
||||
[(X86ucomi (v4f32 VR128:$src1), VR128:$src2)]>;
|
||||
@ -394,6 +397,7 @@ def Int_COMISSrr: PSI<0x2F, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2),
|
||||
def Int_COMISSrm: PSI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2),
|
||||
"comiss\t{$src2, $src1|$src1, $src2}",
|
||||
[(X86comi (v4f32 VR128:$src1), (load addr:$src2))]>;
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
// Aliases of packed SSE1 instructions for scalar use. These all have names that
|
||||
// start with 'Fs'.
|
||||
|
@ -226,6 +226,7 @@ def CQO : RI<0x99, RawFrm, (outs), (ins),
|
||||
// Arithmetic Instructions...
|
||||
//
|
||||
|
||||
let Defs = [EFLAGS] in {
|
||||
let isTwoAddress = 1 in {
|
||||
let isConvertibleToThreeAddress = 1 in {
|
||||
let isCommutable = 1 in
|
||||
@ -337,9 +338,10 @@ def SBB64mi32 : RIi32<0x81, MRM3m, (outs), (ins i64mem:$dst, i64i32imm:$src2),
|
||||
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),
|
||||
@ -352,6 +354,7 @@ def IMUL64m : RI<0xF7, MRM5m, (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),
|
||||
@ -380,9 +383,10 @@ def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem, // GR64 = [mem64]*I8
|
||||
(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
|
||||
@ -396,7 +400,7 @@ def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64]
|
||||
}
|
||||
|
||||
// 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))]>;
|
||||
@ -431,9 +435,10 @@ def DEC64_32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src), "dec{l}\t$dst"
|
||||
[(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
|
||||
@ -592,6 +597,7 @@ def SHRD64mri8 : RIi8<0xAC, MRMDestMem,
|
||||
(outs), (ins i64mem:$dst, GR64:$src2, i8imm:$src3),
|
||||
"shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
TB;
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Logical Instructions...
|
||||
@ -603,6 +609,7 @@ def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src), "not{q}\t$dst",
|
||||
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,
|
||||
@ -688,12 +695,14 @@ def XOR64mi32 : RIi32<0x81, MRM6m, (outs), (ins i64mem:$dst, i64i32imm:$src),
|
||||
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}",
|
||||
@ -729,6 +738,7 @@ def CMP64mi8 : RIi8<0x83, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$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 {
|
||||
@ -1000,7 +1010,7 @@ def PsMOVZX64rm32: I<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src),
|
||||
// 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)]>;
|
||||
|
Loading…
Reference in New Issue
Block a user