X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsInstrInfo.td;h=e86c5e55254bcbc520e7e613897f6ac61b52f6b2;hb=353cf20b9b759a3334d66a8ae1ff3b327761b335;hp=641f37a6fa522e8eb14308166de935f235072adc;hpb=bd2926b0566908611787c688763cd36d8eb55a84;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 641f37a6fa5..e86c5e55254 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -146,51 +146,145 @@ def MipsSDR : SDNode<"MipsISD::SDR", SDTStore, //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// -def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">, - AssemblerPredicate<"FeatureSEInReg">; -def HasBitCount : Predicate<"Subtarget.hasBitCount()">, - AssemblerPredicate<"FeatureBitCount">; -def HasSwap : Predicate<"Subtarget.hasSwap()">, - AssemblerPredicate<"FeatureSwap">; -def HasCondMov : Predicate<"Subtarget.hasCondMov()">, - AssemblerPredicate<"FeatureCondMov">; -def HasFPIdx : Predicate<"Subtarget.hasFPIdx()">, - AssemblerPredicate<"FeatureFPIdx">; -def HasMips32 : Predicate<"Subtarget.hasMips32()">, +def HasMips2 : Predicate<"Subtarget->hasMips2()">, + AssemblerPredicate<"FeatureMips2">; +def HasMips3_32 : Predicate<"Subtarget->hasMips3_32()">, + AssemblerPredicate<"FeatureMips3_32">; +def HasMips3_32r2 : Predicate<"Subtarget->hasMips3_32r2()">, + AssemblerPredicate<"FeatureMips3_32r2">; +def HasMips3 : Predicate<"Subtarget->hasMips3()">, + AssemblerPredicate<"FeatureMips3">; +def HasMips4_32 : Predicate<"Subtarget->hasMips4_32()">, + AssemblerPredicate<"FeatureMips4_32">; +def HasMips4_32r2 : Predicate<"Subtarget->hasMips4_32r2()">, + AssemblerPredicate<"FeatureMips4_32r2">; +def HasMips5_32r2 : Predicate<"Subtarget->hasMips5_32r2()">, + AssemblerPredicate<"FeatureMips5_32r2">; +def HasMips32 : Predicate<"Subtarget->hasMips32()">, AssemblerPredicate<"FeatureMips32">; -def HasMips32r2 : Predicate<"Subtarget.hasMips32r2()">, +def HasMips32r2 : Predicate<"Subtarget->hasMips32r2()">, AssemblerPredicate<"FeatureMips32r2">; -def HasMips64 : Predicate<"Subtarget.hasMips64()">, +def HasMips32r6 : Predicate<"Subtarget->hasMips32r6()">, + AssemblerPredicate<"FeatureMips32r6">; +def NotMips32r6 : Predicate<"!Subtarget->hasMips32r6()">, + AssemblerPredicate<"!FeatureMips32r6">; +def IsGP64bit : Predicate<"Subtarget->isGP64bit()">, + AssemblerPredicate<"FeatureGP64Bit">; +def IsGP32bit : Predicate<"!Subtarget->isGP64bit()">, + AssemblerPredicate<"!FeatureGP64Bit">; +def HasMips64 : Predicate<"Subtarget->hasMips64()">, AssemblerPredicate<"FeatureMips64">; -def NotMips64 : Predicate<"!Subtarget.hasMips64()">, - AssemblerPredicate<"!FeatureMips64">; -def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">, +def HasMips64r2 : Predicate<"Subtarget->hasMips64r2()">, AssemblerPredicate<"FeatureMips64r2">; -def IsN64 : Predicate<"Subtarget.isABI_N64()">, +def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">, + AssemblerPredicate<"FeatureMips64r6">; +def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">, + AssemblerPredicate<"!FeatureMips64r6">; +def IsN64 : Predicate<"Subtarget->isABI_N64()">, AssemblerPredicate<"FeatureN64">; -def NotN64 : Predicate<"!Subtarget.isABI_N64()">, - AssemblerPredicate<"!FeatureN64">; -def InMips16Mode : Predicate<"Subtarget.inMips16Mode()">, +def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; +def HasCnMips : Predicate<"Subtarget->hasCnMips()">, + AssemblerPredicate<"FeatureCnMips">; def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">, AssemblerPredicate<"FeatureMips32">; def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">, AssemblerPredicate<"FeatureMips32">; -def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">, - AssemblerPredicate<"FeatureMips32">; -def HasStdEnc : Predicate<"Subtarget.hasStandardEncoding()">, +def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; +def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; -def NotDSP : Predicate<"!Subtarget.hasDSP()">; -def InMicroMips : Predicate<"Subtarget.inMicroMipsMode()">, +def NotDSP : Predicate<"!Subtarget->hasDSP()">; +def InMicroMips : Predicate<"Subtarget->inMicroMipsMode()">, AssemblerPredicate<"FeatureMicroMips">; -def NotInMicroMips : Predicate<"!Subtarget.inMicroMipsMode()">, +def NotInMicroMips : Predicate<"!Subtarget->inMicroMipsMode()">, AssemblerPredicate<"!FeatureMicroMips">; -def IsLE : Predicate<"Subtarget.isLittle()">; -def IsBE : Predicate<"!Subtarget.isLittle()">; +def IsLE : Predicate<"Subtarget->isLittle()">; +def IsBE : Predicate<"!Subtarget->isLittle()">; +def IsNotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; + +//===----------------------------------------------------------------------===// +// Mips GPR size adjectives. +// They are mutually exclusive. +//===----------------------------------------------------------------------===// + +class GPR_32 { list GPRPredicates = [IsGP32bit]; } +class GPR_64 { list GPRPredicates = [IsGP64bit]; } + +//===----------------------------------------------------------------------===// +// Mips ISA/ASE membership and instruction group membership adjectives. +// They are mutually exclusive. +//===----------------------------------------------------------------------===// -class MipsPat : Pat { - let Predicates = [HasStdEnc]; +// FIXME: I'd prefer to use additive predicates to build the instruction sets +// but we are short on assembler feature bits at the moment. Using a +// subtractive predicate will hopefully keep us under the 32 predicate +// limit long enough to develop an alternative way to handle P1||P2 +// predicates. +class ISA_MIPS1_NOT_32R6_64R6 { + list InsnPredicates = [NotMips32r6, NotMips64r6]; } +class ISA_MIPS2 { list InsnPredicates = [HasMips2]; } +class ISA_MIPS2_NOT_32R6_64R6 { + list InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6]; +} +class ISA_MIPS3 { list InsnPredicates = [HasMips3]; } +class ISA_MIPS3_NOT_32R6_64R6 { + list InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6]; +} +class ISA_MIPS32 { list InsnPredicates = [HasMips32]; } +class ISA_MIPS32_NOT_32R6_64R6 { + list InsnPredicates = [HasMips32, NotMips32r6, NotMips64r6]; +} +class ISA_MIPS32R2 { list InsnPredicates = [HasMips32r2]; } +class ISA_MIPS32R2_NOT_32R6_64R6 { + list InsnPredicates = [HasMips32r2, NotMips32r6, NotMips64r6]; +} +class ISA_MIPS64 { list InsnPredicates = [HasMips64]; } +class ISA_MIPS64_NOT_64R6 { + list InsnPredicates = [HasMips64, NotMips64r6]; +} +class ISA_MIPS64R2 { list InsnPredicates = [HasMips64r2]; } +class ISA_MIPS32R6 { list InsnPredicates = [HasMips32r6]; } +class ISA_MIPS64R6 { list InsnPredicates = [HasMips64r6]; } + +// The portions of MIPS-III that were also added to MIPS32 +class INSN_MIPS3_32 { list InsnPredicates = [HasMips3_32]; } + +// The portions of MIPS-III that were also added to MIPS32 but were removed in +// MIPS32r6 and MIPS64r6. +class INSN_MIPS3_32_NOT_32R6_64R6 { + list InsnPredicates = [HasMips3_32, NotMips32r6, NotMips64r6]; +} + +// The portions of MIPS-III that were also added to MIPS32 +class INSN_MIPS3_32R2 { list InsnPredicates = [HasMips3_32r2]; } + +// The portions of MIPS-IV that were also added to MIPS32 but were removed in +// MIPS32r6 and MIPS64r6. +class INSN_MIPS4_32_NOT_32R6_64R6 { + list InsnPredicates = [HasMips4_32, NotMips32r6, NotMips64r6]; +} + +// The portions of MIPS-IV that were also added to MIPS32r2 but were removed in +// MIPS32r6 and MIPS64r6. +class INSN_MIPS4_32R2_NOT_32R6_64R6 { + list InsnPredicates = [HasMips4_32r2, NotMips32r6, NotMips64r6]; +} + +// The portions of MIPS-V that were also added to MIPS32r2 but were removed in +// MIPS32r6 and MIPS64r6. +class INSN_MIPS5_32R2_NOT_32R6_64R6 { + list InsnPredicates = [HasMips5_32r2, NotMips32r6, NotMips64r6]; +} + +//===----------------------------------------------------------------------===// + +class MipsPat : Pat, PredicateControl { + let EncodingPredicates = [HasStdEnc]; +} + +class MipsInstAlias : + InstAlias, PredicateControl; class IsCommutable { bit isCommutable = 1; @@ -235,23 +329,49 @@ include "MipsInstrFormats.td" // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// +def MipsJumpTargetAsmOperand : AsmOperandClass { + let Name = "JumpTarget"; + let ParserMethod = "parseJumpTarget"; + let PredicateMethod = "isImm"; + let RenderMethod = "addImmOperands"; +} + // Instruction operand types def jmptarget : Operand { let EncoderMethod = "getJumpTargetOpValue"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; let DecoderMethod = "DecodeBranchTarget"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } def calltarget : Operand { let EncoderMethod = "getJumpTargetOpValue"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } +def simm9 : Operand; +def simm10 : Operand; +def simm11 : Operand; + def simm16 : Operand { let DecoderMethod= "DecodeSimm16"; } +def simm19_lsl2 : Operand { + let EncoderMethod = "getSimm19Lsl2Encoding"; + let DecoderMethod = "DecodeSimm19Lsl2"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + +def simm18_lsl3 : Operand { + let EncoderMethod = "getSimm18Lsl3Encoding"; + let DecoderMethod = "DecodeSimm18Lsl3"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + def simm20 : Operand { } @@ -265,7 +385,20 @@ def simm16_64 : Operand { let DecoderMethod = "DecodeSimm16"; } +// Zero +def uimmz : Operand { + let PrintMethod = "printUnsignedImm"; +} + // Unsigned Operand +def uimm2 : Operand { + let PrintMethod = "printUnsignedImm"; +} + +def uimm3 : Operand { + let PrintMethod = "printUnsignedImm"; +} + def uimm5 : Operand { let PrintMethod = "printUnsignedImm"; } @@ -286,19 +419,26 @@ def MipsMemAsmOperand : AsmOperandClass { let ParserMethod = "parseMemOperand"; } +def MipsMemSimm11AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm11"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<11>"; + //let DiagnosticType = "Simm11"; +} + def MipsInvertedImmoperand : AsmOperandClass { let Name = "InvNum"; let RenderMethod = "addImmOperands"; let ParserMethod = "parseInvNum"; } -def PtrRegAsmOperand : AsmOperandClass { - let Name = "PtrReg"; - let ParserMethod = "parsePtrReg"; +def InvertedImOperand : Operand { + let ParserMatchClass = MipsInvertedImmoperand; } - -def InvertedImOperand : Operand { +def InvertedImOperand64 : Operand { let ParserMatchClass = MipsInvertedImmoperand; } @@ -315,9 +455,21 @@ def mem : mem_generic; // MSA specific address operand def mem_msa : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm10); let EncoderMethod = "getMSAMemEncoding"; } +def mem_simm9 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm9); + let EncoderMethod = "getMemEncoding"; +} + +def mem_simm11 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm11); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm11AsmOperand; +} + def mem_ea : Operand { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -328,7 +480,7 @@ def mem_ea : Operand { def PtrRC : Operand { let MIOperandInfo = (ops ptr_rc); let DecoderMethod = "DecodePtrRegisterClass"; - let ParserMatchClass = PtrRegAsmOperand; + let ParserMatchClass = GPR32AsmOperand; } // size operand of ext instruction @@ -356,6 +508,9 @@ def HI16 : SDNodeXFormgetSExtValue() + 1); }]>; +// Node immediate is zero (e.g. insve.d) +def immz : PatLeaf<(imm), [{ return N->getSExtValue() == 0; }]>; + // Node immediate fits as 16-bit sign extended on target immediate. // e.g. addi, andi def immSExt8 : PatLeaf<(imm), [{ return isInt<8>(N->getSExtValue()); }]>; @@ -407,6 +562,8 @@ def addrRegReg : def addrDefault : ComplexPattern; +def addrimm10 : ComplexPattern; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -420,6 +577,7 @@ class ArithLogicR { let isCommutable = isComm; let isReMaterializable = 1; + let TwoOperandAliasConstraint = "$rd = $rs"; } // Arithmetic and logical instructions with 2 register operands. @@ -436,9 +594,9 @@ class ArithLogicI : +class MArithR : InstSE<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - !strconcat(opstr, "\t$rs, $rt"), [], IIImult, FrmR, opstr> { + !strconcat(opstr, "\t$rs, $rt"), [], itin, FrmR, opstr> { let Defs = [HI0, LO0]; let Uses = [HI0, LO0]; let isCommutable = isComm; @@ -448,28 +606,32 @@ class MArithR : class LogicNOR: InstSE<(outs RO:$rd), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set RO:$rd, (not (or RO:$rs, RO:$rt)))], IIArith, FrmR, opstr> { + [(set RO:$rd, (not (or RO:$rs, RO:$rt)))], II_NOR, FrmR, opstr> { let isCommutable = 1; } // Shifts class shift_rotate_imm : InstSE<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt), !strconcat(opstr, "\t$rd, $rt, $shamt"), - [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], IIArith, FrmR, opstr>; + [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], itin, FrmR, opstr> { + let TwoOperandAliasConstraint = "$rt = $rd"; +} -class shift_rotate_reg: InstSE<(outs RO:$rd), (ins RO:$rt, GPR32Opnd:$rs), !strconcat(opstr, "\t$rd, $rt, $rs"), - [(set RO:$rd, (OpNode RO:$rt, GPR32Opnd:$rs))], IIArith, FrmR, opstr>; + [(set RO:$rd, (OpNode RO:$rt, GPR32Opnd:$rs))], itin, FrmR, + opstr>; // Load Upper Imediate class LoadUpper: InstSE<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), - [], IIArith, FrmI, opstr>, IsAsCheapAsAMove { + [], II_LUI, FrmI, opstr>, IsAsCheapAsAMove { let neverHasSideEffects = 1; let isReMaterializable = 1; } @@ -540,14 +702,14 @@ class SetCC_R : InstSE<(outs GPR32Opnd:$rd), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rd, $rs, $rt"), [(set GPR32Opnd:$rd, (cond_op RO:$rs, RO:$rt))], - IIslt, FrmR, opstr>; + II_SLT_SLTU, FrmR, opstr>; class SetCC_I: InstSE<(outs GPR32Opnd:$rt), (ins RO:$rs, Od:$imm16), !strconcat(opstr, "\t$rt, $rs, $imm16"), [(set GPR32Opnd:$rt, (cond_op RO:$rs, imm_type:$imm16))], - IIslt, FrmI, opstr>; + II_SLTI_SLTIU, FrmI, opstr>; // Jump class JumpFJ : let isTerminator = 1; let isBarrier = 1; let hasDelaySlot = 1; - let Predicates = [RelocPIC, HasStdEnc]; + let AdditionalPredicates = [RelocPIC]; let Defs = [AT]; } @@ -581,20 +743,11 @@ class JumpFR; // Indirect branch -class IndirectBranch : - JumpFR { +class IndirectBranch : JumpFR { let isBranch = 1; let isIndirectBranch = 1; } -// Return instruction -class RetBase: JumpFR { - let isReturn = 1; - let isCodeGenOnly = 1; - let hasCtrlDep = 1; - let hasExtraSrcRegAllocReq = 1; -} - // Jump and Link (Call) let isCall=1, hasDelaySlot=1, Defs = [RA] in { class JumpLink : @@ -610,7 +763,7 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in { class JumpLinkReg: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], IIBranch, FrmR, opstr>; + [], IIBranch, FrmR>; class BGEZAL_FT : InstSE<(outs), (ins RO:$rs, opnd:$offset), @@ -705,12 +858,13 @@ class MultDivPseudo +class MAddSubPseudo : PseudoSE<(outs ACC64:$ac), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64:$acin), [(set ACC64:$ac, (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64:$acin))], - IIImult>, + itin>, PseudoInstExpansion<(RealInst GPR32Opnd:$rs, GPR32Opnd:$rt)> { string Constraints = "$acin = $ac"; } @@ -725,21 +879,22 @@ class Div : PseudoSE<(outs DstRC:$rd), (ins SrcRC:$hilo), - [(set DstRC:$rd, (OpNode SrcRC:$hilo))], IIHiLo>; + [(set DstRC:$rd, (OpNode SrcRC:$hilo))], II_MFHI_MFLO>; class MoveFromLOHI: - InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], IIHiLo, FrmR, - opstr> { + InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], II_MFHI_MFLO, + FrmR, opstr> { let Uses = [UseReg]; let neverHasSideEffects = 1; } class PseudoMTLOHI : PseudoSE<(outs DstRC:$lohi), (ins SrcRC:$lo, SrcRC:$hi), - [(set DstRC:$lohi, (MipsMTLOHI SrcRC:$lo, SrcRC:$hi))], IIHiLo>; + [(set DstRC:$lohi, (MipsMTLOHI SrcRC:$lo, SrcRC:$hi))], + II_MTHI_MTLO>; class MoveToLOHI DefRegs>: - InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], IIHiLo, + InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], II_MTHI_MTLO, FrmR, opstr> { let Defs = DefRegs; let neverHasSideEffects = 1; @@ -747,7 +902,8 @@ class MoveToLOHI DefRegs>: class EffectiveAddress : InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, addr:$addr)], NoItinerary, FrmI> { + [(set RO:$rt, addr:$addr)], NoItinerary, FrmI, + !strconcat(opstr, "_lea")> { let isCodeGenOnly = 1; let DecoderMethod = "DecodeMem"; } @@ -755,34 +911,29 @@ class EffectiveAddress : // Count Leading Ones/Zeros in Word class CountLeading0: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz RO:$rs))], IIArith, FrmR, opstr>, - Requires<[HasBitCount, HasStdEnc]>; + [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>; class CountLeading1: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz (not RO:$rs)))], IIArith, FrmR, opstr>, - Requires<[HasBitCount, HasStdEnc]>; - + [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>; // Sign Extend in Register. -class SignExtInReg : +class SignExtInReg : InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), - [(set RO:$rd, (sext_inreg RO:$rt, vt))], IIseb, FrmR, opstr> { - let Predicates = [HasSEInReg, HasStdEnc]; -} + [(set RO:$rd, (sext_inreg RO:$rt, vt))], itin, FrmR, opstr>; // Subword Swap class SubwordSwap: InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [], NoItinerary, FrmR, opstr> { - let Predicates = [HasSwap, HasStdEnc]; let neverHasSideEffects = 1; } // Read Hardware class ReadHardware : InstSE<(outs CPURegOperand:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [], - IIArith, FrmR>; + II_RDHWR, FrmR>; // Ext and Ins class ExtBase { - let Predicates = [HasMips32r2, HasStdEnc]; -} + FrmR, opstr>, ISA_MIPS32R2; class InsBase: InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src), !strconcat(opstr, " $rt, $rs, $pos, $size"), [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))], - NoItinerary, FrmR, opstr> { - let Predicates = [HasMips32r2, HasStdEnc]; + NoItinerary, FrmR, opstr>, ISA_MIPS32R2 { let Constraints = "$src = $rt"; } @@ -891,6 +1039,18 @@ let isPseudo = 1, isCodeGenOnly = 1 in { def STORE_ACC64 : Store<"", ACC64>; } +// We need these two pseudo instructions to avoid offset calculation for long +// branches. See the comment in file MipsLongBranch.cpp for detailed +// explanation. + +// Expands to: lui $dst, %hi($tgt - $baltgt) +def LONG_BRANCH_LUi : PseudoSE<(outs GPR32Opnd:$dst), + (ins brtarget:$tgt, brtarget:$baltgt), []>; + +// Expands to: addiu $dst, $src, %lo($tgt - $baltgt) +def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), + (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; + //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -899,123 +1059,139 @@ let isPseudo = 1, isCodeGenOnly = 1 in { //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) -def ADDiu : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, IIArith, immSExt16, +def ADDiu : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, add>, ADDI_FM<0x9>, IsAsCheapAsAMove; -def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>; +def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>, + ISA_MIPS1_NOT_32R6_64R6; def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xa>; def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xb>; -def ANDi : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd, IILogic, immZExt16, +def ANDi : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, ADDI_FM<0xc>; -def ORi : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, IILogic, immZExt16, +def ORi : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, ADDI_FM<0xd>; -def XORi : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, IILogic, immZExt16, +def XORi : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, ADDI_FM<0xe>; def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM; /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, IIArith, add>, +def ADDu : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, ADD_FM<0, 0x21>; -def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, IIArith, sub>, +def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, ADD_FM<0, 0x23>; let Defs = [HI0, LO0] in -def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, IIImul, mul>, - ADD_FM<0x1c, 2>; +def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, + ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6; def ADD : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>; def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>; def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>; -def AND : MMRel, ArithLogicR<"and", GPR32Opnd, 1, IILogic, and>, +def AND : MMRel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>; -def OR : MMRel, ArithLogicR<"or", GPR32Opnd, 1, IILogic, or>, +def OR : MMRel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; -def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, IILogic, xor>, +def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; def NOR : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; /// Shift Instructions -def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, shl, immZExt5>, - SRA_FM<0, 0>; -def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, srl, immZExt5>, - SRA_FM<2, 0>; -def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, sra, immZExt5>, - SRA_FM<3, 0>; -def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, shl>, SRLV_FM<4, 0>; -def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, srl>, SRLV_FM<6, 0>; -def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, sra>, SRLV_FM<7, 0>; +def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl, + immZExt5>, SRA_FM<0, 0>; +def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl, + immZExt5>, SRA_FM<2, 0>; +def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra, + immZExt5>, SRA_FM<3, 0>; +def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>, + SRLV_FM<4, 0>; +def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>, + SRLV_FM<6, 0>; +def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>, + SRLV_FM<7, 0>; // Rotate Instructions -let Predicates = [HasMips32r2, HasStdEnc] in { - def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, rotr, - immZExt5>, - SRA_FM<2, 1>; - def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, rotr>, - SRLV_FM<6, 1>; -} +def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr, + immZExt5>, + SRA_FM<2, 1>, ISA_MIPS32R2; +def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>, + SRLV_FM<6, 1>, ISA_MIPS32R2; /// Load and Store Instructions /// aligned -def LB : Load<"lb", GPR32Opnd, sextloadi8, IILoad>, MMRel, LW_FM<0x20>; -def LBu : Load<"lbu", GPR32Opnd, zextloadi8, IILoad, addrDefault>, MMRel, +def LB : Load<"lb", GPR32Opnd, sextloadi8, II_LB>, MMRel, LW_FM<0x20>; +def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel, LW_FM<0x24>; -def LH : Load<"lh", GPR32Opnd, sextloadi16, IILoad, addrDefault>, MMRel, +def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel, LW_FM<0x21>; -def LHu : Load<"lhu", GPR32Opnd, zextloadi16, IILoad>, MMRel, LW_FM<0x25>; -def LW : Load<"lw", GPR32Opnd, load, IILoad, addrDefault>, MMRel, +def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; +def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, LW_FM<0x23>; -def SB : Store<"sb", GPR32Opnd, truncstorei8, IIStore>, MMRel, LW_FM<0x28>; -def SH : Store<"sh", GPR32Opnd, truncstorei16, IIStore>, MMRel, LW_FM<0x29>; -def SW : Store<"sw", GPR32Opnd, store, IIStore>, MMRel, LW_FM<0x2b>; +def SB : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>; +def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; +def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>; /// load/store left/right -let Predicates = [NotInMicroMips] in { -def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, IILoad>, LW_FM<0x22>; -def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, IILoad>, LW_FM<0x26>; -def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, IIStore>, LW_FM<0x2a>; -def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, IIStore>, LW_FM<0x2e>; -} - -def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM; -def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>; -def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>; -def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>; -def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>; -def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>; -def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>; - -def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>; -def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>; -def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>; -def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>; -def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>; -def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>; +let EncodingPredicates = [], // FIXME: Lack of HasStdEnc is probably a bug + AdditionalPredicates = [NotInMicroMips] in { +def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>, + ISA_MIPS1_NOT_32R6_64R6; +def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>, + ISA_MIPS1_NOT_32R6_64R6; +def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>, + ISA_MIPS1_NOT_32R6_64R6; +def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, + ISA_MIPS1_NOT_32R6_64R6; +} + +def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; + +def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>, ISA_MIPS2; +def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>, ISA_MIPS2; +def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>, ISA_MIPS2; +def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>, ISA_MIPS2; +def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>, ISA_MIPS2; +def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>, ISA_MIPS2; + +def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>, + ISA_MIPS2_NOT_32R6_64R6; +def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>, + ISA_MIPS2_NOT_32R6_64R6; +def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>, + ISA_MIPS2_NOT_32R6_64R6; +def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>, + ISA_MIPS2_NOT_32R6_64R6; +def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>, + ISA_MIPS2_NOT_32R6_64R6; +def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>, + ISA_MIPS2_NOT_32R6_64R6; def BREAK : MMRel, BRK_FT<"break">, BRK_FM<0xd>; def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>; def TRAP : TrapBase; +def SDBBP : SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; -def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18>; -def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f>; +def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18>, INSN_MIPS3_32; +def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f>, ISA_MIPS32; -def EI : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>; -def DI : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>; +def EI : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>, ISA_MIPS32R2; +def DI : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>, ISA_MIPS32R2; -def WAIT : MMRel, WAIT_FT<"wait">, WAIT_FM; +let EncodingPredicates = [], // FIXME: Lack of HasStdEnc is probably a bug + AdditionalPredicates = [NotInMicroMips] in { +def WAIT : WAIT_FT<"wait">, WAIT_FM; /// Load-linked, Store-conditional -let Predicates = [NotInMicroMips] in { -def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>; -def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>; +def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6; +def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6; } /// Jump and Branch Instructions def J : MMRel, JumpFJ, FJ<2>, - Requires<[RelocStatic, HasStdEnc]>, IsBranch; + AdditionalRequires<[RelocStatic]>, IsBranch; def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>; def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>; def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>; @@ -1030,15 +1206,50 @@ def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>, def B : UncondBranch; def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>; -def JALR : MMRel, JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM; -def JALRPseudo : JumpLinkRegPseudo; -def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>; -def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>; +let AdditionalPredicates = [NotInMicroMips] in { + def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM; + def JALRPseudo : JumpLinkRegPseudo; +} + +// FIXME: JALX really requires either MIPS16 or microMIPS in addition to MIPS32. +def JALX : JumpLink<"jalx", calltarget>, FJ<0x1D>, ISA_MIPS32_NOT_32R6_64R6; +def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, + ISA_MIPS1_NOT_32R6_64R6; +def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>, + ISA_MIPS1_NOT_32R6_64R6; def BAL_BR : BAL_BR_Pseudo; def TAILCALL : TailCall; def TAILCALL_R : TailCallReg; -def RET : MMRel, RetBase<"ret", GPR32Opnd>, MTLO_FM<8>; +// Indirect branches are matched as PseudoIndirectBranch/PseudoIndirectBranch64 +// then are expanded to JR, JR64, JALR, or JALR64 depending on the ISA. +class PseudoIndirectBranchBase : + MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)], IIBranch> { + let isTerminator=1; + let isBarrier=1; + let hasDelaySlot = 1; + let isBranch = 1; + let isIndirectBranch = 1; +} + +def PseudoIndirectBranch : PseudoIndirectBranchBase; + +// Return instructions are matched as a RetRA instruction, then ar expanded +// into PseudoReturn/PseudoReturn64 after register allocation. Finally, +// MipsAsmPrinter expands this into JR, JR64, JALR, or JALR64 depending on the +// ISA. +class PseudoReturnBase : MipsPseudo<(outs), (ins RO:$rs), + [], IIBranch> { + let isTerminator = 1; + let isBarrier = 1; + let hasDelaySlot = 1; + let isReturn = 1; + let isCodeGenOnly = 1; + let hasCtrlDep = 1; + let hasExtraSrcRegAllocReq = 1; +} + +def PseudoReturn : PseudoReturnBase; // Exception handling related node and instructions. // The conversion sequence is: @@ -1062,30 +1273,41 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { } /// Multiply and Divide Instructions. -def MULT : MMRel, Mult<"mult", IIImult, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x18>; -def MULTu : MMRel, Mult<"multu", IIImult, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x19>; -def SDIV : MMRel, Div<"div", IIIdiv, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1a>; -def UDIV : MMRel, Div<"divu", IIIdiv, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1b>; - -def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>; -def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>; -def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>; -def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>; +def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6; +def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6; +def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6; +def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6; + +def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>, + ISA_MIPS1_NOT_32R6_64R6; +def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>, + ISA_MIPS1_NOT_32R6_64R6; +let EncodingPredicates = [], // FIXME: Lack of HasStdEnc is probably a bug + AdditionalPredicates = [NotInMicroMips] in { +def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>, + ISA_MIPS1_NOT_32R6_64R6; +def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>, + ISA_MIPS1_NOT_32R6_64R6; +} /// Sign Ext In Register Instructions. -def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd>, SEB_FM<0x10, 0x20>; -def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd>, SEB_FM<0x18, 0x20>; +def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, + SEB_FM<0x10, 0x20>, ISA_MIPS32R2; +def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, + SEB_FM<0x18, 0x20>, ISA_MIPS32R2; /// Count Leading -def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>; -def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>; +def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>, + ISA_MIPS32_NOT_32R6_64R6; +def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>, + ISA_MIPS32_NOT_32R6_64R6; /// Word Swap Bytes Within Halfwords -def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>; +def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>, ISA_MIPS32R2; /// No operation. def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; @@ -1094,30 +1316,40 @@ def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; // instructions. The same not happens for stack address copies, so an // add op with mem ComplexPattern is used and the stack address copy // can be matched. It's similar to Sparc LEA_ADDRi -def LEA_ADDiu : EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; +def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; // MADD*/MSUB* -def MADD : MMRel, MArithR<"madd", 1>, MULT_FM<0x1c, 0>; -def MADDU : MMRel, MArithR<"maddu", 1>, MULT_FM<0x1c, 1>; -def MSUB : MMRel, MArithR<"msub">, MULT_FM<0x1c, 4>; -def MSUBU : MMRel, MArithR<"msubu">, MULT_FM<0x1c, 5>; - -let Predicates = [HasStdEnc, NotDSP] in { -def PseudoMULT : MultDivPseudo; -def PseudoMULTu : MultDivPseudo; -def PseudoMFHI : PseudoMFLOHI; -def PseudoMFLO : PseudoMFLOHI; -def PseudoMTLOHI : PseudoMTLOHI; -def PseudoMADD : MAddSubPseudo; -def PseudoMADDU : MAddSubPseudo; -def PseudoMSUB : MAddSubPseudo; -def PseudoMSUBU : MAddSubPseudo; -} - -def PseudoSDIV : MultDivPseudo; -def PseudoUDIV : MultDivPseudo; +def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, + ISA_MIPS32_NOT_32R6_64R6; +def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, + ISA_MIPS32_NOT_32R6_64R6; +def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, + ISA_MIPS32_NOT_32R6_64R6; +def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, + ISA_MIPS32_NOT_32R6_64R6; + +let AdditionalPredicates = [NotDSP] in { +def PseudoMULT : MultDivPseudo, + ISA_MIPS1_NOT_32R6_64R6; +def PseudoMULTu : MultDivPseudo, + ISA_MIPS1_NOT_32R6_64R6; +def PseudoMFHI : PseudoMFLOHI, ISA_MIPS1_NOT_32R6_64R6; +def PseudoMFLO : PseudoMFLOHI, ISA_MIPS1_NOT_32R6_64R6; +def PseudoMTLOHI : PseudoMTLOHI, ISA_MIPS1_NOT_32R6_64R6; +def PseudoMADD : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +def PseudoMADDU : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +def PseudoMSUB : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +def PseudoMSUBU : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +} + +def PseudoSDIV : MultDivPseudo, ISA_MIPS1_NOT_32R6_64R6; +def PseudoUDIV : MultDivPseudo, ISA_MIPS1_NOT_32R6_64R6; def RDHWR : ReadHardware, RDHWR_FM; @@ -1125,68 +1357,166 @@ def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>, EXT_FM<0>; def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>; /// Move Control Registers From/To CPU Registers -def MFC0 : MFC3OP<"mfc0", GPR32Opnd>, MFC3OP_FM<0x10, 0>; -def MTC0 : MFC3OP<"mtc0", GPR32Opnd>, MFC3OP_FM<0x10, 4>; +def MFC0 : MFC3OP<"mfc0", GPR32Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32; +def MTC0 : MFC3OP<"mtc0", GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32; def MFC2 : MFC3OP<"mfc2", GPR32Opnd>, MFC3OP_FM<0x12, 0>; def MTC2 : MFC3OP<"mtc2", GPR32Opnd>, MFC3OP_FM<0x12, 4>; +class Barrier : InstSE<(outs), (ins), asmstr, [], NoItinerary, + FrmOther>; +def SSNOP : Barrier<"ssnop">, BARRIER_FM<1>; +def EHB : Barrier<"ehb">, BARRIER_FM<3>; +def PAUSE : Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; + +// JR_HB and JALR_HB are defined here using the new style naming +// scheme because some of this code is shared with Mips32r6InstrInfo.td +// and because of that it doesn't follow the naming convention of the +// rest of the file. To avoid a mixture of old vs new style, the new +// style was chosen. +class JR_HB_DESC_BASE { + dag OutOperandList = (outs); + dag InOperandList = (ins GPROpnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rs"); + list Pattern = []; +} + +class JALR_HB_DESC_BASE { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); + list Pattern = []; +} + +class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, + JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { + let isBranch=1; + let isIndirectBranch=1; + let hasDelaySlot=1; + let isTerminator=1; + let isBarrier=1; +} + +class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, + JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> { + let isIndirectBranch=1; + let hasDelaySlot=1; +} + +class JR_HB_ENC : JR_HB_FM<8>; +class JALR_HB_ENC : JALR_HB_FM<9>; + +def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; +def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32; + +class TLB : InstSE<(outs), (ins), asmstr, [], NoItinerary, + FrmOther>; +def TLBP : TLB<"tlbp">, COP0_TLB_FM<0x08>; +def TLBR : TLB<"tlbr">, COP0_TLB_FM<0x01>; +def TLBWI : TLB<"tlbwi">, COP0_TLB_FM<0x02>; +def TLBWR : TLB<"tlbwr">, COP0_TLB_FM<0x06>; + +class CacheOp : + InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), + !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther>; + +def CACHE : CacheOp<"cache", mem, GPR32Opnd>, CACHEOP_FM<0b101111>, + INSN_MIPS3_32_NOT_32R6_64R6; +def PREF : CacheOp<"pref", mem, GPR32Opnd>, CACHEOP_FM<0b110011>, + INSN_MIPS3_32_NOT_32R6_64R6; + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// -def : InstAlias<"move $dst, $src", - (ADDu GPR32Opnd:$dst, GPR32Opnd:$src,ZERO), 1>, - Requires<[NotMips64]>; -def : InstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>; -def : InstAlias<"addu $rs, $rt, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -def : InstAlias<"add $rs, $rt, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -def : InstAlias<"and $rs, $rt, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -def : InstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; -def : InstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; -def : InstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>; -def : InstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; -def : InstAlias<"not $rt, $rs", - (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; -def : InstAlias<"neg $rt, $rs", - (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; -def : InstAlias<"negu $rt, $rs", - (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; -def : InstAlias<"slt $rs, $rt, $imm", - (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -def : InstAlias<"xor $rs, $rt, $imm", - (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; -def : InstAlias<"or $rs, $rt, $imm", - (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; -def : InstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; -def : InstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; -def : InstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; -def : InstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; -def : InstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; -def : InstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; -def : InstAlias<"bnez $rs,$offset", - (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; -def : InstAlias<"beqz $rs,$offset", - (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; -def : InstAlias<"syscall", (SYSCALL 0), 1>; - -def : InstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; -def : InstAlias<"break", (BREAK 0, 0), 1>; -def : InstAlias<"ei", (EI ZERO), 1>; -def : InstAlias<"di", (DI ZERO), 1>; - -def : InstAlias<"teq $rs, $rt", (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : InstAlias<"tge $rs, $rt", (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : InstAlias<"tgeu $rs, $rt", (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : InstAlias<"tlt $rs, $rt", (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : InstAlias<"tltu $rs, $rt", (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : InstAlias<"tne $rs, $rt", (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : InstAlias<"sub, $rd, $rs, $imm", - (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, InvertedImOperand:$imm)>; -def : InstAlias<"subu, $rd, $rs, $imm", - (ADDiu GPR32Opnd:$rd, GPR32Opnd:$rs, InvertedImOperand:$imm)>; - +def : MipsInstAlias<"move $dst, $src", + (ADDu GPR32Opnd:$dst, GPR32Opnd:$src,ZERO), 1>, + GPR_32 { + let AdditionalPredicates = [NotInMicroMips]; +} +def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"addu $rs, $rt, $imm", + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; +def : MipsInstAlias<"add $rs, $rt, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; +def : MipsInstAlias<"and $rs, $rt, $imm", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; +def : MipsInstAlias<"and $rs, $imm", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; +def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; +let Predicates = [NotInMicroMips] in { +def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; +} +def : MipsInstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32; +def : MipsInstAlias<"not $rt, $rs", + (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; +def : MipsInstAlias<"neg $rt, $rs", + (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; +def : MipsInstAlias<"negu $rt", + (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 0>; +def : MipsInstAlias<"negu $rt, $rs", + (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; +def : MipsInstAlias<"slt $rs, $rt, $imm", + (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; +def : MipsInstAlias<"sltu $rt, $rs, $imm", + (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm16:$imm), 0>; +def : MipsInstAlias<"xor $rs, $rt, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; +def : MipsInstAlias<"or $rs, $rt, $imm", + (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; +def : MipsInstAlias<"or $rs, $imm", + (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; +def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; +def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; +def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"bnez $rs,$offset", + (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"beqz $rs,$offset", + (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; + +def : MipsInstAlias<"break", (BREAK 0, 0), 1>; +def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; +def : MipsInstAlias<"ei", (EI ZERO), 1>; +def : MipsInstAlias<"di", (DI ZERO), 1>; + +def : MipsInstAlias<"teq $rs, $rt", + (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tge $rs, $rt", + (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tgeu $rs, $rt", + (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tlt $rs, $rt", + (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tltu $rs, $rt", + (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tne $rs, $rt", + (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; + +def : MipsInstAlias<"sll $rd, $rt, $rs", + (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"sub, $rd, $rs, $imm", + (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, + InvertedImOperand:$imm), 0>; +def : MipsInstAlias<"sub $rs, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm), + 0>; +def : MipsInstAlias<"subu, $rd, $rs, $imm", + (ADDiu GPR32Opnd:$rd, GPR32Opnd:$rs, + InvertedImOperand:$imm), 0>; +def : MipsInstAlias<"subu $rs, $imm", (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, + InvertedImOperand:$imm), 0>; +def : MipsInstAlias<"sra $rd, $rt, $rs", + (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"srl $rd, $rt, $rs", + (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6; +def : MipsInstAlias<"sync", + (SYNC 0), 1>, ISA_MIPS2; //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// @@ -1232,13 +1562,17 @@ def : MipsPat<(i32 imm:$imm), // Carry MipsPatterns def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), (SUBu GPR32:$lhs, GPR32:$rhs)>; -let Predicates = [HasStdEnc, NotDSP] in { +let AdditionalPredicates = [NotDSP] in { def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs), (ADDu GPR32:$lhs, GPR32:$rhs)>; def : MipsPat<(addc GPR32:$src, immSExt16:$imm), (ADDiu GPR32:$src, imm:$imm)>; } +// SYNC +def : MipsPat<(MipsSync (i32 immz)), + (SYNC 0)>, ISA_MIPS2; + // Call def : MipsPat<(MipsJmpLink (i32 tglobaladdr:$dst)), (JAL tglobaladdr:$dst)>; @@ -1301,14 +1635,11 @@ def : MipsPat<(not GPR32:$in), (NOR GPR32Opnd:$in, ZERO)>; // extended loads -let Predicates = [HasStdEnc] in { - def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; - def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; - def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; -} +def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; +def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; +def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; // peepholes -let Predicates = [HasStdEnc] in def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; // brcond patterns @@ -1402,11 +1733,9 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; // Load halfword/word patterns. let AddedComplexity = 40 in { - let Predicates = [HasStdEnc] in { - def : LoadRegImmPat; - def : LoadRegImmPat; - def : LoadRegImmPat; - } + def : LoadRegImmPat; + def : LoadRegImmPat; + def : LoadRegImmPat; } //===----------------------------------------------------------------------===// @@ -1417,6 +1746,9 @@ include "MipsInstrFPU.td" include "Mips64InstrInfo.td" include "MipsCondMov.td" +include "Mips32r6InstrInfo.td" +include "Mips64r6InstrInfo.td" + // // Mips16 @@ -1434,3 +1766,4 @@ include "MipsMSAInstrInfo.td" // Micromips include "MicroMipsInstrFormats.td" include "MicroMipsInstrInfo.td" +include "MicroMipsInstrFPU.td"