X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86InstrInfo.td;h=fd08e477014276574837c90fe71454e7cb796dbf;hb=768143547ba66c8cbeef09d4234ae908bbf5b9f8;hp=e195f0fb15031e99f9b5d35388d079c550623ca9;hpb=fae299430294b8ead6b37efa014fa50a75d6dbaf;p=oota-llvm.git diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index e195f0fb150..fd08e477014 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -39,7 +39,7 @@ def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>; def SDT_X86CallSeqEnd : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>; -def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; @@ -51,9 +51,7 @@ def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, - [SDNPOutFlag]>; -def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, - [SDNPOutFlag]>; + [SDNPHasChain, SDNPOutFlag]>; def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, [SDNPInFlag, SDNPOutFlag]>; @@ -67,7 +65,7 @@ def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, def X86callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain]>; + [SDNPHasChain, SDNPOutFlag]>; def X86callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; @@ -86,7 +84,8 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc, [SDNPHasChain, SDNPOutFlag]>; -def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; +def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; +def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; //===----------------------------------------------------------------------===// // X86 Operand Definitions. @@ -96,8 +95,7 @@ def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; // class X86MemOperand : Operand { let PrintMethod = printMethod; - let NumMIOperands = 4; - let MIOperandInfo = (ops GR32, i8imm, GR32, i32imm); + let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc, i32imm); } def i8mem : X86MemOperand<"printi8mem">; @@ -109,6 +107,11 @@ def f32mem : X86MemOperand<"printf32mem">; def f64mem : X86MemOperand<"printf64mem">; def f128mem : X86MemOperand<"printf128mem">; +def lea32mem : Operand { + let PrintMethod = "printi32mem"; + let MIOperandInfo = (ops GR32, i8imm, GR32, i32imm); +} + def SSECC : Operand { let PrintMethod = "printSSECC"; } @@ -131,9 +134,9 @@ def brtarget : Operand; // // Define X86 specific addressing mode. -def addr : ComplexPattern; -def leaaddr : ComplexPattern; +def addr : ComplexPattern; +def lea32addr : ComplexPattern; //===----------------------------------------------------------------------===// // X86 Instruction Format Definitions. @@ -160,11 +163,16 @@ def MRMInitReg : Format<32>; //===----------------------------------------------------------------------===// // X86 Instruction Predicate Definitions. -def HasMMX : Predicate<"Subtarget->hasMMX()">; -def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; -def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; -def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; -def FPStack : Predicate<"!Subtarget->hasSSE2()">; +def HasMMX : Predicate<"Subtarget->hasMMX()">; +def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; +def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; +def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; +def FPStack : Predicate<"!Subtarget->hasSSE2()">; +def In32BitMode : Predicate<"!Subtarget->is64Bit()">; +def In64BitMode : Predicate<"Subtarget->is64Bit()">; +def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; +def NotSmallCode : Predicate<"TM.getCodeModel() != CodeModel::Small">; +def IsStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; //===----------------------------------------------------------------------===// // X86 specific pattern fragments. @@ -173,13 +181,14 @@ def FPStack : Predicate<"!Subtarget->hasSSE2()">; // 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 val> { - bits<2> Value = val; +class ImmType val> { + bits<3> Value = val; } def NoImm : ImmType<0>; def Imm8 : ImmType<1>; def Imm16 : ImmType<2>; def Imm32 : ImmType<3>; +def Imm64 : ImmType<4>; // FPFormat - This specifies what form this FP instruction has. This is used by // the Floating-Point stackifier pass. @@ -204,7 +213,7 @@ class X86Inst opcod, Format f, ImmType i, dag ops, string AsmStr> Format Form = f; bits<6> FormBits = Form.Value; ImmType ImmT = i; - bits<2> ImmTypeBits = ImmT.Value; + bits<3> ImmTypeBits = ImmT.Value; dag OperandList = ops; string AsmString = AsmStr; @@ -212,22 +221,21 @@ class X86Inst opcod, Format f, ImmType i, dag ops, string AsmStr> // // Attributes specific to X86 instructions... // - bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix? + bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix? + bit hasAdSizePrefix = 0; // Does this inst have a 0x67 prefix? bits<4> Prefix = 0; // Which prefix byte does this inst have? + bit hasREX_WPrefix = 0; // Does this inst requires the REX.W prefix? FPFormat FPForm; // What flavor of FP instruction is this? bits<3> FPFormBits = 0; } -class Imp uses, list defs> { - list Uses = uses; - list 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 AdSize { bit hasAdSizePrefix = 1; } +class REX_W { bit hasREX_WPrefix = 1; } class TB { bits<4> Prefix = 1; } class REP { bits<4> Prefix = 2; } class D8 { bits<4> Prefix = 3; } @@ -277,15 +285,7 @@ def i32immSExt8 : PatLeaf<(i32 imm), [{ return (int32_t)N->getValue() == (int8_t)N->getValue(); }]>; -def i16immZExt8 : PatLeaf<(i16 imm), [{ - // i16immZExt8 predicate - True if the 16-bit immediate fits in a 8-bit zero - // extended field. - return (uint16_t)N->getValue() == (uint8_t)N->getValue(); -}]>; - // Helper fragments for loads. -def loadiPTR : PatFrag<(ops node:$ptr), (iPTR (load node:$ptr))>; - 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))>; @@ -294,55 +294,64 @@ def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; def loadf64 : PatFrag<(ops node:$ptr), (f64 (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 zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextload node:$ptr, i1))>; -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))>; -def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extload node:$ptr, i1))>; -def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extload node:$ptr, i1))>; -def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extload node:$ptr, i8))>; -def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extload node:$ptr, i8))>; -def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extload node:$ptr, i16))>; +def sextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (sextloadi1 node:$ptr))>; +def sextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (sextloadi1 node:$ptr))>; +def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; +def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; +def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; + +def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; +def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; +def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; +def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; +def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; +def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; + +def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; +def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; +def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; +def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; +def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; +def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; //===----------------------------------------------------------------------===// // Instruction templates... +// class I o, Format f, dag ops, string asm, list pattern> : X86Inst { let Pattern = pattern; + let CodeSize = 3; } class Ii8 o, Format f, dag ops, string asm, list pattern> : X86Inst { let Pattern = pattern; + let CodeSize = 3; } class Ii16 o, Format f, dag ops, string asm, list pattern> : X86Inst { let Pattern = pattern; + let CodeSize = 3; } class Ii32 o, Format f, dag ops, string asm, list pattern> : X86Inst { let Pattern = pattern; + let CodeSize = 3; } //===----------------------------------------------------------------------===// // Instruction list... // +// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into +// a stack adjustment and the codegen must know that they may modify the stack +// pointer before prolog-epilog rewriting occurs. def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN", - [(X86callseq_start imm:$amt)]>; + [(X86callseq_start imm:$amt)]>, Imp<[ESP],[ESP]>; def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKUP", - [(X86callseq_end imm:$amt1, imm:$amt2)]>; + [(X86callseq_end imm:$amt1, imm:$amt2)]>, + Imp<[ESP],[ESP]>; def IMPLICIT_USE : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE", []>; def IMPLICIT_DEF : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF", []>; def IMPLICIT_DEF_GR8 : I<0, Pseudo, (ops GR8:$dst), @@ -359,13 +368,13 @@ def IMPLICIT_DEF_GR32 : I<0, Pseudo, (ops GR32:$dst), def NOOP : I<0x90, RawFrm, (ops), "nop", []>; // Truncate -def TRUNC_GR32_GR8 : I<0x88, MRMDestReg, (ops GR8:$dst, GR32_:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", []>; -def TRUNC_GR16_GR8 : I<0x88, MRMDestReg, (ops GR8:$dst, GR16_:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}}", []>; -def TRUNC_GR32_GR16 : I<0x89, MRMDestReg, (ops GR16:$dst, GR32:$src), - "mov{w} {${src:subreg16}, $dst|$dst, ${src:subreg16}}", - [(set GR16:$dst, (trunc GR32:$src))]>; +def TRUNC_32_to8 : I<0x88, MRMDestReg, (ops GR8:$dst, GR32_:$src), + "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", []>; +def TRUNC_16_to8 : I<0x88, MRMDestReg, (ops GR8:$dst, GR16_:$src), + "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}}", []>; +def TRUNC_32to16 : I<0x89, MRMDestReg, (ops GR16:$dst, GR32:$src), + "mov{w} {${src:subreg16}, $dst|$dst, ${src:subreg16}}", + [(set GR16:$dst, (trunc GR32:$src))]>; //===----------------------------------------------------------------------===// // Control Flow Instructions... @@ -385,14 +394,14 @@ let isBranch = 1, isTerminator = 1, noResults = 1 in I; // Indirect branches -let isBarrier = 1 in +let isBranch = 1, isBarrier = 1 in def JMP : IBr<0xE9, (ops brtarget:$dst), "jmp $dst", [(br bb:$dst)]>; let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in { def JMP32r : I<0xFF, MRM4r, (ops GR32:$dst), "jmp{l} {*}$dst", [(brind GR32:$dst)]>; def JMP32m : I<0xFF, MRM4m, (ops i32mem:$dst), "jmp{l} {*}$dst", - [(brind (loadiPTR addr:$dst))]>; + [(brind (loadi32 addr:$dst))]>; } // Conditional branches @@ -448,22 +457,15 @@ let isCall = 1, noResults = 1 in // Tail call stuff. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in - def TAILJMPd : IBr<0xE9, (ops i32imm:$dst), "jmp ${dst:call} # TAIL CALL", []>; + def TAILJMPd : IBr<0xE9, (ops i32imm:$dst), "jmp ${dst:call} # TAIL CALL", + []>; let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in - def TAILJMPr : I<0xFF, MRM4r, (ops GR32:$dst), "jmp {*}$dst # TAIL CALL", []>; + def TAILJMPr : I<0xFF, MRM4r, (ops GR32:$dst), "jmp {*}$dst # TAIL CALL", + []>; let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 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 GR32:$dst, GR32:$src1, i32imm:$src2), - "add{l} {$src2, $dst|$dst, $src2}", []>; - //===----------------------------------------------------------------------===// // Miscellaneous Instructions... // @@ -514,9 +516,9 @@ def LEA16r : I<0x8D, MRMSrcMem, (ops GR16:$dst, i32mem:$src), "lea{w} {$src|$dst}, {$dst|$src}", []>, OpSize; def LEA32r : I<0x8D, MRMSrcMem, - (ops GR32:$dst, i32mem:$src), + (ops GR32:$dst, lea32mem:$src), "lea{l} {$src|$dst}, {$dst|$src}", - [(set GR32:$dst, leaaddr:$src)]>; + [(set GR32:$dst, lea32addr:$src)]>, Requires<[In32BitMode]>; def REP_MOVSB : I<0xA4, RawFrm, (ops), "{rep;movsb|rep movsb}", [(X86rep_movs i8)]>, @@ -538,6 +540,8 @@ def REP_STOSD : I<0xAB, RawFrm, (ops), "{rep;stosl|rep stosd}", [(X86rep_stos i32)]>, Imp<[EAX,ECX,EDI], [ECX,EDI]>, REP; +def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", [(X86rdtsc)]>, + TB, Imp<[],[RAX,RDX]>; //===----------------------------------------------------------------------===// // Input/Output Instructions... @@ -597,6 +601,7 @@ def MOV16rr : I<0x89, MRMDestReg, (ops GR16:$dst, GR16:$src), "mov{w} {$src, $dst|$dst, $src}", []>, OpSize; def MOV32rr : I<0x89, MRMDestReg, (ops GR32:$dst, GR32:$src), "mov{l} {$src, $dst|$dst, $src}", []>; +let isReMaterializable = 1 in { def MOV8ri : Ii8 <0xB0, AddRegFrm, (ops GR8 :$dst, i8imm :$src), "mov{b} {$src, $dst|$dst, $src}", [(set GR8:$dst, imm:$src)]>; @@ -606,6 +611,7 @@ def MOV16ri : Ii16<0xB8, AddRegFrm, (ops GR16:$dst, i16imm:$src), def MOV32ri : Ii32<0xB8, AddRegFrm, (ops GR32:$dst, i32imm:$src), "mov{l} {$src, $dst|$dst, $src}", [(set GR32:$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)]>; @@ -1066,6 +1072,7 @@ def CMOVNP32rm : I<0x4B, MRMSrcMem, // if !parity, GR32 = [mem32] // unary instructions +let CodeSize = 2 in { def NEG8r : I<0xF6, MRM3r, (ops GR8 :$dst, GR8 :$src), "neg{b} $dst", [(set GR8:$dst, (ineg GR8:$src))]>; def NEG16r : I<0xF7, MRM3r, (ops GR16:$dst, GR16:$src), "neg{w} $dst", @@ -1096,17 +1103,20 @@ let isTwoAddress = 0 in { def NOT32m : I<0xF7, MRM2m, (ops i32mem:$dst), "not{l} $dst", [(store (not (loadi32 addr:$dst)), addr:$dst)]>; } +} // CodeSize // TODO: inc/dec is slow for P4, but fast for Pentium-M. +let CodeSize = 2 in def INC8r : I<0xFE, MRM0r, (ops GR8 :$dst, GR8 :$src), "inc{b} $dst", [(set GR8:$dst, (add GR8:$src, 1))]>; -let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. -def INC16r : I<0xFF, MRM0r, (ops GR16:$dst, GR16:$src), "inc{w} $dst", - [(set GR16:$dst, (add GR16:$src, 1))]>, OpSize; -def INC32r : I<0xFF, MRM0r, (ops GR32:$dst, GR32:$src), "inc{l} $dst", - [(set GR32:$dst, (add GR32:$src, 1))]>; +let isConvertibleToThreeAddress = 1, CodeSize = 1 in { // Can xform into LEA. +def INC16r : I<0x40, AddRegFrm, (ops GR16:$dst, GR16:$src), "inc{w} $dst", + [(set GR16:$dst, (add GR16:$src, 1))]>, + OpSize, Requires<[In32BitMode]>; +def INC32r : I<0x40, AddRegFrm, (ops GR32:$dst, GR32:$src), "inc{l} $dst", + [(set GR32:$dst, (add GR32:$src, 1))]>, Requires<[In32BitMode]>; } -let isTwoAddress = 0 in { +let isTwoAddress = 0, CodeSize = 2 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", @@ -1115,16 +1125,18 @@ let isTwoAddress = 0 in { [(store (add (loadi32 addr:$dst), 1), addr:$dst)]>; } +let CodeSize = 2 in def DEC8r : I<0xFE, MRM1r, (ops GR8 :$dst, GR8 :$src), "dec{b} $dst", [(set GR8:$dst, (add GR8:$src, -1))]>; -let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. -def DEC16r : I<0xFF, MRM1r, (ops GR16:$dst, GR16:$src), "dec{w} $dst", - [(set GR16:$dst, (add GR16:$src, -1))]>, OpSize; -def DEC32r : I<0xFF, MRM1r, (ops GR32:$dst, GR32:$src), "dec{l} $dst", - [(set GR32:$dst, (add GR32:$src, -1))]>; +let isConvertibleToThreeAddress = 1, CodeSize = 1 in { // Can xform into LEA. +def DEC16r : I<0x48, AddRegFrm, (ops GR16:$dst, GR16:$src), "dec{w} $dst", + [(set GR16:$dst, (add GR16:$src, -1))]>, + OpSize, Requires<[In32BitMode]>; +def DEC32r : I<0x48, AddRegFrm, (ops GR32:$dst, GR32:$src), "dec{l} $dst", + [(set GR32:$dst, (add GR32:$src, -1))]>, Requires<[In32BitMode]>; } -let isTwoAddress = 0 in { +let isTwoAddress = 0, CodeSize = 2 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", @@ -1400,6 +1412,14 @@ def SHL32ri : Ii8<0xC1, MRM4r, (ops GR32:$dst, GR32:$src1, i8imm:$src2), [(set GR32:$dst, (shl GR32:$src1, (i8 imm:$src2)))]>; } +// Shift left by one. Not used because (add x, x) is slightly cheaper. +def SHL8r1 : I<0xD0, MRM4r, (ops GR8 :$dst, GR8 :$src1), + "shl{b} $dst", []>; +def SHL16r1 : I<0xD1, MRM4r, (ops GR16:$dst, GR16:$src1), + "shl{w} $dst", []>, OpSize; +def SHL32r1 : I<0xD1, MRM4r, (ops GR32:$dst, GR32:$src1), + "shl{l} $dst", []>; + let isTwoAddress = 0 in { def SHL8mCL : I<0xD2, MRM4m, (ops i8mem :$dst), "shl{b} {%cl, $dst|$dst, %CL}", @@ -1423,6 +1443,18 @@ let isTwoAddress = 0 in { def SHL32mi : Ii8<0xC1, MRM4m, (ops i32mem:$dst, i8imm:$src), "shl{l} {$src, $dst|$dst, $src}", [(store (shl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Shift by 1 + def SHL8m1 : I<0xD0, MRM4m, (ops i8mem :$dst), + "shl{b} $dst", + [(store (shl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def SHL16m1 : I<0xD1, MRM4m, (ops i16mem:$dst), + "shl{w} $dst", + [(store (shl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def SHL32m1 : I<0xD1, MRM4m, (ops i32mem:$dst), + "shl{l} $dst", + [(store (shl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; } def SHR8rCL : I<0xD2, MRM5r, (ops GR8 :$dst, GR8 :$src), @@ -1445,6 +1477,17 @@ def SHR32ri : Ii8<0xC1, MRM5r, (ops GR32:$dst, GR32:$src1, i8imm:$src2), "shr{l} {$src2, $dst|$dst, $src2}", [(set GR32:$dst, (srl GR32:$src1, (i8 imm:$src2)))]>; +// Shift by 1 +def SHR8r1 : I<0xD0, MRM5r, (ops GR8:$dst, GR8:$src1), + "shr{b} $dst", + [(set GR8:$dst, (srl GR8:$src1, (i8 1)))]>; +def SHR16r1 : I<0xD1, MRM5r, (ops GR16:$dst, GR16:$src1), + "shr{w} $dst", + [(set GR16:$dst, (srl GR16:$src1, (i8 1)))]>, OpSize; +def SHR32r1 : I<0xD1, MRM5r, (ops GR32:$dst, GR32:$src1), + "shr{l} $dst", + [(set GR32:$dst, (srl GR32:$src1, (i8 1)))]>; + let isTwoAddress = 0 in { def SHR8mCL : I<0xD2, MRM5m, (ops i8mem :$dst), "shr{b} {%cl, $dst|$dst, %CL}", @@ -1468,6 +1511,17 @@ let isTwoAddress = 0 in { def SHR32mi : Ii8<0xC1, MRM5m, (ops i32mem:$dst, i8imm:$src), "shr{l} {$src, $dst|$dst, $src}", [(store (srl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Shift by 1 + def SHR8m1 : I<0xD0, MRM5m, (ops i8mem :$dst), + "shr{b} $dst", + [(store (srl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def SHR16m1 : I<0xD1, MRM5m, (ops i16mem:$dst), + "shr{w} $dst", + [(store (srl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,OpSize; + def SHR32m1 : I<0xD1, MRM5m, (ops i32mem:$dst), + "shr{l} $dst", + [(store (srl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; } def SAR8rCL : I<0xD2, MRM7r, (ops GR8 :$dst, GR8 :$src), @@ -1490,6 +1544,18 @@ def SAR16ri : Ii8<0xC1, MRM7r, (ops GR16:$dst, GR16:$src1, i8imm:$src2), def SAR32ri : Ii8<0xC1, MRM7r, (ops GR32:$dst, GR32:$src1, i8imm:$src2), "sar{l} {$src2, $dst|$dst, $src2}", [(set GR32:$dst, (sra GR32:$src1, (i8 imm:$src2)))]>; + +// Shift by 1 +def SAR8r1 : I<0xD0, MRM7r, (ops GR8 :$dst, GR8 :$src1), + "sar{b} $dst", + [(set GR8:$dst, (sra GR8:$src1, (i8 1)))]>; +def SAR16r1 : I<0xD1, MRM7r, (ops GR16:$dst, GR16:$src1), + "sar{w} $dst", + [(set GR16:$dst, (sra GR16:$src1, (i8 1)))]>, OpSize; +def SAR32r1 : I<0xD1, MRM7r, (ops GR32:$dst, GR32:$src1), + "sar{l} $dst", + [(set GR32:$dst, (sra GR32:$src1, (i8 1)))]>; + let isTwoAddress = 0 in { def SAR8mCL : I<0xD2, MRM7m, (ops i8mem :$dst), "sar{b} {%cl, $dst|$dst, %CL}", @@ -1513,6 +1579,18 @@ let isTwoAddress = 0 in { def SAR32mi : Ii8<0xC1, MRM7m, (ops i32mem:$dst, i8imm:$src), "sar{l} {$src, $dst|$dst, $src}", [(store (sra (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Shift by 1 + def SAR8m1 : I<0xD0, MRM7m, (ops i8mem :$dst), + "sar{b} $dst", + [(store (sra (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def SAR16m1 : I<0xD1, MRM7m, (ops i16mem:$dst), + "sar{w} $dst", + [(store (sra (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def SAR32m1 : I<0xD1, MRM7m, (ops i32mem:$dst), + "sar{l} $dst", + [(store (sra (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; } // Rotate instructions @@ -1537,6 +1615,17 @@ def ROL32ri : Ii8<0xC1, MRM0r, (ops GR32:$dst, GR32:$src1, i8imm:$src2), "rol{l} {$src2, $dst|$dst, $src2}", [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$src2)))]>; +// Rotate by 1 +def ROL8r1 : I<0xD0, MRM0r, (ops GR8 :$dst, GR8 :$src1), + "rol{b} $dst", + [(set GR8:$dst, (rotl GR8:$src1, (i8 1)))]>; +def ROL16r1 : I<0xD1, MRM0r, (ops GR16:$dst, GR16:$src1), + "rol{w} $dst", + [(set GR16:$dst, (rotl GR16:$src1, (i8 1)))]>, OpSize; +def ROL32r1 : I<0xD1, MRM0r, (ops GR32:$dst, GR32:$src1), + "rol{l} $dst", + [(set GR32:$dst, (rotl GR32:$src1, (i8 1)))]>; + let isTwoAddress = 0 in { def ROL8mCL : I<0xD2, MRM0m, (ops i8mem :$dst), "rol{b} {%cl, $dst|$dst, %CL}", @@ -1560,6 +1649,18 @@ let isTwoAddress = 0 in { def ROL32mi : Ii8<0xC1, MRM0m, (ops i32mem:$dst, i8imm:$src), "rol{l} {$src, $dst|$dst, $src}", [(store (rotl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Rotate by 1 + def ROL8m1 : I<0xD0, MRM0m, (ops i8mem :$dst), + "rol{b} $dst", + [(store (rotl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def ROL16m1 : I<0xD1, MRM0m, (ops i16mem:$dst), + "rol{w} $dst", + [(store (rotl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def ROL32m1 : I<0xD1, MRM0m, (ops i32mem:$dst), + "rol{l} $dst", + [(store (rotl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; } def ROR8rCL : I<0xD2, MRM1r, (ops GR8 :$dst, GR8 :$src), @@ -1581,6 +1682,18 @@ def ROR16ri : Ii8<0xC1, MRM1r, (ops GR16:$dst, GR16:$src1, i8imm:$src2), def ROR32ri : Ii8<0xC1, MRM1r, (ops GR32:$dst, GR32:$src1, i8imm:$src2), "ror{l} {$src2, $dst|$dst, $src2}", [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$src2)))]>; + +// Rotate by 1 +def ROR8r1 : I<0xD0, MRM1r, (ops GR8 :$dst, GR8 :$src1), + "ror{b} $dst", + [(set GR8:$dst, (rotr GR8:$src1, (i8 1)))]>; +def ROR16r1 : I<0xD1, MRM1r, (ops GR16:$dst, GR16:$src1), + "ror{w} $dst", + [(set GR16:$dst, (rotr GR16:$src1, (i8 1)))]>, OpSize; +def ROR32r1 : I<0xD1, MRM1r, (ops GR32:$dst, GR32:$src1), + "ror{l} $dst", + [(set GR32:$dst, (rotr GR32:$src1, (i8 1)))]>; + let isTwoAddress = 0 in { def ROR8mCL : I<0xD2, MRM1m, (ops i8mem :$dst), "ror{b} {%cl, $dst|$dst, %CL}", @@ -1604,6 +1717,18 @@ let isTwoAddress = 0 in { def ROR32mi : Ii8<0xC1, MRM1m, (ops i32mem:$dst, i8imm:$src), "ror{l} {$src, $dst|$dst, $src}", [(store (rotr (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Rotate by 1 + def ROR8m1 : I<0xD0, MRM1m, (ops i8mem :$dst), + "ror{b} $dst", + [(store (rotr (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def ROR16m1 : I<0xD1, MRM1m, (ops i16mem:$dst), + "ror{w} $dst", + [(store (rotr (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def ROR32m1 : I<0xD1, MRM1m, (ops i32mem:$dst), + "ror{l} $dst", + [(store (rotr (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; } @@ -1958,60 +2083,52 @@ def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8 let isCommutable = 1 in { // TEST X, Y --> TEST Y, X def TEST8rr : I<0x84, MRMDestReg, (ops GR8:$src1, GR8:$src2), "test{b} {$src2, $src1|$src1, $src2}", - [(X86test GR8:$src1, GR8:$src2)]>; + [(X86cmp (and GR8:$src1, GR8:$src2), 0)]>; def TEST16rr : I<0x85, MRMDestReg, (ops GR16:$src1, GR16:$src2), "test{w} {$src2, $src1|$src1, $src2}", - [(X86test GR16:$src1, GR16:$src2)]>, OpSize; + [(X86cmp (and GR16:$src1, GR16:$src2), 0)]>, OpSize; def TEST32rr : I<0x85, MRMDestReg, (ops GR32:$src1, GR32:$src2), "test{l} {$src2, $src1|$src1, $src2}", - [(X86test GR32:$src1, GR32:$src2)]>; + [(X86cmp (and GR32:$src1, GR32:$src2), 0)]>; } -def TEST8mr : I<0x84, MRMDestMem, (ops i8mem :$src1, GR8 :$src2), - "test{b} {$src2, $src1|$src1, $src2}", - [(X86test (loadi8 addr:$src1), GR8:$src2)]>; -def TEST16mr : I<0x85, MRMDestMem, (ops i16mem:$src1, GR16:$src2), - "test{w} {$src2, $src1|$src1, $src2}", - [(X86test (loadi16 addr:$src1), GR16:$src2)]>, - OpSize; -def TEST32mr : I<0x85, MRMDestMem, (ops i32mem:$src1, GR32:$src2), - "test{l} {$src2, $src1|$src1, $src2}", - [(X86test (loadi32 addr:$src1), GR32:$src2)]>; + def TEST8rm : I<0x84, MRMSrcMem, (ops GR8 :$src1, i8mem :$src2), "test{b} {$src2, $src1|$src1, $src2}", - [(X86test GR8:$src1, (loadi8 addr:$src2))]>; + [(X86cmp (and GR8:$src1, (loadi8 addr:$src2)), 0)]>; def TEST16rm : I<0x85, MRMSrcMem, (ops GR16:$src1, i16mem:$src2), "test{w} {$src2, $src1|$src1, $src2}", - [(X86test GR16:$src1, (loadi16 addr:$src2))]>, + [(X86cmp (and GR16:$src1, (loadi16 addr:$src2)), 0)]>, OpSize; def TEST32rm : I<0x85, MRMSrcMem, (ops GR32:$src1, i32mem:$src2), "test{l} {$src2, $src1|$src1, $src2}", - [(X86test GR32:$src1, (loadi32 addr:$src2))]>; + [(X86cmp (and GR32:$src1, (loadi32 addr:$src2)), 0)]>; def TEST8ri : Ii8 <0xF6, MRM0r, // flags = GR8 & imm8 (ops GR8:$src1, i8imm:$src2), "test{b} {$src2, $src1|$src1, $src2}", - [(X86test GR8:$src1, imm:$src2)]>; + [(X86cmp (and GR8:$src1, imm:$src2), 0)]>; def TEST16ri : Ii16<0xF7, MRM0r, // flags = GR16 & imm16 (ops GR16:$src1, i16imm:$src2), "test{w} {$src2, $src1|$src1, $src2}", - [(X86test GR16:$src1, imm:$src2)]>, OpSize; + [(X86cmp (and GR16:$src1, imm:$src2), 0)]>, OpSize; def TEST32ri : Ii32<0xF7, MRM0r, // flags = GR32 & imm32 (ops GR32:$src1, i32imm:$src2), "test{l} {$src2, $src1|$src1, $src2}", - [(X86test GR32:$src1, imm:$src2)]>; + [(X86cmp (and GR32:$src1, imm:$src2), 0)]>; + def TEST8mi : Ii8 <0xF6, MRM0m, // flags = [mem8] & imm8 (ops i8mem:$src1, i8imm:$src2), "test{b} {$src2, $src1|$src1, $src2}", - [(X86test (loadi8 addr:$src1), imm:$src2)]>; + [(X86cmp (and (loadi8 addr:$src1), imm:$src2), 0)]>; def TEST16mi : Ii16<0xF7, MRM0m, // flags = [mem16] & imm16 (ops i16mem:$src1, i16imm:$src2), "test{w} {$src2, $src1|$src1, $src2}", - [(X86test (loadi16 addr:$src1), imm:$src2)]>, + [(X86cmp (and (loadi16 addr:$src1), imm:$src2), 0)]>, OpSize; def TEST32mi : Ii32<0xF7, MRM0m, // flags = [mem32] & imm32 (ops i32mem:$src1, i32imm:$src2), "test{l} {$src2, $src1|$src1, $src2}", - [(X86test (loadi32 addr:$src1), imm:$src2)]>; + [(X86cmp (and (loadi32 addr:$src1), imm:$src2), 0)]>; // Condition code ops, incl. set if equal/not equal/... @@ -2279,21 +2396,15 @@ def MOVZX32rm16: I<0xB7, MRMSrcMem, (ops GR32:$dst, i16mem:$src), [(set GR32:$dst, (zextloadi32i16 addr:$src))]>, TB; def CBW : I<0x98, RawFrm, (ops), - "{cbtw|cbw}", []>, Imp<[AL],[AX]>; // AX = signext(AL) + "{cbtw|cbw}", []>, Imp<[AL],[AX]>, OpSize; // AX = signext(AL) def CWDE : I<0x98, RawFrm, (ops), "{cwtl|cwde}", []>, Imp<[AX],[EAX]>; // EAX = signext(AX) def CWD : I<0x99, RawFrm, (ops), - "{cwtd|cwd}", []>, Imp<[AX],[AX,DX]>; // DX:AX = signext(AX) + "{cwtd|cwd}", []>, Imp<[AX],[AX,DX]>, OpSize; // DX:AX = signext(AX) def CDQ : I<0x99, RawFrm, (ops), "{cltd|cdq}", []>, Imp<[EAX],[EAX,EDX]>; // EDX:EAX = signext(EAX) -//===----------------------------------------------------------------------===// -// Miscellaneous Instructions -//===----------------------------------------------------------------------===// - -def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", [(X86rdtsc)]>, - TB, Imp<[],[EAX,EDX]>; //===----------------------------------------------------------------------===// // Alias Instructions @@ -2340,15 +2451,11 @@ def DWARF_LOC : I<0, Pseudo, (ops i32imm:$line, i32imm:$col, i32imm:$file), [(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>; -def DWARF_LABEL : I<0, Pseudo, (ops i32imm:$id), - "\nLdebug_loc${id:debug}:", - [(dwarf_label (i32 imm:$id))]>; - //===----------------------------------------------------------------------===// // Non-Instruction Patterns //===----------------------------------------------------------------------===// -// ConstantPool GlobalAddress, ExternalSymbol +// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable def : Pat<(i32 (X86Wrapper tconstpool :$dst)), (MOV32ri tconstpool :$dst)>; def : Pat<(i32 (X86Wrapper tjumptable :$dst)), (MOV32ri tjumptable :$dst)>; def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>; @@ -2370,18 +2477,16 @@ def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst), // Calls def : Pat<(X86tailcall GR32:$dst), - (CALL32r GR32:$dst)>; + (CALL32r GR32:$dst)>; -def : Pat<(X86tailcall tglobaladdr:$dst), +def : Pat<(X86tailcall (i32 tglobaladdr:$dst)), (CALLpcrel32 tglobaladdr:$dst)>; -def : Pat<(X86tailcall texternalsym:$dst), +def : Pat<(X86tailcall (i32 texternalsym:$dst)), (CALLpcrel32 texternalsym:$dst)>; - - -def : Pat<(X86call tglobaladdr:$dst), +def : Pat<(X86call (i32 tglobaladdr:$dst)), (CALLpcrel32 tglobaladdr:$dst)>; -def : Pat<(X86call texternalsym:$dst), +def : Pat<(X86call (i32 texternalsym:$dst)), (CALLpcrel32 texternalsym:$dst)>; // X86 specific add which produces a flag. @@ -2403,11 +2508,21 @@ def : Pat<(subc GR32:$src1, imm:$src2), def : Pat<(subc GR32:$src1, i32immSExt8:$src2), (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; -def : Pat<(truncstore (i8 imm:$src), addr:$dst, i1), +def : Pat<(truncstorei1 (i8 imm:$src), addr:$dst), (MOV8mi addr:$dst, imm:$src)>; -def : Pat<(truncstore GR8:$src, addr:$dst, i1), +def : Pat<(truncstorei1 GR8:$src, addr:$dst), (MOV8mr addr:$dst, GR8:$src)>; +// Comparisons. + +// TEST R,R is smaller than CMP R,0 +def : Pat<(X86cmp GR8:$src1, 0), + (TEST8rr GR8:$src1, GR8:$src1)>; +def : Pat<(X86cmp GR16:$src1, 0), + (TEST16rr GR16:$src1, GR16:$src1)>; +def : Pat<(X86cmp GR32:$src1, 0), + (TEST32rr GR32:$src1, GR32:$src1)>; + // {s|z}extload bool -> {s|z}extload byte def : Pat<(sextloadi16i1 addr:$src), (MOVSX16rm8 addr:$src)>; def : Pat<(sextloadi32i1 addr:$src), (MOVSX32rm8 addr:$src)>; @@ -2494,3 +2609,9 @@ include "X86InstrMMX.td" //===----------------------------------------------------------------------===// include "X86InstrSSE.td" + +//===----------------------------------------------------------------------===// +// X86-64 Support +//===----------------------------------------------------------------------===// + +include "X86InstrX86-64.td"