// Mips profiles and nodes
//===----------------------------------------------------------------------===//
+def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
+def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
+def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
+ SDTCisSameAs<1, 2>, SDTCisInt<3>]>;
+def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
+def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+
// Call
-def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
-def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
- SDNPOutFlag]>;
+def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
+ SDNPOutFlag]>;
// Hi and Lo nodes are used to handle global addresses. Used on
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
// Return
-def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
-def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
- SDNPOptInFlag]>;
+def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
+ SDNPOptInFlag]>;
// These are target-independent nodes, but have target-specific formats.
-def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
-def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
- SDTCisVT<1, i32>]>;
+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart,
+ [SDNPHasChain, SDNPOutFlag]>;
+def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
+ [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
-def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart,
- [SDNPHasChain, SDNPOutFlag]>;
-def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
- [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+// Select Condition Code
+def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>;
//===----------------------------------------------------------------------===//
// Mips Instruction Predicate Definitions.
//===----------------------------------------------------------------------===//
-def IsStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">;
+def IsAllegrex : Predicate<"Subtarget.isAllegrex()">;
//===----------------------------------------------------------------------===//
// Mips Operand, Complex Patterns and Transformations Definitions.
def uimm16 : Operand<i32>;
def simm16 : Operand<i32>;
def shamt : Operand<i32>;
-def addrlabel : Operand<i32>;
// Address operand
def mem : Operand<i32> {
[], IIAlu>;
// Arithmetic 2 register operands
-let isCommutable = 1 in
class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
Operand Od, PatLeaf imm_type> :
FI< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, uimm16:$c),
!strconcat(instr_asm, " $dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, immSExt16:$c))], IIAlu>;
+ [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>;
class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
FR< op,
instr_asm,
[(set CPURegs:$dst, addr:$addr)], IIAlu>;
+class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
+ FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
+ !strconcat(instr_asm, " $dst, $src"),
+ [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>;
+
+
//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//
// As stack alignment is always done with addiu, we need a 16-bit immediate
let Defs = [SP], Uses = [SP] in {
-def ADJCALLSTACKDOWN : PseudoInstMips<(outs), (ins uimm16:$amt),
- "!ADJCALLSTACKDOWN $amt",
- [(callseq_start imm:$amt)]>;
-def ADJCALLSTACKUP : PseudoInstMips<(outs), (ins uimm16:$amt1, uimm16:$amt2),
- "!ADJCALLSTACKUP $amt1",
- [(callseq_end imm:$amt1, imm:$amt2)]>;
+def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt),
+ "!ADJCALLSTACKDOWN $amt",
+ [(callseq_start imm:$amt)]>;
+def ADJCALLSTACKUP : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2),
+ "!ADJCALLSTACKUP $amt1",
+ [(callseq_end imm:$amt1, imm:$amt2)]>;
}
// When handling PIC code the assembler needs .cpload and .cprestore
// directives. If the real instructions corresponding these directives
// are used, we have the same behavior, but get also a bunch of warnings
// from the assembler.
-def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
- ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>;
-def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
- ".cprestore $loc\n", []>;
+def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg),
+ ".set noreorder\n\t.cpload $reg\n\t.set reorder\n",
+ []>;
+def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc),
+ ".cprestore $loc\n", []>;
+
+// The supported Mips ISAs dont have any instruction close to the SELECT_CC
+// operation. The solution is to create a Mips pseudo SELECT_CC instruction
+// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally
+// replace it for real supported nodes into EmitInstrWithCustomInserter
+let usesCustomDAGSchedInserter = 1 in {
+ def Select_CC : MipsPseudo<(outs CPURegs:$dst),
+ (ins CPURegs:$CmpRes, CPURegs:$T, CPURegs:$F), "# MipsSelect_CC",
+ [(set CPURegs:$dst, (MipsSelectCC CPURegs:$CmpRes,
+ CPURegs:$T, CPURegs:$F))]>;
+}
//===----------------------------------------------------------------------===//
// Instruction definition
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
// immZExt32 is used here so it can match GlobalAddress immediates.
+// MUL is a assembly macro in the current used ISAs.
def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>;
def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
-def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
+//def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>;
def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
def ADD : ArithOverflowR<0x00, 0x20, "add">;
def MTHI : MoveFromTo<0x11, "mthi">;
def MTLO : MoveFromTo<0x13, "mtlo">;
-// Count Leading
-// CLO/CLZ are part of the newer MIPS32(tm) instruction
-// set and not older Mips I keep this for future use
-// though.
-//def CLO : CountLeading<0x21, "clo">;
-//def CLZ : CountLeading<0x20, "clz">;
-
-// MADD*/MSUB* are not part of MipsI either.
-//def MADD : MArithR<0x00, "madd">;
-//def MADDU : MArithR<0x01, "maddu">;
-//def MSUB : MArithR<0x04, "msub">;
-//def MSUBU : MArithR<0x05, "msubu">;
-
// No operation
let addr=0 in
def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>;
// can be matched. It's similar to Sparc LEA_ADDRi
def LEA_ADDiu : EffectiveAddress<"addiu $dst, ${addr:stackloc}">;
+// Count Leading
+// CLO/CLZ are part of the newer MIPS32(tm) instruction
+// set and not older Mips I keep this for future use
+// though.
+//def CLO : CountLeading<0x21, "clo">;
+//def CLZ : CountLeading<0x20, "clz">;
+
+// MADD*/MSUB* are not part of MipsI either.
+//def MADD : MArithR<0x00, "madd">;
+//def MADDU : MArithR<0x01, "maddu">;
+//def MSUB : MArithR<0x04, "msub">;
+//def MSUBU : MArithR<0x05, "msubu">;
+
+let Predicates = [IsAllegrex] in {
+ let shamt = 0x10, rs = 0 in
+ def SEB : SignExtInReg<0x21, "seb", i8>;
+
+ let shamt = 0x18, rs = 0 in
+ def SEH : SignExtInReg<0x20, "seh", i16>;
+}
+
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
def : Pat<(i32 imm:$imm),
(ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>;
+// Carry patterns
+def : Pat<(subc CPURegs:$lhs, CPURegs:$rhs),
+ (SUBu CPURegs:$lhs, CPURegs:$rhs)>;
+def : Pat<(addc CPURegs:$lhs, CPURegs:$rhs),
+ (ADDu CPURegs:$lhs, CPURegs:$rhs)>;
+def : Pat<(addc CPURegs:$src, imm:$imm),
+ (ADDiu CPURegs:$src, imm:$imm)>;
+
// Call
def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
(JAL tglobaladdr:$dst)>;
def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)),
(ADDiu CPURegs:$hi, tjumptable:$lo)>;
-// Mips does not have not, so we increase the operation
+// Mips does not have "not", so we expand our way
def : Pat<(not CPURegs:$in),
(NOR CPURegs:$in, ZERO)>;
def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>;
def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
-// some peepholes
+// peepholes
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
-///
-/// brcond patterns
-///
-
+// brcond patterns
// direct match equal/notequal zero branches
def : Pat<(brcond (setne CPURegs:$lhs, 0), bb:$dst),
(BNE CPURegs:$lhs, ZERO, bb:$dst)>;
def : Pat<(brcond CPURegs:$cond, bb:$dst),
(BNE CPURegs:$cond, ZERO, bb:$dst)>;
-///
/// setcc patterns, only matched when there
/// is no brcond following a setcc operation
-///
-
-// setcc 2 register operands
def : Pat<(setle CPURegs:$lhs, CPURegs:$rhs),
(XORi (SLT CPURegs:$rhs, CPURegs:$lhs), 1)>;
def : Pat<(setule CPURegs:$lhs, CPURegs:$rhs),
(XORi (OR (SLT CPURegs:$lhs, CPURegs:$rhs),
(SLT CPURegs:$rhs, CPURegs:$lhs)), 1)>;
-// setcc reg/imm operands
def : Pat<(setge CPURegs:$lhs, immSExt16:$rhs),
(XORi (SLTi CPURegs:$lhs, immSExt16:$rhs), 1)>;
def : Pat<(setuge CPURegs:$lhs, immZExt16:$rhs),
(XORi (SLTiu CPURegs:$lhs, immZExt16:$rhs), 1)>;
+
+//===----------------------------------------------------------------------===//
+// Floating Point Support
+//===----------------------------------------------------------------------===//
+
+include "MipsInstrFPU.td"
+