X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsInstrInfo.td;h=2c1893044b01abcecaaa86d5a0bf9e1f0af5d78a;hb=b07a3d68972039426a87f1cac82e348e3bb1877b;hp=ddf18d88ac7bfa332b22e524133d74b23ac9fe9b;hpb=91ef849e6cb01a019dc50ed4e95c058e01616062;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index ddf18d88ac7..2c1893044b0 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -1,4 +1,4 @@ -//===- MipsInstrInfo.td - Mips Register defs --------------------*- C++ -*-===// +//===- MipsInstrInfo.td - Target Description for Mips Target -*- tablegen -*-=// // // The LLVM Compiler Infrastructure // @@ -6,6 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// This file contains the Mips implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Instruction format superclass @@ -19,39 +23,115 @@ include "MipsInstrFormats.td" 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, 2>, - SDTCisSameAs<2, 3>, SDTCisInt<1>]>; +def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>, + SDTCisSameAs<3, 4>, + SDTCisInt<4>]>; def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def SDT_MipsMAddMSub : SDTypeProfile<0, 4, + [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>, + SDTCisSameAs<2, 3>]>; +def SDT_MipsDivRem : SDTypeProfile<0, 2, + [SDTCisInt<0>, + SDTCisSameAs<0, 1>]>; + +def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; + +def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, + SDTCisVT<1, iPTR>]>; +def SDT_Sync : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; + +def SDT_Ext : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>, SDTCisSameAs<2, 3>]>; +def SDT_Ins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>, SDTCisSameAs<2, 3>, + SDTCisSameAs<0, 4>]>; // Call -def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, - SDNPOutFlag]>; +def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, + SDNPVariadic]>; -// Hi and Lo nodes are used to handle global addresses. Used on -// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol +// Hi and Lo nodes are used to handle global addresses. Used on +// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol // static model. (nothing to do with Mips Registers Hi and Lo) def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; 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, - SDNPOptInFlag]>; +def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, + SDNPOptInGlue]>; // These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, - [SDNPHasChain, SDNPOutFlag]>; + [SDNPHasChain, SDNPOutGlue]>; def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, - [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; - -// Select Condition Code -def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>; + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +// MAdd*/MSub* nodes +def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; + +// DivRem(u) nodes +def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem, + [SDNPOutGlue]>; +def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, + [SDNPOutGlue]>; + +// 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]>; + +def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain]>; + +def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>; +def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>; //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// -def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">; +def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">; +def HasBitCount : Predicate<"Subtarget.hasBitCount()">; +def HasSwap : Predicate<"Subtarget.hasSwap()">; +def HasCondMov : Predicate<"Subtarget.hasCondMov()">; +def HasMips32 : Predicate<"Subtarget.hasMips32()">; +def HasMips32r2 : Predicate<"Subtarget.hasMips32r2()">; +def HasMips64 : Predicate<"Subtarget.hasMips64()">; +def NotMips64 : Predicate<"!Subtarget.hasMips64()">; +def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">; +def IsN64 : Predicate<"Subtarget.isABI_N64()">; +def NotN64 : Predicate<"!Subtarget.isABI_N64()">; //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. @@ -60,34 +140,44 @@ def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">; // Instruction operand types def brtarget : Operand; def calltarget : Operand; -def uimm16 : Operand; def simm16 : Operand; +def simm16_64 : Operand; def shamt : Operand; +// Unsigned Operand +def uimm16 : Operand { + let PrintMethod = "printUnsignedImm"; +} + // Address operand def mem : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops simm16, CPURegs); + let MIOperandInfo = (ops CPURegs, simm16); +} + +def mem64 : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops CPU64Regs, simm16_64); +} + +def mem_ea : Operand { + let PrintMethod = "printMemOperandEA"; + let MIOperandInfo = (ops CPURegs, simm16); } // Transformation Function - get the lower 16 bits. def LO16 : SDNodeXFormgetValue() & 0xFFFF); + return getI32Imm((unsigned)N->getZExtValue() & 0xFFFF); }]>; // Transformation Function - get the higher 16 bits. def HI16 : SDNodeXFormgetValue() >> 16); + return getI32Imm((unsigned)N->getZExtValue() >> 16); }]>; // Node immediate fits as 16-bit sign extended on target immediate. // e.g. addi, andi -def immSExt16 : PatLeaf<(imm), [{ - if (N->getValueType(0) == MVT::i32) - return (int32_t)N->getValue() == (short)N->getValue(); - else - return (int64_t)N->getValue() == (short)N->getValue(); -}]>; +def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; // Node immediate fits as 16-bit zero extended on target immediate. // The LO16 param means that only the lower 16 bits of the node @@ -95,104 +185,142 @@ def immSExt16 : PatLeaf<(imm), [{ // e.g. addiu, sltiu def immZExt16 : PatLeaf<(imm), [{ if (N->getValueType(0) == MVT::i32) - return (uint32_t)N->getValue() == (unsigned short)N->getValue(); + return (uint32_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); else - return (uint64_t)N->getValue() == (unsigned short)N->getValue(); + return (uint64_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); }], LO16>; // shamt field must fit in 5 bits. def immZExt5 : PatLeaf<(imm), [{ - return N->getValue() == ((N->getValue()) & 0x1f) ; + return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ; }]>; // Mips Address Mode! SDNode frameindex could possibily be a match // since load and store instructions from stack used it. -def addr : ComplexPattern; +def addr : ComplexPattern; + +//===----------------------------------------------------------------------===// +// Pattern fragment for load/store +//===----------------------------------------------------------------------===// +class UnalignedLoad : PatFrag<(ops node:$ptr), (Node node:$ptr), [{ + LoadSDNode *LD = cast(N); + return LD->getMemoryVT().getSizeInBits()/8 > LD->getAlignment(); +}]>; + +class AlignedLoad : PatFrag<(ops node:$ptr), (Node node:$ptr), [{ + LoadSDNode *LD = cast(N); + return LD->getMemoryVT().getSizeInBits()/8 <= LD->getAlignment(); +}]>; + +class UnalignedStore : PatFrag<(ops node:$val, node:$ptr), + (Node node:$val, node:$ptr), [{ + StoreSDNode *SD = cast(N); + return SD->getMemoryVT().getSizeInBits()/8 > SD->getAlignment(); +}]>; + +class AlignedStore : PatFrag<(ops node:$val, node:$ptr), + (Node node:$val, node:$ptr), [{ + StoreSDNode *SD = cast(N); + return SD->getMemoryVT().getSizeInBits()/8 <= SD->getAlignment(); +}]>; + +// Load/Store PatFrags. +def sextloadi16_a : AlignedLoad; +def zextloadi16_a : AlignedLoad; +def extloadi16_a : AlignedLoad; +def load_a : AlignedLoad; +def sextloadi32_a : AlignedLoad; +def zextloadi32_a : AlignedLoad; +def extloadi32_a : AlignedLoad; +def truncstorei16_a : AlignedStore; +def store_a : AlignedStore; +def truncstorei32_a : AlignedStore; +def sextloadi16_u : UnalignedLoad; +def zextloadi16_u : UnalignedLoad; +def extloadi16_u : UnalignedLoad; +def load_u : UnalignedLoad; +def sextloadi32_u : UnalignedLoad; +def zextloadi32_u : UnalignedLoad; +def extloadi32_u : UnalignedLoad; +def truncstorei16_u : UnalignedStore; +def store_u : UnalignedStore; +def truncstorei32_u : UnalignedStore; //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// // Arithmetic 3 register operands -let isCommutable = 1 in class ArithR op, bits<6> func, string instr_asm, SDNode OpNode, - InstrItinClass itin>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; + InstrItinClass itin, bit isComm = 0>: + FR { + let isCommutable = isComm; +} -let isCommutable = 1 in -class ArithOverflowR op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [], IIAlu>; +class ArithOverflowR op, bits<6> func, string instr_asm, + bit isComm = 0>: + FR { + let isCommutable = isComm; +} // Arithmetic 2 register operands class ArithI op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; + FI; + +class ArithOverflowI op, string instr_asm, SDNode OpNode, + Operand Od, PatLeaf imm_type> : + FI; // Arithmetic Multiply ADD/SUB -let rd=0 in -class MArithR func, string instr_asm> : - FR< 0x1c, - func, - (outs CPURegs:$rs), - (ins CPURegs:$rt), - !strconcat(instr_asm, "\t$rs, $rt"), - [], IIImul>; +let rd = 0, shamt = 0, Defs = [HI, LO], Uses = [HI, LO] in +class MArithR func, string instr_asm, SDNode op, bit isComm = 0> : + FR<0x1c, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, "\t$rs, $rt"), + [(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul> { + let isCommutable = isComm; +} // Logical +let isCommutable = 1 in class LogicR func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; class LogicI op, string instr_asm, SDNode OpNode>: - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, uimm16:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>; + FI; +let isCommutable = 1 in class LogicNOR op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>; + FR; // Shifts -let rt = 0 in -class LogicR_shift_imm func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, shamt:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu>; +class LogicR_shift_rotate_imm func, bits<5> _rs, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, shamt:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, (i32 immZExt5:$c)))], IIAlu> { + let rs = _rs; +} -class LogicR_shift_reg func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; +class LogicR_shift_rotate_reg func, bits<5> _shamt, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu> { + let shamt = _shamt; +} // Load Upper Imediate class LoadUpper op, string instr_asm>: @@ -203,155 +331,216 @@ class LoadUpper op, string instr_asm>: [], IIAlu>; // Memory Load/Store -let isSimpleLoad = 1, hasDelaySlot = 1 in -class LoadM op, string instr_asm, PatFrag OpNode>: - FI< op, - (outs CPURegs:$dst), - (ins mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>; +let canFoldAsLoad = 1 in +class LoadM op, string instr_asm, PatFrag OpNode, RegisterClass RC, + Operand MemOpnd, bit Pseudo>: + FI { + let isPseudo = Pseudo; +} -class StoreM op, string instr_asm, PatFrag OpNode>: - FI< op, - (outs), - (ins CPURegs:$dst, mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(OpNode CPURegs:$dst, addr:$addr)], IIStore>; +class StoreM op, string instr_asm, PatFrag OpNode, RegisterClass RC, + Operand MemOpnd, bit Pseudo>: + FI { + let isPseudo = Pseudo; +} -// Conditional Branch -let isBranch = 1, isTerminator=1, hasDelaySlot = 1 in { -class CBranch op, string instr_asm, PatFrag cond_op>: - FI< op, - (outs), - (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), - !strconcat(instr_asm, "\t$a, $b, $offset"), - [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], - IIBranch>; +// 32-bit load. +multiclass LoadM32 op, string instr_asm, PatFrag OpNode, + bit Pseudo = 0> { + def #NAME# : LoadM, + Requires<[NotN64]>; + def _P8 : LoadM, + Requires<[IsN64]>; +} + +// 64-bit load. +multiclass LoadM64 op, string instr_asm, PatFrag OpNode, + bit Pseudo = 0> { + def #NAME# : LoadM, + Requires<[NotN64]>; + def _P8 : LoadM, + Requires<[IsN64]>; +} + +// 32-bit store. +multiclass StoreM32 op, string instr_asm, PatFrag OpNode, + bit Pseudo = 0> { + def #NAME# : StoreM, + Requires<[NotN64]>; + def _P8 : StoreM, + Requires<[IsN64]>; +} +// 64-bit store. +multiclass StoreM64 op, string instr_asm, PatFrag OpNode, + bit Pseudo = 0> { + def #NAME# : StoreM, + Requires<[NotN64]>; + def _P8 : StoreM, + Requires<[IsN64]>; +} -class CBranchZero op, string instr_asm, PatFrag cond_op>: - FI< op, - (outs), - (ins CPURegs:$src, brtarget:$offset), - !strconcat(instr_asm, "\t$src, $offset"), - [(brcond (cond_op CPURegs:$src, 0), bb:$offset)], - IIBranch>; +// Conditional Branch +class CBranch op, string instr_asm, PatFrag cond_op, RegisterClass RC>: + CBranchBase { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; } -// SetCC -class SetCC_R op, bits<6> func, string instr_asm, - PatFrag cond_op>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))], - IIAlu>; +class CBranchZero op, bits<5> _rt, string instr_asm, PatFrag cond_op, + RegisterClass RC>: + CBranchBase { + let rt = _rt; + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; +} -class SetCC_I op, string instr_asm, PatFrag cond_op, - Operand Od, PatLeaf imm_type>: - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))], - IIAlu>; +// SetCC +class SetCC_R op, bits<6> func, string instr_asm, PatFrag cond_op, + RegisterClass RC>: + FR; + +class SetCC_I op, string instr_asm, PatFrag cond_op, Operand Od, + PatLeaf imm_type, RegisterClass RC>: + FI; // Unconditional branch let isBranch=1, isTerminator=1, isBarrier=1, hasDelaySlot = 1 in class JumpFJ op, string instr_asm>: - FJ< op, - (outs), - (ins brtarget:$target), - !strconcat(instr_asm, "\t$target"), - [(br bb:$target)], IIBranch>; + FJ; let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in class JumpFR op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs), - (ins CPURegs:$target), - !strconcat(instr_asm, "\t$target"), - [(brind CPURegs:$target)], IIBranch>; + FR; // Jump and Link (Call) let isCall=1, hasDelaySlot=1, // All calls clobber the non-callee saved registers... - Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, - T3, T4, T5, T6, T7, T8, T9, K0, K1], Uses = [GP] in { + Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { class JumpLink op, string instr_asm>: - FJ< op, - (outs), - (ins calltarget:$target), - !strconcat(instr_asm, "\t$target"), - [(MipsJmpLink imm:$target)], IIBranch>; + FJ; let rd=31 in class JumpLinkReg op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs), - (ins CPURegs:$rs), - !strconcat(instr_asm, "\t$rs"), - [(MipsJmpLink CPURegs:$rs)], IIBranch>; + FR; class BranchLink: - FI< 0x1, - (outs), - (ins CPURegs:$rs, brtarget:$target), - !strconcat(instr_asm, "\t$rs, $target"), - [], IIBranch>; + FI<0x1, (outs), (ins CPURegs:$rs, brtarget:$target, variable_ops), + !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch>; } // Mul, Div -class MulDiv func, string instr_asm, InstrItinClass itin>: - FR< 0x00, - func, - (outs), - (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$a, $b"), - [], itin>; +let Defs = [HI, LO] in { + let isCommutable = 1 in + class Mul func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$a, $b"), [], itin>; + + class Div func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$$zero, $a, $b"), + [(op CPURegs:$a, CPURegs:$b)], itin>; +} // Move from Hi/Lo +let shamt = 0 in { +let rs = 0, rt = 0 in class MoveFromLOHI func, string instr_asm>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins), - !strconcat(instr_asm, "\t$dst"), - [], IIHiLo>; + FR<0x00, func, (outs CPURegs:$dst), (ins), + !strconcat(instr_asm, "\t$dst"), [], IIHiLo>; +let rt = 0, rd = 0 in class MoveToLOHI func, string instr_asm>: - FR< 0x00, - func, - (outs), - (ins CPURegs:$src), - !strconcat(instr_asm, "\t$src"), - [], IIHiLo>; - -// Count Leading Ones/Zeros in Word -class CountLeading func, string instr_asm>: - FR< 0x1c, - func, - (outs CPURegs:$dst), - (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [], IIAlu>; + FR<0x00, func, (outs), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$src"), [], IIHiLo>; +} class EffectiveAddress : - FI<0x09, - (outs CPURegs:$dst), - (ins mem:$addr), - instr_asm, - [(set CPURegs:$dst, addr:$addr)], IIAlu>; + FI<0x09, (outs CPURegs:$dst), (ins mem_ea:$addr), + instr_asm, [(set CPURegs:$dst, addr:$addr)], IIAlu>; +// Count Leading Ones/Zeros in Word +class CountLeading func, string instr_asm, list pattern>: + FR<0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>, + Requires<[HasBitCount]> { + let shamt = 0; + let rt = rd; +} + +// Sign Extend in Register. class SignExtInReg func, string instr_asm, ValueType vt>: - FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; + FR<0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), + [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; + +// Byte Swap +class ByteSwap func, string instr_asm>: + FR<0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), + [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>; + +// Conditional Move +class CondMov func, string instr_asm, PatLeaf MovCode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T, + 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; +} +// Ext and Ins +class ExtIns _funct, string instr_asm, dag outs, dag ins, + list pattern, InstrItinClass itin>: + FR<0x1f, _funct, outs, ins, !strconcat(instr_asm, " $rt, $rs, $pos, $sz"), + pattern, itin>, Requires<[HasMips32r2]> { + bits<5> pos; + bits<5> sz; + let rd = sz; + let shamt = pos; +} + +// Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*). +class Atomic2Ops : + MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + !strconcat("atomic_", Opstr, "\t$dst, $ptr, $incr"), + [(set CPURegs:$dst, + (Op CPURegs:$ptr, CPURegs:$incr))]>; + +// Atomic Compare & Swap. +class AtomicCmpSwap : + MipsPseudo<(outs CPURegs:$dst), + (ins CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap), + !strconcat("atomic_cmp_swap_", Width, + "\t$dst, $ptr, $cmp, $swap"), + [(set CPURegs:$dst, + (Op CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap))]>; //===----------------------------------------------------------------------===// // Pseudo instructions @@ -361,10 +550,10 @@ class SignExtInReg func, string instr_asm, ValueType vt>: let Defs = [SP], Uses = [SP] in { def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt), "!ADJCALLSTACKDOWN $amt", - [(callseq_start imm:$amt)]>; + [(callseq_start timm:$amt)]>; def ADJCALLSTACKUP : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2), "!ADJCALLSTACKUP $amt1", - [(callseq_end imm:$amt1, imm:$amt2)]>; + [(callseq_end timm:$amt1, timm:$amt2)]>; } // Some assembly macros need to avoid pseudoinstructions and assembler @@ -374,25 +563,47 @@ def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>; def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>; def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>; +// These macros are inserted to prevent GAS from complaining +// when using the AT register. +def NOAT : MipsPseudo<(outs), (ins), ".set\tnoat", []>; +def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; + // 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 : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; -def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$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 { - class PseudoSelCC: - MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, - [(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>; +def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>; + +let usesCustomInserter = 1 in { + def ATOMIC_LOAD_ADD_I8 : Atomic2Ops; + def ATOMIC_LOAD_ADD_I16 : Atomic2Ops; + def ATOMIC_LOAD_ADD_I32 : Atomic2Ops; + def ATOMIC_LOAD_SUB_I8 : Atomic2Ops; + def ATOMIC_LOAD_SUB_I16 : Atomic2Ops; + def ATOMIC_LOAD_SUB_I32 : Atomic2Ops; + def ATOMIC_LOAD_AND_I8 : Atomic2Ops; + def ATOMIC_LOAD_AND_I16 : Atomic2Ops; + def ATOMIC_LOAD_AND_I32 : Atomic2Ops; + def ATOMIC_LOAD_OR_I8 : Atomic2Ops; + def ATOMIC_LOAD_OR_I16 : Atomic2Ops; + def ATOMIC_LOAD_OR_I32 : Atomic2Ops; + def ATOMIC_LOAD_XOR_I8 : Atomic2Ops; + def ATOMIC_LOAD_XOR_I16 : Atomic2Ops; + def ATOMIC_LOAD_XOR_I32 : Atomic2Ops; + def ATOMIC_LOAD_NAND_I8 : Atomic2Ops; + def ATOMIC_LOAD_NAND_I16 : Atomic2Ops; + def ATOMIC_LOAD_NAND_I32 : Atomic2Ops; + + def ATOMIC_SWAP_I8 : Atomic2Ops; + def ATOMIC_SWAP_I16 : Atomic2Ops; + def ATOMIC_SWAP_I32 : Atomic2Ops; + + def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap; + def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap; + def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap; } -def Select_CC : PseudoSelCC; - //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -402,61 +613,88 @@ def Select_CC : PseudoSelCC; //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) -def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>; -def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>; -def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>; -def SLTiu : SetCC_I<0x0b, "sltiu", setult, uimm16, immZExt16>; +def ADDiu : ArithI<0x09, "addiu", add, simm16, immSExt16>; +def ADDi : ArithOverflowI<0x08, "addi", add, simm16, immSExt16>; +def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16, CPURegs>; +def SLTiu : SetCC_I<0x0b, "sltiu", setult, simm16, immSExt16, CPURegs>; def ANDi : LogicI<0x0c, "andi", and>; def ORi : LogicI<0x0d, "ori", or>; def XORi : LogicI<0x0e, "xori", xor>; def LUi : LoadUpper<0x0f, "lui">; /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>; +def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu, 1>; def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>; -def ADD : ArithOverflowR<0x00, 0x20, "add">; +def ADD : ArithOverflowR<0x00, 0x20, "add", 1>; def SUB : ArithOverflowR<0x00, 0x22, "sub">; -def SLT : SetCC_R<0x00, 0x2a, "slt", setlt>; -def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult>; +def SLT : SetCC_R<0x00, 0x2a, "slt", setlt, CPURegs>; +def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult, CPURegs>; def AND : LogicR<0x24, "and", and>; def OR : LogicR<0x25, "or", or>; def XOR : LogicR<0x26, "xor", xor>; def NOR : LogicNOR<0x00, 0x27, "nor">; /// Shift Instructions -def SLL : LogicR_shift_imm<0x00, "sll", shl>; -def SRL : LogicR_shift_imm<0x02, "srl", srl>; -def SRA : LogicR_shift_imm<0x03, "sra", sra>; -def SLLV : LogicR_shift_reg<0x04, "sllv", shl>; -def SRLV : LogicR_shift_reg<0x06, "srlv", srl>; -def SRAV : LogicR_shift_reg<0x07, "srav", sra>; +def SLL : LogicR_shift_rotate_imm<0x00, 0x00, "sll", shl>; +def SRL : LogicR_shift_rotate_imm<0x02, 0x00, "srl", srl>; +def SRA : LogicR_shift_rotate_imm<0x03, 0x00, "sra", sra>; +def SLLV : LogicR_shift_rotate_reg<0x04, 0x00, "sllv", shl>; +def SRLV : LogicR_shift_rotate_reg<0x06, 0x00, "srlv", srl>; +def SRAV : LogicR_shift_rotate_reg<0x07, 0x00, "srav", sra>; + +// Rotate Instructions +let Predicates = [HasMips32r2] in { + def ROTR : LogicR_shift_rotate_imm<0x02, 0x01, "rotr", rotr>; + def ROTRV : LogicR_shift_rotate_reg<0x06, 0x01, "rotrv", rotr>; +} /// Load and Store Instructions -def LB : LoadM<0x20, "lb", sextloadi8>; -def LBu : LoadM<0x24, "lbu", zextloadi8>; -def LH : LoadM<0x21, "lh", sextloadi16>; -def LHu : LoadM<0x25, "lhu", zextloadi16>; -def LW : LoadM<0x23, "lw", load>; -def SB : StoreM<0x28, "sb", truncstorei8>; -def SH : StoreM<0x29, "sh", truncstorei16>; -def SW : StoreM<0x2b, "sw", store>; +/// aligned +defm LB : LoadM32<0x20, "lb", sextloadi8>; +defm LBu : LoadM32<0x24, "lbu", zextloadi8>; +defm LH : LoadM32<0x21, "lh", sextloadi16_a>; +defm LHu : LoadM32<0x25, "lhu", zextloadi16_a>; +defm LW : LoadM32<0x23, "lw", load_a>; +defm SB : StoreM32<0x28, "sb", truncstorei8>; +defm SH : StoreM32<0x29, "sh", truncstorei16_a>; +defm SW : StoreM32<0x2b, "sw", store_a>; + +/// unaligned +defm ULH : LoadM32<0x21, "ulh", sextloadi16_u, 1>; +defm ULHu : LoadM32<0x25, "ulhu", zextloadi16_u, 1>; +defm ULW : LoadM32<0x23, "ulw", load_u, 1>; +defm USH : StoreM32<0x29, "ush", truncstorei16_u, 1>; +defm USW : StoreM32<0x2b, "usw", store_u, 1>; + +let hasSideEffects = 1 in +def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype", + [(MipsSync imm:$stype)], NoItinerary> +{ + let opcode = 0; + let Inst{25-11} = 0; + let Inst{5-0} = 15; +} + +/// Load-linked, Store-conditional +let mayLoad = 1 in + def LL : FI<0x30, (outs CPURegs:$dst), (ins mem:$addr), + "ll\t$dst, $addr", [], IILoad>; +let mayStore = 1, 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">; +let isIndirectBranch = 1 in + def JR : JumpFR<0x00, 0x08, "jr">; def JAL : JumpLink<0x03, "jal">; def JALR : JumpLinkReg<0x00, 0x09, "jalr">; -def BEQ : CBranch<0x04, "beq", seteq>; -def BNE : CBranch<0x05, "bne", setne>; - -let rt=1 in - def BGEZ : CBranchZero<0x01, "bgez", setge>; - -let rt=0 in { - def BGTZ : CBranchZero<0x07, "bgtz", setgt>; - def BLEZ : CBranchZero<0x07, "blez", setle>; - def BLTZ : CBranchZero<0x01, "bltz", setlt>; -} +def BEQ : CBranch<0x04, "beq", seteq, CPURegs>; +def BNE : CBranch<0x05, "bne", setne, CPURegs>; +def BGEZ : CBranchZero<0x01, 1, "bgez", setge, CPURegs>; +def BGTZ : CBranchZero<0x07, 0, "bgtz", setgt, CPURegs>; +def BLEZ : CBranchZero<0x07, 0, "blez", setle, CPURegs>; +def BLTZ : CBranchZero<0x01, 0, "bltz", setlt, CPURegs>; def BGEZAL : BranchLink<"bgezal">; def BLTZAL : BranchLink<"bltzal">; @@ -466,13 +704,11 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target), "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>; -/// Multiply and Divide Instructions. -let Defs = [HI, LO] in { - def MULT : MulDiv<0x18, "mult", IIImul>; - def MULTu : MulDiv<0x19, "multu", IIImul>; - def DIV : MulDiv<0x1a, "div", IIIdiv>; - def DIVu : MulDiv<0x1b, "divu", IIIdiv>; -} +/// Multiply and Divide Instructions. +def MULT : Mul<0x18, "mult", IIImul>; +def MULTu : Mul<0x19, "multu", IIImul>; +def SDIV : Div; +def UDIV : Div; let Defs = [HI] in def MTHI : MoveToLOHI<0x11, "mthi">; @@ -486,13 +722,43 @@ let Uses = [LO] in /// Sign Ext In Register Instructions. let Predicates = [HasSEInReg] in { - let shamt = 0x10, rs = 0 in + let shamt = 0x10, rs = 0 in def SEB : SignExtInReg<0x21, "seb", i8>; - let shamt = 0x18, rs = 0 in + let shamt = 0x18, rs = 0 in def SEH : SignExtInReg<0x20, "seh", i16>; } +/// Count Leading +def CLZ : CountLeading<0b100000, "clz", + [(set CPURegs:$dst, (ctlz CPURegs:$src))]>; +def CLO : CountLeading<0b100001, "clo", + [(set CPURegs:$dst, (ctlz (not CPURegs:$src)))]>; + +/// Byte Swap +let Predicates = [HasSwap] in { + let shamt = 0x3, rs = 0 in + def WSBW : ByteSwap<0x20, "wsbw">; +} + +/// Conditional Move +def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>; +def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>; + +// Conditional moves: +// These instructions are expanded in +// MipsISelLowering::EmitInstrWithCustomInserter if target does not have +// conditional move instructions. +// flag:int, data:int +let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in + class CondMovIntInt funct, string instr_asm> : + FR<0, funct, (outs CPURegs:$dst), + (ins CPURegs:$T, CPURegs:$cond, CPURegs:$F), + !strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>; + +def MOVZ_I : CondMovIntInt<0x0a, "movz">; +def MOVN_I : CondMovIntInt<0x0b, "movn">; + /// No operation let addr=0 in def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>; @@ -501,24 +767,39 @@ let addr=0 in // 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\t$dst, ${addr:stackloc}">; +def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, $addr">; -// 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">; +// 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">; -// 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">; +// MADD*/MSUB* +def MADD : MArithR<0, "madd", MipsMAdd, 1>; +def MADDU : MArithR<1, "maddu", MipsMAddu, 1>; +def MSUB : MArithR<4, "msub", MipsMSub>; +def MSUBU : MArithR<5, "msubu", MipsMSubu>; // MUL is a assembly macro in the current used ISAs. In recent ISA's // it is a real instruction. -//def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; +def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul, 1>, Requires<[HasMips32]>; + +def RDHWR : ReadHardware; + +def EXT : ExtIns<0, "ext", (outs CPURegs:$rt), + (ins CPURegs:$rs, uimm16:$pos, uimm16:$sz), + [(set CPURegs:$rt, + (MipsExt CPURegs:$rs, immZExt5:$pos, immZExt5:$sz))], + NoItinerary>; + +let Constraints = "$src = $rt" in +def INS : ExtIns<4, "ins", (outs CPURegs:$rt), + (ins CPURegs:$rs, uimm16:$pos, uimm16:$sz, CPURegs:$src), + [(set CPURegs:$rt, + (MipsIns CPURegs:$rs, immZExt5:$pos, immZExt5:$sz, + CPURegs:$src))], + NoItinerary>; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -539,7 +820,7 @@ 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), +def : Pat<(addc CPURegs:$src, immSExt16:$imm), (ADDiu CPURegs:$src, imm:$imm)>; // Call @@ -547,82 +828,136 @@ def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), (JAL tglobaladdr:$dst)>; def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), (JAL texternalsym:$dst)>; -def : Pat<(MipsJmpLink CPURegs:$dst), - (JALR CPURegs:$dst)>; +//def : Pat<(MipsJmpLink CPURegs:$dst), +// (JALR CPURegs:$dst)>; // hi/lo relocs def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : Pat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; +def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; +def : Pat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; +def : Pat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)), + (ADDiu CPURegs:$hi, tblockaddress:$lo)>; def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; +def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)), (ADDiu CPURegs:$hi, tjumptable:$lo)>; def : Pat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; +def : Pat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)), (ADDiu CPURegs:$hi, tconstpool:$lo)>; // gp_rel relocs -def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), +def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), (ADDiu CPURegs:$gp, tglobaladdr:$in)>; -def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), +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<(MipsTprelLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; +def : Pat<(add CPURegs:$hi, (MipsTprelLo tglobaltlsaddr:$lo)), + (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>; + +// wrapper_pic +class WrapperPICPat: + Pat<(MipsWrapperPIC node:$in), + (ADDiu GP, node:$in)>; + +def : WrapperPICPat; +def : WrapperPICPat; +def : WrapperPICPat; +def : WrapperPICPat; +def : WrapperPICPat; + // Mips does not have "not", so we expand our way def : Pat<(not CPURegs:$in), (NOR CPURegs:$in, ZERO)>; // extended load and stores -def : Pat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; -def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; -def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; +def : Pat<(extloadi1 addr:$src), (LBu addr:$src)>; +def : Pat<(extloadi8 addr:$src), (LBu addr:$src)>; +def : Pat<(extloadi16_a addr:$src), (LHu addr:$src)>; +def : Pat<(extloadi16_u addr:$src), (ULHu addr:$src)>; // peepholes def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; // 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 (seteq CPURegs:$lhs, 0), bb:$dst), - (BEQ CPURegs:$lhs, ZERO, bb:$dst)>; - -def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BGEZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; -def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BGEZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; - -def : Pat<(brcond (setgt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BGTZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; -def : Pat<(brcond (setugt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BGTZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; - -def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BLEZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; -def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BLEZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; - -def : Pat<(brcond (setlt CPURegs:$lhs, immSExt16:$rhs), bb:$dst), - (BNE (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setult CPURegs:$lhs, immZExt16:$rhs), bb:$dst), - (BNE (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BNE (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BNE (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; - -def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BLTZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; -def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BLTZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>; - -// generic brcond pattern -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 +multiclass BrcondPats { +def : Pat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst), + (BNEOp RC:$lhs, ZEROReg, bb:$dst)>; +def : Pat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst), + (BEQOp RC:$lhs, ZEROReg, bb:$dst)>; + +def : Pat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; +def : Pat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; +def : Pat<(brcond (i32 (setge RC:$lhs, immSExt16:$rhs)), bb:$dst), + (BEQ (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; +def : Pat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst), + (BEQ (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; + +def : Pat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; +def : Pat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; + +def : Pat<(brcond RC:$cond, bb:$dst), + (BNEOp RC:$cond, ZEROReg, bb:$dst)>; +} + +defm : BrcondPats; + +// select patterns +multiclass MovzPats { + def : Pat<(select (i32 (setge CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (i32 (setuge CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (i32 (setge CPURegs:$lhs, immSExt16:$rhs)), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>; + def : Pat<(select (i32 (setuge CPURegs:$lh, immSExt16:$rh)), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>; + def : Pat<(select (i32 (setle CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (i32 (setule CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (i32 (seteq CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), + (MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (i32 (seteq CPURegs:$lhs, 0)), RC:$T, RC:$F), + (MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>; +} + +multiclass MovnPats { + def : Pat<(select (i32 (setne CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), + (MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select CPURegs:$cond, RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$cond, RC:$F)>; + def : Pat<(select (i32 (setne CPURegs:$lhs, 0)), RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>; +} + +defm : MovzPats; +defm : MovnPats; + +// setcc patterns +def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), + (SLTiu (XOR CPURegs:$lhs, CPURegs:$rhs), 1)>; +def : Pat<(setne CPURegs:$lhs, CPURegs:$rhs), + (SLTu ZERO, (XOR CPURegs:$lhs, CPURegs:$rhs))>; + def : Pat<(setle CPURegs:$lhs, CPURegs:$rhs), (XORi (SLT CPURegs:$rhs, CPURegs:$lhs), 1)>; def : Pat<(setule CPURegs:$lhs, CPURegs:$rhs), @@ -638,22 +973,18 @@ def : Pat<(setge CPURegs:$lhs, CPURegs:$rhs), def : Pat<(setuge CPURegs:$lhs, CPURegs:$rhs), (XORi (SLTu CPURegs:$lhs, CPURegs:$rhs), 1)>; -def : Pat<(setne CPURegs:$lhs, CPURegs:$rhs), - (OR (SLT CPURegs:$lhs, CPURegs:$rhs), - (SLT CPURegs:$rhs, CPURegs:$lhs))>; - -def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), - (XORi (OR (SLT CPURegs:$lhs, CPURegs:$rhs), - (SLT CPURegs:$rhs, CPURegs:$lhs)), 1)>; - 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)>; +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 //===----------------------------------------------------------------------===// include "MipsInstrFPU.td" +include "Mips64InstrInfo.td"