Newer
Older
//===- X86InstrInfo.td - Describe the X86 Instruction Set -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the X86 instruction set, defining the instructions, and
// properties of the instructions which are needed for code generation, machine
// code emission, and analysis.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// X86 specific DAG Nodes.
//
def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisInt<1>,
SDTCisSameAs<1, 2>]>;
def SDTX86Cmov : SDTypeProfile<1, 4,
[SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
SDTCisVT<3, OtherVT>, SDTCisVT<4, FlagVT>]>;
def SDTX86BrCond : SDTypeProfile<0, 3,
[SDTCisVT<0, OtherVT>,
SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>;
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>;
//===----------------------------------------------------------------------===//
// X86 Operand Definitions.
//
// *mem - Operand definitions for the funky X86 addressing mode operands.
//
class X86MemOperand<string printMethod> : Operand<i32> {
let PrintMethod = printMethod;
Chris Lattner
committed
let NumMIOperands = 4;
let MIOperandInfo = (ops R32, i8imm, R32, i32imm);
def i8mem : X86MemOperand<"printi8mem">;
def i16mem : X86MemOperand<"printi16mem">;
def i32mem : X86MemOperand<"printi32mem">;
def i64mem : X86MemOperand<"printi64mem">;
def f32mem : X86MemOperand<"printf32mem">;
def f64mem : X86MemOperand<"printf64mem">;
def f80mem : X86MemOperand<"printf80mem">;
def SSECC : Operand<i8> {
let PrintMethod = "printSSECC";
}
// A couple of more descriptive operand definitions.
// 16-bits but only 8 bits are significant.
def i16i8imm : Operand<i16>;
// 32-bits but only 8 bits are significant.
def i32i8imm : Operand<i32>;
Chris Lattner
committed
// PCRelative calls need special operand formatting.
let PrintMethod = "printCallOperand" in
def calltarget : Operand<i32>;
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT>;
//===----------------------------------------------------------------------===//
// X86 Complex Pattern Definitions.
//
// Define X86 specific addressing mode.
def addr : ComplexPattern<i32, 4, "SelectAddr", []>;
def leaaddr : ComplexPattern<i32, 4, "SelectLEAAddr",
[add,
frameindex, constpool, globaladdr, externalsym]>;
//===----------------------------------------------------------------------===//
// X86 Instruction Format Definitions.
//
// Format specifies the encoding used by the instruction. This is part of the
// ad-hoc solution used to emit machine instruction encodings by our machine
// code emitter.
class Format<bits<5> val> {
bits<5> Value = val;
}
def Pseudo : Format<0>; def RawFrm : Format<1>;
def AddRegFrm : Format<2>; def MRMDestReg : Format<3>;
def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>;
def MRMSrcMem : Format<6>;
def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>;
def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>;
def MRM6r : Format<22>; def MRM7r : Format<23>;
def MRM0m : Format<24>; def MRM1m : Format<25>; def MRM2m : Format<26>;
def MRM3m : Format<27>; def MRM4m : Format<28>; def MRM5m : Format<29>;
def MRM6m : Format<30>; def MRM7m : Format<31>;
//===----------------------------------------------------------------------===//
// X86 specific pattern fragments.
//
// ImmType - This specifies the immediate type used by an instruction. This is
// part of the ad-hoc solution used to emit machine instruction encodings by our
// machine code emitter.
class ImmType<bits<2> val> {
bits<2> Value = val;
}
def NoImm : ImmType<0>;
def Imm8 : ImmType<1>;
def Imm16 : ImmType<2>;
def Imm32 : ImmType<3>;
// FPFormat - This specifies what form this FP instruction has. This is used by
// the Floating-Point stackifier pass.
class FPFormat<bits<3> val> {
bits<3> Value = val;
}
def NotFP : FPFormat<0>;
def ZeroArgFP : FPFormat<1>;
def OneArgFP : FPFormat<2>;
def OneArgFPRW : FPFormat<3>;
def TwoArgFP : FPFormat<4>;
def CompareFP : FPFormat<5>;
def CondMovFP : FPFormat<6>;
def SpecialFP : FPFormat<7>;
class X86Inst<bits<8> opcod, Format f, ImmType i, dag ops, string AsmStr>
: Instruction {
bits<8> Opcode = opcod;
Format Form = f;
bits<5> FormBits = Form.Value;
ImmType ImmT = i;
bits<2> ImmTypeBits = ImmT.Value;
dag OperandList = ops;
string AsmString = AsmStr;
//
// Attributes specific to X86 instructions...
//
bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix?
bits<4> Prefix = 0; // Which prefix byte does this inst have?
FPFormat FPForm; // What flavor of FP instruction is this?
bits<3> FPFormBits = 0;
}
class Imp<list<Register> uses, list<Register> defs> {
list<Register> Uses = uses;
list<Register> Defs = defs;
}
// Prefix byte classes which are used to indicate to the ad-hoc machine code
// emitter that various prefix bytes are required.
class OpSize { bit hasOpSizePrefix = 1; }
class TB { bits<4> Prefix = 1; }
class REP { bits<4> Prefix = 2; }
class D8 { bits<4> Prefix = 3; }
class D9 { bits<4> Prefix = 4; }
class DA { bits<4> Prefix = 5; }
class DB { bits<4> Prefix = 6; }
class DC { bits<4> Prefix = 7; }
class DD { bits<4> Prefix = 8; }
class DE { bits<4> Prefix = 9; }
class DF { bits<4> Prefix = 10; }
class XD { bits<4> Prefix = 11; }
class XS { bits<4> Prefix = 12; }
//===----------------------------------------------------------------------===//
// Pattern fragments...
//
def i16immSExt8 : PatLeaf<(i16 imm), [{
// i16immSExt8 predicate - True if the 16-bit immediate fits in a 8-bit
// sign extended field.
return (int)N->getValue() == (signed char)N->getValue();
}]>;
def i32immSExt8 : PatLeaf<(i32 imm), [{
// i32immSExt8 predicate - True if the 32-bit immediate fits in a 8-bit
// sign extended field.
return (int)N->getValue() == (signed char)N->getValue();
}]>;
def i16immZExt8 : PatLeaf<(i16 imm), [{
// i16immZExt8 predicate - True if the 16-bit immediate fits in a 8-bit zero
// extended field.
return (unsigned)N->getValue() == (unsigned char)N->getValue();
}]>;
// Helper fragments for loads.
def loadi8 : PatFrag<(ops node:$ptr), (i8 (load node:$ptr))>;
def loadi16 : PatFrag<(ops node:$ptr), (i16 (load node:$ptr))>;
def loadi32 : PatFrag<(ops node:$ptr), (i32 (load node:$ptr))>;
def sextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (sextload node:$ptr, i1))>;
def sextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (sextload node:$ptr, i1))>;
def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextload node:$ptr, i8))>;
def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextload node:$ptr, i8))>;
def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextload node:$ptr, i16))>;
def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextload node:$ptr, i1))>;
def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextload node:$ptr, i1))>;
def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextload node:$ptr, i8))>;
def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextload node:$ptr, i8))>;
def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextload node:$ptr, i16))>;
def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extload node:$ptr, i1))>;
//===----------------------------------------------------------------------===//
// Instruction templates...
class I<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
: X86Inst<o, f, NoImm, ops, asm> {
let Pattern = pattern;
}
class Ii8 <bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
: X86Inst<o, f, Imm8 , ops, asm> {
let Pattern = pattern;
}
class Ii16<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
: X86Inst<o, f, Imm16, ops, asm> {
let Pattern = pattern;
}
class Ii32<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
: X86Inst<o, f, Imm32, ops, asm> {
let Pattern = pattern;
}
//===----------------------------------------------------------------------===//
// Instruction list...
//
def PHI : I<0, Pseudo, (ops variable_ops), "PHINODE", []>; // PHI node.
def NOOP : I<0x90, RawFrm, (ops), "nop", []>; // nop
def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN", []>;
def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2),
"#ADJCALLSTACKUP", []>;
def IMPLICIT_USE : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE", []>;
def IMPLICIT_DEF : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF", []>;
let isTerminator = 1 in
let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
def FP_REG_KILL : I<0, Pseudo, (ops), "#FP_REG_KILL", []>;
//===----------------------------------------------------------------------===//
// Control Flow Instructions...
//
let isTerminator = 1, isReturn = 1, isBarrier = 1 in
def RET : I<0xC3, RawFrm, (ops), "ret", [(ret)]>;
let isTerminator = 1, isReturn = 1, isBarrier = 1 in
def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>;
// All branches are RawFrm, Void, Branch, and Terminators
let isBranch = 1, isTerminator = 1 in
class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
I<opcode, RawFrm, ops, asm, pattern>;
let isBarrier = 1 in
def JMP : IBr<0xE9, (ops brtarget:$dst), "jmp $dst", [(br bb:$dst)]>;
def JE : IBr<0x84, (ops brtarget:$dst), "je $dst",
[(X86Brcond bb:$dst, SETEQ, STATUS)]>, Imp<[STATUS],[]>, TB;
def JNE : IBr<0x85, (ops brtarget:$dst), "jne $dst",
[(X86Brcond bb:$dst, SETNE, STATUS)]>, Imp<[STATUS],[]>, TB;
def JL : IBr<0x8C, (ops brtarget:$dst), "jl $dst",
[(X86Brcond bb:$dst, SETLT, STATUS)]>, Imp<[STATUS],[]>, TB;
def JLE : IBr<0x8E, (ops brtarget:$dst), "jle $dst",
[(X86Brcond bb:$dst, SETLE, STATUS)]>, Imp<[STATUS],[]>, TB;
def JG : IBr<0x8F, (ops brtarget:$dst), "jg $dst",
[(X86Brcond bb:$dst, SETGT, STATUS)]>, Imp<[STATUS],[]>, TB;
def JGE : IBr<0x8D, (ops brtarget:$dst), "jge $dst",
[(X86Brcond bb:$dst, SETGE, STATUS)]>, Imp<[STATUS],[]>, TB;
def JB : IBr<0x82, (ops brtarget:$dst), "jb $dst",
[(X86Brcond bb:$dst, SETULT, STATUS)]>, Imp<[STATUS],[]>, TB;
def JBE : IBr<0x86, (ops brtarget:$dst), "jbe $dst",
[(X86Brcond bb:$dst, SETULE, STATUS)]>, Imp<[STATUS],[]>, TB;
def JA : IBr<0x87, (ops brtarget:$dst), "ja $dst",
[(X86Brcond bb:$dst, SETUGT, STATUS)]>, Imp<[STATUS],[]>, TB;
def JAE : IBr<0x83, (ops brtarget:$dst), "jae $dst",
[(X86Brcond bb:$dst, SETUGE, STATUS)]>, Imp<[STATUS],[]>, TB;
def JS : IBr<0x88, (ops brtarget:$dst), "js $dst", []>, TB;
def JNS : IBr<0x89, (ops brtarget:$dst), "jns $dst", []>, TB;
def JP : IBr<0x8A, (ops brtarget:$dst), "jp $dst", []>, TB;
def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst", []>, TB;
//===----------------------------------------------------------------------===//
// Call Instructions...
//
// All calls clobber the non-callee saved registers...
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7] in {
def CALLpcrel32 : I<0xE8, RawFrm, (ops calltarget:$dst), "call $dst", []>;
def CALL32r : I<0xFF, MRM2r, (ops R32:$dst), "call {*}$dst", []>;
def CALL32m : I<0xFF, MRM2m, (ops i32mem:$dst), "call {*}$dst", []>;
// Tail call stuff.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TAILJMPd : IBr<0xE9, (ops calltarget:$dst), "jmp $dst # TAIL CALL", []>;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TAILJMPr : I<0xFF, MRM4r, (ops R32:$dst), "jmp {*}$dst # TAIL CALL", []>;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TAILJMPm : I<0xFF, MRM4m, (ops i32mem:$dst),
"jmp {*}$dst # TAIL CALL", []>;
// ADJSTACKPTRri - This is a standard ADD32ri instruction, identical in every
// way, except that it is marked as being a terminator. This causes the epilog
// inserter to insert reloads of callee saved registers BEFORE this. We need
// this until we have a more accurate way of tracking where the stack pointer is
// within a function.
let isTerminator = 1, isTwoAddress = 1 in
def ADJSTACKPTRri : Ii32<0x81, MRM0r, (ops R32:$dst, R32:$src1, i32imm:$src2),
"add{l} {$src2, $dst|$dst, $src2}", []>;
//===----------------------------------------------------------------------===//
// Miscellaneous Instructions...
//
Chris Lattner
committed
def LEAVE : I<0xC9, RawFrm,
Chris Lattner
committed
def POP32r : I<0x58, AddRegFrm,
(ops R32:$reg), "pop{l} $reg", []>, Imp<[ESP],[ESP]>;
let isTwoAddress = 1 in // R32 = bswap R32
Chris Lattner
committed
def BSWAP32r : I<0xC8, AddRegFrm,
(ops R32:$dst, R32:$src), "bswap{l} $dst", []>, TB;
Chris Lattner
committed
def XCHG8rr : I<0x86, MRMDestReg, // xchg R8, R8
(ops R8:$src1, R8:$src2),
Chris Lattner
committed
def XCHG16rr : I<0x87, MRMDestReg, // xchg R16, R16
(ops R16:$src1, R16:$src2),
"xchg{w} {$src2|$src1}, {$src1|$src2}", []>, OpSize;
Chris Lattner
committed
def XCHG32rr : I<0x87, MRMDestReg, // xchg R32, R32
(ops R32:$src1, R32:$src2),
def XCHG8mr : I<0x86, MRMDestMem,
(ops i8mem:$src1, R8:$src2),
def XCHG16mr : I<0x87, MRMDestMem,
(ops i16mem:$src1, R16:$src2),
"xchg{w} {$src2|$src1}, {$src1|$src2}", []>, OpSize;
def XCHG32mr : I<0x87, MRMDestMem,
(ops i32mem:$src1, R32:$src2),
def XCHG8rm : I<0x86, MRMSrcMem,
(ops R8:$src1, i8mem:$src2),
def XCHG16rm : I<0x87, MRMSrcMem,
(ops R16:$src1, i16mem:$src2),
"xchg{w} {$src2|$src1}, {$src1|$src2}", []>, OpSize;
def XCHG32rm : I<0x87, MRMSrcMem,
(ops R32:$src1, i32mem:$src2),
def LEA16r : I<0x8D, MRMSrcMem,
(ops R16:$dst, i32mem:$src),
"lea{w} {$src|$dst}, {$dst|$src}", []>, OpSize;
def LEA32r : I<0x8D, MRMSrcMem,
(ops R32:$dst, i32mem:$src),
"lea{l} {$src|$dst}, {$dst|$src}",
[(set R32:$dst, leaaddr:$src)]>;
def REP_MOVSB : I<0xA4, RawFrm, (ops), "{rep;movsb|rep movsb}", []>,
Chris Lattner
committed
Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>, REP;
def REP_MOVSW : I<0xA5, RawFrm, (ops), "{rep;movsw|rep movsw}", []>,
Chris Lattner
committed
Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>, REP, OpSize;
def REP_MOVSD : I<0xA5, RawFrm, (ops), "{rep;movsd|rep movsd}", []>,
Chris Lattner
committed
Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>, REP;
def REP_STOSB : I<0xAA, RawFrm, (ops), "{rep;stosb|rep stosb}", []>,
Chris Lattner
committed
Imp<[AL,ECX,EDI], [ECX,EDI]>, REP;
def REP_STOSW : I<0xAB, RawFrm, (ops), "{rep;stosw|rep stosw}", []>,
Chris Lattner
committed
Imp<[AX,ECX,EDI], [ECX,EDI]>, REP, OpSize;
def REP_STOSD : I<0xAB, RawFrm, (ops), "{rep;stosl|rep stosd}", []>,
Chris Lattner
committed
Imp<[EAX,ECX,EDI], [ECX,EDI]>, REP;
//===----------------------------------------------------------------------===//
// Input/Output Instructions...
//
Chris Lattner
committed
def IN8rr : I<0xEC, RawFrm, (ops),
"in{b} {%dx, %al|%AL, %DX}",
[(set AL, (readport DX))]>, Imp<[DX], [AL]>;
Chris Lattner
committed
def IN16rr : I<0xED, RawFrm, (ops),
"in{w} {%dx, %ax|%AX, %DX}",
[(set AX, (readport DX))]>, Imp<[DX], [AX]>, OpSize;
Chris Lattner
committed
def IN32rr : I<0xED, RawFrm, (ops),
"in{l} {%dx, %eax|%EAX, %DX}",
[(set EAX, (readport DX))]>, Imp<[DX],[EAX]>;
def IN8ri : Ii8<0xE4, RawFrm, (ops i16i8imm:$port),
"in{b} {$port, %al|%AL, $port}",
[(set AL, (readport i16immZExt8:$port))]>,
Imp<[], [AL]>;
def IN16ri : Ii8<0xE5, RawFrm, (ops i16i8imm:$port),
"in{w} {$port, %ax|%AX, $port}",
[(set AX, (readport i16immZExt8:$port))]>,
Imp<[], [AX]>, OpSize;
def IN32ri : Ii8<0xE5, RawFrm, (ops i16i8imm:$port),
"in{l} {$port, %eax|%EAX, $port}",
[(set EAX, (readport i16immZExt8:$port))]>,
Imp<[],[EAX]>;
Chris Lattner
committed
def OUT8rr : I<0xEE, RawFrm, (ops),
"out{b} {%al, %dx|%DX, %AL}",
[(writeport AL, DX)]>, Imp<[DX, AL], []>;
def OUT16rr : I<0xEF, RawFrm, (ops),
"out{w} {%ax, %dx|%DX, %AX}",
[(writeport AX, DX)]>, Imp<[DX, AX], []>, OpSize;
def OUT32rr : I<0xEF, RawFrm, (ops),
"out{l} {%eax, %dx|%DX, %EAX}",
[(writeport EAX, DX)]>, Imp<[DX, EAX], []>;
def OUT8ir : Ii8<0xE6, RawFrm, (ops i16i8imm:$port),
"out{b} {%al, $port|$port, %AL}",
[(writeport AL, i16immZExt8:$port)]>,
def OUT16ir : Ii8<0xE7, RawFrm, (ops i16i8imm:$port),
"out{w} {%ax, $port|$port, %AX}",
[(writeport AX, i16immZExt8:$port)]>,
def OUT32ir : Ii8<0xE7, RawFrm, (ops i16i8imm:$port),
"out{l} {%eax, $port|$port, %EAX}",
[(writeport EAX, i16immZExt8:$port)]>,
//===----------------------------------------------------------------------===//
// Move Instructions...
//
def MOV8rr : I<0x88, MRMDestReg, (ops R8 :$dst, R8 :$src),
def MOV16rr : I<0x89, MRMDestReg, (ops R16:$dst, R16:$src),
def MOV32rr : I<0x89, MRMDestReg, (ops R32:$dst, R32:$src),
def MOV8ri : Ii8 <0xB0, AddRegFrm, (ops R8 :$dst, i8imm :$src),
"mov{b} {$src, $dst|$dst, $src}",
[(set R8:$dst, imm:$src)]>;
def MOV16ri : Ii16<0xB8, AddRegFrm, (ops R16:$dst, i16imm:$src),
"mov{w} {$src, $dst|$dst, $src}",
[(set R16:$dst, imm:$src)]>, OpSize;
def MOV32ri : Ii32<0xB8, AddRegFrm, (ops R32:$dst, i32imm:$src),
"mov{l} {$src, $dst|$dst, $src}",
[(set R32:$dst, imm:$src)]>;
def MOV8mi : Ii8 <0xC6, MRM0m, (ops i8mem :$dst, i8imm :$src),
"mov{b} {$src, $dst|$dst, $src}",
[(store (i8 imm:$src), addr:$dst)]>;
def MOV16mi : Ii16<0xC7, MRM0m, (ops i16mem:$dst, i16imm:$src),
"mov{w} {$src, $dst|$dst, $src}",
[(store (i16 imm:$src), addr:$dst)]>, OpSize;
def MOV32mi : Ii32<0xC7, MRM0m, (ops i32mem:$dst, i32imm:$src),
"mov{l} {$src, $dst|$dst, $src}",
[(store (i32 imm:$src), addr:$dst)]>;
def MOV8rm : I<0x8A, MRMSrcMem, (ops R8 :$dst, i8mem :$src),
"mov{b} {$src, $dst|$dst, $src}",
[(set R8:$dst, (load addr:$src))]>;
def MOV16rm : I<0x8B, MRMSrcMem, (ops R16:$dst, i16mem:$src),
"mov{w} {$src, $dst|$dst, $src}",
[(set R16:$dst, (load addr:$src))]>, OpSize;
def MOV32rm : I<0x8B, MRMSrcMem, (ops R32:$dst, i32mem:$src),
"mov{l} {$src, $dst|$dst, $src}",
[(set R32:$dst, (load addr:$src))]>;
def MOV8mr : I<0x88, MRMDestMem, (ops i8mem :$dst, R8 :$src),
"mov{b} {$src, $dst|$dst, $src}",
[(store R8:$src, addr:$dst)]>;
def MOV16mr : I<0x89, MRMDestMem, (ops i16mem:$dst, R16:$src),
"mov{w} {$src, $dst|$dst, $src}",
[(store R16:$src, addr:$dst)]>, OpSize;
def MOV32mr : I<0x89, MRMDestMem, (ops i32mem:$dst, R32:$src),
"mov{l} {$src, $dst|$dst, $src}",
[(store R32:$src, addr:$dst)]>;
//===----------------------------------------------------------------------===//
// Fixed-Register Multiplication and Division Instructions...
//
// Extra precision multiplication
def MUL8r : I<0xF6, MRM4r, (ops R8:$src), "mul{b} $src", []>,
Chris Lattner
committed
Imp<[AL],[AX]>; // AL,AH = AL*R8
def MUL16r : I<0xF7, MRM4r, (ops R16:$src), "mul{w} $src", []>,
Chris Lattner
committed
Imp<[AX],[AX,DX]>, OpSize; // AX,DX = AX*R16
def MUL32r : I<0xF7, MRM4r, (ops R32:$src), "mul{l} $src", []>,
Chris Lattner
committed
Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*R32
Chris Lattner
committed
def MUL8m : I<0xF6, MRM4m, (ops i8mem :$src),
"mul{b} $src", []>, Imp<[AL],[AX]>; // AL,AH = AL*[mem8]
Chris Lattner
committed
def MUL16m : I<0xF7, MRM4m, (ops i16mem:$src),
"mul{w} $src", []>, Imp<[AX],[AX,DX]>,
OpSize; // AX,DX = AX*[mem16]
Chris Lattner
committed
def MUL32m : I<0xF7, MRM4m, (ops i32mem:$src),
"mul{l} $src", []>, Imp<[EAX],[EAX,EDX]>;// EAX,EDX = EAX*[mem32]
def IMUL8r : I<0xF6, MRM5r, (ops R8:$src), "imul{b} $src", []>,
Imp<[AL],[AX]>; // AL,AH = AL*R8
def IMUL16r : I<0xF7, MRM5r, (ops R16:$src), "imul{w} $src", []>,
Imp<[AX],[AX,DX]>, OpSize; // AX,DX = AX*R16
def IMUL32r : I<0xF7, MRM5r, (ops R32:$src), "imul{l} $src", []>,
Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*R32
def IMUL8m : I<0xF6, MRM5m, (ops i8mem :$src),
"imul{b} $src", []>, Imp<[AL],[AX]>; // AL,AH = AL*[mem8]
def IMUL16m : I<0xF7, MRM5m, (ops i16mem:$src),
"imul{w} $src", []>, Imp<[AX],[AX,DX]>,
OpSize; // AX,DX = AX*[mem16]
def IMUL32m : I<0xF7, MRM5m, (ops i32mem:$src),
"imul{l} $src", []>,
Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*[mem32]
def DIV8r : I<0xF6, MRM6r, (ops R8:$src), // AX/r8 = AL,AH
def DIV16r : I<0xF7, MRM6r, (ops R16:$src), // DX:AX/r16 = AX,DX
"div{w} $src", []>, Imp<[AX,DX],[AX,DX]>, OpSize;
def DIV32r : I<0xF7, MRM6r, (ops R32:$src), // EDX:EAX/r32 = EAX,EDX
def DIV8m : I<0xF6, MRM6m, (ops i8mem:$src), // AX/[mem8] = AL,AH
def DIV16m : I<0xF7, MRM6m, (ops i16mem:$src), // DX:AX/[mem16] = AX,DX
"div{w} $src", []>, Imp<[AX,DX],[AX,DX]>, OpSize;
def DIV32m : I<0xF7, MRM6m, (ops i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX
// Signed division/remainder.
def IDIV8r : I<0xF6, MRM7r, (ops R8:$src), // AX/r8 = AL,AH
def IDIV16r: I<0xF7, MRM7r, (ops R16:$src), // DX:AX/r16 = AX,DX
"idiv{w} $src", []>, Imp<[AX,DX],[AX,DX]>, OpSize;
def IDIV32r: I<0xF7, MRM7r, (ops R32:$src), // EDX:EAX/r32 = EAX,EDX
def IDIV8m : I<0xF6, MRM7m, (ops i8mem:$src), // AX/[mem8] = AL,AH
def IDIV16m: I<0xF7, MRM7m, (ops i16mem:$src), // DX:AX/[mem16] = AX,DX
"idiv{w} $src", []>, Imp<[AX,DX],[AX,DX]>, OpSize;
def IDIV32m: I<0xF7, MRM7m, (ops i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX
// Sign-extenders for division.
def CBW : I<0x98, RawFrm, (ops),
"{cbtw|cbw}", []>, Imp<[AL],[AH]>; // AX = signext(AL)
def CWD : I<0x99, RawFrm, (ops),
"{cwtd|cwd}", []>, Imp<[AX],[DX]>; // DX:AX = signext(AX)
def CDQ : I<0x99, RawFrm, (ops),
"{cltd|cdq}", []>, Imp<[EAX],[EDX]>; // EDX:EAX = signext(EAX)
//===----------------------------------------------------------------------===//
// Two address Instructions...
//
let isTwoAddress = 1 in {
// Conditional moves
def CMOVB16rr : I<0x42, MRMSrcReg, // if <u, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovb {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETULT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVB16rm : I<0x42, MRMSrcMem, // if <u, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovb {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETULT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVB32rr : I<0x42, MRMSrcReg, // if <u, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovb {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETULT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVB32rm : I<0x42, MRMSrcMem, // if <u, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovb {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETULT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVAE16rr: I<0x43, MRMSrcReg, // if >=u, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovae {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETUGE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVAE16rm: I<0x43, MRMSrcMem, // if >=u, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovae {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETUGE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVAE32rr: I<0x43, MRMSrcReg, // if >=u, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovae {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETUGE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVAE32rm: I<0x43, MRMSrcMem, // if >=u, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovae {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETUGE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVE16rr : I<0x44, MRMSrcReg, // if ==, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmove {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETEQ, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVE16rm : I<0x44, MRMSrcMem, // if ==, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmove {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETEQ, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVE32rr : I<0x44, MRMSrcReg, // if ==, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmove {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETEQ, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVE32rm : I<0x44, MRMSrcMem, // if ==, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmove {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETEQ, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVNE16rr: I<0x45, MRMSrcReg, // if !=, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovne {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETNE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVNE16rm: I<0x45, MRMSrcMem, // if !=, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovne {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETNE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVNE32rr: I<0x45, MRMSrcReg, // if !=, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovne {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETNE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVNE32rm: I<0x45, MRMSrcMem, // if !=, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovne {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETNE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVBE16rr: I<0x46, MRMSrcReg, // if <=u, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovbe {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETULE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVBE16rm: I<0x46, MRMSrcMem, // if <=u, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovbe {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETULE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVBE32rr: I<0x46, MRMSrcReg, // if <=u, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovbe {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETULE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVBE32rm: I<0x46, MRMSrcMem, // if <=u, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovbe {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETULE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVA16rr : I<0x47, MRMSrcReg, // if >u, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmova {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETUGT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVA16rm : I<0x47, MRMSrcMem, // if >u, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmova {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETUGT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVA32rr : I<0x47, MRMSrcReg, // if >u, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmova {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETUGT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVA32rm : I<0x47, MRMSrcMem, // if >u, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
"cmova {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETUGT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVL16rr : I<0x4C, MRMSrcReg, // if <s, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovl {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETLT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVL16rm : I<0x4C, MRMSrcMem, // if <s, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovl {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETLT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVL32rr : I<0x4C, MRMSrcReg, // if <s, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovl {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETLT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVL32rm : I<0x4C, MRMSrcMem, // if <s, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovl {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETLT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVGE16rr: I<0x4D, MRMSrcReg, // if >=s, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovge {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETGE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVGE16rm: I<0x4D, MRMSrcMem, // if >=s, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovge {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETGE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVGE32rr: I<0x4D, MRMSrcReg, // if >=s, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovge {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETGE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVGE32rm: I<0x4D, MRMSrcMem, // if >=s, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovge {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETGE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVLE16rr: I<0x4E, MRMSrcReg, // if <=s, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovle {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETLE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVLE16rm: I<0x4E, MRMSrcMem, // if <=s, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovle {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETLE, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVLE32rr: I<0x4E, MRMSrcReg, // if <=s, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovle {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETLE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVLE32rm: I<0x4E, MRMSrcMem, // if <=s, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovle {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETLE, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVG16rr : I<0x4F, MRMSrcReg, // if >s, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovg {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, R16:$src2,
SETGT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVG16rm : I<0x4F, MRMSrcMem, // if >s, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovg {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (X86cmov R16:$src1, (loadi16 addr:$src2),
SETGT, STATUS))]>,
Imp<[STATUS],[]>, TB, OpSize;
def CMOVG32rr : I<0x4F, MRMSrcReg, // if >s, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
"cmovg {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, R32:$src2,
SETGT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVG32rm : I<0x4F, MRMSrcMem, // if >s, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
"cmovg {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (X86cmov R32:$src1, (loadi32 addr:$src2),
SETGT, STATUS))]>,
Imp<[STATUS],[]>, TB;
def CMOVS16rr : I<0x48, MRMSrcReg, // if signed, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovs {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVS16rm : I<0x48, MRMSrcMem, // if signed, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovs {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVS32rr : I<0x48, MRMSrcReg, // if signed, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
def CMOVS32rm : I<0x48, MRMSrcMem, // if signed, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
def CMOVNS16rr: I<0x49, MRMSrcReg, // if !signed, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovns {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVNS16rm: I<0x49, MRMSrcMem, // if !signed, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovns {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVNS32rr: I<0x49, MRMSrcReg, // if !signed, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
def CMOVNS32rm: I<0x49, MRMSrcMem, // if !signed, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
def CMOVP16rr : I<0x4A, MRMSrcReg, // if parity, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovp {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVP16rm : I<0x4A, MRMSrcMem, // if parity, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovp {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVP32rr : I<0x4A, MRMSrcReg, // if parity, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
def CMOVP32rm : I<0x4A, MRMSrcMem, // if parity, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
def CMOVNP16rr : I<0x4B, MRMSrcReg, // if !parity, R16 = R16
(ops R16:$dst, R16:$src1, R16:$src2),
"cmovnp {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVNP16rm : I<0x4B, MRMSrcMem, // if !parity, R16 = [mem16]
(ops R16:$dst, R16:$src1, i16mem:$src2),
"cmovnp {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def CMOVNP32rr : I<0x4B, MRMSrcReg, // if !parity, R32 = R32
(ops R32:$dst, R32:$src1, R32:$src2),
def CMOVNP32rm : I<0x4B, MRMSrcMem, // if !parity, R32 = [mem32]
(ops R32:$dst, R32:$src1, i32mem:$src2),
def NEG8r : I<0xF6, MRM3r, (ops R8 :$dst, R8 :$src), "neg{b} $dst",
[(set R8:$dst, (ineg R8:$src))]>;
def NEG16r : I<0xF7, MRM3r, (ops R16:$dst, R16:$src), "neg{w} $dst",
[(set R16:$dst, (ineg R16:$src))]>, OpSize;
def NEG32r : I<0xF7, MRM3r, (ops R32:$dst, R32:$src), "neg{l} $dst",
[(set R32:$dst, (ineg R32:$src))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def NEG8m : I<0xF6, MRM3m, (ops i8mem :$dst), "neg{b} $dst",
[(store (ineg (loadi8 addr:$dst)), addr:$dst)]>;
def NEG16m : I<0xF7, MRM3m, (ops i16mem:$dst), "neg{w} $dst",
[(store (ineg (loadi16 addr:$dst)), addr:$dst)]>, OpSize;
def NEG32m : I<0xF7, MRM3m, (ops i32mem:$dst), "neg{l} $dst",
[(store (ineg (loadi32 addr:$dst)), addr:$dst)]>;
Chris Lattner
committed
}
def NOT8r : I<0xF6, MRM2r, (ops R8 :$dst, R8 :$src), "not{b} $dst",
[(set R8:$dst, (not R8:$src))]>;
def NOT16r : I<0xF7, MRM2r, (ops R16:$dst, R16:$src), "not{w} $dst",
[(set R16:$dst, (not R16:$src))]>, OpSize;
def NOT32r : I<0xF7, MRM2r, (ops R32:$dst, R32:$src), "not{l} $dst",
[(set R32:$dst, (not R32:$src))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def NOT8m : I<0xF6, MRM2m, (ops i8mem :$dst), "not{b} $dst",
[(store (not (loadi8 addr:$dst)), addr:$dst)]>;
def NOT16m : I<0xF7, MRM2m, (ops i16mem:$dst), "not{w} $dst",
[(store (not (loadi16 addr:$dst)), addr:$dst)]>, OpSize;
def NOT32m : I<0xF7, MRM2m, (ops i32mem:$dst), "not{l} $dst",
[(store (not (loadi32 addr:$dst)), addr:$dst)]>;
Chris Lattner
committed
}
// TODO: inc/dec is slow for P4, but fast for Pentium-M.
def INC8r : I<0xFE, MRM0r, (ops R8 :$dst, R8 :$src), "inc{b} $dst",
[(set R8:$dst, (add R8:$src, 1))]>;
let isConvertibleToThreeAddress = 1 in { // Can transform into LEA.
def INC16r : I<0xFF, MRM0r, (ops R16:$dst, R16:$src), "inc{w} $dst",
[(set R16:$dst, (add R16:$src, 1))]>, OpSize;
def INC32r : I<0xFF, MRM0r, (ops R32:$dst, R32:$src), "inc{l} $dst",
[(set R32:$dst, (add R32:$src, 1))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def INC8m : I<0xFE, MRM0m, (ops i8mem :$dst), "inc{b} $dst",
[(store (add (loadi8 addr:$dst), 1), addr:$dst)]>;
def INC16m : I<0xFF, MRM0m, (ops i16mem:$dst), "inc{w} $dst",
[(store (add (loadi16 addr:$dst), 1), addr:$dst)]>, OpSize;
def INC32m : I<0xFF, MRM0m, (ops i32mem:$dst), "inc{l} $dst",
[(store (add (loadi32 addr:$dst), 1), addr:$dst)]>;
Chris Lattner
committed
}
def DEC8r : I<0xFE, MRM1r, (ops R8 :$dst, R8 :$src), "dec{b} $dst",
[(set R8:$dst, (add R8:$src, -1))]>;
let isConvertibleToThreeAddress = 1 in { // Can transform into LEA.
def DEC16r : I<0xFF, MRM1r, (ops R16:$dst, R16:$src), "dec{w} $dst",
[(set R16:$dst, (add R16:$src, -1))]>, OpSize;
def DEC32r : I<0xFF, MRM1r, (ops R32:$dst, R32:$src), "dec{l} $dst",
[(set R32:$dst, (add R32:$src, -1))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def DEC8m : I<0xFE, MRM1m, (ops i8mem :$dst), "dec{b} $dst",
[(store (add (loadi8 addr:$dst), -1), addr:$dst)]>;
def DEC16m : I<0xFF, MRM1m, (ops i16mem:$dst), "dec{w} $dst",
[(store (add (loadi16 addr:$dst), -1), addr:$dst)]>, OpSize;
def DEC32m : I<0xFF, MRM1m, (ops i32mem:$dst), "dec{l} $dst",
[(store (add (loadi32 addr:$dst), -1), addr:$dst)]>;
Chris Lattner
committed
}
// Logical operators...
let isCommutable = 1 in { // X = AND Y, Z --> X = AND Z, Y
def AND8rr : I<0x20, MRMDestReg,
(ops R8 :$dst, R8 :$src1, R8 :$src2),
"and{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (and R8:$src1, R8:$src2))]>;
def AND16rr : I<0x21, MRMDestReg,
(ops R16:$dst, R16:$src1, R16:$src2),
"and{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (and R16:$src1, R16:$src2))]>, OpSize;
def AND32rr : I<0x21, MRMDestReg,
(ops R32:$dst, R32:$src1, R32:$src2),
"and{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (and R32:$src1, R32:$src2))]>;
def AND8rm : I<0x22, MRMSrcMem,
(ops R8 :$dst, R8 :$src1, i8mem :$src2),
"and{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (and R8:$src1, (load addr:$src2)))]>;
def AND16rm : I<0x23, MRMSrcMem,
(ops R16:$dst, R16:$src1, i16mem:$src2),
"and{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (and R16:$src1, (load addr:$src2)))]>, OpSize;
def AND32rm : I<0x23, MRMSrcMem,
(ops R32:$dst, R32:$src1, i32mem:$src2),
"and{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (and R32:$src1, (load addr:$src2)))]>;
def AND8ri : Ii8<0x80, MRM4r,
(ops R8 :$dst, R8 :$src1, i8imm :$src2),
"and{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (and R8:$src1, imm:$src2))]>;
def AND16ri : Ii16<0x81, MRM4r,
(ops R16:$dst, R16:$src1, i16imm:$src2),
"and{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (and R16:$src1, imm:$src2))]>, OpSize;
def AND32ri : Ii32<0x81, MRM4r,
(ops R32:$dst, R32:$src1, i32imm:$src2),
"and{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (and R32:$src1, imm:$src2))]>;
def AND16ri8 : Ii8<0x83, MRM4r,
(ops R16:$dst, R16:$src1, i16i8imm:$src2),
"and{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (and R16:$src1, i16immSExt8:$src2))]>,
OpSize;
def AND32ri8 : Ii8<0x83, MRM4r,
(ops R32:$dst, R32:$src1, i32i8imm:$src2),
"and{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (and R32:$src1, i32immSExt8:$src2))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def AND8mr : I<0x20, MRMDestMem,
(ops i8mem :$dst, R8 :$src),
"and{b} {$src, $dst|$dst, $src}",
[(store (and (load addr:$dst), R8:$src), addr:$dst)]>;
def AND16mr : I<0x21, MRMDestMem,
(ops i16mem:$dst, R16:$src),