diff options
Diffstat (limited to 'lib/Target/Mips/MipsInstrInfo.td')
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.td | 661 |
1 files changed, 336 insertions, 325 deletions
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index b9e8895..ebdbaa4 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -23,11 +23,9 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisInt<4>]>; def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -def SDT_ExtractLOHI : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVT<1, untyped>, - SDTCisVT<2, i32>]>; -def SDT_InsertLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, - SDTCisVT<1, i32>, - SDTCisSameAs<1, 2>]>; +def SDT_MFLOHI : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVT<1, untyped>]>; +def SDT_MTLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, + SDTCisInt<1>, SDTCisSameAs<1, 2>]>; def SDT_MipsMultDiv : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, SDTCisInt<1>, SDTCisSameAs<1, 2>]>; def SDT_MipsMAddMSub : SDTypeProfile<1, 3, @@ -86,11 +84,12 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, [SDNPHasChain, SDNPSideEffect, SDNPOptInGlue, SDNPOutGlue]>; -// Node used to extract integer from LO/HI register. -def ExtractLOHI : SDNode<"MipsISD::ExtractLOHI", SDT_ExtractLOHI>; +// Nodes used to extract LO/HI registers. +def MipsMFHI : SDNode<"MipsISD::MFHI", SDT_MFLOHI>; +def MipsMFLO : SDNode<"MipsISD::MFLO", SDT_MFLOHI>; // Node used to insert 32-bit integers to LOHI register pair. -def InsertLOHI : SDNode<"MipsISD::InsertLOHI", SDT_InsertLOHI>; +def MipsMTLOHI : SDNode<"MipsISD::MTLOHI", SDT_MTLOHI>; // Mult nodes. def MipsMult : SDNode<"MipsISD::Mult", SDT_MipsMultDiv>; @@ -115,7 +114,7 @@ def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsDivRem16, // Wrapper node patterns give the instruction selector a chance to replace // target constant nodes that would otherwise remain unchanged with ADDiu // nodes. Without these wrapper node patterns, the following conditional move -// instrucion is emitted when function cmov2 in test/CodeGen/Mips/cmov.ll is +// instruction is emitted when function cmov2 in test/CodeGen/Mips/cmov.ll is // compiled: // movn %got(d)($gp), %got(c)($gp), $4 // This instruction is illegal since movn can take only register operands. @@ -182,6 +181,12 @@ def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">, def HasStdEnc : Predicate<"Subtarget.hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; def NotDSP : Predicate<"!Subtarget.hasDSP()">; +def InMicroMips : Predicate<"Subtarget.inMicroMipsMode()">, + AssemblerPredicate<"FeatureMicroMips">; +def NotInMicroMips : Predicate<"!Subtarget.inMicroMipsMode()">, + AssemblerPredicate<"!FeatureMicroMips">; +def IsLE : Predicate<"Subtarget.isLittle()">; +def IsBE : Predicate<"!Subtarget.isLittle()">; class MipsPat<dag pattern, dag result> : Pat<pattern, result> { let Predicates = [HasStdEnc]; @@ -242,7 +247,7 @@ def brtarget : Operand<OtherVT> { def calltarget : Operand<iPTR> { let EncoderMethod = "getJumpTargetOpValue"; } -def calltarget64: Operand<i64>; + def simm16 : Operand<i32> { let DecoderMethod= "DecodeSimm16"; } @@ -256,48 +261,67 @@ def uimm20 : Operand<i32> { def uimm10 : Operand<i32> { } -def simm16_64 : Operand<i64>; -def shamt : Operand<i32>; +def simm16_64 : Operand<i64> { + let DecoderMethod = "DecodeSimm16"; +} // Unsigned Operand +def uimm5 : Operand<i32> { + let PrintMethod = "printUnsignedImm"; +} + +def uimm6 : Operand<i32> { + let PrintMethod = "printUnsignedImm"; +} + def uimm16 : Operand<i32> { let PrintMethod = "printUnsignedImm"; } +def pcrel16 : Operand<i32> { +} + def MipsMemAsmOperand : AsmOperandClass { let Name = "Mem"; let ParserMethod = "parseMemOperand"; } -// Address operand -def mem : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32, simm16); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemAsmOperand; - let OperandType = "OPERAND_MEMORY"; +def MipsInvertedImmoperand : AsmOperandClass { + let Name = "InvNum"; + let RenderMethod = "addImmOperands"; + let ParserMethod = "parseInvNum"; +} + +def PtrRegAsmOperand : AsmOperandClass { + let Name = "PtrReg"; + let ParserMethod = "parsePtrReg"; +} + + +def InvertedImOperand : Operand<i32> { + let ParserMatchClass = MipsInvertedImmoperand; } -def mem64 : Operand<i64> { +// Address operand +def mem : Operand<iPTR> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR64, simm16_64); + let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncoding"; let ParserMatchClass = MipsMemAsmOperand; let OperandType = "OPERAND_MEMORY"; } -def mem_ea : Operand<i32> { +def mem_ea : Operand<iPTR> { let PrintMethod = "printMemOperandEA"; - let MIOperandInfo = (ops GPR32, simm16); + let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncoding"; let OperandType = "OPERAND_MEMORY"; } -def mem_ea_64 : Operand<i64> { - let PrintMethod = "printMemOperandEA"; - let MIOperandInfo = (ops GPR64, simm16_64); - let EncoderMethod = "getMemEncoding"; - let OperandType = "OPERAND_MEMORY"; +def PtrRC : Operand<iPTR> { + let MIOperandInfo = (ops ptr_rc); + let DecoderMethod = "DecodePtrRegisterClass"; + let ParserMatchClass = PtrRegAsmOperand; } // size operand of ext instruction @@ -370,6 +394,9 @@ def addr : def addrRegImm : ComplexPattern<iPTR, 2, "selectAddrRegImm", [frameindex]>; +def addrRegReg : + ComplexPattern<iPTR, 2, "selectAddrRegReg", [frameindex]>; + def addrDefault : ComplexPattern<iPTR, 2, "selectAddrDefault", [frameindex]>; @@ -404,9 +431,9 @@ class ArithLogicI<string opstr, Operand Od, RegisterOperand RO, // Arithmetic Multiply ADD/SUB class MArithR<string opstr, bit isComm = 0> : InstSE<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - !strconcat(opstr, "\t$rs, $rt"), [], IIImult, FrmR> { - let Defs = [HI, LO]; - let Uses = [HI, LO]; + !strconcat(opstr, "\t$rs, $rt"), [], IIImult, FrmR, opstr> { + let Defs = [HI0, LO0]; + let Uses = [HI0, LO0]; let isCommutable = isComm; } @@ -435,121 +462,66 @@ class shift_rotate_reg<string opstr, RegisterOperand RO, // Load Upper Imediate class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>: InstSE<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), - [], IIArith, FrmI>, IsAsCheapAsAMove { + [], IIArith, FrmI, opstr>, IsAsCheapAsAMove { let neverHasSideEffects = 1; let isReMaterializable = 1; } -class FMem<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: FFI<op, outs, ins, asmstr, pattern> { - bits<21> addr; - let Inst{25-21} = addr{20-16}; - let Inst{15-0} = addr{15-0}; - let DecoderMethod = "DecodeMem"; -} - // Memory Load/Store -class Load<string opstr, SDPatternOperator OpNode, DAGOperand RO, - InstrItinClass Itin, Operand MemOpnd, ComplexPattern Addr, - string ofsuffix> : - InstSE<(outs RO:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, (OpNode Addr:$addr))], NoItinerary, FrmI, - !strconcat(opstr, ofsuffix)> { +class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : + InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let canFoldAsLoad = 1; let mayLoad = 1; } -class Store<string opstr, SDPatternOperator OpNode, DAGOperand RO, - InstrItinClass Itin, Operand MemOpnd, ComplexPattern Addr, - string ofsuffix> : - InstSE<(outs), (ins RO:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RO:$rt, Addr:$addr)], NoItinerary, FrmI, - !strconcat(opstr, ofsuffix)> { +class Store<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : + InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RO:$rt, Addr:$addr)], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let mayStore = 1; } -multiclass LoadM<string opstr, DAGOperand RO, - SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, - ComplexPattern Addr = addr> { - def NAME : Load<opstr, OpNode, RO, Itin, mem, Addr, "">, - Requires<[NotN64, HasStdEnc]>; - def _P8 : Load<opstr, OpNode, RO, Itin, mem64, Addr, "_p8">, - Requires<[IsN64, HasStdEnc]> { - let DecoderNamespace = "Mips64"; - let isCodeGenOnly = 1; - } -} - -multiclass StoreM<string opstr, DAGOperand RO, - SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, - ComplexPattern Addr = addr> { - def NAME : Store<opstr, OpNode, RO, Itin, mem, Addr, "">, - Requires<[NotN64, HasStdEnc]>; - def _P8 : Store<opstr, OpNode, RO, Itin, mem64, Addr, "_p8">, - Requires<[IsN64, HasStdEnc]> { - let DecoderNamespace = "Mips64"; - let isCodeGenOnly = 1; - } -} - // Load/Store Left/Right let canFoldAsLoad = 1 in class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, - Operand MemOpnd> : - InstSE<(outs RO:$rt), (ins MemOpnd:$addr, RO:$src), + InstrItinClass Itin> : + InstSE<(outs RO:$rt), (ins mem:$addr, RO:$src), !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, (OpNode addr:$addr, RO:$src))], NoItinerary, FrmI> { + [(set RO:$rt, (OpNode addr:$addr, RO:$src))], Itin, FrmI> { let DecoderMethod = "DecodeMem"; string Constraints = "$src = $rt"; } class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, - Operand MemOpnd>: - InstSE<(outs), (ins RO:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RO:$rt, addr:$addr)], NoItinerary, FrmI> { + InstrItinClass Itin> : + InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RO:$rt, addr:$addr)], Itin, FrmI> { let DecoderMethod = "DecodeMem"; } -multiclass LoadLeftRightM<string opstr, SDNode OpNode, RegisterOperand RO> { - def NAME : LoadLeftRight<opstr, OpNode, RO, mem>, - Requires<[NotN64, HasStdEnc]>; - def _P8 : LoadLeftRight<opstr, OpNode, RO, mem64>, - Requires<[IsN64, HasStdEnc]> { - let DecoderNamespace = "Mips64"; - let isCodeGenOnly = 1; - } -} - -multiclass StoreLeftRightM<string opstr, SDNode OpNode, RegisterOperand RO> { - def NAME : StoreLeftRight<opstr, OpNode, RO, mem>, - Requires<[NotN64, HasStdEnc]>; - def _P8 : StoreLeftRight<opstr, OpNode, RO, mem64>, - Requires<[IsN64, HasStdEnc]> { - let DecoderNamespace = "Mips64"; - let isCodeGenOnly = 1; - } -} - // Conditional Branch -class CBranch<string opstr, PatFrag cond_op, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, RO:$rt, brtarget:$offset), +class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op, + RegisterOperand RO> : + 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, - FrmI> { + FrmI, opstr> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; let Defs = [AT]; } -class CBranchZero<string opstr, PatFrag cond_op, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, brtarget:$offset), +class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op, + RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, opnd:$offset), !strconcat(opstr, "\t$rs, $offset"), - [(brcond (i32 (cond_op RO:$rs, 0)), bb:$offset)], IIBranch, FrmI> { + [(brcond (i32 (cond_op RO:$rs, 0)), bb:$offset)], IIBranch, + FrmI, opstr> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; @@ -572,9 +544,9 @@ class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type, // Jump class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator, - SDPatternOperator targetoperator> : + SDPatternOperator targetoperator, string bopstr> : InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), - [(operator targetoperator:$target)], IIBranch, FrmJ> { + [(operator targetoperator:$target)], IIBranch, FrmJ, bopstr> { let isTerminator=1; let isBarrier=1; let hasDelaySlot = 1; @@ -583,9 +555,9 @@ class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator, } // Unconditional branch -class UncondBranch<string opstr> : - InstSE<(outs), (ins brtarget:$offset), !strconcat(opstr, "\t$offset"), - [(br bb:$offset)], IIBranch, FrmI> { +class UncondBranch<Instruction BEQInst> : + PseudoSE<(outs), (ins brtarget:$offset), [(br bb:$offset)], IIBranch>, + PseudoInstExpansion<(BEQInst ZERO, ZERO, brtarget:$offset)> { let isBranch = 1; let isTerminator = 1; let isBarrier = 1; @@ -596,17 +568,20 @@ class UncondBranch<string opstr> : // Base class for indirect branch and return instruction classes. let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in -class JumpFR<RegisterOperand RO, SDPatternOperator operator = null_frag>: - InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch, FrmR>; +class JumpFR<string opstr, RegisterOperand RO, + SDPatternOperator operator = null_frag>: + InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch, + FrmR, opstr>; // Indirect branch -class IndirectBranch<RegisterOperand RO>: JumpFR<RO, brind> { +class IndirectBranch<string opstr, RegisterOperand RO> : + JumpFR<opstr, RO, brind> { let isBranch = 1; let isIndirectBranch = 1; } // Return instruction -class RetBase<RegisterOperand RO>: JumpFR<RO> { +class RetBase<string opstr, RegisterOperand RO>: JumpFR<opstr, RO> { let isReturn = 1; let isCodeGenOnly = 1; let hasCtrlDep = 1; @@ -615,9 +590,9 @@ class RetBase<RegisterOperand RO>: JumpFR<RO> { // Jump and Link (Call) let isCall=1, hasDelaySlot=1, Defs = [RA] in { - class JumpLink<string opstr> : - InstSE<(outs), (ins calltarget:$target), !strconcat(opstr, "\t$target"), - [(MipsJmpLink imm:$target)], IIBranch, FrmJ> { + class JumpLink<string opstr, DAGOperand opnd> : + InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), + [(MipsJmpLink imm:$target)], IIBranch, FrmJ, opstr> { let DecoderMethod = "DecodeJumpTarget"; } @@ -628,11 +603,11 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in { class JumpLinkReg<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], IIBranch, FrmR>; + [], IIBranch, FrmR, opstr>; - class BGEZAL_FT<string opstr, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, brtarget:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI>; + class BGEZAL_FT<string opstr, DAGOperand opnd, RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, opnd:$offset), + !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr>; } @@ -660,6 +635,20 @@ class ER_FT<string opstr> : InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther>; +// Interrupts +class DEI_FT<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$rt), (ins), + !strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther>; + +// Wait +class WAIT_FT<string opstr> : + InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther> { + let Inst{31-26} = 0x10; + let Inst{25} = 1; + let Inst{24-6} = 0; + let Inst{5-0} = 0x20; +} + // Sync let hasSideEffects = 1 in class SYNC_FT : @@ -669,8 +658,12 @@ class SYNC_FT : let hasSideEffects = 1 in class TEQ_FT<string opstr, RegisterOperand RO> : InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_), - !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, FrmI>; + !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, + FrmI, opstr>; +class TEQI_FT<string opstr, RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, uimm16:$imm16), + !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr>; // Mul, Div class Mult<string opstr, InstrItinClass itin, RegisterOperand RO, list<Register> DefRegs> : @@ -698,10 +691,10 @@ class MultDivPseudo<Instruction RealInst, RegisterClass R0, RegisterOperand R1, // Pseudo multiply add/sub instruction with explicit accumulator register // operands. class MAddSubPseudo<Instruction RealInst, SDPatternOperator OpNode> - : PseudoSE<(outs ACRegs:$ac), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, ACRegs:$acin), - [(set ACRegs:$ac, - (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt, ACRegs:$acin))], + : PseudoSE<(outs ACC64:$ac), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64:$acin), + [(set ACC64:$ac, + (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64:$acin))], IIImult>, PseudoInstExpansion<(RealInst GPR32Opnd:$rs, GPR32Opnd:$rt)> { string Constraints = "$acin = $ac"; @@ -710,25 +703,35 @@ class MAddSubPseudo<Instruction RealInst, SDPatternOperator OpNode> class Div<string opstr, InstrItinClass itin, RegisterOperand RO, list<Register> DefRegs> : InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$$zero, $rs, $rt"), - [], itin, FrmR> { + [], itin, FrmR, opstr> { let Defs = DefRegs; } // Move from Hi/Lo -class MoveFromLOHI<string opstr, RegisterOperand RO, list<Register> UseRegs>: - InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], IIHiLo, FrmR> { - let Uses = UseRegs; +class PseudoMFLOHI<RegisterClass DstRC, RegisterClass SrcRC, SDNode OpNode> + : PseudoSE<(outs DstRC:$rd), (ins SrcRC:$hilo), + [(set DstRC:$rd, (OpNode SrcRC:$hilo))], IIHiLo>; + +class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>: + InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], IIHiLo, FrmR, + opstr> { + let Uses = [UseReg]; let neverHasSideEffects = 1; } +class PseudoMTLOHI<RegisterClass DstRC, RegisterClass SrcRC> + : PseudoSE<(outs DstRC:$lohi), (ins SrcRC:$lo, SrcRC:$hi), + [(set DstRC:$lohi, (MipsMTLOHI SrcRC:$lo, SrcRC:$hi))], IIHiLo>; + class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>: - InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], IIHiLo, FrmR> { + InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], IIHiLo, + FrmR, opstr> { let Defs = DefRegs; let neverHasSideEffects = 1; } -class EffectiveAddress<string opstr, RegisterOperand RO, Operand Mem> : - InstSE<(outs RO:$rt), (ins Mem:$addr), !strconcat(opstr, "\t$rt, $addr"), +class EffectiveAddress<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RO:$rt, addr:$addr)], NoItinerary, FrmI> { let isCodeGenOnly = 1; let DecoderMethod = "DecodeMem"; @@ -737,26 +740,26 @@ class EffectiveAddress<string opstr, RegisterOperand RO, Operand Mem> : // Count Leading Ones/Zeros in Word class CountLeading0<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz RO:$rs))], IIArith, FrmR>, + [(set RO:$rd, (ctlz RO:$rs))], IIArith, FrmR, opstr>, Requires<[HasBitCount, HasStdEnc]>; class CountLeading1<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz (not RO:$rs)))], IIArith, FrmR>, + [(set RO:$rd, (ctlz (not RO:$rs)))], IIArith, FrmR, opstr>, Requires<[HasBitCount, HasStdEnc]>; // Sign Extend in Register. class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO> : InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), - [(set RO:$rd, (sext_inreg RO:$rt, vt))], IIseb, FrmR> { + [(set RO:$rd, (sext_inreg RO:$rt, vt))], IIseb, FrmR, opstr> { let Predicates = [HasSEInReg, HasStdEnc]; } // Subword Swap class SubwordSwap<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [], - NoItinerary, FrmR> { + NoItinerary, FrmR, opstr> { let Predicates = [HasSwap, HasStdEnc]; let neverHasSideEffects = 1; } @@ -767,66 +770,60 @@ class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> : IIArith, FrmR>; // Ext and Ins -class ExtBase<string opstr, RegisterOperand RO>: - InstSE<(outs RO:$rt), (ins RO:$rs, uimm16:$pos, size_ext:$size), +class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, + SDPatternOperator Op = null_frag>: + InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ext:$size), !strconcat(opstr, " $rt, $rs, $pos, $size"), - [(set RO:$rt, (MipsExt RO:$rs, imm:$pos, imm:$size))], NoItinerary, - FrmR> { + [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], NoItinerary, + FrmR, opstr> { let Predicates = [HasMips32r2, HasStdEnc]; } -class InsBase<string opstr, RegisterOperand RO>: - InstSE<(outs RO:$rt), (ins RO:$rs, uimm16:$pos, size_ins:$size, RO:$src), +class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, + SDPatternOperator Op = null_frag>: + InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src), !strconcat(opstr, " $rt, $rs, $pos, $size"), - [(set RO:$rt, (MipsIns RO:$rs, imm:$pos, imm:$size, RO:$src))], - NoItinerary, FrmR> { + [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))], + NoItinerary, FrmR, opstr> { let Predicates = [HasMips32r2, HasStdEnc]; let Constraints = "$src = $rt"; } // Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*). -class Atomic2Ops<PatFrag Op, RegisterClass DRC, RegisterClass PRC> : - PseudoSE<(outs DRC:$dst), (ins PRC:$ptr, DRC:$incr), - [(set DRC:$dst, (Op PRC:$ptr, DRC:$incr))]>; - -multiclass Atomic2Ops32<PatFrag Op> { - def NAME : Atomic2Ops<Op, GPR32, GPR32>, Requires<[NotN64, HasStdEnc]>; - def _P8 : Atomic2Ops<Op, GPR32, GPR64>, Requires<[IsN64, HasStdEnc]>; -} +class Atomic2Ops<PatFrag Op, RegisterClass DRC> : + PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), + [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>; // Atomic Compare & Swap. -class AtomicCmpSwap<PatFrag Op, RegisterClass DRC, RegisterClass PRC> : - PseudoSE<(outs DRC:$dst), (ins PRC:$ptr, DRC:$cmp, DRC:$swap), - [(set DRC:$dst, (Op PRC:$ptr, DRC:$cmp, DRC:$swap))]>; - -multiclass AtomicCmpSwap32<PatFrag Op> { - def NAME : AtomicCmpSwap<Op, GPR32, GPR32>, - Requires<[NotN64, HasStdEnc]>; - def _P8 : AtomicCmpSwap<Op, GPR32, GPR64>, - Requires<[IsN64, HasStdEnc]>; -} +class AtomicCmpSwap<PatFrag Op, RegisterClass DRC> : + PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap), + [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>; -class LLBase<string opstr, RegisterOperand RO, Operand Mem> : - InstSE<(outs RO:$rt), (ins Mem:$addr), !strconcat(opstr, "\t$rt, $addr"), +class LLBase<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { let DecoderMethod = "DecodeMem"; let mayLoad = 1; } -class SCBase<string opstr, RegisterOperand RO, Operand Mem> : - InstSE<(outs RO:$dst), (ins RO:$rt, Mem:$addr), +class SCBase<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$dst), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { let DecoderMethod = "DecodeMem"; let mayStore = 1; let Constraints = "$rt = $dst"; } -class MFC3OP<dag outs, dag ins, string asmstr> : - InstSE<outs, ins, asmstr, [], NoItinerary, FrmFR>; +class MFC3OP<string asmstr, RegisterOperand RO> : + InstSE<(outs RO:$rt, RO:$rd, uimm16:$sel), (ins), + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; -let isBarrier = 1, isTerminator = 1, isCodeGenOnly = 1 in -def TRAP : InstSE<(outs), (ins), "break", [(trap)], NoItinerary, FrmOther> { - let Inst = 0x0000000d; +class TrapBase<Instruction RealInst> + : PseudoSE<(outs), (ins), [(trap)], NoItinerary>, + PseudoInstExpansion<(RealInst 0, 0)> { + let isBarrier = 1; + let isTerminator = 1; + let isCodeGenOnly = 1; } //===----------------------------------------------------------------------===// @@ -845,38 +842,38 @@ def ADJCALLSTACKUP : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), } let usesCustomInserter = 1 in { - defm ATOMIC_LOAD_ADD_I8 : Atomic2Ops32<atomic_load_add_8>; - defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32<atomic_load_add_16>; - defm ATOMIC_LOAD_ADD_I32 : Atomic2Ops32<atomic_load_add_32>; - defm ATOMIC_LOAD_SUB_I8 : Atomic2Ops32<atomic_load_sub_8>; - defm ATOMIC_LOAD_SUB_I16 : Atomic2Ops32<atomic_load_sub_16>; - defm ATOMIC_LOAD_SUB_I32 : Atomic2Ops32<atomic_load_sub_32>; - defm ATOMIC_LOAD_AND_I8 : Atomic2Ops32<atomic_load_and_8>; - defm ATOMIC_LOAD_AND_I16 : Atomic2Ops32<atomic_load_and_16>; - defm ATOMIC_LOAD_AND_I32 : Atomic2Ops32<atomic_load_and_32>; - defm ATOMIC_LOAD_OR_I8 : Atomic2Ops32<atomic_load_or_8>; - defm ATOMIC_LOAD_OR_I16 : Atomic2Ops32<atomic_load_or_16>; - defm ATOMIC_LOAD_OR_I32 : Atomic2Ops32<atomic_load_or_32>; - defm ATOMIC_LOAD_XOR_I8 : Atomic2Ops32<atomic_load_xor_8>; - defm ATOMIC_LOAD_XOR_I16 : Atomic2Ops32<atomic_load_xor_16>; - defm ATOMIC_LOAD_XOR_I32 : Atomic2Ops32<atomic_load_xor_32>; - defm ATOMIC_LOAD_NAND_I8 : Atomic2Ops32<atomic_load_nand_8>; - defm ATOMIC_LOAD_NAND_I16 : Atomic2Ops32<atomic_load_nand_16>; - defm ATOMIC_LOAD_NAND_I32 : Atomic2Ops32<atomic_load_nand_32>; - - defm ATOMIC_SWAP_I8 : Atomic2Ops32<atomic_swap_8>; - defm ATOMIC_SWAP_I16 : Atomic2Ops32<atomic_swap_16>; - defm ATOMIC_SWAP_I32 : Atomic2Ops32<atomic_swap_32>; - - defm ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap32<atomic_cmp_swap_8>; - defm ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap32<atomic_cmp_swap_16>; - defm ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap32<atomic_cmp_swap_32>; + def ATOMIC_LOAD_ADD_I8 : Atomic2Ops<atomic_load_add_8, GPR32>; + def ATOMIC_LOAD_ADD_I16 : Atomic2Ops<atomic_load_add_16, GPR32>; + def ATOMIC_LOAD_ADD_I32 : Atomic2Ops<atomic_load_add_32, GPR32>; + def ATOMIC_LOAD_SUB_I8 : Atomic2Ops<atomic_load_sub_8, GPR32>; + def ATOMIC_LOAD_SUB_I16 : Atomic2Ops<atomic_load_sub_16, GPR32>; + def ATOMIC_LOAD_SUB_I32 : Atomic2Ops<atomic_load_sub_32, GPR32>; + def ATOMIC_LOAD_AND_I8 : Atomic2Ops<atomic_load_and_8, GPR32>; + def ATOMIC_LOAD_AND_I16 : Atomic2Ops<atomic_load_and_16, GPR32>; + def ATOMIC_LOAD_AND_I32 : Atomic2Ops<atomic_load_and_32, GPR32>; + def ATOMIC_LOAD_OR_I8 : Atomic2Ops<atomic_load_or_8, GPR32>; + def ATOMIC_LOAD_OR_I16 : Atomic2Ops<atomic_load_or_16, GPR32>; + def ATOMIC_LOAD_OR_I32 : Atomic2Ops<atomic_load_or_32, GPR32>; + def ATOMIC_LOAD_XOR_I8 : Atomic2Ops<atomic_load_xor_8, GPR32>; + def ATOMIC_LOAD_XOR_I16 : Atomic2Ops<atomic_load_xor_16, GPR32>; + def ATOMIC_LOAD_XOR_I32 : Atomic2Ops<atomic_load_xor_32, GPR32>; + def ATOMIC_LOAD_NAND_I8 : Atomic2Ops<atomic_load_nand_8, GPR32>; + def ATOMIC_LOAD_NAND_I16 : Atomic2Ops<atomic_load_nand_16, GPR32>; + def ATOMIC_LOAD_NAND_I32 : Atomic2Ops<atomic_load_nand_32, GPR32>; + + def ATOMIC_SWAP_I8 : Atomic2Ops<atomic_swap_8, GPR32>; + def ATOMIC_SWAP_I16 : Atomic2Ops<atomic_swap_16, GPR32>; + def ATOMIC_SWAP_I32 : Atomic2Ops<atomic_swap_32, GPR32>; + + def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, GPR32>; + def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, GPR32>; + def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, GPR32>; } /// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1, isCodeGenOnly = 1 in { - defm LOAD_AC64 : LoadM<"", ACRegs>; - defm STORE_AC64 : StoreM<"", ACRegs>; + def LOAD_ACC64 : Load<"", ACC64>; + def STORE_ACC64 : Store<"", ACC64>; } //===----------------------------------------------------------------------===// @@ -911,6 +908,7 @@ def ADDu : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, IIArith, add>, ADD_FM<0, 0x21>; def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, IIArith, sub>, ADD_FM<0, 0x23>; +let Defs = [HI0, LO0] in def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, IIImul, mul>, ADD_FM<0x1c, 2>; def ADD : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; @@ -926,11 +924,11 @@ def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, IILogic, xor>, def NOR : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; /// Shift Instructions -def SLL : MMRel, shift_rotate_imm<"sll", shamt, GPR32Opnd, shl, immZExt5>, +def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, shl, immZExt5>, SRA_FM<0, 0>; -def SRL : MMRel, shift_rotate_imm<"srl", shamt, GPR32Opnd, srl, immZExt5>, +def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, srl, immZExt5>, SRA_FM<2, 0>; -def SRA : MMRel, shift_rotate_imm<"sra", shamt, GPR32Opnd, sra, immZExt5>, +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>; @@ -938,7 +936,7 @@ def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, sra>, SRLV_FM<7, 0>; // Rotate Instructions let Predicates = [HasMips32r2, HasStdEnc] in { - def ROTR : MMRel, shift_rotate_imm<"rotr", shamt, GPR32Opnd, rotr, + def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, rotr, immZExt5>, SRA_FM<2, 1>; def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, rotr>, @@ -947,65 +945,85 @@ let Predicates = [HasMips32r2, HasStdEnc] in { /// Load and Store Instructions /// aligned -defm LB : LoadM<"lb", GPR32Opnd, sextloadi8, IILoad>, MMRel, LW_FM<0x20>; -defm LBu : LoadM<"lbu", GPR32Opnd, zextloadi8, IILoad, addrDefault>, MMRel, - LW_FM<0x24>; -defm LH : LoadM<"lh", GPR32Opnd, sextloadi16, IILoad, addrDefault>, MMRel, - LW_FM<0x21>; -defm LHu : LoadM<"lhu", GPR32Opnd, zextloadi16, IILoad>, MMRel, LW_FM<0x25>; -defm LW : LoadM<"lw", GPR32Opnd, load, IILoad, addrDefault>, MMRel, LW_FM<0x23>; -defm SB : StoreM<"sb", GPR32Opnd, truncstorei8, IIStore>, MMRel, LW_FM<0x28>; -defm SH : StoreM<"sh", GPR32Opnd, truncstorei16, IIStore>, MMRel, LW_FM<0x29>; -defm SW : StoreM<"sw", GPR32Opnd, store, IIStore>, MMRel, LW_FM<0x2b>; +def LB : Load<"lb", GPR32Opnd, sextloadi8, IILoad>, MMRel, LW_FM<0x20>; +def LBu : Load<"lbu", GPR32Opnd, zextloadi8, IILoad, addrDefault>, MMRel, + LW_FM<0x24>; +def LH : Load<"lh", GPR32Opnd, sextloadi16, IILoad, 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, + 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>; /// load/store left/right -defm LWL : LoadLeftRightM<"lwl", MipsLWL, GPR32Opnd>, LW_FM<0x22>; -defm LWR : LoadLeftRightM<"lwr", MipsLWR, GPR32Opnd>, LW_FM<0x26>; -defm SWL : StoreLeftRightM<"swl", MipsSWL, GPR32Opnd>, LW_FM<0x2a>; -defm SWR : StoreLeftRightM<"swr", MipsSWR, GPR32Opnd>, LW_FM<0x2e>; +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 : SYNC_FT, SYNC_FM; -def TEQ : TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>; +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 : BRK_FT<"break">, BRK_FM<0xd>; def SYSCALL : SYS_FT<"syscall">, SYS_FM<0xc>; +def TRAP : TrapBase<BREAK>; def ERET : ER_FT<"eret">, ER_FM<0x18>; def DERET : ER_FT<"deret">, ER_FM<0x1f>; -/// Load-linked, Store-conditional -let Predicates = [NotN64, HasStdEnc] in { - def LL : LLBase<"ll", GPR32Opnd, mem>, LW_FM<0x30>; - def SC : SCBase<"sc", GPR32Opnd, mem>, LW_FM<0x38>; -} +def EI : DEI_FT<"ei", GPR32Opnd>, EI_FM<1>; +def DI : DEI_FT<"di", GPR32Opnd>, EI_FM<0>; -let Predicates = [IsN64, HasStdEnc], DecoderNamespace = "Mips64" in { - def LL_P8 : LLBase<"ll", GPR32Opnd, mem64>, LW_FM<0x30>; - def SC_P8 : SCBase<"sc", GPR32Opnd, mem64>, LW_FM<0x38>; -} +def WAIT : WAIT_FT<"wait">; + +/// Load-linked, Store-conditional +def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>; +def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>; /// Jump and Branch Instructions -def J : JumpFJ<jmptarget, "j", br, bb>, FJ<2>, +def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>, Requires<[RelocStatic, HasStdEnc]>, IsBranch; -def JR : IndirectBranch<GPR32Opnd>, MTLO_FM<8>; -def B : UncondBranch<"b">, B_FM; -def BEQ : CBranch<"beq", seteq, GPR32Opnd>, BEQ_FM<4>; -def BNE : CBranch<"bne", setne, GPR32Opnd>, BEQ_FM<5>; -def BGEZ : CBranchZero<"bgez", setge, GPR32Opnd>, BGEZ_FM<1, 1>; -def BGTZ : CBranchZero<"bgtz", setgt, GPR32Opnd>, BGEZ_FM<7, 0>; -def BLEZ : CBranchZero<"blez", setle, GPR32Opnd>, BGEZ_FM<6, 0>; -def BLTZ : CBranchZero<"bltz", setlt, GPR32Opnd>, BGEZ_FM<1, 0>; - -def JAL : JumpLink<"jal">, FJ<3>; -def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM; +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>; +def BGEZ : MMRel, CBranchZero<"bgez", brtarget, setge, GPR32Opnd>, + BGEZ_FM<1, 1>; +def BGTZ : MMRel, CBranchZero<"bgtz", brtarget, setgt, GPR32Opnd>, + BGEZ_FM<7, 0>; +def BLEZ : MMRel, CBranchZero<"blez", brtarget, setle, GPR32Opnd>, + BGEZ_FM<6, 0>; +def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>, + BGEZ_FM<1, 0>; +def B : UncondBranch<BEQ>; + +def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>; +def JALR : MMRel, JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM; def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>; -def BGEZAL : BGEZAL_FT<"bgezal", GPR32Opnd>, BGEZAL_FM<0x11>; -def BLTZAL : BGEZAL_FT<"bltzal", GPR32Opnd>, BGEZAL_FM<0x10>; +def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>; +def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>; def BAL_BR : BAL_BR_Pseudo<BGEZAL>; -def TAILCALL : JumpFJ<calltarget, "j", MipsTailCall, imm>, FJ<2>, IsTailCall; -def TAILCALL_R : JumpFR<GPR32Opnd, MipsTailCall>, MTLO_FM<8>, IsTailCall; +def TAILCALL : MMRel, JumpFJ<calltarget, "j", MipsTailCall, imm, "tcall">, + FJ<2>, IsTailCall; +def TAILCALL_R : MMRel, JumpFR<"tcallr", GPR32Opnd, MipsTailCall>, MTLO_FM<8>, + IsTailCall; -def RET : RetBase<GPR32Opnd>, MTLO_FM<8>; +def RET : MMRel, RetBase<"ret", GPR32Opnd>, MTLO_FM<8>; // Exception handling related node and instructions. // The conversion sequence is: @@ -1029,34 +1047,30 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { } /// Multiply and Divide Instructions. -def MULT : MMRel, Mult<"mult", IIImult, GPR32Opnd, [HI, LO]>, +def MULT : MMRel, Mult<"mult", IIImult, GPR32Opnd, [HI0, LO0]>, MULT_FM<0, 0x18>; -def MULTu : MMRel, Mult<"multu", IIImult, GPR32Opnd, [HI, LO]>, +def MULTu : MMRel, Mult<"multu", IIImult, GPR32Opnd, [HI0, LO0]>, MULT_FM<0, 0x19>; -def PseudoMULT : MultDivPseudo<MULT, ACRegs, GPR32Opnd, MipsMult, IIImult>; -def PseudoMULTu : MultDivPseudo<MULTu, ACRegs, GPR32Opnd, MipsMultu, IIImult>; -def SDIV : Div<"div", IIIdiv, GPR32Opnd, [HI, LO]>, MULT_FM<0, 0x1a>; -def UDIV : Div<"divu", IIIdiv, GPR32Opnd, [HI, LO]>, MULT_FM<0, 0x1b>; -def PseudoSDIV : MultDivPseudo<SDIV, ACRegs, GPR32Opnd, MipsDivRem, IIIdiv, - 0, 1, 1>; -def PseudoUDIV : MultDivPseudo<UDIV, ACRegs, GPR32Opnd, MipsDivRemU, IIIdiv, - 0, 1, 1>; +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 : MoveToLOHI<"mthi", GPR32Opnd, [HI]>, MTLO_FM<0x11>; -def MTLO : MoveToLOHI<"mtlo", GPR32Opnd, [LO]>, MTLO_FM<0x13>; -def MFHI : MoveFromLOHI<"mfhi", GPR32Opnd, [HI]>, MFLO_FM<0x10>; -def MFLO : MoveFromLOHI<"mflo", GPR32Opnd, [LO]>, MFLO_FM<0x12>; +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>; /// Sign Ext In Register Instructions. -def SEB : SignExtInReg<"seb", i8, GPR32Opnd>, SEB_FM<0x10, 0x20>; -def SEH : SignExtInReg<"seh", i16, GPR32Opnd>, SEB_FM<0x18, 0x20>; +def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd>, SEB_FM<0x10, 0x20>; +def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd>, SEB_FM<0x18, 0x20>; /// Count Leading -def CLZ : CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>; -def CLO : CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>; +def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>; +def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>; /// Word Swap Bytes Within Halfwords -def WSBH : SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>; +def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>; /// No operation. def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; @@ -1065,39 +1079,41 @@ 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, mem_ea>, LW_FM<9>; +def LEA_ADDiu : EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; // MADD*/MSUB* -def MADD : MArithR<"madd", 1>, MULT_FM<0x1c, 0>; -def MADDU : MArithR<"maddu", 1>, MULT_FM<0x1c, 1>; -def MSUB : MArithR<"msub">, MULT_FM<0x1c, 4>; -def MSUBU : MArithR<"msubu">, MULT_FM<0x1c, 5>; +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<MULT, ACC64, GPR32Opnd, MipsMult, IIImult>; +def PseudoMULTu : MultDivPseudo<MULTu, ACC64, GPR32Opnd, MipsMultu, IIImult>; +def PseudoMFHI : PseudoMFLOHI<GPR32, ACC64, MipsMFHI>; +def PseudoMFLO : PseudoMFLOHI<GPR32, ACC64, MipsMFLO>; +def PseudoMTLOHI : PseudoMTLOHI<ACC64, GPR32>; def PseudoMADD : MAddSubPseudo<MADD, MipsMAdd>; def PseudoMADDU : MAddSubPseudo<MADDU, MipsMAddu>; def PseudoMSUB : MAddSubPseudo<MSUB, MipsMSub>; def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu>; +} + +def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, IIIdiv, + 0, 1, 1>; +def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, IIIdiv, + 0, 1, 1>; def RDHWR : ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM; -def EXT : ExtBase<"ext", GPR32Opnd>, EXT_FM<0>; -def INS : InsBase<"ins", GPR32Opnd>, EXT_FM<4>; +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_3OP : MFC3OP<(outs GPR32Opnd:$rt), - (ins GPR32Opnd:$rd, uimm16:$sel), - "mfc0\t$rt, $rd, $sel">, MFC3OP_FM<0x10, 0>; - -def MTC0_3OP : MFC3OP<(outs GPR32Opnd:$rd, uimm16:$sel), - (ins GPR32Opnd:$rt), - "mtc0\t$rt, $rd, $sel">, MFC3OP_FM<0x10, 4>; - -def MFC2_3OP : MFC3OP<(outs GPR32Opnd:$rt), - (ins GPR32Opnd:$rd, uimm16:$sel), - "mfc2\t$rt, $rd, $sel">, MFC3OP_FM<0x12, 0>; - -def MTC2_3OP : MFC3OP<(outs GPR32Opnd:$rd, uimm16:$sel), - (ins GPR32Opnd:$rt), - "mtc2\t$rt, $rd, $sel">, MFC3OP_FM<0x12, 4>; +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>; //===----------------------------------------------------------------------===// // Instruction aliases @@ -1129,14 +1145,11 @@ def : InstAlias<"xor $rs, $rt, $imm", 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_3OP GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; -def : InstAlias<"mtc0 $rt, $rd", - (MTC0_3OP GPR32Opnd:$rd, 0, GPR32Opnd:$rt), 0>; -def : InstAlias<"mfc2 $rt, $rd", - (MFC2_3OP GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; -def : InstAlias<"mtc2 $rt, $rd", - (MTC2_3OP GPR32Opnd:$rd, 0, GPR32Opnd:$rt), 0>; +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", @@ -1145,6 +1158,20 @@ 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)>; + //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// @@ -1152,7 +1179,7 @@ def : InstAlias<"break", (BREAK 0, 0), 1>; class LoadImm32< string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadImm32Reg : LoadImm32<"li", shamt,GPR32Opnd>; +def LoadImm32Reg : LoadImm32<"li", uimm5, GPR32Opnd>; class LoadAddress<string instr_asm, Operand MemOpnd, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins MemOpnd:$addr), @@ -1162,9 +1189,7 @@ def LoadAddr32Reg : LoadAddress<"la", mem, GPR32Opnd>; class LoadAddressImm<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadAddr32Imm : LoadAddressImm<"la", shamt,GPR32Opnd>; - - +def LoadAddr32Imm : LoadAddressImm<"la", uimm5, GPR32Opnd>; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -1261,24 +1286,15 @@ def : MipsPat<(not GPR32:$in), (NOR GPR32Opnd:$in, ZERO)>; // extended loads -let Predicates = [NotN64, HasStdEnc] in { +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)>; } -let Predicates = [IsN64, HasStdEnc] in { - def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu_P8 addr:$src)>; - def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu_P8 addr:$src)>; - def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu_P8 addr:$src)>; -} // peepholes -let Predicates = [NotN64, HasStdEnc] in { - def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; -} -let Predicates = [IsN64, HasStdEnc] in { - def : MipsPat<(store (i32 0), addr:$dst), (SW_P8 ZERO, addr:$dst)>; -} +let Predicates = [HasStdEnc] in +def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; // brcond patterns multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BNEOp, @@ -1369,22 +1385,13 @@ defm : SetgeImmPats<GPR32, SLTi, SLTiu>; // bswap pattern def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; -// mflo/hi patterns. -def : MipsPat<(i32 (ExtractLOHI ACRegs:$ac, imm:$lohi_idx)), - (EXTRACT_SUBREG ACRegs:$ac, imm:$lohi_idx)>; - // Load halfword/word patterns. let AddedComplexity = 40 in { - let Predicates = [NotN64, HasStdEnc] in { + let Predicates = [HasStdEnc] in { def : LoadRegImmPat<LBu, i32, zextloadi8>; def : LoadRegImmPat<LH, i32, sextloadi16>; def : LoadRegImmPat<LW, i32, load>; } - let Predicates = [IsN64, HasStdEnc] in { - def : LoadRegImmPat<LBu_P8, i32, zextloadi8>; - def : LoadRegImmPat<LH_P8, i32, sextloadi16>; - def : LoadRegImmPat<LW_P8, i32, load>; - } } //===----------------------------------------------------------------------===// @@ -1405,6 +1412,10 @@ include "Mips16InstrInfo.td" include "MipsDSPInstrFormats.td" include "MipsDSPInstrInfo.td" +// MSA +include "MipsMSAInstrFormats.td" +include "MipsMSAInstrInfo.td" + // Micromips include "MicroMipsInstrFormats.td" include "MicroMipsInstrInfo.td" |