X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsInstrInfo.td;h=6d83cceab4037562b263c58d401e68a033b98042;hb=35e39f0c8aff5bde9b4083377f0ec906578e3b46;hp=e3dfc5eb26b9d1653ca01454ba65c358fbd94ac2;hpb=61a2eb1df5864a129ae2f64538dba6dda8d9db2b;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index e3dfc5eb26b..6d83cceab40 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -77,6 +77,9 @@ def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; def MipsRet : SDNode<"MipsISD::Ret", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def MipsERet : SDNode<"MipsISD::ERet", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPSideEffect]>; + // These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, [SDNPHasChain, SDNPSideEffect, SDNPOutGlue]>; @@ -146,52 +149,199 @@ 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 NotMips4_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 HasMips32r5 : Predicate<"Subtarget->hasMips32r5()">, + AssemblerPredicate<"FeatureMips32r5">; +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()">, +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()">, - AssemblerPredicate<"FeatureN64">; -def NotN64 : Predicate<"!Subtarget.isABI_N64()">, - AssemblerPredicate<"!FeatureN64">; -def InMips16Mode : Predicate<"Subtarget.inMips16Mode()">, +def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">, + AssemblerPredicate<"FeatureMips64r6">; +def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">, + AssemblerPredicate<"!FeatureMips64r6">; +def HasMicroMips32r6 : Predicate<"Subtarget->inMicroMips32r6Mode()">, + AssemblerPredicate<"FeatureMicroMips,FeatureMips32r6">; +def HasMicroMips64r6 : Predicate<"Subtarget->inMicroMips64r6Mode()">, + AssemblerPredicate<"FeatureMicroMips,FeatureMips64r6">; +def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; -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 HasCnMips : Predicate<"Subtarget->hasCnMips()">, + AssemblerPredicate<"FeatureCnMips">; +def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; +def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">; +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()">; +def UseTCCInDIV : AssemblerPredicate<"FeatureUseTCCInDIV">; +def HasEVA : Predicate<"Subtarget->hasEVA()">, + AssemblerPredicate<"FeatureEVA,FeatureMips32r2">; +def HasMSA : Predicate<"Subtarget->hasMSA()">, + AssemblerPredicate<"FeatureMSA">; + + +//===----------------------------------------------------------------------===// +// 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. +//===----------------------------------------------------------------------===// + +// 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_4_32 { + list InsnPredicates = [NotMips4_32]; +} +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_MIPS32R5 { list InsnPredicates = [HasMips32r5]; } +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]; } +class ISA_MICROMIPS { list InsnPredicates = [InMicroMips]; } +class ISA_MICROMIPS32R6 { + list InsnPredicates = [HasMicroMips32r6]; +} +class ISA_MICROMIPS64R6 { + list InsnPredicates = [HasMicroMips64r6]; +} +class ISA_MICROMIPS32_NOT_MIPS32R6 { + list InsnPredicates = [InMicroMips, NotMips32r6]; +} + +class INSN_EVA { list InsnPredicates = [HasEVA]; } +class INSN_EVA_NOT_32R6_64R6 { + list InsnPredicates = [NotMips32r6, NotMips64r6, HasEVA]; +} + +// The portions of MIPS-III that were also added to MIPS32 +class INSN_MIPS3_32 { list InsnPredicates = [HasMips3_32]; } -class MipsPat : Pat { - let Predicates = [HasStdEnc]; +// 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 ASE_CNMIPS { + list InsnPredicates = [HasCnMips]; +} + +class ASE_MSA { + list InsnPredicates = [HasMSA]; +} + +class ASE_MSA_NOT_MSA64 { + list InsnPredicates = [HasMSA, NotMips64]; +} + +class ASE_MSA64 { + list InsnPredicates = [HasMSA, HasMips64]; +} + +// Class used for separating microMIPSr6 and microMIPS (r3) instruction. +// It can be used only on instructions that doesn't inherit PredicateControl. +class ISA_MICROMIPS_NOT_32R6_64R6 : PredicateControl { + let InsnPredicates = [InMicroMips, NotMips32r6, NotMips64r6]; +} + +//===----------------------------------------------------------------------===// + +class MipsPat : Pat, PredicateControl { + let EncodingPredicates = [HasStdEnc]; +} + +class MipsInstAlias : + InstAlias, PredicateControl; + class IsCommutable { bit isCommutable = 1; } @@ -222,7 +372,7 @@ class IsAsCheapAsAMove { } class NeverHasSideEffects { - bit neverHasSideEffects = 1; + bit hasSideEffects = 0; } //===----------------------------------------------------------------------===// @@ -235,43 +385,190 @@ include "MipsInstrFormats.td" // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// +class ConstantSImmAsmOperandClass Supers = []> + : AsmOperandClass { + let Name = "ConstantSImm" # Bits; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isConstantSImm<" # Bits # ">"; + let SuperClasses = Supers; + let DiagnosticType = "SImm" # Bits; +} + +class ConstantUImmAsmOperandClass Supers = [], + int Offset = 0> : AsmOperandClass { + let Name = "ConstantUImm" # Bits # "_" # Offset; + let RenderMethod = "addConstantUImmOperands<" # Bits # ", " # Offset # ">"; + let PredicateMethod = "isConstantUImm<" # Bits # ", " # Offset # ">"; + let SuperClasses = Supers; + let DiagnosticType = "UImm" # Bits # "_" # Offset; +} + +def ConstantUImm10AsmOperandClass + : ConstantUImmAsmOperandClass<10, []>; +def ConstantUImm8AsmOperandClass + : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>; +def ConstantUImm7AsmOperandClass + : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>; +def ConstantUImm6AsmOperandClass + : ConstantUImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>; +def ConstantSImm6AsmOperandClass + : ConstantSImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>; +def ConstantUImm5Plus32AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32>; +def ConstantUImm5Plus32NormalizeAsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32> { + let Name = "ConstantUImm5_32_Norm"; + // We must also subtract 32 when we render the operand. + let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; +} +def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { + let Name = "UImm5Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledUImm<5, 2>"; + let SuperClasses = [ConstantUImm6AsmOperandClass]; + let DiagnosticType = "UImm5_Lsl2"; +} +def ConstantUImm5ReportUImm6AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]> { + let Name = "ConstantUImm5_0_Report_UImm6"; + let DiagnosticType = "UImm5_0_Report_UImm6"; +} +def ConstantUImm5AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]>; +def ConstantUImm4AsmOperandClass + : ConstantUImmAsmOperandClass< + 4, [ConstantUImm5AsmOperandClass, + ConstantUImm5Plus32AsmOperandClass, + ConstantUImm5Plus32NormalizeAsmOperandClass]>; +def ConstantUImm3AsmOperandClass + : ConstantUImmAsmOperandClass<3, [ConstantUImm4AsmOperandClass]>; +def ConstantUImm2Plus1AsmOperandClass + : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass], 1>; +def ConstantUImm2AsmOperandClass + : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass]>; +def ConstantUImm1AsmOperandClass + : ConstantUImmAsmOperandClass<1, [ConstantUImm2AsmOperandClass]>; +def ConstantImmzAsmOperandClass : AsmOperandClass { + let Name = "ConstantImmz"; + let RenderMethod = "addConstantUImmOperands<1>"; + let PredicateMethod = "isConstantImmz"; + let SuperClasses = [ConstantUImm1AsmOperandClass]; + let DiagnosticType = "Immz"; +} + +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 imm64: Operand; + +def simm6 : Operand { + let ParserMatchClass = ConstantSImm6AsmOperandClass; + let OperandType = "OPERAND_IMMEDIATE"; +} +def simm9 : Operand; +def simm10 : Operand; +def simm11 : Operand; + def simm16 : Operand { let DecoderMethod= "DecodeSimm16"; } -def simm20 : Operand { +def simm19_lsl2 : Operand { + let EncoderMethod = "getSimm19Lsl2Encoding"; + let DecoderMethod = "DecodeSimm19Lsl2"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } -def uimm20 : Operand { +def simm18_lsl3 : Operand { + let EncoderMethod = "getSimm18Lsl3Encoding"; + let DecoderMethod = "DecodeSimm18Lsl3"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } -def uimm10 : Operand { +def simm20 : Operand; +def simm32 : Operand; + +def uimm20 : Operand { } def simm16_64 : Operand { let DecoderMethod = "DecodeSimm16"; } -// Unsigned Operand -def uimm5 : Operand { +// Zero +def uimmz : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantImmzAsmOperandClass; +} + +// Unsigned Operands +foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10} in + def uimm # I : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = + !cast("ConstantUImm" # I # "AsmOperandClass"); + } + +def uimm2_plus1 : Operand { let PrintMethod = "printUnsignedImm"; + let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>"; + let DecoderMethod = "DecodeUImmWithOffset<2, 1>"; + let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; } -def uimm6 : Operand { +def uimm5_plus32 : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5Plus32AsmOperandClass; +} + +def uimm5_plus32_normalize : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; +} + +def uimm5_lsl2 : Operand { + let EncoderMethod = "getUImm5Lsl2Encoding"; + let DecoderMethod = "DecodeUImm5lsl2"; + let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass; +} + +def uimm5_plus32_normalize_64 : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; +} + +foreach I = {5} in + def uimm # I # _64 : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = + !cast("ConstantUImm" # I # "AsmOperandClass"); + } + +// Like uimm5_64 but reports a less confusing error for 32-63 when +// an instruction alias permits that. +def uimm5_64_report_uimm6 : Operand { let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass; } def uimm16 : Operand { @@ -286,19 +583,49 @@ def MipsMemAsmOperand : AsmOperandClass { let ParserMethod = "parseMemOperand"; } +def MipsMemSimm9AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm9"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<9>"; +} + +def MipsMemSimm9GPRAsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm9GPR"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffsetGPR<9>"; +} + +def MipsMemSimm11AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm11"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<11>"; +} + +def MipsMemSimm16AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm16"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<16>"; +} + 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 +642,34 @@ 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"; + let ParserMatchClass = MipsMemSimm9AsmOperand; +} + +def mem_simm9gpr : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm9); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm9GPRAsmOperand; +} + +def mem_simm11 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm11); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm11AsmOperand; +} + +def mem_simm16 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm16); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm16AsmOperand; +} + def mem_ea : Operand { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -328,7 +680,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 +708,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 +762,8 @@ def addrRegReg : def addrDefault : ComplexPattern; +def addrimm10 : ComplexPattern; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -420,6 +777,7 @@ class ArithLogicR { let isCommutable = isComm; let isReMaterializable = 1; + let TwoOperandAliasConstraint = "$rd = $rs"; } // Arithmetic and logical instructions with 2 register operands. @@ -459,7 +817,9 @@ 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))], itin, FrmR, opstr>; + [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], itin, FrmR, opstr> { + let TwoOperandAliasConstraint = "$rt = $rd"; +} class shift_rotate_reg: @@ -468,11 +828,11 @@ class shift_rotate_reg; -// Load Upper Imediate +// Load Upper Immediate class LoadUpper: InstSE<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), [], II_LUI, FrmI, opstr>, IsAsCheapAsAMove { - let neverHasSideEffects = 1; + let hasSideEffects = 0; let isReMaterializable = 1; } @@ -486,14 +846,19 @@ class Load : - InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + InstSE<(outs), (ins RO:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RO:$rt, Addr:$addr)], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let mayStore = 1; } +class Store : + StoreMemory; + // Load/Store Left/Right let canFoldAsLoad = 1 in class LoadLeftRight : + InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem2"; + let mayLoad = 1; +} + +class SW_FT2 : + InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem2"; + let mayStore = 1; +} + +// COP3 Load/Store +class LW_FT3 : + InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem3"; + let mayLoad = 1; +} + +class SW_FT3 : + InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem3"; + let mayStore = 1; +} + // Conditional Branch class CBranch : + RegisterOperand RO, bit DelaySlot = 1> : InstSE<(outs), (ins RO:$rs, RO:$rt, opnd:$offset), !strconcat(opstr, "\t$rs, $rt, $offset"), - [(brcond (i32 (cond_op RO:$rs, RO:$rt)), bb:$offset)], IIBranch, + [(brcond (i32 (cond_op RO:$rs, RO:$rt)), bb:$offset)], II_BCC, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; } class CBranchZero : + RegisterOperand RO, bit DelaySlot = 1> : InstSE<(outs), (ins RO:$rs, opnd:$offset), !strconcat(opstr, "\t$rs, $offset"), - [(brcond (i32 (cond_op RO:$rs, 0)), bb:$offset)], IIBranch, + [(brcond (i32 (cond_op RO:$rs, 0)), bb:$offset)], II_BCCZ, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; } @@ -542,20 +941,20 @@ 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 : InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), - [(operator targetoperator:$target)], IIBranch, FrmJ, bopstr> { + [(operator targetoperator:$target)], II_J, FrmJ, bopstr> { let isTerminator=1; let isBarrier=1; let hasDelaySlot = 1; @@ -565,13 +964,13 @@ class JumpFJ : - PseudoSE<(outs), (ins brtarget:$offset), [(br bb:$offset)], IIBranch>, + PseudoSE<(outs), (ins brtarget:$offset), [(br bb:$offset)], II_B>, PseudoInstExpansion<(BEQInst ZERO, ZERO, brtarget:$offset)> { let isBranch = 1; let isTerminator = 1; let isBarrier = 1; let hasDelaySlot = 1; - let Predicates = [RelocPIC, HasStdEnc]; + let AdditionalPredicates = [RelocPIC]; let Defs = [AT]; } @@ -579,61 +978,55 @@ class UncondBranch : let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in class JumpFR: - InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch, + InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR, FrmR, opstr>; // 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 : InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), - [(MipsJmpLink imm:$target)], IIBranch, FrmJ, opstr> { + [(MipsJmpLink imm:$target)], II_JAL, FrmJ, opstr> { let DecoderMethod = "DecodeJumpTarget"; } class JumpLinkRegPseudo: - PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], IIBranch>, + PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>, PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>; class JumpLinkReg: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], IIBranch, FrmR, opstr>; + [], II_JALR, FrmR, opstr>; - class BGEZAL_FT : + class BGEZAL_FT : InstSE<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr>; + !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZAL, FrmI, opstr> { + let hasDelaySlot = DelaySlot; + } } let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, hasExtraSrcRegAllocReq = 1, Defs = [AT] in { class TailCall : - PseudoSE<(outs), (ins calltarget:$target), [], IIBranch>, + PseudoSE<(outs), (ins calltarget:$target), [], II_J>, PseudoInstExpansion<(JumpInst jmptarget:$target)>; class TailCallReg : - PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], IIBranch>, + PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, PseudoInstExpansion<(JRInst ResRO:$rs)>; } class BAL_BR_Pseudo : - PseudoSE<(outs), (ins brtarget:$offset), [], IIBranch>, + PseudoSE<(outs), (ins brtarget:$offset), [], II_BCCZAL>, PseudoInstExpansion<(RealInst ZERO, brtarget:$offset)> { let isBranch = 1; let isTerminator = 1; @@ -672,6 +1065,13 @@ class SYNC_FT : InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)], NoItinerary, FrmOther, opstr>; +class SYNCI_FT : + InstSE<(outs), (ins mem_simm16:$addr), !strconcat(opstr, "\t$addr"), [], + NoItinerary, FrmOther, opstr> { + let hasSideEffects = 1; + let DecoderMethod = "DecodeSyncI"; +} + let hasSideEffects = 1 in class TEQ_FT : InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_), @@ -688,7 +1088,7 @@ class Mult { let isCommutable = 1; let Defs = DefRegs; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } // Pseudo multiply/divide instruction with explicit accumulator register @@ -734,7 +1134,7 @@ class MoveFromLOHI: InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], II_MFHI_MFLO, FrmR, opstr> { let Uses = [UseReg]; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } class PseudoMTLOHI @@ -746,7 +1146,7 @@ class MoveToLOHI DefRegs>: InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], II_MTHI_MTLO, FrmR, opstr> { let Defs = DefRegs; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } class EffectiveAddress : @@ -760,53 +1160,45 @@ 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))], II_CLZ, 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)))], II_CLO, FrmR, opstr>, - Requires<[HasBitCount, HasStdEnc]>; - + [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>; // Sign Extend in Register. class SignExtInReg : InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), - [(set RO:$rd, (sext_inreg RO:$rt, vt))], itin, 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; +class SubwordSwap: + InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [], itin, + FrmR, opstr> { + let hasSideEffects = 0; } // Read Hardware class ReadHardware : InstSE<(outs CPURegOperand:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [], - II_RDHWR, FrmR>; + II_RDHWR, FrmR, "rdhwr">; // Ext and Ins class ExtBase: InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ext:$size), !strconcat(opstr, " $rt, $rs, $pos, $size"), - [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], NoItinerary, - FrmR, opstr> { - let Predicates = [HasMips32r2, HasStdEnc]; -} + [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], II_EXT, + 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]; + II_INS, FrmR, opstr>, ISA_MIPS32R2 { let Constraints = "$src = $rt"; } @@ -835,8 +1227,12 @@ class SCBase : let Constraints = "$rt = $dst"; } -class MFC3OP : - InstSE<(outs RO:$rt, RO:$rd, uimm16:$sel), (ins), +class MFC3OP : + InstSE<(outs RO:$rt), (ins RD:$rd, uimm16:$sel), + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; + +class MTC3OP : + InstSE<(outs RO:$rd), (ins RD:$rt, uimm16:$sel), !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; class TrapBase @@ -855,6 +1251,9 @@ class TrapBase let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; +let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, hasSideEffects=1 in +def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; + let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt), [(callseq_start timm:$amt)]>; @@ -897,6 +1296,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 //===----------------------------------------------------------------------===// @@ -905,50 +1316,60 @@ let isPseudo = 1, isCodeGenOnly = 1 in { //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) -def ADDiu : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, - add>, +let AdditionalPredicates = [NotInMicroMips] in { +def ADDiu : MMRel, StdMMR6Rel, 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, II_ANDI, immZExt16, - and>, +let AdditionalPredicates = [NotInMicroMips] in { +def ANDi : MMRel, StdMMR6Rel, + ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, ADDI_FM<0xc>; -def ORi : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, - or>, +} +def ORi : MMRel, StdMMR6Rel, + ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, ADDI_FM<0xd>; -def XORi : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, - xor>, +def XORi : MMRel, StdMMR6Rel, + ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, ADDI_FM<0xe>; def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM; - +let AdditionalPredicates = [NotInMicroMips] in { /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, +def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, ADD_FM<0, 0x21>; 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, II_MUL, mul>, - ADD_FM<0x1c, 2>; -def ADD : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; + ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6; +def ADD : MMRel, StdMMR6Rel, 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, II_AND, and>, +let AdditionalPredicates = [NotInMicroMips] in { +def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>; -def OR : MMRel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, +def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; -def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, +def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; -def NOR : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; +} +def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; /// Shift Instructions +let AdditionalPredicates = [NotInMicroMips] in { 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>, @@ -959,94 +1380,196 @@ 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, II_ROTR, rotr, - immZExt5>, SRA_FM<2, 1>; - def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, 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>; +let AdditionalPredicates = [NotInMicroMips] in { +def LW : StdMMR6Rel, 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 : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, + LW_FM<0x28>; +def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; +let AdditionalPredicates = [NotInMicroMips] in { +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>; - -def BREAK : MMRel, BRK_FT<"break">, BRK_FM<0xd>; +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; +} + +let AdditionalPredicates = [NotInMicroMips] in { +// COP2 Memory Instructions +def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, + ISA_MIPS1_NOT_32R6_64R6; +def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>, + ISA_MIPS1_NOT_32R6_64R6; +def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>, + ISA_MIPS2_NOT_32R6_64R6; +def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>, + ISA_MIPS2_NOT_32R6_64R6; + +// COP3 Memory Instructions +let DecoderNamespace = "COP3_" in { + def LWC3 : LW_FT3<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>; + def SWC3 : SW_FT3<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>; + def LDC3 : LW_FT3<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, + ISA_MIPS2; + def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, + ISA_MIPS2; +} +} + +def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; +def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; + +let AdditionalPredicates = [NotInMicroMips] in { + 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; + +let AdditionalPredicates = [NotInMicroMips] in { +def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>; +} def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>; def TRAP : TrapBase; +def SDBBP : MMRel, 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>; +let AdditionalPredicates = [NotInMicroMips] in { +def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18, 0x0>, INSN_MIPS3_32; +def ERETNC : MMRel, ER_FT<"eretnc">, ER_FM<0x18, 0x1>, ISA_MIPS32R5; +} +def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f, 0x0>, ISA_MIPS32; -def EI : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>; -def DI : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>; +let AdditionalPredicates = [NotInMicroMips] in { +def EI : MMRel, StdMMR6Rel, 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 BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>, + BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6; def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>; +def BNEL : MMRel, CBranch<"bnel", brtarget, setne, GPR32Opnd, 0>, + BEQ_FM<21>, ISA_MIPS2_NOT_32R6_64R6; def BGEZ : MMRel, CBranchZero<"bgez", brtarget, setge, GPR32Opnd>, BGEZ_FM<1, 1>; +def BGEZL : MMRel, CBranchZero<"bgezl", brtarget, setge, GPR32Opnd, 0>, + BGEZ_FM<1, 3>, ISA_MIPS2_NOT_32R6_64R6; def BGTZ : MMRel, CBranchZero<"bgtz", brtarget, setgt, GPR32Opnd>, BGEZ_FM<7, 0>; +def BGTZL : MMRel, CBranchZero<"bgtzl", brtarget, setgt, GPR32Opnd, 0>, + BGEZ_FM<23, 0>, ISA_MIPS2_NOT_32R6_64R6; def BLEZ : MMRel, CBranchZero<"blez", brtarget, setle, GPR32Opnd>, BGEZ_FM<6, 0>; +def BLEZL : MMRel, CBranchZero<"blezl", brtarget, setle, GPR32Opnd, 0>, + BGEZ_FM<22, 0>, ISA_MIPS2_NOT_32R6_64R6; def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>, BGEZ_FM<1, 0>; +def BLTZL : MMRel, CBranchZero<"bltzl", brtarget, setlt, GPR32Opnd, 0>, + BGEZ_FM<1, 2>, ISA_MIPS2_NOT_32R6_64R6; 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; +} + +def JALX : MMRel, 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 BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd, 0>, + BGEZAL_FM<0x13>, ISA_MIPS2_NOT_32R6_64R6; +def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>, + ISA_MIPS1_NOT_32R6_64R6; +def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd, 0>, + BGEZAL_FM<0x12>, ISA_MIPS2_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)], + II_IndirectBranchPseudo> { + 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 are 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), + [], II_ReturnPseudo> { + 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: @@ -1071,29 +1594,43 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { /// Multiply and Divide Instructions. def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x18>; + MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6; def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x19>; + MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6; def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1a>; + MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6; def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1b>; + MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6; -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 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, II_SEB>, SEB_FM<0x10, 0x20>; -def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, SEB_FM<0x18, 0x20>; +def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, + SEB_FM<0x10, 0x20>, ISA_MIPS32R2; +def SEH : MMRel, StdMMR6Rel, 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>; +let AdditionalPredicates = [NotInMicroMips] in { + /// Word Swap Bytes Within Halfwords + def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, SEB_FM<2, 0x20>, + ISA_MIPS32R2; +} /// No operation. def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; @@ -1105,114 +1642,378 @@ def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; // MADD*/MSUB* -def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>; -def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>; -def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>; -def MSUBU : MMRel, MArithR<"msubu", II_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 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; + 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; def PseudoUDIV : MultDivPseudo; - -def RDHWR : ReadHardware, RDHWR_FM; - + 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { +def RDHWR : MMRel, ReadHardware, RDHWR_FM; +} 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 MFC2 : MFC3OP<"mfc2", GPR32Opnd>, MFC3OP_FM<0x12, 0>; -def MTC2 : MFC3OP<"mtc2", GPR32Opnd>, MFC3OP_FM<0x12, 4>; +def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32; +def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32; +def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd>, MFC3OP_FM<0x12, 0>; +def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd>, MFC3OP_FM<0x12, 4>; + +class Barrier : InstSE<(outs), (ins), asmstr, [], NoItinerary, + FrmOther, asmstr>; +def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop">, BARRIER_FM<1>; +def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>; +def PAUSE : MMRel, StdMMR6Rel, 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, asmstr>; +def TLBP : MMRel, TLB<"tlbp">, COP0_TLB_FM<0x08>; +def TLBR : MMRel, TLB<"tlbr">, COP0_TLB_FM<0x01>; +def TLBWI : MMRel, TLB<"tlbwi">, COP0_TLB_FM<0x02>; +def TLBWR : MMRel, TLB<"tlbwr">, COP0_TLB_FM<0x06>; + +class CacheOp : + InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), + !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther, + instr_asm> { + let DecoderMethod = "DecodeCacheOp"; +} + +def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, + INSN_MIPS3_32_NOT_32R6_64R6; +def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, + INSN_MIPS3_32_NOT_32R6_64R6; + +def ROL : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), + "rol\t$rs, $rt, $rd">; +def ROLImm : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "rol\t$rs, $rt, $imm">; +def : MipsInstAlias<"rol $rd, $rs", + (ROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"rol $rd, $imm", + (ROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>; + +def ROR : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), + "ror\t$rs, $rt, $rd">; +def RORImm : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "ror\t$rs, $rt, $imm">; +def : MipsInstAlias<"ror $rd, $rs", + (ROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"ror $rd, $imm", + (RORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>; + +def DROL : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), + "drol\t$rs, $rt, $rd">, ISA_MIPS64; +def DROLImm : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "drol\t$rs, $rt, $imm">, ISA_MIPS64; +def : MipsInstAlias<"drol $rd, $rs", + (DROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, ISA_MIPS64; +def : MipsInstAlias<"drol $rd, $imm", + (DROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; + +def DROR : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), + "dror\t$rs, $rt, $rd">, ISA_MIPS64; +def DRORImm : MipsAsmPseudoInst<(outs), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "dror\t$rs, $rt, $imm">, ISA_MIPS64; +def : MipsInstAlias<"dror $rd, $rs", + (DROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, ISA_MIPS64; +def : MipsInstAlias<"dror $rd, $imm", + (DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; //===----------------------------------------------------------------------===// // 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", + (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, + GPR_32 { + let AdditionalPredicates = [NotInMicroMips]; +} +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<"addu $rs, $imm", + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; +def : MipsInstAlias<"add $rs, $rt, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"add $rs, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; +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<"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<"xor $rs, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, 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>; +let AdditionalPredicates = [NotInMicroMips] in { +def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; +} +def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>; +def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>; +let AdditionalPredicates = [NotInMicroMips] in { +def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; +} +def : MipsInstAlias<"bnez $rs,$offset", + (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"bnezl $rs,$offset", + (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"beqz $rs,$offset", + (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"beqzl $rs,$offset", + (BEQL 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>; +let AdditionalPredicates = [NotInMicroMips] in { +def : MipsInstAlias<"ei", (EI ZERO), 1>, ISA_MIPS32R2; +} +def : MipsInstAlias<"di", (DI ZERO), 1>, ISA_MIPS32R2; +let AdditionalPredicates = [NotInMicroMips] in { + 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>, ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"sub $rs, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm), + 0>, ISA_MIPS1_NOT_32R6_64R6; +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 //===----------------------------------------------------------------------===// -class LoadImm32< string instr_asm, Operand Od, RegisterOperand RO> : +class LoadImmediate32 : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadImm32Reg : LoadImm32<"li", uimm5, GPR32Opnd>; +def LoadImm32 : LoadImmediate32<"li", simm32, GPR32Opnd>; -class LoadAddress : +class LoadAddressFromReg32 : MipsAsmPseudoInst<(outs RO:$rt), (ins MemOpnd:$addr), !strconcat(instr_asm, "\t$rt, $addr")> ; -def LoadAddr32Reg : LoadAddress<"la", mem, GPR32Opnd>; +def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>; -class LoadAddressImm : +class LoadAddressFromImm32 : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadAddr32Imm : LoadAddressImm<"la", uimm5, GPR32Opnd>; +def LoadAddrImm32 : LoadAddressFromImm32<"la", simm32, GPR32Opnd>; + +def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), + "jal\t$rd, $rs"> ; +def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), + "jal\t$rs"> ; + +def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "nor\t$rs, $rt, $imm"> ; + +let hasDelaySlot = 1 in { +def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), + (ins imm64:$imm64, brtarget:$offset), + "bne\t$rt, $imm64, $offset">; +def BeqImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), + (ins imm64:$imm64, brtarget:$offset), + "beq\t$rt, $imm64, $offset">; + +class CondBranchPseudo : + MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, + brtarget:$offset), + !strconcat(instr_asm, "\t$rs, $rt, $offset")>; +} + +def BLT : CondBranchPseudo<"blt">; +def BLE : CondBranchPseudo<"ble">; +def BGE : CondBranchPseudo<"bge">; +def BGT : CondBranchPseudo<"bgt">; +def BLTU : CondBranchPseudo<"bltu">; +def BLEU : CondBranchPseudo<"bleu">; +def BGEU : CondBranchPseudo<"bgeu">; +def BGTU : CondBranchPseudo<"bgtu">; +def BLTL : CondBranchPseudo<"bltl">, ISA_MIPS2_NOT_32R6_64R6; +def BLEL : CondBranchPseudo<"blel">, ISA_MIPS2_NOT_32R6_64R6; +def BGEL : CondBranchPseudo<"bgel">, ISA_MIPS2_NOT_32R6_64R6; +def BGTL : CondBranchPseudo<"bgtl">, ISA_MIPS2_NOT_32R6_64R6; +def BLTUL: CondBranchPseudo<"bltul">, ISA_MIPS2_NOT_32R6_64R6; +def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6; +def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; +def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; + +class CondBranchImmPseudo : + MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), + !strconcat(instr_asm, "\t$rs, $imm, $offset")>; + +def BLTImmMacro : CondBranchImmPseudo<"blt">; +def BLEImmMacro : CondBranchImmPseudo<"ble">; +def BGEImmMacro : CondBranchImmPseudo<"bge">; +def BGTImmMacro : CondBranchImmPseudo<"bgt">; +def BLTUImmMacro : CondBranchImmPseudo<"bltu">; +def BLEUImmMacro : CondBranchImmPseudo<"bleu">; +def BGEUImmMacro : CondBranchImmPseudo<"bgeu">; +def BGTUImmMacro : CondBranchImmPseudo<"bgtu">; +def BLTLImmMacro : CondBranchImmPseudo<"bltl">, ISA_MIPS2_NOT_32R6_64R6; +def BLELImmMacro : CondBranchImmPseudo<"blel">, ISA_MIPS2_NOT_32R6_64R6; +def BGELImmMacro : CondBranchImmPseudo<"bgel">, ISA_MIPS2_NOT_32R6_64R6; +def BGTLImmMacro : CondBranchImmPseudo<"bgtl">, ISA_MIPS2_NOT_32R6_64R6; +def BLTULImmMacro : CondBranchImmPseudo<"bltul">, ISA_MIPS2_NOT_32R6_64R6; +def BLEULImmMacro : CondBranchImmPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6; +def BGEULImmMacro : CondBranchImmPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; +def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; + +// FIXME: Predicates are removed because instructions are matched regardless of +// predicates, because PredicateControl was not in the hierarchy. This was +// done to emit more precise error message from expansion function. +// Once the tablegen-erated errors are made better, this needs to be fixed and +// predicates needs to be restored. + +def SDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "div\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6; + +def UDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "divu\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6; + +def DSDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "ddiv\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6; + +def DUDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "ddivu\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6; + +def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), + "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; + +def Ulhu : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), + "ulhu\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; + +def Ulw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), + "ulw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -1226,10 +2027,12 @@ class StoreRegImmPat : MipsPat<(store ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>; // Small immediates +let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(i32 immSExt16:$in), (ADDiu ZERO, imm:$in)>; def : MipsPat<(i32 immZExt16:$in), (ORi ZERO, imm:$in)>; +} def : MipsPat<(i32 immLow16Zero:$in), (LUi (HI16 imm:$in))>; @@ -1240,13 +2043,23 @@ 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)>; } +// Support multiplication for pre-Mips32 targets that don't have +// the MUL instruction. +def : MipsPat<(mul GPR32:$lhs, GPR32:$rhs), + (PseudoMFLO (PseudoMULT GPR32:$lhs, GPR32:$rhs))>, + ISA_MIPS1_NOT_32R6_64R6; + +// SYNC +def : MipsPat<(MipsSync (i32 immz)), + (SYNC 0)>, ISA_MIPS2; + // Call def : MipsPat<(MipsJmpLink (i32 tglobaladdr:$dst)), (JAL tglobaladdr:$dst)>; @@ -1304,19 +2117,18 @@ def : WrapperPat; def : WrapperPat; def : WrapperPat; +let AdditionalPredicates = [NotInMicroMips] in { // Mips does not have "not", so we expand our way 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 @@ -1410,13 +2222,23 @@ 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; + let AdditionalPredicates = [NotInMicroMips] in { + def : LoadRegImmPat; } } +// Atomic load patterns. +def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>; +def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>; +def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>; + +// Atomic store patterns. +def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>; +def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>; +def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>; + //===----------------------------------------------------------------------===// // Floating Point Support //===----------------------------------------------------------------------===// @@ -1425,6 +2247,9 @@ include "MipsInstrFPU.td" include "Mips64InstrInfo.td" include "MipsCondMov.td" +include "Mips32r6InstrInfo.td" +include "Mips64r6InstrInfo.td" + // // Mips16 @@ -1439,7 +2264,23 @@ include "MipsDSPInstrInfo.td" include "MipsMSAInstrFormats.td" include "MipsMSAInstrInfo.td" +// EVA +include "MipsEVAInstrFormats.td" +include "MipsEVAInstrInfo.td" + // Micromips include "MicroMipsInstrFormats.td" include "MicroMipsInstrInfo.td" include "MicroMipsInstrFPU.td" + +// Micromips r6 +include "MicroMips32r6InstrFormats.td" +include "MicroMips32r6InstrInfo.td" + +// Micromips64 r6 +include "MicroMips64r6InstrFormats.td" +include "MicroMips64r6InstrInfo.td" + +// Micromips DSP +include "MicroMipsDSPInstrFormats.td" +include "MicroMipsDSPInstrInfo.td"