[SDTCisVT<0, i32>,
SDTCisSameAs<0, 1>]>;
+def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
+
+def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
+ SDTCisVT<1, iPTR>]>;
+
// Call
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink,
[SDNPHasChain, SDNPOutGlue, SDNPOptInGlue,
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>;
+// TlsGd node is used to handle General Dynamic TLS
+def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>;
+
+// TprelHi and TprelLo nodes are used to handle Local Exec TLS
+def MipsTprelHi : SDNode<"MipsISD::TprelHi", SDTIntUnaryOp>;
+def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>;
+
+// Thread pointer
+def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>;
+
// Return
def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
SDNPOptInGlue]>;
def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem,
[SDNPOutGlue]>;
-// wrapper node
+// Target constant nodes that are not part of any isel patterns and remain
+// unchanged can cause instructions with illegal operands to be emitted.
+// 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
+// compiled:
+// movn %got(d)($gp), %got(c)($gp), $4
+// This instruction is illegal since movn can take only register operands.
+
def MipsWrapperPIC : SDNode<"MipsISD::WrapperPIC", SDTIntUnaryOp>;
+// Pointer to dynamically allocated stack area.
+def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc,
+ [SDNPHasChain, SDNPInGlue]>;
+
//===----------------------------------------------------------------------===//
// Mips Instruction Predicate Definitions.
//===----------------------------------------------------------------------===//
CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"),
[], NoItinerary>;
+// Read Hardware
+class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$dst), (ins HWRegs:$src),
+ "rdhwr\t$dst, $src", [], IIAlu> {
+ let rs = 0;
+ let shamt = 0;
+}
+
//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc\n", []>;
+let usesCustomInserter = 1 in {
+ def ATOMIC_LOAD_ADD_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_add_8\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_add_8 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_ADD_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_add_16\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_add_16 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_ADD_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_add_32\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_add_32 CPURegs:$ptr, CPURegs:$incr))]>;
+
+ def ATOMIC_LOAD_SUB_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_sub_8\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_sub_8 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_SUB_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_sub_16\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_sub_16 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_SUB_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_sub_32\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_sub_32 CPURegs:$ptr, CPURegs:$incr))]>;
+
+ def ATOMIC_LOAD_AND_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_and_8\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_and_8 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_AND_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_and_16\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_and_16 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_AND_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_and_32\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_and_32 CPURegs:$ptr, CPURegs:$incr))]>;
+
+ def ATOMIC_LOAD_OR_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_or_8\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_or_8 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_OR_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_or_16\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_or_16 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_OR_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_or_32\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_or_32 CPURegs:$ptr, CPURegs:$incr))]>;
+
+ def ATOMIC_LOAD_XOR_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_xor_8\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_xor_8 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_XOR_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_xor_16\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_xor_16 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_XOR_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_xor_32\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_xor_32 CPURegs:$ptr, CPURegs:$incr))]>;
+
+ def ATOMIC_LOAD_NAND_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_nand_8\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_nand_8 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_NAND_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_nand_16\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_nand_16 CPURegs:$ptr, CPURegs:$incr))]>;
+ def ATOMIC_LOAD_NAND_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ "atomic_load_nand_32\t$dst, $ptr, $incr",
+ [(set CPURegs:$dst, (atomic_load_nand_32 CPURegs:$ptr, CPURegs:$incr))]>;
+
+ def ATOMIC_SWAP_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val),
+ "atomic_swap_8\t$dst, $ptr, $val",
+ [(set CPURegs:$dst, (atomic_swap_8 CPURegs:$ptr, CPURegs:$val))]>;
+ def ATOMIC_SWAP_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val),
+ "atomic_swap_16\t$dst, $ptr, $val",
+ [(set CPURegs:$dst, (atomic_swap_16 CPURegs:$ptr, CPURegs:$val))]>;
+ def ATOMIC_SWAP_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val),
+ "atomic_swap_32\t$dst, $ptr, $val",
+ [(set CPURegs:$dst, (atomic_swap_32 CPURegs:$ptr, CPURegs:$val))]>;
+
+ def ATOMIC_CMP_SWAP_I8 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval),
+ "atomic_cmp_swap_8\t$dst, $ptr, $oldval, $newval",
+ [(set CPURegs:$dst,
+ (atomic_cmp_swap_8 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>;
+ def ATOMIC_CMP_SWAP_I16 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval),
+ "atomic_cmp_swap_16\t$dst, $ptr, $oldval, $newval",
+ [(set CPURegs:$dst,
+ (atomic_cmp_swap_16 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>;
+ def ATOMIC_CMP_SWAP_I32 : MipsPseudo<
+ (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval),
+ "atomic_cmp_swap_32\t$dst, $ptr, $oldval, $newval",
+ [(set CPURegs:$dst,
+ (atomic_cmp_swap_32 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>;
+}
+
//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//
def SH : StoreM<0x29, "sh", truncstorei16>;
def SW : StoreM<0x2b, "sw", store>;
+/// Load-linked, Store-conditional
+let hasDelaySlot = 1 in
+ def LL : FI<0x30, (outs CPURegs:$dst), (ins mem:$addr),
+ "ll\t$dst, $addr", [], IILoad>;
+let Constraints = "$src = $dst" in
+ def SC : FI<0x38, (outs CPURegs:$dst), (ins CPURegs:$src, mem:$addr),
+ "sc\t$src, $addr", [], IIStore>;
+
/// Jump and Branch Instructions
def J : JumpFJ<0x02, "j">;
def JR : JumpFR<0x00, 0x08, "jr">;
// can be matched. It's similar to Sparc LEA_ADDRi
def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">;
+// DynAlloc node points to dynamically allocated stack space.
+// $sp is added to the list of implicitly used registers to prevent dead code
+// elimination from removing instructions that modify $sp.
+let Uses = [SP] in
+def DynAlloc : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">;
+
// MADD*/MSUB*
def MADD : MArithR<0, "madd", MipsMAdd, 1>;
def MADDU : MArithR<1, "maddu", MipsMAddu, 1>;
// it is a real instruction.
def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul, 1>, Requires<[IsMips32]>;
+def RDHWR : ReadHardware;
+
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)),
(ADDiu CPURegs:$gp, tconstpool:$in)>;
+// tlsgd
+def : Pat<(add CPURegs:$gp, (MipsTlsGd tglobaltlsaddr:$in)),
+ (ADDiu CPURegs:$gp, tglobaltlsaddr:$in)>;
+
+// tprel hi/lo
+def : Pat<(MipsTprelHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>;
+def : Pat<(add CPURegs:$hi, (MipsTprelLo tglobaltlsaddr:$lo)),
+ (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>;
+
// wrapper_pic
class WrapperPICPat<SDNode node>:
Pat<(MipsWrapperPIC node:$in),
def : Pat<(setuge CPURegs:$lhs, immSExt16:$rhs),
(XORi (SLTiu CPURegs:$lhs, immSExt16:$rhs), 1)>;
+// select MipsDynAlloc
+def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>;
+
//===----------------------------------------------------------------------===//
// Floating Point Support
//===----------------------------------------------------------------------===//