//===- X86InstrSel.td - Describe the X86 Instruction Selector -------*- 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 is used by the instruction selector and is used to map // LLVM instructions to a corresponding set of machine instructions // // //===----------------------------------------------------------------------===// include "../Target.td" // ret br switch invoke unwind // add sub mul div rem setcc (eq ne lt gt le ge) // and or xor sbl sbr // malloc free alloca load store // getelementptr phi cast call vanext vaarg class InstrSubclass { int Value = v; } // provide a grouping of InstrSubclasses class InstrSubclassCollection l> { list List = l; string PreCode = pre; string PostCode = post; } // virtual registers let Namespace = "Virtual" in { def DestReg : Register; def DestRegp1 : Register; // DestReg+1 def Op0Reg : Register; def Op0Regp1 : Register; // Op0Reg+1 def Op1Reg : Register; def Op1Regp1 : Register; // Op1Reg+1 def TmpReg01 : Register; def TmpReg01p1: Register; def TmpReg02 : Register; def TmpReg02p1: Register; def NullReg : Register; // represents no register } class InstrClass l> { string FunctionName = fn; string InstructionName = n; string PreCode = pre; string PostCode = post; // add lists of what subclasses this InstrClass supports list Supports = l; } // helper class to build BMI instruction class addedOperand { string Name = op; } def MBI_Reg : addedOperand<"Reg">; def MBI_GlobalAddr : addedOperand<"GlobalAddr">; def MBI_ZImm : addedOperand<"ZImm">; def MBI_DirectMem : addedOperand<"DirectMem">; def MBI_RegOffset : addedOperand<"RegOffset">; def MBI_FrameRef : addedOperand<"FrameRef">; def MBI_ConstPoolRef : addedOperand<"ConstPoolRef">; def MBI_CCReg : addedOperand<"CCReg">; def MBI_RegDef : addedOperand<"RegDef">; def MBI_PCDisp : addedOperand<"PCDisp">; def MBI_MReg : addedOperand<"MReg">; def MBI_SImm : addedOperand<"SImm">; def MBI_MBB : addedOperand<"MBB">; def MBI_FrameIndex : addedOperand<"FrameIndex">; def MBI_ConstPoolIdx : addedOperand<"ConstPoolIdx">; def MBI_ExternSymbol : addedOperand<"ExternSymbol">; class TargInstr lops> { string Name = n; // make this a reference to the Instruction class string Namespace; int NumOperands = numops; list Params = lops; // will this work for mem-mem instrs, destination is implicitly a register } //TargInstr let Namespace = "Virtual" in { // virtual instructions for creating registers def CreateRegInt : TargInstr<"CreateRegInt",0,[]>; def CreateRegByte : TargInstr<"CreateRegByte",0,[]>; def CreateRegShort: TargInstr<"CreateRegShort",0,[]>; def CreateRegLong : TargInstr<"CreateRegLong",0,[]>; def CreateRegUInt : TargInstr<"CreateRegUInt",0,[]>; def CreateRegUByte : TargInstr<"CreateRegUByte",0,[]>; def CreateRegUShort: TargInstr<"CreateRegUShort",0,[]>; def CreateRegULong : TargInstr<"CreateRegULong",0,[]>; def CreateRegFloat : TargInstr<"CreateRegFloat",0,[]>; def CreateRegDouble : TargInstr<"CreateRegDouble",0,[]>; def CreateRegPointer: TargInstr<"CreateRegPointer",0,[]>; def NullInstr : TargInstr<"NullInstruction",0,[]>; // ignored } class TargInstrSet l, list targs, list> r> { InstrClass Class = c; list List = l; list Instructions = targs; list< list > Operands = r; // generalized for all operand types string PreCode = pre; string PostCode = post; } // -------------------------------------------------------------------- // Begin architecture-specific information // -------------------------------------------------------------------- include "X86RegisterInfo.td" include "X86InstrSelInfo.td" // set up the subclasses of instructions // value is what the subclass's case value def cByte : InstrSubclass<1>; def cInt : InstrSubclass<2>; def cShort : InstrSubclass<3>; def cFP : InstrSubclass<4>; def cLong : InstrSubclass<5>; def EQ : InstrSubclass<1>; def NE : InstrSubclass<2>; def LT : InstrSubclass<3>; def GE : InstrSubclass<4>; def GT : InstrSubclass<5>; def LE : InstrSubclass<6>; def True : InstrSubclass<1>; def False : InstrSubclass<0>; def NegOne : InstrSubclass<-1>; def PosOne : InstrSubclass<1>; def Cons :InstrSubclass<2>; def Other : InstrSubclass<0>; def Regular: InstrSubclass<0>; def Zero : InstrSubclass<0>; def NoOps : InstrSubclass<0>; def Ops : InstrSubclass<1>; def Signed : InstrSubclass<0>; def Unsigned : InstrSubclass<1>; def SuccessorIsNextBB : InstrSubclass<0>; def SuccessorIsNotNextBB: InstrSubclass<1>; def Cond: InstrSubclass<0>; def Uncond: InstrSubclass<1>; def ConstTwo: InstrSubclass<2>; def ConstNotTwo: InstrSubclass<3>; def Reg: InstrSubclass<6>; // group subclasses, specify how to determine instruction subclass def OperandSize: InstrSubclassCollection<"unsigned OperandSize = getClassB(Op0Val->getType());","", [cByte, cShort, cInt, cFP, cLong]>; def Conditional: InstrSubclassCollection<"unsigned Conditional;", "", [EQ, NE, LT, GE, GT, LE]>; def SpecialCase: InstrSubclassCollection<"unsigned SpecialCase;", "", [True, False]>; //TODO write funcs for separating out special cases def AddSpecialCases: InstrSubclassCollection<"Subclasses AddSpecialCases = Other;", "", [NegOne,PosOne,Cons,Other]>; def SubSpecialCases: InstrSubclassCollection<"unsigned SubSpecialCases = Other;", "", [NegOne,PosOne,Cons,Other]>; def XorSpecialCases: InstrSubclassCollection<"unsigned XorSpecialCases = Other;","", [NegOne,Other]>; // Instruction subclasses, as defined in llvm/Instructions.h: // iTerminators.h : ReturnInst, BranchInst, SwitchInst, InvokeInst, UnwindInst // iPHINode.h : PHINode, // iOperators.h : SetCondInst, // iMemory.h : AllocationInst, MallocInst, AllocaInst, FreeInst, LoadInst, StoreInst, GetElementPtrInst, // iOther.h : CastInst, CallInst, ShiftInst, VANextInst, VAArgInst, // InstrTypes.h : TerminatorInst, BinaryOperator // general classes of LLVM instructions, and the subclass sets that apply to them def add : InstrClass<"BinaryOperator","Add","","",[AddSpecialCases, OperandSize]>; def sub : InstrClass<"BinaryOperator","Sub","","",[SubSpecialCases, OperandSize]>; // def mul : InstrClass<"BinaryOperator","Mul","","",[OperandSize]>; // def div : InstrClass<"BinaryOperator","Div","","",[OperandSize]>; // def rem : InstrClass<"BinaryOperator","Rem","","",[OperandSize]>; def logic_and : InstrClass<"BinaryOperator","And","","",[OperandSize]>; def logic_or : InstrClass<"BinaryOperator","Or","","",[OperandSize]>; def logic_xor : InstrClass<"BinaryOperator","Xor","","",[XorSpecialCases, OperandSize]>; // //def mov : InstrClass<"ShiftInst","Mov","","",[OperandSize]>; // def setcc: InstrClass<"SetCondInst","SetCondInst","","",[OperandSize]>; // def branch : InstrClass<"BranchInst","BranchInst","","",[Conditional]>; // def retrn : InstrClass<"ReturnInst","ReturnInst","","",[]>; // definition of machine instructions for instruction subclasses // ADD def ADD_Other_cByte : TargInstrSet; def ADD_Other_cShort : TargInstrSet; def ADD_Other_cInt : TargInstrSet; def ADD_Other_cLong : TargInstrSet; def ADD_Other_cFP : TargInstrSet; def ADD_Constant_cByte : TargInstrSet; def ADD_Constant_cShort :TargInstrSet; def ADD_Constant_cInt :TargInstrSet; def ADD_PosOne_cByte : TargInstrSet; def ADD_PosOne_cShort : TargInstrSet; def ADD_PosOne_cInt : TargInstrSet; def ADD_NegOne_cByte : TargInstrSet; def ADD_NegOne_cShort : TargInstrSet; def ADD_NegOne_cInt : TargInstrSet; // SUBTRACT def SUB_Other_cByte : TargInstrSet; def SUB_Other_cShort : TargInstrSet; def SUB_Other_cInt : TargInstrSet; def SUB_Other_cLong : TargInstrSet; def SUB_Other_cFP : TargInstrSet; def SUB_Constant_cByte : TargInstrSet; def SUB_Constant_cShort :TargInstrSet; def SUB_Constant_cInt :TargInstrSet; def SUB_PosOne_cByte : TargInstrSet; def SUB_PosOne_cShort : TargInstrSet; def SUB_PosOne_cInt : TargInstrSet; def SUB_NegOne_cByte : TargInstrSet; def SUB_NegOne_cShort : TargInstrSet; def SUB_NegOne_cInt : TargInstrSet; // def SHIFT_S_L_Const_Byte : // def SHIFT_S_L_Const_Short : // def SHIFT_S_L_Const_Int : // def SHIFT_S_L_Const_SHLDIR32 : // def SHIFT_S_L_Reg_Byte : // def SHIFT_S_L_Reg_Short : // def SHIFT_S_L_Reg_Int : // def SHIFT_S_R_Const_Byte : // def SHIFT_S_R_Const_Short : // def SHIFT_S_R_Const_Int : // def SHIFT_S_R_Const_SHRDIR32 : // def SHIFT_S_R_Reg_Byte : // def SHIFT_S_R_Reg_Short : // def SHIFT_S_R_Reg_Int : // def SHIFT_U_L_Const_Byte : // def SHIFT_U_L_Const_Short : // def SHIFT_U_L_Const_Int : // def SHIFT_U_L_Const_SHLDIR32 : // def SHIFT_U_L_Reg_Byte : // def SHIFT_U_L_Reg_Short : // def SHIFT_U_L_Reg_Int : // def SHIFT_U_R_Const_Byte : // def SHIFT_U_R_Const_Short : // def SHIFT_U_R_Const_Int : // def SHIFT_U_R_Const_SHRDIR32 : // def SHIFT_U_R_Reg_Byte : // def SHIFT_U_R_Reg_Short : // def SHIFT_U_R_Reg_Int : // def CMP_i_Byte : TargInstrSet; // def CMP_i_Short : TargInstrSet; // def CMP_i_Int : TargInstrSet; // //def CMP_i_Long : // not supported // def CMP_z_Byte : TargInstrSet(Op1); uint64_t Op1v = cast(CI)->getRawValue(); Op1v &= (1ULL << (8 << Class)) - 1;","",[Zero,cByte],[TESTrr8],[["DestReg","Op0Reg","Op0Reg"]]>; // def CMP_z_Short : TargInstrSet(Op1); uint64_t Op1v = cast(CI)->getRawValue(); Op1v &= (1ULL << (8 << Class)) - 1;","",[Zero,cShort],[TESTrr16],[["DestReg","Op0Reg","Op0Reg"]]>; // def CMP_z_Int : TargInstrSet(Op1); uint64_t Op1v = cast(CI)->getRawValue(); Op1v &= (1ULL << (8 << Class)) - 1;","",[Zero,cInt],[TESTrr32],[["DestReg","Op0Reg","Op0Reg"]]>; // //def CMP_z_Long : // not supported // def CMP_r_Byte : TargInstrSet; // def CMP_r_Short : TargInstrSet; // def CMP_r_Int : TargInstrSet; // //def CMP_r_Long : // two cases of long, depending on num of operands // def CMP_r_FP : TargInstrSet; // def RET_NoOps : TargInstrSet; // def RET_Op_Byte : TargInstrSetgetType()));","",[Ops,cByte],[IMPLICIT_USE],[["NullReg","EAX","ESP"]]>; // def RET_Op_Short : TargInstrSetgetType()));","",[Ops,cShort],[IMPLICIT_USE],[["NullReg","EAX","ESP"]]>; // def RET_Op_Int : TargInstrSetgetType()));","",[Ops,cInt],[IMPLICIT_USE],[["NullReg","EAX","ESP"]]>; // def RET_Op_FP : TargInstrSet; // def RET_Op_Long : TargInstrSet; // def BR_Uncond : TargInstrSet; // def BR_Cond_S_EQ : // def BR_Cond_S_NE // def BR_Cond_S_B // def BR_Cond_S_AE // def BR_Cond_S_A // def BR_Cond_S_BE // def BR_Cond_U_EQ // def BR_Cond_U_NE // def BR_Cond_U_LT // def BR_Cond_U_GE // def BR_Cond_U_GT // def BR_Cond_U_LE // def BR_Cond_U_S // def BR_Cond_U_NS // def CALL_Byte // def CALL_Short // def CALL_Int // def CALL_Long // def CALL_FP def AND_Byte : TargInstrSet; def AND_Short : TargInstrSet; def AND_Int : TargInstrSet; def AND_Long : TargInstrSet; def OR_Byte : TargInstrSet; def OR_Short : TargInstrSet; def OR_Int : TargInstrSet; def OR_Long : TargInstrSet; def XOR_NegOne_Byte : TargInstrSet; def XOR_NegOne_Short: TargInstrSet; def XOR_NegOne_Int : TargInstrSet; //def XOR_NegOne_Long : // not supported (treat as regular long XOR) def XOR_Other_Byte : TargInstrSet; def XOR_Other_Short : TargInstrSet; def XOR_Other_Int : TargInstrSet; def XOR_Other_Long : TargInstrSet; // // TODO support for arbitrary values as operand arguments // // or make ConstantInt versions as well-known variables // // ConstantInt, unsigned Val // def MUL_ConstTwo_Byte : TargInstrSet(I.getOperand(1)); unsigned Val = (unsigned)CI->getRawValue(); unsigned Shift = ExactLog2(Val);","",[ConstTwo,cByte],[SHLir32],[["DestReg","Op0Reg","Shift-1"]]>; // def MUL_ConstTwo_Short : TargInstrSet(I.getOperand(1)); unsigned Val = (unsigned)CI->getRawValue(); unsigned Shift = ExactLog2(Val);","",[ConstTwo,cShort],[SHLir32],[["DestReg","Op0Reg","Shift-1"]]>; // def MUL_ConstTwo_Int : TargInstrSet(I.getOperand(1)); unsigned Val = (unsigned)CI->getRawValue(); unsigned Shift = ExactLog2(Val);","",[ConstTwo,cInt],[SHLir32],[["DestReg","Op0Reg","Shift-1"]]>; // def MUL_ConstNotTwo_Byte : TargInstrSet; //TODO fixme, define ConstRHS // def MUL_ConstNotTwo_Short : TargInstrSet; // def MUL_ConstNotTwo_Int : TargInstrSet; // //def MUL_ConstNotTwo_Long : // //def MUL_ConstNotTwo_FP : // def MUL_Reg_Byte : TargInstrSet; // def MUL_Reg_Short : TargInstrSet; // def MUL_Reg_Int : TargInstrSet; // //def MUL_Reg_Long : // not supported (assert) // def MUL_Reg_FP : TargInstrSet; // def STO_Byte // def STO_Short // def STO_Int // def STO_FP // def STO_Long // DIVREM // CAST // PHI // LOAD ARGS TO VIRTUAL REGS // COPY CONSTANT //TODO // handling various operand options // allowing for arbitrary code or operand arguments // generate skeletons for selector function //