diff options
Diffstat (limited to 'lib/Target/Mips')
74 files changed, 3785 insertions, 1259 deletions
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk index 18d1177..235e788 100644 --- a/lib/Target/Mips/Android.mk +++ b/lib/Target/Mips/Android.mk @@ -20,7 +20,6 @@ mips_codegen_SRC_FILES := \ Mips16ISelLowering.cpp \ Mips16InstrInfo.cpp \ Mips16RegisterInfo.cpp \ - MipsABIInfo.cpp \ MipsAnalyzeImmediate.cpp \ MipsAsmPrinter.cpp \ MipsCCState.cpp \ diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 0c5b41f..1040bf7 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsRegisterInfo.h" #include "MipsTargetStreamer.h" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -26,8 +27,8 @@ #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" #include <memory> using namespace llvm; @@ -75,9 +76,10 @@ public: Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 | Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 | Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 | - Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 | - Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit | - Mips::FeatureGP64Bit | Mips::FeatureNaN2008; + Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 | + Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 | + Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips | + Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008; private: unsigned ATReg; @@ -95,6 +97,7 @@ class MipsAsmParser : public MCTargetAsmParser { } MCSubtargetInfo &STI; + MipsABIInfo ABI; SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions; MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a // nullptr, which indicates that no function is currently @@ -147,6 +150,12 @@ class MipsAsmParser : public MCTargetAsmParser { MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands); MipsAsmParser::OperandMatchResultTy + parseRegisterPair (OperandVector &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMovePRegPair(OperandVector &Operands); + + MipsAsmParser::OperandMatchResultTy parseRegisterList (OperandVector &Operands); bool searchSymbolAlias(OperandVector &Operands); @@ -160,6 +169,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); + bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + bool expandLoadImm(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); @@ -168,6 +180,8 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); + bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); @@ -175,6 +189,10 @@ class MipsAsmParser : public MCTargetAsmParser { void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd); + + bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); @@ -310,7 +328,9 @@ public: MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII, const MCTargetOptions &Options) - : MCTargetAsmParser(), STI(sti) { + : MCTargetAsmParser(), STI(sti), + ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()), + sti.getCPU(), Options)) { MCAsmParserExtension::Initialize(parser); // Initialize the set of available features. @@ -326,12 +346,6 @@ public: getTargetStreamer().updateABIInfo(*this); - // Assert exactly one ABI was chosen. - assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) + - ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) + - ((STI.getFeatureBits() & Mips::FeatureN32) != 0) + - ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1); - if (!isABI_O32() && !useOddSPReg() != 0) report_fatal_error("-mno-odd-spreg requires the O32 ABI"); @@ -343,9 +357,10 @@ public: bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; } - bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; } - bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; } - bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; } + const MipsABIInfo &getABI() const { return ABI; } + bool isABI_N32() const { return ABI.IsN32(); } + bool isABI_N64() const { return ABI.IsN64(); } + bool isABI_O32() const { return ABI.IsO32(); } bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; } bool useOddSPReg() const { @@ -372,12 +387,27 @@ public: bool hasMips64r2() const { return (STI.getFeatureBits() & Mips::FeatureMips64r2); } + bool hasMips32r3() const { + return (STI.getFeatureBits() & Mips::FeatureMips32r3); + } + bool hasMips64r3() const { + return (STI.getFeatureBits() & Mips::FeatureMips64r3); + } + bool hasMips32r5() const { + return (STI.getFeatureBits() & Mips::FeatureMips32r5); + } + bool hasMips64r5() const { + return (STI.getFeatureBits() & Mips::FeatureMips64r5); + } bool hasMips32r6() const { return (STI.getFeatureBits() & Mips::FeatureMips32r6); } bool hasMips64r6() const { return (STI.getFeatureBits() & Mips::FeatureMips64r6); } + bool hasCnMips() const { + return (STI.getFeatureBits() & Mips::FeatureCnMips); + } bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); } bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); } bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); } @@ -428,7 +458,8 @@ private: k_PhysRegister, /// A physical register from the Mips namespace k_RegisterIndex, /// A register index in one or more RegKind. k_Token, /// A simple token - k_RegList /// A physical register list + k_RegList, /// A physical register list + k_RegPair /// A pair of physical register } Kind; public: @@ -663,6 +694,16 @@ public: Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg())); } + void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg())); + } + + void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg())); + } + /// Render the operand to an MCInst as a GPR64 /// Asserts if the wrong number of operands are requested, or the operand /// is not a k_RegisterIndex compatible with RegKind_GPR @@ -760,6 +801,15 @@ public: addExpr(Inst, Expr); } + void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg())); + + const MCExpr *Expr = getMemOff(); + addExpr(Inst, Expr); + } + void addRegListOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); @@ -767,6 +817,19 @@ public: Inst.addOperand(MCOperand::CreateReg(RegNo)); } + void addRegPairOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + unsigned RegNo = getRegPair(); + Inst.addOperand(MCOperand::CreateReg(RegNo++)); + Inst.addOperand(MCOperand::CreateReg(RegNo)); + } + + void addMovePRegPairOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + for (auto RegNo : getRegList()) + Inst.addOperand(MCOperand::CreateReg(RegNo)); + } + bool isReg() const override { // As a special case until we sort out the definition of div/divu, pretend // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. @@ -792,6 +855,37 @@ public: template <unsigned Bits> bool isMemWithSimmOffset() const { return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()); } + bool isMemWithGRPMM16Base() const { + return isMem() && getMemBase()->isMM16AsmReg(); + } + template <unsigned Bits> bool isMemWithUimmOffsetSP() const { + return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) + && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); + } + template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const { + return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) + && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() + && (getMemBase()->getGPR32Reg() == Mips::SP); + } + bool isRegList16() const { + if (!isRegList()) + return false; + + int Size = RegList.List->size(); + if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 || + RegList.List->back() != Mips::RA) + return false; + + int PrevReg = *RegList.List->begin(); + for (int i = 1; i < Size - 1; i++) { + int Reg = (*(RegList.List))[i]; + if ( Reg != PrevReg + 1) + return false; + PrevReg = Reg; + } + + return true; + } bool isInvNum() const { return Kind == k_Immediate; } bool isLSAImm() const { if (!isConstantImm()) @@ -800,11 +894,31 @@ public: return 1 <= Val && Val <= 4; } bool isRegList() const { return Kind == k_RegList; } + bool isMovePRegPair() const { + if (Kind != k_RegList || RegList.List->size() != 2) + return false; + + unsigned R0 = RegList.List->front(); + unsigned R1 = RegList.List->back(); + + if ((R0 == Mips::A1 && R1 == Mips::A2) || + (R0 == Mips::A1 && R1 == Mips::A3) || + (R0 == Mips::A2 && R1 == Mips::A3) || + (R0 == Mips::A0 && R1 == Mips::S5) || + (R0 == Mips::A0 && R1 == Mips::S6) || + (R0 == Mips::A0 && R1 == Mips::A1) || + (R0 == Mips::A0 && R1 == Mips::A2) || + (R0 == Mips::A0 && R1 == Mips::A3)) + return true; + + return false; + } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } + bool isRegPair() const { return Kind == k_RegPair; } unsigned getReg() const override { // As a special case until we sort out the definition of div/divu, pretend @@ -846,6 +960,11 @@ public: return *(RegList.List); } + unsigned getRegPair() const { + assert((Kind == k_RegPair) && "Invalid access!"); + return RegIdx.Index; + } + static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, MipsAsmParser &Parser) { auto Op = make_unique<MipsOperand>(k_Token, Parser); @@ -947,14 +1066,21 @@ public: assert (Regs.size() > 0 && "Empty list not allowed"); auto Op = make_unique<MipsOperand>(k_RegList, Parser); - Op->RegList.List = new SmallVector<unsigned, 10>(); - for (auto Reg : Regs) - Op->RegList.List->push_back(Reg); + Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end()); Op->StartLoc = StartLoc; Op->EndLoc = EndLoc; return Op; } + static std::unique_ptr<MipsOperand> + CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { + auto Op = make_unique<MipsOperand>(k_RegPair, Parser); + Op->RegIdx.Index = RegNo; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + bool isGPRAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; } @@ -964,6 +1090,19 @@ public: return ((RegIdx.Index >= 2 && RegIdx.Index <= 7) || RegIdx.Index == 16 || RegIdx.Index == 17); } + bool isMM16AsmRegZero() const { + if (!(isRegIdx() && RegIdx.Kind)) + return false; + return (RegIdx.Index == 0 || + (RegIdx.Index >= 2 && RegIdx.Index <= 7) || + RegIdx.Index == 17); + } + bool isMM16AsmRegMoveP() const { + if (!(isRegIdx() && RegIdx.Kind)) + return false; + return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || + (RegIdx.Index >= 16 && RegIdx.Index <= 20)); + } bool isFGRAsmReg() const { // AFGR64 is $0-$15 but we handle this in getAFGR64() return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; @@ -1014,6 +1153,7 @@ public: case k_PhysRegister: case k_RegisterIndex: case k_Token: + case k_RegPair: break; } } @@ -1047,6 +1187,9 @@ public: OS << Reg << " "; OS << ">"; break; + case k_RegPair: + OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; + break; } } }; // class MipsOperand @@ -1085,6 +1228,13 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, switch (Opcode) { default: break; + case Mips::BBIT0: + case Mips::BBIT032: + case Mips::BBIT1: + case Mips::BBIT132: + assert(hasCnMips() && "instruction only valid for octeon cpus"); + // Fall through + case Mips::BEQ: case Mips::BNE: case Mips::BEQ_MM: @@ -1125,6 +1275,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 1LL << (inMicroMipsMode() ? 1 : 2))) return Error(IDLoc, "branch to misaligned address"); break; + case Mips::BEQZ16_MM: + case Mips::BNEZ16_MM: + assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); + Offset = Inst.getOperand(1); + if (!Offset.isImm()) + break; // We'll deal with this situation later on when applying fixups. + if (!isIntN(8, Offset.getImm())) + return Error(IDLoc, "branch target out of range"); + if (OffsetToAlignment(Offset.getImm(), 2LL)) + return Error(IDLoc, "branch to misaligned address"); + break; } } @@ -1136,6 +1297,74 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, "nop instruction"); } + if (hasCnMips()) { + const unsigned Opcode = Inst.getOpcode(); + MCOperand Opnd; + int Imm; + + switch (Opcode) { + default: + break; + + case Mips::BBIT0: + case Mips::BBIT032: + case Mips::BBIT1: + case Mips::BBIT132: + assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); + // The offset is handled above + Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 || + Opcode == Mips::BBIT1 ? 63 : 31)) + return Error(IDLoc, "immediate operand value out of range"); + if (Imm > 31) { + Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032 + : Mips::BBIT132); + Inst.getOperand(1).setImm(Imm - 32); + } + break; + + case Mips::CINS: + case Mips::CINS32: + case Mips::EXTS: + case Mips::EXTS32: + assert(MCID.getNumOperands() == 4 && "unexpected number of operands"); + // Check length + Opnd = Inst.getOperand(3); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 31) + return Error(IDLoc, "immediate operand value out of range"); + // Check position + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > (Opcode == Mips::CINS || + Opcode == Mips::EXTS ? 63 : 31)) + return Error(IDLoc, "immediate operand value out of range"); + if (Imm > 31) { + Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32); + Inst.getOperand(2).setImm(Imm - 32); + } + break; + + case Mips::SEQi: + case Mips::SNEi: + assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!isInt<10>(Imm)) + return Error(IDLoc, "immediate operand value out of range"); + break; + } + } + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { // If this instruction has a delay slot and .set reorder is active, // emit a NOP after it. @@ -1189,8 +1418,38 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } // for } // if load/store - // TODO: Handle this with the AsmOperandClass.PredicateMethod. if (inMicroMipsMode()) { + if (MCID.mayLoad()) { + // Try to create 16-bit GP relative load instruction. + for (unsigned i = 0; i < MCID.getNumOperands(); i++) { + const MCOperandInfo &OpInfo = MCID.OpInfo[i]; + if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || + (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { + MCOperand &Op = Inst.getOperand(i); + if (Op.isImm()) { + int MemOffset = Op.getImm(); + MCOperand &DstReg = Inst.getOperand(0); + MCOperand &BaseReg = Inst.getOperand(1); + if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) && + getContext().getRegisterInfo()->getRegClass( + Mips::GPRMM16RegClassID).contains(DstReg.getReg()) && + BaseReg.getReg() == Mips::GP) { + MCInst TmpInst; + TmpInst.setLoc(IDLoc); + TmpInst.setOpcode(Mips::LWGP_MM); + TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg())); + TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); + TmpInst.addOperand(MCOperand::CreateImm(MemOffset)); + Instructions.push_back(TmpInst); + return false; + } + } + } + } // for + } // if load + + // TODO: Handle this with the AsmOperandClass.PredicateMethod. + MCOperand Opnd; int Imm; @@ -1260,6 +1519,57 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535)) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::LBU16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -1 || Imm > 14) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::SB16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 15) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LHU16_MM: + case Mips::SH16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 30 || (Imm % 2 != 0)) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LW16_MM: + case Mips::SW16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::CACHE: + case Mips::PREF: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!isUInt<5>(Imm)) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::ADDIUPC_MM: + MCOperand Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + int Imm = Opnd.getImm(); + if ((Imm % 4 != 0) || !isIntN(25, Imm)) + return Error(IDLoc, "immediate operand value out of range"); + break; } } @@ -1278,6 +1588,11 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { case Mips::LoadAddr32Imm: case Mips::LoadAddr32Reg: case Mips::LoadImm64Reg: + case Mips::B_MM_Pseudo: + case Mips::LWM_MM: + case Mips::SWM_MM: + case Mips::JalOneReg: + case Mips::JalTwoReg: return true; default: return false; @@ -1287,9 +1602,7 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { switch (Inst.getOpcode()) { - default: - assert(0 && "unimplemented expansion"); - return true; + default: llvm_unreachable("unimplemented expansion"); case Mips::LoadImm32Reg: return expandLoadImm(Inst, IDLoc, Instructions); case Mips::LoadImm64Reg: @@ -1302,6 +1615,14 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, return expandLoadAddressImm(Inst, IDLoc, Instructions); case Mips::LoadAddr32Reg: return expandLoadAddressReg(Inst, IDLoc, Instructions); + case Mips::B_MM_Pseudo: + return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); + case Mips::SWM_MM: + case Mips::LWM_MM: + return expandLoadStoreMultiple(Inst, IDLoc, Instructions); + case Mips::JalOneReg: + case Mips::JalTwoReg: + return expandJalWithRegs(Inst, IDLoc, Instructions); } } @@ -1336,6 +1657,48 @@ void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc, } } +bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + // Create a JALR instruction which is going to replace the pseudo-JAL. + MCInst JalrInst; + JalrInst.setLoc(IDLoc); + const MCOperand FirstRegOp = Inst.getOperand(0); + const unsigned Opcode = Inst.getOpcode(); + + if (Opcode == Mips::JalOneReg) { + // jal $rs => jalr $rs + if (inMicroMipsMode()) { + JalrInst.setOpcode(Mips::JALR16_MM); + JalrInst.addOperand(FirstRegOp); + } else { + JalrInst.setOpcode(Mips::JALR); + JalrInst.addOperand(MCOperand::CreateReg(Mips::RA)); + JalrInst.addOperand(FirstRegOp); + } + } else if (Opcode == Mips::JalTwoReg) { + // jal $rd, $rs => jalr $rd, $rs + JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); + JalrInst.addOperand(FirstRegOp); + const MCOperand SecondRegOp = Inst.getOperand(1); + JalrInst.addOperand(SecondRegOp); + } + Instructions.push_back(JalrInst); + + // If .set reorder is active, emit a NOP after it. + if (AssemblerOptions.back()->isReorder()) { + // This is a 32-bit NOP because these 2 pseudo-instructions + // do not have a short delay slot. + MCInst NopInst; + NopInst.setOpcode(Mips::SLL); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateImm(0)); + Instructions.push_back(NopInst); + } + + return false; +} + bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; @@ -1587,6 +1950,49 @@ MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, } } +bool MipsAsmParser::expandUncondBranchMMPseudo( + MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && + "unexpected number of operands"); + + MCOperand Offset = Inst.getOperand(0); + if (Offset.isExpr()) { + Inst.clear(); + Inst.setOpcode(Mips::BEQ_MM); + Inst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + Inst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr())); + } else { + assert(Offset.isImm() && "expected immediate operand kind"); + if (isIntN(11, Offset.getImm())) { + // If offset fits into 11 bits then this instruction becomes microMIPS + // 16-bit unconditional branch instruction. + Inst.setOpcode(Mips::B16_MM); + } else { + if (!isIntN(17, Offset.getImm())) + Error(IDLoc, "branch target out of range"); + if (OffsetToAlignment(Offset.getImm(), 1LL << 1)) + Error(IDLoc, "branch to misaligned address"); + Inst.clear(); + Inst.setOpcode(Mips::BEQ_MM); + Inst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + Inst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + Inst.addOperand(MCOperand::CreateImm(Offset.getImm())); + } + } + Instructions.push_back(Inst); + + if (AssemblerOptions.back()->isReorder()) { + // If .set reorder is active, emit a NOP after the branch instruction. + MCInst NopInst; + NopInst.setOpcode(Mips::MOVE16_MM); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + Instructions.push_back(NopInst); + } + return false; +} + void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) { @@ -1703,6 +2109,29 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, TempInst.clear(); } +bool +MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + unsigned OpNum = Inst.getNumOperands(); + unsigned Opcode = Inst.getOpcode(); + unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; + + assert (Inst.getOperand(OpNum - 1).isImm() && + Inst.getOperand(OpNum - 2).isReg() && + Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); + + if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && + Inst.getOperand(OpNum - 1).getImm() >= 0 && + Inst.getOperand(OpNum - 2).getReg() == Mips::SP && + Inst.getOperand(OpNum - 3).getReg() == Mips::RA) + // It can be implemented as SWM16 or LWM16 instruction. + NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; + + Inst.setOpcode(NewOpcode); + Instructions.push_back(Inst); + return false; +} + unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // As described by the Mips32r2 spec, the registers Rd and Rs for // jalr.hb must be different. @@ -1727,8 +2156,6 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { - default: - break; case Match_Success: { if (processInstruction(Inst, IDLoc, Instructions)) return true; @@ -1757,7 +2184,8 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_RequiresDifferentSrcAndDst: return Error(IDLoc, "source and destination must be different"); } - return true; + + llvm_unreachable("Implement any new match types added!"); } void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) { @@ -2642,6 +3070,61 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseRegisterPair(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + + SMLoc S = Parser.getTok().getLoc(); + if (parseAnyRegister(Operands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + SMLoc E = Parser.getTok().getLoc(); + MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back()); + unsigned Reg = Op.getGPR32Reg(); + Operands.pop_back(); + Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; + SmallVector<unsigned, 10> Regs; + + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_ParseFail; + + SMLoc S = Parser.getTok().getLoc(); + + if (parseAnyRegister(TmpOperands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); + unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); + Regs.push_back(RegNo); + + SMLoc E = Parser.getTok().getLoc(); + if (Parser.getTok().isNot(AsmToken::Comma)) { + Error(E, "',' expected"); + return MatchOperand_ParseFail; + } + + // Remove comma. + Parser.Lex(); + + if (parseAnyRegister(TmpOperands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); + RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); + Regs.push_back(RegNo); + + Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); + + return MatchOperand_Success; +} + MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind VK = @@ -2804,67 +3287,84 @@ bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { bool MipsAsmParser::parseSetNoAtDirective() { MCAsmParser &Parser = getParser(); // Line should look like: ".set noat". - // set at reg to 0. + + // Set the $at register to $0. AssemblerOptions.back()->setATReg(0); - // eat noat - Parser.Lex(); + + Parser.Lex(); // Eat "noat". + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token, expected end of statement"); return false; } + + getTargetStreamer().emitDirectiveSetNoAt(); Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetAtDirective() { + // Line can be: ".set at", which sets $at to $1 + // or ".set at=$reg", which sets $at to $reg. MCAsmParser &Parser = getParser(); - // Line can be .set at - defaults to $1 - // or .set at=$reg - int AtRegNo; - getParser().Lex(); + Parser.Lex(); // Eat "at". + if (getLexer().is(AsmToken::EndOfStatement)) { + // No register was specified, so we set $at to $1. AssemblerOptions.back()->setATReg(1); + + getTargetStreamer().emitDirectiveSetAt(); Parser.Lex(); // Consume the EndOfStatement. return false; - } else if (getLexer().is(AsmToken::Equal)) { - getParser().Lex(); // Eat the '='. - if (getLexer().isNot(AsmToken::Dollar)) { - reportParseError("unexpected token, expected dollar sign '$'"); + } + + if (getLexer().isNot(AsmToken::Equal)) { + reportParseError("unexpected token, expected equals sign"); + return false; + } + Parser.Lex(); // Eat "=". + + if (getLexer().isNot(AsmToken::Dollar)) { + if (getLexer().is(AsmToken::EndOfStatement)) { + reportParseError("no register specified"); return false; - } - Parser.Lex(); // Eat the '$'. - const AsmToken &Reg = Parser.getTok(); - if (Reg.is(AsmToken::Identifier)) { - AtRegNo = matchCPURegisterName(Reg.getIdentifier()); - } else if (Reg.is(AsmToken::Integer)) { - AtRegNo = Reg.getIntVal(); } else { - reportParseError("unexpected token, expected identifier or integer"); - return false; - } - - if (AtRegNo < 0 || AtRegNo > 31) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected dollar sign '$'"); return false; } + } + Parser.Lex(); // Eat "$". - if (!AssemblerOptions.back()->setATReg(AtRegNo)) { - reportParseError("invalid register"); - return false; - } - getParser().Lex(); // Eat the register. + // Find out what "reg" is. + unsigned AtRegNo; + const AsmToken &Reg = Parser.getTok(); + if (Reg.is(AsmToken::Identifier)) { + AtRegNo = matchCPURegisterName(Reg.getIdentifier()); + } else if (Reg.is(AsmToken::Integer)) { + AtRegNo = Reg.getIntVal(); + } else { + reportParseError("unexpected token, expected identifier or integer"); + return false; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - Parser.Lex(); // Consume the EndOfStatement. + // Check if $reg is a valid register. If it is, set $at to $reg. + if (!AssemblerOptions.back()->setATReg(AtRegNo)) { + reportParseError("invalid register"); return false; - } else { - reportParseError("unexpected token in statement"); + } + Parser.Lex(); // Eat "reg". + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); return false; } + + getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo); + + Parser.Lex(); // Consume the EndOfStatement. + return false; } bool MipsAsmParser::parseSetReorderDirective() { @@ -3118,9 +3618,13 @@ bool MipsAsmParser::parseSetArchDirective() { .Case("mips5", "mips5") .Case("mips32", "mips32") .Case("mips32r2", "mips32r2") + .Case("mips32r3", "mips32r3") + .Case("mips32r5", "mips32r5") .Case("mips32r6", "mips32r6") .Case("mips64", "mips64") .Case("mips64r2", "mips64r2") + .Case("mips64r3", "mips64r3") + .Case("mips64r5", "mips64r5") .Case("mips64r6", "mips64r6") .Case("cnmips", "cnmips") .Case("r4000", "mips3") // This is an implementation of Mips3. @@ -3178,6 +3682,14 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { selectArch("mips32r2"); getTargetStreamer().emitDirectiveSetMips32R2(); break; + case Mips::FeatureMips32r3: + selectArch("mips32r3"); + getTargetStreamer().emitDirectiveSetMips32R3(); + break; + case Mips::FeatureMips32r5: + selectArch("mips32r5"); + getTargetStreamer().emitDirectiveSetMips32R5(); + break; case Mips::FeatureMips32r6: selectArch("mips32r6"); getTargetStreamer().emitDirectiveSetMips32R6(); @@ -3190,6 +3702,14 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { selectArch("mips64r2"); getTargetStreamer().emitDirectiveSetMips64R2(); break; + case Mips::FeatureMips64r3: + selectArch("mips64r3"); + getTargetStreamer().emitDirectiveSetMips64R3(); + break; + case Mips::FeatureMips64r5: + selectArch("mips64r5"); + getTargetStreamer().emitDirectiveSetMips64R5(); + break; case Mips::FeatureMips64r6: selectArch("mips64r6"); getTargetStreamer().emitDirectiveSetMips64R6(); @@ -3294,12 +3814,20 @@ bool MipsAsmParser::parseDirectiveCPSetup() { if (!eatComma("unexpected token, expected comma")) return true; - StringRef Name; - if (Parser.parseIdentifier(Name)) - reportParseError("expected identifier"); - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + const MCExpr *Expr; + if (Parser.parseExpression(Expr)) { + reportParseError("expected expression"); + return false; + } + + if (Expr->getKind() != MCExpr::SymbolRef) { + reportParseError("expected symbol"); + return false; + } + const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); - getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg); + getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(), + SaveIsReg); return false; } @@ -3375,12 +3903,20 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetFeature(Mips::FeatureMips32); } else if (Tok.getString() == "mips32r2") { return parseSetFeature(Mips::FeatureMips32r2); + } else if (Tok.getString() == "mips32r3") { + return parseSetFeature(Mips::FeatureMips32r3); + } else if (Tok.getString() == "mips32r5") { + return parseSetFeature(Mips::FeatureMips32r5); } else if (Tok.getString() == "mips32r6") { return parseSetFeature(Mips::FeatureMips32r6); } else if (Tok.getString() == "mips64") { return parseSetFeature(Mips::FeatureMips64); } else if (Tok.getString() == "mips64r2") { return parseSetFeature(Mips::FeatureMips64r2); + } else if (Tok.getString() == "mips64r3") { + return parseSetFeature(Mips::FeatureMips64r3); + } else if (Tok.getString() == "mips64r5") { + return parseSetFeature(Mips::FeatureMips64r5); } else if (Tok.getString() == "mips64r6") { return parseSetFeature(Mips::FeatureMips64r6); } else if (Tok.getString() == "dsp") { @@ -3518,43 +4054,44 @@ bool MipsAsmParser::parseDirectiveModule() { return false; } - if (Lexer.is(AsmToken::Identifier)) { - StringRef Option = Parser.getTok().getString(); - Parser.Lex(); - - if (Option == "oddspreg") { - getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32()); - clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); + StringRef Option; + if (Parser.parseIdentifier(Option)) { + reportParseError("expected .module option identifier"); + return false; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } + if (Option == "oddspreg") { + getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32()); + clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); return false; - } else if (Option == "nooddspreg") { - if (!isABI_O32()) { - Error(L, "'.module nooddspreg' requires the O32 ABI"); - return false; - } + } - getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32()); - setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "nooddspreg") { + if (!isABI_O32()) { + Error(L, "'.module nooddspreg' requires the O32 ABI"); + return false; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } + getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32()); + setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); return false; - } else if (Option == "fp") { - return parseDirectiveModuleFP(); } + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "fp") { + return parseDirectiveModuleFP(); + } else { return Error(L, "'" + Twine(Option) + "' is not a valid .module option."); } - - return false; } /// parseDirectiveModuleFP diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 1f201b0..36ba8e5 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -21,7 +21,6 @@ add_llvm_target(MipsCodeGen Mips16ISelDAGToDAG.cpp Mips16ISelLowering.cpp Mips16RegisterInfo.cpp - MipsABIInfo.cpp MipsAnalyzeImmediate.cpp MipsAsmPrinter.cpp MipsCCState.cpp diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 48904ce..8849366 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -30,34 +30,15 @@ typedef MCDisassembler::DecodeStatus DecodeStatus; namespace { -/// A disasembler class for Mips. -class MipsDisassemblerBase : public MCDisassembler { +class MipsDisassembler : public MCDisassembler { + bool IsMicroMips; + bool IsBigEndian; public: - MipsDisassemblerBase(const MCSubtargetInfo &STI, MCContext &Ctx, - bool IsBigEndian) + MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian) : MCDisassembler(STI, Ctx), - IsN64(STI.getFeatureBits() & Mips::FeatureN64), + IsMicroMips(STI.getFeatureBits() & Mips::FeatureMicroMips), IsBigEndian(IsBigEndian) {} - virtual ~MipsDisassemblerBase() {} - - bool isN64() const { return IsN64; } - -private: - bool IsN64; -protected: - bool IsBigEndian; -}; - -/// A disasembler class for Mips32. -class MipsDisassembler : public MipsDisassemblerBase { - bool IsMicroMips; -public: - MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool bigEndian) - : MipsDisassemblerBase(STI, Ctx, bigEndian) { - IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips; - } - bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; } bool hasMips32r6() const { @@ -77,19 +58,6 @@ public: raw_ostream &CStream) const override; }; -/// A disasembler class for Mips64. -class Mips64Disassembler : public MipsDisassemblerBase { -public: - Mips64Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx, - bool bigEndian) : - MipsDisassemblerBase(STI, Ctx, bigEndian) {} - - DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const override; -}; - } // end anonymous namespace // Forward declare these because the autogenerated code will reference them. @@ -109,6 +77,16 @@ static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -223,6 +201,20 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst, uint64_t Address, const void *Decoder); +// DecodeBranchTarget7MM - Decode microMIPS branch offset, which is +// shifted left by 1 bit. +static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + +// DecodeBranchTarget10MM - Decode microMIPS branch offset, which is +// shifted left by 1 bit. +static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + // DecodeBranchTargetMM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, @@ -247,9 +239,44 @@ static DecodeStatus DecodeCacheOp(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeCacheOpR6(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeCacheOpMM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeSyncI(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMemMMImm4(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -272,11 +299,35 @@ static DecodeStatus DecodeFMem3(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeLiSimm7(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeSimm4(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSimm16(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -305,6 +356,18 @@ static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + +static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + +static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + +static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + /// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't /// handle. template <typename InsnType> @@ -345,6 +408,14 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + namespace llvm { extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, TheMips64elTarget; @@ -364,20 +435,6 @@ static MCDisassembler *createMipselDisassembler( return new MipsDisassembler(STI, Ctx, false); } -static MCDisassembler *createMips64Disassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new Mips64Disassembler(STI, Ctx, true); -} - -static MCDisassembler *createMips64elDisassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new Mips64Disassembler(STI, Ctx, false); -} - extern "C" void LLVMInitializeMipsDisassembler() { // Register the disassembler. TargetRegistry::RegisterMCDisassembler(TheMipsTarget, @@ -385,15 +442,15 @@ extern "C" void LLVMInitializeMipsDisassembler() { TargetRegistry::RegisterMCDisassembler(TheMipselTarget, createMipselDisassembler); TargetRegistry::RegisterMCDisassembler(TheMips64Target, - createMips64Disassembler); + createMipsDisassembler); TargetRegistry::RegisterMCDisassembler(TheMips64elTarget, - createMips64elDisassembler); + createMipselDisassembler); } #include "MipsGenDisassemblerTables.inc" static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { - const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D); + const MipsDisassembler *Dis = static_cast<const MipsDisassembler*>(D); const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); return *(RegInfo->getRegClass(RC).begin() + RegNo); } @@ -700,6 +757,26 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, return MCDisassembler::Success; } +/// Read two bytes from the ArrayRef and return 16 bit halfword sorted +/// according to the given endianess. +static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address, + uint64_t &Size, uint32_t &Insn, + bool IsBigEndian) { + // We want to read exactly 2 Bytes of data. + if (Bytes.size() < 2) { + Size = 0; + return MCDisassembler::Fail; + } + + if (IsBigEndian) { + Insn = (Bytes[0] << 8) | Bytes[1]; + } else { + Insn = (Bytes[1] << 8) | Bytes[0]; + } + + return MCDisassembler::Success; +} + /// Read four bytes from the ArrayRef and return 32 bit word sorted /// according to the given endianess static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address, @@ -711,15 +788,19 @@ static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address, return MCDisassembler::Fail; } + // High 16 bits of a 32-bit microMIPS instruction (where the opcode is) + // always precede the low 16 bits in the instruction stream (that is, they + // are placed at lower addresses in the instruction stream). + // + // microMIPS byte ordering: + // Big-endian: 0 | 1 | 2 | 3 + // Little-endian: 1 | 0 | 3 | 2 + if (IsBigEndian) { // Encoded as a big-endian 32-bit word in the stream. Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); } else { - // Encoded as a small-endian 32-bit word in the stream. - // Little-endian byte ordering: - // mips32r2: 4 | 3 | 2 | 1 - // microMIPS: 2 | 1 | 4 | 3 if (IsMicroMips) { Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) | (Bytes[1] << 24); @@ -738,14 +819,25 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, raw_ostream &VStream, raw_ostream &CStream) const { uint32_t Insn; - - DecodeStatus Result = - readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, IsMicroMips); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; + DecodeStatus Result; if (IsMicroMips) { - DEBUG(dbgs() << "Trying MicroMips32 table (32-bit opcodes):\n"); + Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian); + + DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, + this, STI); + if (Result != MCDisassembler::Fail) { + Size = 2; + return Result; + } + + Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, true); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + + DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, this, STI); @@ -756,6 +848,10 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, return MCDisassembler::Fail; } + Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + if (hasCOP3()) { DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); Result = @@ -786,39 +882,19 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } - DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); - // Calling the auto-generated decoder function. - Result = - decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; + if (isGP64()) { + DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableMips6432, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } } - return MCDisassembler::Fail; -} - -DecodeStatus Mips64Disassembler::getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef<uint8_t> Bytes, - uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const { - uint32_t Insn; - - DecodeStatus Result = - readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; - + DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); // Calling the auto-generated decoder function. Result = - decodeInstruction(DecoderTableMips6432, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; - } - // If we fail to decode in Mips64 decoder space we can try in Mips32 - Result = decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; @@ -854,7 +930,33 @@ static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - return MCDisassembler::Fail; + if (RegNo > 7) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, Mips::GPRMM16RegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 7) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, Mips::GPRMM16ZeroRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 7) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, Mips::GPRMM16MovePRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; } static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, @@ -872,7 +974,7 @@ static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - if (static_cast<const MipsDisassembler *>(Decoder)->isN64()) + if (static_cast<const MipsDisassembler *>(Decoder)->isGP64()) return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); @@ -953,7 +1055,8 @@ static DecodeStatus DecodeMem(MCInst &Inst, Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - if(Inst.getOpcode() == Mips::SC){ + if(Inst.getOpcode() == Mips::SC || + Inst.getOpcode() == Mips::SCD){ Inst.addOperand(MCOperand::CreateReg(Reg)); } @@ -981,6 +1084,55 @@ static DecodeStatus DecodeCacheOp(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeCacheOpMM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<12>(Insn & 0xfff); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + unsigned Hint = fieldFromInstruction(Insn, 21, 5); + + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::CreateImm(Hint)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeCacheOpR6(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = fieldFromInstruction(Insn, 7, 9); + unsigned Hint = fieldFromInstruction(Insn, 16, 5); + unsigned Base = fieldFromInstruction(Insn, 21, 5); + + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::CreateImm(Hint)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeSyncI(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<16>(Insn & 0xffff); + unsigned Base = fieldFromInstruction(Insn, 21, 5); + + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 16, 10)); @@ -1027,6 +1179,106 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, return MCDisassembler::Success; } +static DecodeStatus DecodeMemMMImm4(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Offset = Insn & 0xf; + unsigned Reg = fieldFromInstruction(Insn, 7, 3); + unsigned Base = fieldFromInstruction(Insn, 4, 3); + + switch (Inst.getOpcode()) { + case Mips::LBU16_MM: + case Mips::LHU16_MM: + case Mips::LW16_MM: + if (DecodeGPRMM16RegisterClass(Inst, Reg, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + break; + case Mips::SB16_MM: + case Mips::SH16_MM: + case Mips::SW16_MM: + if (DecodeGPRMM16ZeroRegisterClass(Inst, Reg, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + break; + } + + if (DecodeGPRMM16RegisterClass(Inst, Base, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + + switch (Inst.getOpcode()) { + case Mips::LBU16_MM: + if (Offset == 0xf) + Inst.addOperand(MCOperand::CreateImm(-1)); + else + Inst.addOperand(MCOperand::CreateImm(Offset)); + break; + case Mips::SB16_MM: + Inst.addOperand(MCOperand::CreateImm(Offset)); + break; + case Mips::LHU16_MM: + case Mips::SH16_MM: + Inst.addOperand(MCOperand::CreateImm(Offset << 1)); + break; + case Mips::LW16_MM: + case Mips::SW16_MM: + Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + break; + } + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Offset = Insn & 0x1F; + unsigned Reg = fieldFromInstruction(Insn, 5, 5); + + Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); + + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Mips::SP)); + Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Offset = Insn & 0x7F; + unsigned Reg = fieldFromInstruction(Insn, 7, 3); + + Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); + + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Mips::GP)); + Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<4>(Insn & 0xf); + + if (DecodeRegListOperand16(Inst, Insn, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::CreateReg(Mips::SP)); + Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1052,6 +1304,9 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst, // fallthrough default: Inst.addOperand(MCOperand::CreateReg(Reg)); + if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) + Inst.addOperand(MCOperand::CreateReg(Reg+1)); + Inst.addOperand(MCOperand::CreateReg(Base)); Inst.addOperand(MCOperand::CreateImm(Offset)); } @@ -1131,6 +1386,23 @@ static DecodeStatus DecodeFMem3(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<11>(Insn & 0x07ff); + unsigned Reg = fieldFromInstruction(Insn, 16, 5); + unsigned Base = fieldFromInstruction(Insn, 11, 5); + + Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + + return MCDisassembler::Success; +} static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1324,6 +1596,24 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = SignExtend32<7>(Offset) << 1; + Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = SignExtend32<10>(Offset) << 1; + Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, unsigned Offset, uint64_t Address, @@ -1342,6 +1632,46 @@ static DecodeStatus DecodeJumpTargetMM(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder) { + if (Value == 0) + Inst.addOperand(MCOperand::CreateImm(1)); + else if (Value == 0x7) + Inst.addOperand(MCOperand::CreateImm(-1)); + else + Inst.addOperand(MCOperand::CreateImm(Value << 2)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(Value << 2)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeLiSimm7(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder) { + if (Value == 0x7F) + Inst.addOperand(MCOperand::CreateImm(-1)); + else + Inst.addOperand(MCOperand::CreateImm(Value)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeSimm4(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<4>(Value))); + return MCDisassembler::Success; +} + static DecodeStatus DecodeSimm16(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1391,6 +1721,36 @@ static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, return MCDisassembler::Success; } +static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + int32_t DecodedValue; + switch (Insn) { + case 0: DecodedValue = 256; break; + case 1: DecodedValue = 257; break; + case 510: DecodedValue = -258; break; + case 511: DecodedValue = -257; break; + default: DecodedValue = SignExtend32<9>(Insn); break; + } + Inst.addOperand(MCOperand::CreateImm(DecodedValue * 4)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + // Insn must be >= 0, since it is unsigned that condition is always true. + assert(Insn < 16); + int32_t DecodedValues[] = {128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, + 255, 32768, 65535}; + Inst.addOperand(MCOperand::CreateImm(DecodedValues[Insn])); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(Insn << 2)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1413,3 +1773,69 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, return MCDisassembler::Success; } + +static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3}; + unsigned RegLst = fieldFromInstruction(Insn, 4, 2); + unsigned RegNum = RegLst & 0x3; + + for (unsigned i = 0; i <= RegNum; i++) + Inst.addOperand(MCOperand::CreateReg(Regs[i])); + + Inst.addOperand(MCOperand::CreateReg(Mips::RA)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + + unsigned RegPair = fieldFromInstruction(Insn, 7, 3); + + switch (RegPair) { + default: + return MCDisassembler::Fail; + case 0: + Inst.addOperand(MCOperand::CreateReg(Mips::A1)); + Inst.addOperand(MCOperand::CreateReg(Mips::A2)); + break; + case 1: + Inst.addOperand(MCOperand::CreateReg(Mips::A1)); + Inst.addOperand(MCOperand::CreateReg(Mips::A3)); + break; + case 2: + Inst.addOperand(MCOperand::CreateReg(Mips::A2)); + Inst.addOperand(MCOperand::CreateReg(Mips::A3)); + break; + case 3: + Inst.addOperand(MCOperand::CreateReg(Mips::A0)); + Inst.addOperand(MCOperand::CreateReg(Mips::S5)); + break; + case 4: + Inst.addOperand(MCOperand::CreateReg(Mips::A0)); + Inst.addOperand(MCOperand::CreateReg(Mips::S6)); + break; + case 5: + Inst.addOperand(MCOperand::CreateReg(Mips::A0)); + Inst.addOperand(MCOperand::CreateReg(Mips::A1)); + break; + case 6: + Inst.addOperand(MCOperand::CreateReg(Mips::A0)); + Inst.addOperand(MCOperand::CreateReg(Mips::A2)); + break; + case 7: + Inst.addOperand(MCOperand::CreateReg(Mips::A0)); + Inst.addOperand(MCOperand::CreateReg(Mips::A3)); + break; + } + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<23>(Insn) << 2)); + return MCDisassembler::Success; +} diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index ab6b225..aad549d 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -134,8 +134,8 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) { ME->print(OS); return; - } else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr))) - assert(false && "Unexpected MCExpr type."); + } else + SRE = cast<MCSymbolRefExpr>(Expr); MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); @@ -233,6 +233,8 @@ printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { break; case Mips::SWM32_MM: case Mips::LWM32_MM: + case Mips::SWM16_MM: + case Mips::LWM16_MM: opNum = MI->getNumOperands() - 2; break; } @@ -260,6 +262,11 @@ printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { } void MipsInstPrinter:: +printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O) { + printRegName(O, MI->getOperand(opNum).getReg()); +} + +void MipsInstPrinter:: printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) { llvm_unreachable("TODO"); } @@ -283,6 +290,7 @@ bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI, bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { switch (MI.getOpcode()) { case Mips::BEQ: + case Mips::BEQ_MM: // beq $zero, $zero, $L2 => b $L2 // beq $r0, $zero, $L2 => beqz $r0, $L2 return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) && diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 42df013..468dc07 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -99,6 +99,7 @@ private: void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); + void printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O); void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O); bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, diff --git a/lib/Target/Mips/MCTargetDesc/Android.mk b/lib/Target/Mips/MCTargetDesc/Android.mk index 89e132d..7f462d3 100644 --- a/lib/Target/Mips/MCTargetDesc/Android.mk +++ b/lib/Target/Mips/MCTargetDesc/Android.mk @@ -8,6 +8,7 @@ mips_mc_desc_TBLGEN_TABLES := \ mips_mc_desc_SRC_FILES := \ MipsABIFlagsSection.cpp \ + MipsABIInfo.cpp \ MipsAsmBackend.cpp \ MipsELFObjectWriter.cpp \ MipsELFStreamer.cpp \ diff --git a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt index 6b3788c..c63af7c 100644 --- a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMMipsDesc + MipsABIInfo.cpp MipsABIFlagsSection.cpp MipsAsmBackend.cpp MipsELFObjectWriter.cpp diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 8bcfb0f..473f4f2 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -145,6 +145,10 @@ public: ISALevel = 64; if (P.hasMips64r6()) ISARevision = 6; + else if (P.hasMips64r5()) + ISARevision = 5; + else if (P.hasMips64r3()) + ISARevision = 3; else if (P.hasMips64r2()) ISARevision = 2; else @@ -153,6 +157,10 @@ public: ISALevel = 32; if (P.hasMips32r6()) ISARevision = 6; + else if (P.hasMips32r5()) + ISARevision = 5; + else if (P.hasMips32r3()) + ISARevision = 3; else if (P.hasMips32r2()) ISARevision = 2; else diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp new file mode 100644 index 0000000..faf9741 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -0,0 +1,92 @@ +//===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MipsABIInfo.h" +#include "MipsRegisterInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCTargetOptions.h" + +using namespace llvm; + +namespace { +static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; + +static const MCPhysReg Mips64IntRegs[8] = { + Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, + Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64}; +} + +const ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const { + if (IsO32()) + return makeArrayRef(O32IntRegs); + if (IsN32() || IsN64()) + return makeArrayRef(Mips64IntRegs); + llvm_unreachable("Unhandled ABI"); +} + +const ArrayRef<MCPhysReg> MipsABIInfo::GetVarArgRegs() const { + if (IsO32()) + return makeArrayRef(O32IntRegs); + if (IsN32() || IsN64()) + return makeArrayRef(Mips64IntRegs); + llvm_unreachable("Unhandled ABI"); +} + +unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { + if (IsO32()) + return CC != CallingConv::Fast ? 16 : 0; + if (IsN32() || IsN64() || IsEABI()) + return 0; + llvm_unreachable("Unhandled ABI"); +} + +MipsABIInfo MipsABIInfo::computeTargetABI(Triple TT, StringRef CPU, + const MCTargetOptions &Options) { + if (Options.getABIName().startswith("o32")) + return MipsABIInfo::O32(); + else if (Options.getABIName().startswith("n32")) + return MipsABIInfo::N32(); + else if (Options.getABIName().startswith("n64")) + return MipsABIInfo::N64(); + else if (Options.getABIName().startswith("eabi")) + return MipsABIInfo::EABI(); + else if (!Options.getABIName().empty()) + llvm_unreachable("Unknown ABI option for MIPS"); + + // FIXME: This shares code with the selectMipsCPU routine that's + // used and not shared in a couple of other places. This needs unifying + // at some level. + if (CPU.empty() || CPU == "generic") { + if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel) + CPU = "mips32"; + else + CPU = "mips64"; + } + + return StringSwitch<MipsABIInfo>(CPU) + .Case("mips1", MipsABIInfo::O32()) + .Case("mips2", MipsABIInfo::O32()) + .Case("mips32", MipsABIInfo::O32()) + .Case("mips32r2", MipsABIInfo::O32()) + .Case("mips32r3", MipsABIInfo::O32()) + .Case("mips32r5", MipsABIInfo::O32()) + .Case("mips32r6", MipsABIInfo::O32()) + .Case("mips16", MipsABIInfo::O32()) + .Case("mips3", MipsABIInfo::N64()) + .Case("mips4", MipsABIInfo::N64()) + .Case("mips5", MipsABIInfo::N64()) + .Case("mips64", MipsABIInfo::N64()) + .Case("mips64r2", MipsABIInfo::N64()) + .Case("mips64r3", MipsABIInfo::N64()) + .Case("mips64r5", MipsABIInfo::N64()) + .Case("mips64r6", MipsABIInfo::N64()) + .Case("octeon", MipsABIInfo::N64()) + .Default(MipsABIInfo::Unknown()); +} diff --git a/lib/Target/Mips/MipsABIInfo.h b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index bea585e..008e08e 100644 --- a/lib/Target/Mips/MipsABIInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -7,15 +7,19 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSABIINFO_H -#define MIPSABIINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/CallingConv.h" +#include "llvm/MC/MCRegisterInfo.h" namespace llvm { +class MCTargetOptions; +class StringRef; + class MipsABIInfo { public: enum class ABI { Unknown, O32, N32, N64, EABI }; @@ -31,6 +35,8 @@ public: static MipsABIInfo N32() { return MipsABIInfo(ABI::N32); } static MipsABIInfo N64() { return MipsABIInfo(ABI::N64); } static MipsABIInfo EABI() { return MipsABIInfo(ABI::EABI); } + static MipsABIInfo computeTargetABI(Triple TT, StringRef CPU, + const MCTargetOptions &Options); bool IsKnown() const { return ThisABI != ABI::Unknown; } bool IsO32() const { return ThisABI == ABI::O32; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index efeb54d..acf6f21 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -103,6 +103,22 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case Mips::fixup_MICROMIPS_26_S1: Value >>= 1; break; + case Mips::fixup_MICROMIPS_PC7_S1: + Value -= 4; + // Forcing a signed division because Value can be negative. + Value = (int64_t) Value / 2; + // We now check if Value can be encoded as a 7-bit signed immediate. + if (!isIntN(7, Value) && Ctx) + Ctx->FatalError(Fixup.getLoc(), "out of range PC7 fixup"); + break; + case Mips::fixup_MICROMIPS_PC10_S1: + Value -= 2; + // Forcing a signed division because Value can be negative. + Value = (int64_t) Value / 2; + // We now check if Value can be encoded as a 10-bit signed immediate. + if (!isIntN(10, Value) && Ctx) + Ctx->FatalError(Fixup.getLoc(), "out of range PC10 fixup"); + break; case Mips::fixup_MICROMIPS_PC16_S1: Value -= 4; // Forcing a signed division because Value can be negative. @@ -149,7 +165,8 @@ MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const { // microMIPS: x | x | a | b static bool needsMMLEByteOrder(unsigned Kind) { - return Kind >= Mips::fixup_MICROMIPS_26_S1 && + return Kind != Mips::fixup_MICROMIPS_PC10_S1 && + Kind >= Mips::fixup_MICROMIPS_26_S1 && Kind < Mips::LastTargetFixupKind; } @@ -182,6 +199,7 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, switch ((unsigned)Kind) { case FK_Data_2: case Mips::fixup_Mips_16: + case Mips::fixup_MICROMIPS_PC10_S1: FullSize = 2; break; case FK_Data_8: @@ -271,6 +289,8 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_MICROMIPS_HI16", 0, 16, 0 }, { "fixup_MICROMIPS_LO16", 0, 16, 0 }, { "fixup_MICROMIPS_GOT16", 0, 16, 0 }, + { "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC10_S1", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 0, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 }, @@ -334,6 +354,8 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_MICROMIPS_HI16", 16, 16, 0 }, { "fixup_MICROMIPS_LO16", 16, 16, 0 }, { "fixup_MICROMIPS_GOT16", 16, 16, 0 }, + { "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC10_S1", 6, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 16, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 }, diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index d4f4983..dd0e54c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -16,8 +16,8 @@ #define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSASMBACKEND_H #include "MCTargetDesc/MipsFixupKinds.h" -#include "llvm/MC/MCAsmBackend.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmBackend.h" namespace llvm { diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 4ea7846..e14dc8d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -11,6 +11,7 @@ #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELF.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" @@ -161,6 +162,12 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, case Mips::fixup_MICROMIPS_GOT16: Type = ELF::R_MICROMIPS_GOT16; break; + case Mips::fixup_MICROMIPS_PC7_S1: + Type = ELF::R_MICROMIPS_PC7_S1; + break; + case Mips::fixup_MICROMIPS_PC10_S1: + Type = ELF::R_MICROMIPS_PC10_S1; + break; case Mips::fixup_MICROMIPS_PC16_S1: Type = ELF::R_MICROMIPS_PC16_S1; break; @@ -219,7 +226,7 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, unsigned Type) const { - // FIXME: This is extremelly conservative. This really needs to use a + // FIXME: This is extremely conservative. This really needs to use a // whitelist with a clear explanation for why each realocation needs to // point to the symbol, not to the section. switch (Type) { @@ -244,8 +251,11 @@ MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, case ELF::R_MICROMIPS_LO16: return true; - case ELF::R_MIPS_26: case ELF::R_MIPS_32: + if (MCELF::getOther(SD) & (ELF::STO_MIPS_MICROMIPS >> 2)) + return true; + // falltrough + case ELF::R_MIPS_26: case ELF::R_MIPS_64: case ELF::R_MIPS_GPREL16: return false; diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index 136146b..bc76d8a 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -37,7 +37,7 @@ public: MCCodeEmitter *Emitter, const MCSubtargetInfo &STI) : MCELFStreamer(Context, MAB, OS, Emitter) { - RegInfoRecord = new MipsRegInfoRecord(this, Context, STI); + RegInfoRecord = new MipsRegInfoRecord(this, Context); MipsOptionRecords.push_back( std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord)); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 317db16..fa8d6a6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -158,6 +158,12 @@ namespace Mips { // resulting in - R_MICROMIPS_GOT16 fixup_MICROMIPS_GOT16, + // resulting in - R_MICROMIPS_PC7_S1 + fixup_MICROMIPS_PC7_S1, + + // resulting in - R_MICROMIPS_PC10_S1 + fixup_MICROMIPS_PC10_S1, + // resulting in - R_MICROMIPS_PC16_S1 fixup_MICROMIPS_PC16_S1, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 2f5d196..e2bd5a8 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -34,6 +34,7 @@ MipsMCAsmInfo::MipsMCAsmInfo(StringRef TT) { Data32bitsDirective = "\t.4byte\t"; Data64bitsDirective = "\t.8byte\t"; PrivateGlobalPrefix = "$"; + PrivateLabelPrefix = "$"; CommentString = "#"; ZeroDirective = "\t.space\t"; GPRel32Directive = "\t.gpword\t"; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index d632c27..8208725 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -20,9 +20,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCFixup.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/raw_ostream.h" @@ -173,7 +173,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 // so we have to special check for them. unsigned Opcode = TmpInst.getOpcode(); - if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) + if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && + (Opcode != Mips::SLL_MM) && !Binary) llvm_unreachable("unimplemented opcode in EncodeInstruction()"); if (STI.getFeatureBits() & Mips::FeatureMicroMips) { @@ -219,6 +220,50 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, return 0; } +/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetOpValueMM expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::Create(0, Expr, + MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); + return 0; +} + +/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS +/// 10-bit branch target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetOpValuePC10 expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::Create(0, Expr, + MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); + return 0; +} + /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. @@ -635,6 +680,77 @@ MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, } unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI); + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 1; + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Register is encoded in bits 9-5, offset is encoded in bits 4-0. + assert(MI.getOperand(OpNo).isReg() && + MI.getOperand(OpNo).getReg() == Mips::SP && + "Unexpected base register!"); + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return OffBits & 0x1F; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Register is encoded in bits 9-7, offset is encoded in bits 6-0. + assert(MI.getOperand(OpNo).isReg() && + MI.getOperand(OpNo).getReg() == Mips::GP && + "Unexpected base register!"); + + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return OffBits & 0x7F; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -657,6 +773,30 @@ getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, return (OffBits & 0x0FFF) | RegBits; } +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // opNum can be invalid if instruction had reglist as operand + // MemOperand is always last operand of instruction (base + offset) + switch (MI.getOpcode()) { + default: + break; + case Mips::SWM16_MM: + case Mips::LWM16_MM: + OpNo = MI.getNumOperands() - 2; + break; + } + + // Offset is encoded in bits 4-0. + assert(MI.getOperand(OpNo).isReg()); + // Base register is always SP - thus it is not encoded. + assert(MI.getOperand(OpNo+1).isImm()); + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + + return ((OffBits >> 2) & 0x0F); +} + unsigned MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, @@ -788,4 +928,64 @@ MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, return res; } +unsigned +MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + return (MI.getNumOperands() - 4); +} + +unsigned +MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); +} + +unsigned +MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + unsigned res = 0; + + if (MI.getOperand(0).getReg() == Mips::A1 && + MI.getOperand(1).getReg() == Mips::A2) + res = 0; + else if (MI.getOperand(0).getReg() == Mips::A1 && + MI.getOperand(1).getReg() == Mips::A3) + res = 1; + else if (MI.getOperand(0).getReg() == Mips::A2 && + MI.getOperand(1).getReg() == Mips::A3) + res = 2; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::S5) + res = 3; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::S6) + res = 4; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::A1) + res = 5; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::A2) + res = 6; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::A3) + res = 7; + + return res; +} + +unsigned +MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); + // The immediate is encoded as 'immediate >> 2'. + unsigned Res = static_cast<unsigned>(MO.getImm()); + assert((Res & 3) == 0); + return Res >> 2; +} + #include "MipsGenMCCodeEmitter.inc" diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 9016fcf..b01726d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -31,8 +31,8 @@ class MCSubtargetInfo; class raw_ostream; class MipsMCCodeEmitter : public MCCodeEmitter { - MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; + MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete; + void operator=(const MipsMCCodeEmitter &) = delete; const MCInstrInfo &MCII; MCContext &Ctx; bool IsLittleEndian; @@ -101,6 +101,20 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + // getBranchTarget7OpValue - Return binary encoding of the microMIPS branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS + // 10-bit branch target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + // getBranchTargetOpValue - Return binary encoding of the microMIPS branch // target operand. If the machine operand requires relocation, // record the relocation and return zero. @@ -142,9 +156,27 @@ public: unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; @@ -172,12 +204,28 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; unsigned getRegisterListOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; }; // class MipsMCCodeEmitter } // namespace llvm. diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index bab4254..9b56067 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -43,7 +43,7 @@ using namespace llvm; /// Select the Mips CPU for the given triple and cpu name. /// FIXME: Merge with the copy in MipsSubtarget.cpp -static inline StringRef selectMipsCPU(StringRef TT, StringRef CPU) { +StringRef MIPS_MC::selectMipsCPU(StringRef TT, StringRef CPU) { if (CPU.empty() || CPU == "generic") { Triple TheTriple(TT); if (TheTriple.getArch() == Triple::mips || @@ -69,7 +69,7 @@ static MCRegisterInfo *createMipsMCRegisterInfo(StringRef TT) { static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS) { - CPU = selectMipsCPU(TT, CPU); + CPU = MIPS_MC::selectMipsCPU(TT, CPU); MCSubtargetInfo *X = new MCSubtargetInfo(); InitMipsMCSubtargetInfo(X, TT, CPU, FS); return X; @@ -130,10 +130,8 @@ createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, return S; } -static MCStreamer *createMipsNullStreamer(MCContext &Ctx) { - MCStreamer *S = llvm::createNullStreamer(Ctx); - new MipsTargetStreamer(*S); - return S; +static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) { + return new MipsTargetStreamer(S); } extern "C" void LLVMInitializeMipsTargetMC() { @@ -190,11 +188,14 @@ extern "C" void LLVMInitializeMipsTargetMC() { TargetRegistry::RegisterAsmStreamer(TheMips64Target, createMCAsmStreamer); TargetRegistry::RegisterAsmStreamer(TheMips64elTarget, createMCAsmStreamer); - TargetRegistry::RegisterNullStreamer(TheMipsTarget, createMipsNullStreamer); - TargetRegistry::RegisterNullStreamer(TheMipselTarget, createMipsNullStreamer); - TargetRegistry::RegisterNullStreamer(TheMips64Target, createMipsNullStreamer); - TargetRegistry::RegisterNullStreamer(TheMips64elTarget, - createMipsNullStreamer); + TargetRegistry::RegisterNullTargetStreamer(TheMipsTarget, + createMipsNullTargetStreamer); + TargetRegistry::RegisterNullTargetStreamer(TheMipselTarget, + createMipsNullTargetStreamer); + TargetRegistry::RegisterNullTargetStreamer(TheMips64Target, + createMipsNullTargetStreamer); + TargetRegistry::RegisterNullTargetStreamer(TheMips64elTarget, + createMipsNullTargetStreamer); // Register the asm backend. TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index f08a8f4..9528b4e 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -55,10 +55,13 @@ MCAsmBackend *createMipsAsmBackendEL64(const Target &T, const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); -MCObjectWriter *createMipsELFObjectWriter(raw_ostream &OS, - uint8_t OSABI, - bool IsLittleEndian, - bool Is64Bit); +MCObjectWriter *createMipsELFObjectWriter(raw_ostream &OS, uint8_t OSABI, + bool IsLittleEndian, bool Is64Bit); + +namespace MIPS_MC { +StringRef selectMipsCPU(StringRef TT, StringRef CPU); +} + } // End llvm namespace // Defines symbolic names for Mips registers. This defines a mapping from diff --git a/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp index 0ef2208..188e3e8 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -9,14 +9,15 @@ #include "MipsOptionRecord.h" #include "MipsELFStreamer.h" +#include "MipsTargetStreamer.h" #include "llvm/MC/MCSectionELF.h" using namespace llvm; void MipsRegInfoRecord::EmitMipsOptionRecord() { MCAssembler &MCA = Streamer->getAssembler(); - Triple T(STI.getTargetTriple()); - uint64_t Features = STI.getFeatureBits(); + MipsTargetStreamer *MTS = + static_cast<MipsTargetStreamer *>(Streamer->getTargetStreamer()); Streamer->PushSection(); @@ -24,17 +25,16 @@ void MipsRegInfoRecord::EmitMipsOptionRecord() { // we don't emit .Mips.options for other ELFs other than N64. // Since .reginfo has the same information as .Mips.options (ODK_REGINFO), // we can use the same abstraction (MipsRegInfoRecord class) to handle both. - if (Features & Mips::FeatureN64) { + if (MTS->getABI().IsN64()) { // The EntrySize value of 1 seems strange since the records are neither // 1-byte long nor fixed length but it matches the value GAS emits. const MCSectionELF *Sec = Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS, - ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, - SectionKind::getMetadata(), 1, ""); + ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, 1, ""); MCA.getOrCreateSectionData(*Sec).setAlignment(8); Streamer->SwitchSection(Sec); - Streamer->EmitIntValue(1, 1); // kind + Streamer->EmitIntValue(ELF::ODK_REGINFO, 1); // kind Streamer->EmitIntValue(40, 1); // size Streamer->EmitIntValue(0, 2); // section Streamer->EmitIntValue(0, 4); // info @@ -46,11 +46,10 @@ void MipsRegInfoRecord::EmitMipsOptionRecord() { Streamer->EmitIntValue(ri_cprmask[3], 4); Streamer->EmitIntValue(ri_gp_value, 8); } else { - const MCSectionELF *Sec = - Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, - SectionKind::getMetadata(), 24, ""); + const MCSectionELF *Sec = Context.getELFSection( + ".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, 24, ""); MCA.getOrCreateSectionData(*Sec) - .setAlignment(Features & Mips::FeatureN32 ? 8 : 4); + .setAlignment(MTS->getABI().IsN32() ? 8 : 4); Streamer->SwitchSection(Sec); Streamer->EmitIntValue(ri_gprmask, 4); diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 1e092f2..64d7cab 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -43,6 +43,9 @@ void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { + forbidModuleDirective(); +} void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {} void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {} @@ -67,9 +70,13 @@ void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetPop() {} void MipsTargetStreamer::emitDirectiveSetPush() {} @@ -144,6 +151,11 @@ void MipsTargetAsmStreamer::emitDirectiveSetAt() { MipsTargetStreamer::emitDirectiveSetAt(); } +void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { + OS << "\t.set\tat=$" << Twine(RegNo) << "\n"; + MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo); +} + void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { OS << "\t.set\tnoat\n"; MipsTargetStreamer::emitDirectiveSetNoAt(); @@ -223,6 +235,16 @@ void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { MipsTargetStreamer::emitDirectiveSetMips32R2(); } +void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() { + OS << "\t.set\tmips32r3\n"; + MipsTargetStreamer::emitDirectiveSetMips32R3(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() { + OS << "\t.set\tmips32r5\n"; + MipsTargetStreamer::emitDirectiveSetMips32R5(); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() { OS << "\t.set\tmips32r6\n"; MipsTargetStreamer::emitDirectiveSetMips32R6(); @@ -238,6 +260,16 @@ void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { MipsTargetStreamer::emitDirectiveSetMips64R2(); } +void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() { + OS << "\t.set\tmips64r3\n"; + MipsTargetStreamer::emitDirectiveSetMips64R3(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() { + OS << "\t.set\tmips64r5\n"; + MipsTargetStreamer::emitDirectiveSetMips64R5(); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() { OS << "\t.set\tmips64r6\n"; MipsTargetStreamer::emitDirectiveSetMips64R6(); @@ -335,19 +367,32 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { MCAssembler &MCA = getStreamer().getAssembler(); - uint64_t Features = STI.getFeatureBits(); Triple T(STI.getTargetTriple()); Pic = (MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) ? true : false; - // Update e_header flags - unsigned EFlags = 0; + uint64_t Features = STI.getFeatureBits(); + + // Set the header flags that we can in the constructor. + // FIXME: This is a fairly terrible hack. We set the rest + // of these in the destructor. The problem here is two-fold: + // + // a: Some of the eflags can be set/reset by directives. + // b: There aren't any usage paths that initialize the ABI + // pointer until after we initialize either an assembler + // or the target machine. + // We can fix this by making the target streamer construct + // the ABI, but this is fraught with wide ranging dependency + // issues as well. + unsigned EFlags = MCA.getELFHeaderEFlags(); // Architecture if (Features & Mips::FeatureMips64r6) EFlags |= ELF::EF_MIPS_ARCH_64R6; - else if (Features & Mips::FeatureMips64r2) + else if (Features & Mips::FeatureMips64r2 || + Features & Mips::FeatureMips64r3 || + Features & Mips::FeatureMips64r5) EFlags |= ELF::EF_MIPS_ARCH_64R2; else if (Features & Mips::FeatureMips64) EFlags |= ELF::EF_MIPS_ARCH_64; @@ -359,7 +404,9 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, EFlags |= ELF::EF_MIPS_ARCH_3; else if (Features & Mips::FeatureMips32r6) EFlags |= ELF::EF_MIPS_ARCH_32R6; - else if (Features & Mips::FeatureMips32r2) + else if (Features & Mips::FeatureMips32r2 || + Features & Mips::FeatureMips32r3 || + Features & Mips::FeatureMips32r5) EFlags |= ELF::EF_MIPS_ARCH_32R2; else if (Features & Mips::FeatureMips32) EFlags |= ELF::EF_MIPS_ARCH_32; @@ -368,19 +415,6 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, else EFlags |= ELF::EF_MIPS_ARCH_1; - // ABI - // N64 does not require any ABI bits. - if (Features & Mips::FeatureO32) - EFlags |= ELF::EF_MIPS_ABI_O32; - else if (Features & Mips::FeatureN32) - EFlags |= ELF::EF_MIPS_ABI2; - - if (Features & Mips::FeatureGP64Bit) { - if (Features & Mips::FeatureO32) - EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ - } else if (Features & Mips::FeatureMips64r2 || Features & Mips::FeatureMips64) - EFlags |= ELF::EF_MIPS_32BITMODE; - // Other options. if (Features & Mips::FeatureNaN2008) EFlags |= ELF::EF_MIPS_NAN2008; @@ -388,8 +422,6 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, // -mabicalls and -mplt are not implemented but we should act as if they were // given. EFlags |= ELF::EF_MIPS_CPIC; - if (Features & Mips::FeatureN64) - EFlags |= ELF::EF_MIPS_PIC; MCA.setELFHeaderEFlags(EFlags); } @@ -424,6 +456,32 @@ void MipsTargetELFStreamer::finish() { DataSectionData.setAlignment(std::max(16u, DataSectionData.getAlignment())); BSSSectionData.setAlignment(std::max(16u, BSSSectionData.getAlignment())); + uint64_t Features = STI.getFeatureBits(); + + // Update e_header flags. See the FIXME and comment above in + // the constructor for a full rundown on this. + unsigned EFlags = MCA.getELFHeaderEFlags(); + + // ABI + // N64 does not require any ABI bits. + if (getABI().IsO32()) + EFlags |= ELF::EF_MIPS_ABI_O32; + else if (getABI().IsN32()) + EFlags |= ELF::EF_MIPS_ABI2; + + if (Features & Mips::FeatureGP64Bit) { + if (getABI().IsO32()) + EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ + } else if (Features & Mips::FeatureMips64r2 || Features & Mips::FeatureMips64) + EFlags |= ELF::EF_MIPS_32BITMODE; + + // If we've set the cpic eflag and we're n64, go ahead and set the pic + // one as well. + if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64()) + EFlags |= ELF::EF_MIPS_PIC; + + MCA.setELFHeaderEFlags(EFlags); + // Emit all the option records. // At the moment we are only emitting .Mips.options (ODK_REGINFO) and // .reginfo. @@ -493,9 +551,8 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { MCContext &Context = MCA.getContext(); MCStreamer &OS = getStreamer(); - const MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHT_REL, - SectionKind::getMetadata()); + const MCSectionELF *Sec = Context.getELFSection( + ".pdr", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHT_REL); const MCSymbolRefExpr *ExprRef = MCSymbolRefExpr::Create(Name, MCSymbolRefExpr::VK_None, Context); @@ -604,7 +661,7 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { // addui $gp, $gp, %lo(_gp_disp) // addu $gp, $gp, $reg // when support for position independent code is enabled. - if (!Pic || (isN32() || isN64())) + if (!Pic || (getABI().IsN32() || getABI().IsN64())) return; // There's a GNU extension controlled by -mno-shared that allows @@ -653,7 +710,7 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, const MCSymbol &Sym, bool IsReg) { // Only N32 and N64 emit anything for .cpsetup iff PIC is set. - if (!Pic || !(isN32() || isN64())) + if (!Pic || !(getABI().IsN32() || getABI().IsN64())) return; MCAssembler &MCA = getStreamer().getAssembler(); @@ -677,9 +734,10 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, Inst.clear(); const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( - Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext()); + &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext()); const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create( - Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext()); + &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext()); + // lui $gp, %hi(%neg(%gp_rel(funcSym))) Inst.setOpcode(Mips::LUi); Inst.addOperand(MCOperand::CreateReg(Mips::GP)); @@ -709,9 +767,8 @@ void MipsTargetELFStreamer::emitMipsAbiFlags() { MCAssembler &MCA = getStreamer().getAssembler(); MCContext &Context = MCA.getContext(); MCStreamer &OS = getStreamer(); - const MCSectionELF *Sec = - Context.getELFSection(".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, - ELF::SHF_ALLOC, SectionKind::getMetadata(), 24, ""); + const MCSectionELF *Sec = Context.getELFSection( + ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24, ""); MCSectionData &ABIShndxSD = MCA.getOrCreateSectionData(*Sec); ABIShndxSD.setAlignment(8); OS.SwitchSection(Sec); diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td index 59bf949..560afa4 100644 --- a/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -108,6 +108,40 @@ class ADDIUR2_FM_MM16 { let Inst{0} = 0; } +class LOAD_STORE_FM_MM16<bits<6> op> { + bits<3> rt; + bits<7> addr; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rt; + let Inst{6-4} = addr{6-4}; + let Inst{3-0} = addr{3-0}; +} + +class LOAD_STORE_SP_FM_MM16<bits<6> op> { + bits<5> rt; + bits<5> offset; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-5} = rt; + let Inst{4-0} = offset; +} + +class LOAD_GP_FM_MM16<bits<6> op> { + bits<3> rt; + bits<7> offset; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rt; + let Inst{6-0} = offset; +} + class ADDIUS5_FM_MM16 { bits<5> rd; bits<4> imm; @@ -195,6 +229,49 @@ class ADDIUR1SP_FM_MM16 { let Inst{0} = 1; } +class BRKSDBBP16_FM_MM<bits<6> op> { + bits<4> code_; + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-4} = op; + let Inst{3-0} = code_; +} + +class BEQNEZ_FM_MM16<bits<6> op> { + bits<3> rs; + bits<7> offset; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rs; + let Inst{6-0} = offset; +} + +class B16_FM { + bits<10> offset; + + bits<16> Inst; + + let Inst{15-10} = 0x33; + let Inst{9-0} = offset; +} + +class MOVEP_FM_MM16 { + bits<3> dst_regs; + bits<3> rt; + bits<3> rs; + + bits<16> Inst; + + let Inst{15-10} = 0x21; + let Inst{9-7} = dst_regs; + let Inst{6-4} = rt; + let Inst{3-1} = rs; + let Inst{0} = 0; +} + //===----------------------------------------------------------------------===// // MicroMIPS 32-bit Instruction Formats //===----------------------------------------------------------------------===// @@ -817,3 +894,52 @@ class LWM_FM_MM<bits<4> funct> : MMArch { let Inst{15-12} = funct; let Inst{11-0} = addr{11-0}; } + +class LWM_FM_MM16<bits<4> funct> : MMArch { + bits<2> rt; + bits<4> addr; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-6} = funct; + let Inst{5-4} = rt; + let Inst{3-0} = addr; +} + +class CACHE_PREF_FM_MM<bits<6> op, bits<4> funct> : MMArch { + bits<21> addr; + bits<5> hint; + bits<5> base = addr{20-16}; + bits<12> offset = addr{11-0}; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = hint; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11-0} = offset; +} + +class BARRIER_FM_MM<bits<5> op> : MMArch { + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = 0x0; + let Inst{20-16} = 0x0; + let Inst{15-11} = op; + let Inst{10-6} = 0x0; + let Inst{5-0} = 0x0; +} + +class ADDIUPC_FM_MM { + bits<3> rs; + bits<23> imm; + + bits<32> Inst; + + let Inst{31-26} = 0x1e; + let Inst{25-23} = rs; + let Inst{22-0} = imm; +} diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index e854620..e20df2f 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,7 +1,13 @@ def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>; +def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>; -def simm4 : Operand<i32>; +def simm4 : Operand<i32> { + let DecoderMethod = "DecodeSimm4"; +} def simm7 : Operand<i32>; +def li_simm7 : Operand<i32> { + let DecoderMethod = "DecodeLiSimm7"; +} def simm12 : Operand<i32> { let DecoderMethod = "DecodeSimm12"; @@ -9,14 +15,17 @@ def simm12 : Operand<i32> { def uimm5_lsl2 : Operand<OtherVT> { let EncoderMethod = "getUImm5Lsl2Encoding"; + let DecoderMethod = "DecodeUImm5lsl2"; } def uimm6_lsl2 : Operand<i32> { let EncoderMethod = "getUImm6Lsl2Encoding"; + let DecoderMethod = "DecodeUImm6Lsl2"; } def simm9_addiusp : Operand<i32> { let EncoderMethod = "getSImm9AddiuspValue"; + let DecoderMethod = "DecodeSimm9SP"; } def uimm3_shift : Operand<i32> { @@ -25,10 +34,12 @@ def uimm3_shift : Operand<i32> { def simm3_lsa2 : Operand<i32> { let EncoderMethod = "getSImm3Lsa2Value"; + let DecoderMethod = "DecodeAddiur2Simm7"; } def uimm4_andi : Operand<i32> { let EncoderMethod = "getUImm4AndValue"; + let DecoderMethod = "DecodeANDI16Imm"; } def immSExtAddiur2 : ImmLeaf<i32, [{return Imm == 1 || Imm == -1 || @@ -46,6 +57,54 @@ def immZExt2Shift : ImmLeaf<i32, [{return Imm >= 1 && Imm <= 8;}]>; def immLi16 : ImmLeaf<i32, [{return Imm >= -1 && Imm <= 126;}]>; +def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass { + let Name = "MicroMipsMem"; + let RenderMethod = "addMicroMipsMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithGRPMM16Base"; +} + +class mem_mm_4_generic : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPRMM16, simm4); + let OperandType = "OPERAND_MEMORY"; + let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; +} + +def mem_mm_4 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4"; +} + +def mem_mm_4_lsl1 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4Lsl1"; +} + +def mem_mm_4_lsl2 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4Lsl2"; +} + +def MicroMipsMemSPAsmOperand : AsmOperandClass { + let Name = "MicroMipsMemSP"; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>"; +} + +def mem_mm_sp_imm5_lsl2 : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPR32:$base, simm5:$offset); + let OperandType = "OPERAND_MEMORY"; + let ParserMatchClass = MicroMipsMemSPAsmOperand; + let EncoderMethod = "getMemEncodingMMSPImm5Lsl2"; +} + +def mem_mm_gp_imm7_lsl2 : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPRMM16:$base, simm7:$offset); + let OperandType = "OPERAND_MEMORY"; + let EncoderMethod = "getMemEncodingMMGPImm7Lsl2"; +} + def mem_mm_12 : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -54,6 +113,22 @@ def mem_mm_12 : Operand<i32> { let OperandType = "OPERAND_MEMORY"; } +def MipsMemUimm4AsmOperand : AsmOperandClass { + let Name = "MemOffsetUimm4"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithUimmOffsetSP<6>"; +} + +def mem_mm_4sp : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPR32, uimm8); + let EncoderMethod = "getMemEncodingMMImm4sp"; + let ParserMatchClass = MipsMemUimm4AsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + def jmptarget_mm : Operand<OtherVT> { let EncoderMethod = "getJumpTargetOpValueMM"; } @@ -62,10 +137,30 @@ def calltarget_mm : Operand<iPTR> { let EncoderMethod = "getJumpTargetOpValueMM"; } +def brtarget7_mm : Operand<OtherVT> { + let EncoderMethod = "getBranchTarget7OpValueMM"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget7MM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + +def brtarget10_mm : Operand<OtherVT> { + let EncoderMethod = "getBranchTargetOpValueMMPC10"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget10MM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + def brtarget_mm : Operand<OtherVT> { let EncoderMethod = "getBranchTargetOpValueMM"; let OperandType = "OPERAND_PCREL"; let DecoderMethod = "DecodeBranchTargetMM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + +def simm23_lsl2 : Operand<i32> { + let EncoderMethod = "getSimm23Lsl2Encoding"; + let DecoderMethod = "DecodeSimm23Lsl2"; } class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op, @@ -97,6 +192,58 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, let DecoderMethod = "DecodeMemMMImm12"; } +/// A register pair used by movep instruction. +def MovePRegPairAsmOperand : AsmOperandClass { + let Name = "MovePRegPair"; + let ParserMethod = "parseMovePRegPair"; + let PredicateMethod = "isMovePRegPair"; +} + +def movep_regpair : Operand<i32> { + let EncoderMethod = "getMovePRegPairOpValue"; + let ParserMatchClass = MovePRegPairAsmOperand; + let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeMovePRegPair"; + let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd); +} + +class MovePMM16<string opstr, RegisterOperand RO> : +MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt), + !strconcat(opstr, "\t$dst_regs, $rs, $rt"), [], + NoItinerary, FrmR> { + let isReMaterializable = 1; +} + +/// A register pair used by load/store pair instructions. +def RegPairAsmOperand : AsmOperandClass { + let Name = "RegPair"; + let ParserMethod = "parseRegisterPair"; +} + +def regpair : Operand<i32> { + let EncoderMethod = "getRegisterPairOpValue"; + let ParserMatchClass = RegPairAsmOperand; + let PrintMethod = "printRegisterPair"; + let DecoderMethod = "DecodeRegPairOperand"; + let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd); +} + +class StorePairMM<string opstr, InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + InstSE<(outs), (ins regpair:$rt, mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayStore = 1; +} + +class LoadPairMM<string opstr, InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + InstSE<(outs regpair:$rt), (ins mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayLoad = 1; +} + class LLBaseMM<string opstr, RegisterOperand RO> : InstSE<(outs RO:$rt), (ins mem_mm_12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { @@ -156,6 +303,50 @@ class ShiftIMM16<string opstr, Operand ImmOpnd, RegisterOperand RO, MicroMipsInst16<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt), !strconcat(opstr, "\t$rd, $rt, $shamt"), [], Itin, FrmR>; +class LoadMM16<string opstr, DAGOperand RO, SDPatternOperator OpNode, + InstrItinClass Itin, Operand MemOpnd> : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMImm4"; + let canFoldAsLoad = 1; + let mayLoad = 1; +} + +class StoreMM16<string opstr, DAGOperand RTOpnd, DAGOperand RO, + SDPatternOperator OpNode, InstrItinClass Itin, + Operand MemOpnd> : + MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMImm4"; + let mayStore = 1; +} + +class LoadSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, + Operand MemOpnd> : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; + let canFoldAsLoad = 1; + let mayLoad = 1; +} + +class StoreSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, + Operand MemOpnd> : + MicroMipsInst16<(outs), (ins RO:$rt, MemOpnd:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; + let mayStore = 1; +} + +class LoadGPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, + Operand MemOpnd> : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMGPImm7Lsl2"; + let canFoldAsLoad = 1; + let mayLoad = 1; +} + class AddImmUR2<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm), !strconcat(opstr, "\t$rd, $rs, $imm"), @@ -192,8 +383,7 @@ class MoveMM16<string opstr, RegisterOperand RO, bit isComm = 0, let isReMaterializable = 1; } -class LoadImmMM16<string opstr, Operand Od, RegisterOperand RO, - SDPatternOperator imm_type = null_frag> : +class LoadImmMM16<string opstr, Operand Od, RegisterOperand RO> : MicroMipsInst16<(outs RO:$rd), (ins Od:$imm), !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmI> { let isReMaterializable = 1; @@ -223,7 +413,6 @@ class JumpRAddiuStackMM16 : [], IIBranch, FrmR> { let isTerminator = 1; let isBarrier = 1; - let hasDelaySlot = 1; let isBranch = 1; let isIndirectBranch = 1; } @@ -247,6 +436,21 @@ class JumpRegCMM16<string opstr, RegisterOperand RO> : let isIndirectBranch = 1; } +// Break16 and Sdbbp16 +class BrkSdbbp16MM<string opstr> : + MicroMipsInst16<(outs), (ins uimm4:$code_), + !strconcat(opstr, "\t$code_"), + [], NoItinerary, FrmOther>; + +class CBranchZeroMM<string opstr, DAGOperand opnd, RegisterOperand RO> : + MicroMipsInst16<(outs), (ins RO:$rs, opnd:$offset), + !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; + let Defs = [AT]; +} + // MicroMIPS Jump and Link (Call) - Short Delay Slot let isCall = 1, hasDelaySlot = 1, Defs = [RA] in { class JumpLinkMM<string opstr, DAGOperand opnd> : @@ -271,6 +475,10 @@ class LoadWordIndexedScaledMM<string opstr, RegisterOperand RO, InstSE<(outs RO:$rd), (ins PtrRC:$base, PtrRC:$index), !strconcat(opstr, "\t$rd, ${index}(${base})"), [], Itin, FrmFI>; +class AddImmUPC<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$rs), (ins simm23_lsl2:$imm), + !strconcat(opstr, "\t$rs, $imm"), [], NoItinerary, FrmR>; + /// A list of registers used by load/store multiple instructions. def RegListAsmOperand : AsmOperandClass { let Name = "RegList"; @@ -284,6 +492,20 @@ def reglist : Operand<i32> { let DecoderMethod = "DecodeRegListOperand"; } +def RegList16AsmOperand : AsmOperandClass { + let Name = "RegList16"; + let ParserMethod = "parseRegisterList"; + let PredicateMethod = "isRegList16"; + let RenderMethod = "addRegListOperands"; +} + +def reglist16 : Operand<i32> { + let EncoderMethod = "getRegisterListOpValue16"; + let DecoderMethod = "DecodeRegListOperand16"; + let PrintMethod = "printRegisterList"; + let ParserMatchClass = RegList16AsmOperand; +} + class StoreMultMM<string opstr, InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr), @@ -300,6 +522,36 @@ class LoadMultMM<string opstr, let mayLoad = 1; } +class StoreMultMM16<string opstr, + InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; + let mayStore = 1; +} + +class LoadMultMM16<string opstr, + InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; + let mayLoad = 1; +} + +class UncondBranchMM16<string opstr> : + MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), + !strconcat(opstr, "\t$offset"), + [], IIBranch, FrmI> { + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let hasDelaySlot = 1; + let Predicates = [RelocPIC, InMicroMips]; + let Defs = [AT]; +} + def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, ARITH_FM_MM16<0>; def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, @@ -316,6 +568,25 @@ def SLL16_MM : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, SHIFT_FM_MM16<0>; def SRL16_MM : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, SHIFT_FM_MM16<1>; +def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, zextloadi8, II_LBU, + mem_mm_4>, LOAD_STORE_FM_MM16<0x02>; +def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU, + mem_mm_4_lsl1>, LOAD_STORE_FM_MM16<0x0a>; +def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW, mem_mm_4_lsl2>, + LOAD_STORE_FM_MM16<0x1a>; +def SB16_MM : StoreMM16<"sb16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei8, + II_SB, mem_mm_4>, LOAD_STORE_FM_MM16<0x22>; +def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, + II_SH, mem_mm_4_lsl1>, + LOAD_STORE_FM_MM16<0x2a>; +def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, + mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>; +def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_imm7_lsl2>, + LOAD_GP_FM_MM16<0x19>; +def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, + LOAD_STORE_SP_FM_MM16<0x12>; +def SWSP_MM : StoreSPMM16<"sw", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, + LOAD_STORE_SP_FM_MM16<0x32>; def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16; def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16; def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16; @@ -323,13 +594,21 @@ def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16; def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>; def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; -def LI16_MM : LoadImmMM16<"li16", simm7, GPRMM16Opnd, immLi16>, - LI_FM_MM16, IsAsCheapAsAMove; +def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16; +def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16, + IsAsCheapAsAMove; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>; def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>; def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>; def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>; def JR16_MM : JumpRegMM16<"jr16", GPR32Opnd>, JALR_FM_MM16<0x0c>; +def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>, + BEQNEZ_FM_MM16<0x23>; +def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>, + BEQNEZ_FM_MM16<0x2b>; +def B16_MM : UncondBranchMM16<"b16">, B16_FM; +def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>; +def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>; class WaitMM<string opstr> : InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [], @@ -387,6 +666,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, MULT_FM_MM<0x2ec>; + /// Arithmetic Instructions with PC and Immediate + def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM; + /// Shift Instructions def SLL_MM : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>, SRA_FM_MM<0, 0>; @@ -434,6 +716,25 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { /// Load and Store Instructions - multiple def SWM32_MM : StoreMultMM<"swm32">, LWM_FM_MM<0xd>; def LWM32_MM : LoadMultMM<"lwm32">, LWM_FM_MM<0x5>; + def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>; + def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>; + + /// Load and Store Pair Instructions + def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>; + def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>; + + /// Load and Store multiple pseudo Instructions + class LoadWordMultMM<string instr_asm > : + MipsAsmPseudoInst<(outs reglist:$rt), (ins mem_mm_12:$addr), + !strconcat(instr_asm, "\t$rt, $addr")> ; + + class StoreWordMultMM<string instr_asm > : + MipsAsmPseudoInst<(outs), (ins reglist:$rt, mem_mm_12:$addr), + !strconcat(instr_asm, "\t$rt, $addr")> ; + + + def SWM_MM : StoreWordMultMM<"swm">; + def LWM_MM : LoadWordMultMM<"lwm">; /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, @@ -487,6 +788,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def J_MM : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">, J_FM_MM<0x35>; def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>; + def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>; } def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>; def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>; @@ -550,6 +852,16 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def LL_MM : LLBaseMM<"ll", GPR32Opnd>, LL_FM_MM<0x3>; def SC_MM : SCBaseMM<"sc", GPR32Opnd>, LL_FM_MM<0xb>; + let DecoderMethod = "DecodeCacheOpMM" in { + def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12>, + CACHE_PREF_FM_MM<0x08, 0x6>; + def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12>, + CACHE_PREF_FM_MM<0x18, 0x2>; + } + def SSNOP_MM : MMRel, Barrier<"ssnop">, BARRIER_FM_MM<0x1>; + def EHB_MM : MMRel, Barrier<"ehb">, BARRIER_FM_MM<0x3>; + def PAUSE_MM : MMRel, Barrier<"pause">, BARRIER_FM_MM<0x5>; + def TLBP_MM : MMRel, TLB<"tlbp">, COP0_TLB_FM_MM<0x0d>; def TLBR_MM : MMRel, TLB<"tlbr">, COP0_TLB_FM_MM<0x4d>; def TLBWI_MM : MMRel, TLB<"tlbwi">, COP0_TLB_FM_MM<0x8d>; @@ -565,6 +877,13 @@ let Predicates = [InMicroMips] in { // MicroMips arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// +def : MipsPat<(i32 immLi16:$imm), + (LI16_MM immLi16:$imm)>; +def : MipsPat<(i32 immSExt16:$imm), + (ADDiu_MM ZERO, immSExt16:$imm)>; +def : MipsPat<(i32 immZExt16:$imm), + (ORi_MM ZERO, immZExt16:$imm)>; + def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm), (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>; def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm), @@ -587,9 +906,27 @@ def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), def : MipsPat<(srl GPR32:$src, immZExt5:$imm), (SRL_MM GPR32:$src, immZExt5:$imm)>; +def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), + (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>; +def : MipsPat<(store GPR32:$src, addr:$addr), + (SW_MM GPR32:$src, addr:$addr)>; + +def : MipsPat<(load addrimm4lsl2:$addr), + (LW16_MM addrimm4lsl2:$addr)>; +def : MipsPat<(load addr:$addr), + (LW_MM addr:$addr)>; + //===----------------------------------------------------------------------===// // MicroMips instruction aliases //===----------------------------------------------------------------------===// +class UncondBranchMMPseudo<string opstr> : + MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), + !strconcat(opstr, "\t$offset")>; + + def B_MM_Pseudo : UncondBranchMMPseudo<"b">; + def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>; + def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>; + def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>; } diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 87f1b04..cb09c1a 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -22,7 +22,6 @@ namespace llvm { class MipsTargetMachine; class FunctionPass; - FunctionPass *createMipsISelDag(MipsTargetMachine &TM); FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM); diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 3e1d047..01c548e 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -69,14 +69,6 @@ def FeatureNaN2008 : SubtargetFeature<"nan2008", "IsNaN2008bit", "true", "IEEE 754-2008 NaN encoding.">; def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", "true", "Only supports single precision float">; -def FeatureO32 : SubtargetFeature<"o32", "ABI", "MipsABIInfo::O32()", - "Enable o32 ABI">; -def FeatureN32 : SubtargetFeature<"n32", "ABI", "MipsABIInfo::N32()", - "Enable n32 ABI">; -def FeatureN64 : SubtargetFeature<"n64", "ABI", "MipsABIInfo::N64()", - "Enable n64 ABI">; -def FeatureEABI : SubtargetFeature<"eabi", "ABI", "MipsABIInfo::EABI()", - "Enable eabi ABI">; def FeatureNoOddSPReg : SubtargetFeature<"nooddspreg", "UseOddSPReg", "false", "Disable odd numbered single-precision " "registers">; @@ -122,10 +114,16 @@ def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", "Mips32r2", "Mips32r2 ISA Support", [FeatureMips3_32r2, FeatureMips4_32r2, FeatureMips5_32r2, FeatureMips32]>; +def FeatureMips32r3 : SubtargetFeature<"mips32r3", "MipsArchVersion", + "Mips32r3", "Mips32r3 ISA Support", + [FeatureMips32r2]>; +def FeatureMips32r5 : SubtargetFeature<"mips32r5", "MipsArchVersion", + "Mips32r5", "Mips32r5 ISA Support", + [FeatureMips32r3]>; def FeatureMips32r6 : SubtargetFeature<"mips32r6", "MipsArchVersion", "Mips32r6", "Mips32r6 ISA Support [experimental]", - [FeatureMips32r2, FeatureFP64Bit, + [FeatureMips32r5, FeatureFP64Bit, FeatureNaN2008]>; def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", "Mips64", "Mips64 ISA Support", @@ -133,10 +131,16 @@ def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion", "Mips64r2", "Mips64r2 ISA Support", [FeatureMips64, FeatureMips32r2]>; +def FeatureMips64r3 : SubtargetFeature<"mips64r3", "MipsArchVersion", + "Mips64r3", "Mips64r3 ISA Support", + [FeatureMips64r2, FeatureMips32r3]>; +def FeatureMips64r5 : SubtargetFeature<"mips64r5", "MipsArchVersion", + "Mips64r5", "Mips64r5 ISA Support", + [FeatureMips64r3, FeatureMips32r5]>; def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion", "Mips64r6", "Mips64r6 ISA Support [experimental]", - [FeatureMips32r6, FeatureMips64r2, + [FeatureMips32r6, FeatureMips64r5, FeatureNaN2008]>; def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true", @@ -162,20 +166,24 @@ def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips", class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, MipsGenericItineraries, Features>; -def : Proc<"mips1", [FeatureMips1, FeatureO32]>; -def : Proc<"mips2", [FeatureMips2, FeatureO32]>; -def : Proc<"mips32", [FeatureMips32, FeatureO32]>; -def : Proc<"mips32r2", [FeatureMips32r2, FeatureO32]>; -def : Proc<"mips32r6", [FeatureMips32r6, FeatureO32]>; - -def : Proc<"mips3", [FeatureMips3, FeatureN64]>; -def : Proc<"mips4", [FeatureMips4, FeatureN64]>; -def : Proc<"mips5", [FeatureMips5, FeatureN64]>; -def : Proc<"mips64", [FeatureMips64, FeatureN64]>; -def : Proc<"mips64r2", [FeatureMips64r2, FeatureN64]>; -def : Proc<"mips64r6", [FeatureMips64r6, FeatureN64]>; -def : Proc<"mips16", [FeatureMips16, FeatureO32]>; -def : Proc<"octeon", [FeatureMips64r2, FeatureN64, FeatureCnMips]>; +def : Proc<"mips1", [FeatureMips1]>; +def : Proc<"mips2", [FeatureMips2]>; +def : Proc<"mips32", [FeatureMips32]>; +def : Proc<"mips32r2", [FeatureMips32r2]>; +def : Proc<"mips32r3", [FeatureMips32r3]>; +def : Proc<"mips32r5", [FeatureMips32r5]>; +def : Proc<"mips32r6", [FeatureMips32r6]>; + +def : Proc<"mips3", [FeatureMips3]>; +def : Proc<"mips4", [FeatureMips4]>; +def : Proc<"mips5", [FeatureMips5]>; +def : Proc<"mips64", [FeatureMips64]>; +def : Proc<"mips64r2", [FeatureMips64r2]>; +def : Proc<"mips64r3", [FeatureMips64r3]>; +def : Proc<"mips64r5", [FeatureMips64r5]>; +def : Proc<"mips64r6", [FeatureMips64r6]>; +def : Proc<"mips16", [FeatureMips16]>; +def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>; def MipsAsmParser : AsmParser { let ShouldEmitMatchRegisterName = 0; diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp index 6070276..abecfa0 100644 --- a/lib/Target/Mips/Mips16FrameLowering.cpp +++ b/lib/Target/Mips/Mips16FrameLowering.cpp @@ -36,7 +36,7 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); uint64_t StackSize = MFI->getStackSize(); @@ -84,7 +84,7 @@ void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); uint64_t StackSize = MFI->getStackSize(); @@ -154,7 +154,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Amount = -Amount; const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); TII.adjustStackPtr(Mips::SP, Amount, MBB, I); } @@ -174,7 +174,7 @@ void Mips16FrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); const MipsRegisterInfo &RI = TII.getRegisterInfo(); const BitVector Reserved = RI.getReservedRegs(MF); bool SaveS2 = Reserved[Mips::S2]; diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index 9488e63..32dc90a 100644 --- a/lib/Target/Mips/Mips16HardFloat.cpp +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -247,12 +247,12 @@ static void swapFPIntParams // Having called needsFPHelperFromSig // static void assureFPCallStub(Function &F, Module *M, - const MipsSubtarget &Subtarget) { + const MipsTargetMachine &TM) { // for now we only need them for static relocation - if (Subtarget.getRelocationModel() == Reloc::PIC_) + if (TM.getRelocationModel() == Reloc::PIC_) return; LLVMContext &Context = M->getContext(); - bool LE = Subtarget.isLittle(); + bool LE = TM.isLittleEndian(); std::string Name = F.getName(); std::string SectionName = ".mips16.call.fp." + Name; std::string StubName = "__call_stub_fp_" + Name; @@ -362,8 +362,8 @@ static bool isIntrinsicInline(Function *F) { // Returns of float, double and complex need to be handled with a helper // function. // -static bool fixupFPReturnAndCall - (Function &F, Module *M, const MipsSubtarget &Subtarget) { +static bool fixupFPReturnAndCall(Function &F, Module *M, + const MipsTargetMachine &TM) { bool Modified = false; LLVMContext &C = M->getContext(); Type *MyVoid = Type::getVoidTy(C); @@ -426,9 +426,9 @@ static bool fixupFPReturnAndCall Modified=true; F.addFnAttr("saveS2"); } - if (Subtarget.getRelocationModel() != Reloc::PIC_ ) { + if (TM.getRelocationModel() != Reloc::PIC_ ) { if (needsFPHelperFromSig(*F_)) { - assureFPCallStub(*F_, M, Subtarget); + assureFPCallStub(*F_, M, TM); Modified=true; } } @@ -439,9 +439,9 @@ static bool fixupFPReturnAndCall } static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, - const MipsSubtarget &Subtarget ) { - bool PicMode = Subtarget.getRelocationModel() == Reloc::PIC_; - bool LE = Subtarget.isLittle(); + const MipsTargetMachine &TM) { + bool PicMode = TM.getRelocationModel() == Reloc::PIC_; + bool LE = TM.isLittleEndian(); LLVMContext &Context = M->getContext(); std::string Name = F->getName(); std::string SectionName = ".mips16.fn." + Name; @@ -458,7 +458,6 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, FStub->setSection(SectionName); BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); InlineAsmHelper IAH(Context, BB); - IAH.Out(" .set macro"); if (PicMode) { IAH.Out(".set noreorder"); IAH.Out(".cpload $$25"); @@ -467,7 +466,6 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, IAH.Out("la $$25," + LocalName); } else { - IAH.Out(".set reorder"); IAH.Out("la $$25," + Name); } swapFPIntParams(PV, M, IAH, LE, false); @@ -522,11 +520,11 @@ bool Mips16HardFloat::runOnModule(Module &M) { } if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") || F->hasFnAttribute("nomips16")) continue; - Modified |= fixupFPReturnAndCall(*F, &M, Subtarget); + Modified |= fixupFPReturnAndCall(*F, &M, TM); FPParamVariant V = whichFPParamVariantNeeded(*F); if (V != NoSig) { Modified = true; - createFPFnStub(F, &M, V, Subtarget); + createFPFnStub(F, &M, V, TM); } } return Modified; diff --git a/lib/Target/Mips/Mips16HardFloat.h b/lib/Target/Mips/Mips16HardFloat.h index 19b7bf2..586cc25 100644 --- a/lib/Target/Mips/Mips16HardFloat.h +++ b/lib/Target/Mips/Mips16HardFloat.h @@ -25,26 +25,16 @@ using namespace llvm; namespace llvm { class Mips16HardFloat : public ModulePass { - public: static char ID; - Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), - TM(TM_), Subtarget(TM.getSubtarget<MipsSubtarget>()) { - } - - const char *getPassName() const override { - return "MIPS16 Hard Float Pass"; - } + Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), TM(TM_) {} + const char *getPassName() const override { return "MIPS16 Hard Float Pass"; } bool runOnModule(Module &M) override; protected: - /// Keep a pointer to the MipsSubtarget around so that we can make the right - /// decision when generating code for different targets. - const TargetMachine &TM; - const MipsSubtarget &Subtarget; - + const MipsTargetMachine &TM; }; ModulePass *createMips16HardFloat(MipsTargetMachine &TM); diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index 7732be4..3221ccb 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -37,7 +37,7 @@ using namespace llvm; #define DEBUG_TYPE "mips-isel" bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); if (!Subtarget->inMips16Mode()) return false; return MipsDAGToDAGISel::runOnMachineFunction(MF); @@ -72,11 +72,10 @@ void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(); - const TargetRegisterClass *RC = - (const TargetRegisterClass*)&Mips::CPU16RegsRegClass; + const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); @@ -103,7 +102,7 @@ void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg(); @@ -135,7 +134,7 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { switch (SD->getMemoryVT().getSizeInBits()) { case 8: case 16: - AliasReg = TM.getSubtargetImpl()->getFrameLowering()->hasFP(*MF) + AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) ? AliasFPReg : getMips16SPAliasReg(); return; @@ -147,7 +146,7 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { switch (SD->getMemoryVT().getSizeInBits()) { case 8: case 16: - AliasReg = TM.getSubtargetImpl()->getFrameLowering()->hasFP(*MF) + AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) ? AliasFPReg : getMips16SPAliasReg(); return; diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index d4852c4..ede4f37 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -149,7 +149,7 @@ Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::BSWAP, MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i64, Expand); - computeRegisterProperties(); + computeRegisterProperties(STI.getRegisterInfo()); } const MipsTargetLowering * @@ -497,14 +497,14 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, SDValue JumpTarget = Callee; // T9 should contain the address of the callee function if - // -reloction-model=pic or it is an indirect call. + // -relocation-model=pic or it is an indirect call. if (IsPICCall || !GlobalOrExternal) { unsigned V0Reg = Mips::V0; if (NeedMips16Helper) { RegsToPass.push_front(std::make_pair(V0Reg, Callee)); JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, getPointerTy()); ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget); - JumpTarget = getAddrGlobal(S, JumpTarget.getValueType(), DAG, + JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG, MipsII::MO_GOT, Chain, FuncInfo->callPtrInfo(S->getSymbol())); } else @@ -522,8 +522,7 @@ MachineBasicBlock *Mips16TargetLowering:: emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -580,13 +579,12 @@ emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { return BB; } -MachineBasicBlock *Mips16TargetLowering::emitSelT16 - (unsigned Opc1, unsigned Opc2, - MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -645,13 +643,13 @@ MachineBasicBlock *Mips16TargetLowering::emitSelT16 } -MachineBasicBlock *Mips16TargetLowering::emitSeliT16 - (unsigned Opc1, unsigned Opc2, - MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2, + MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -710,14 +708,13 @@ MachineBasicBlock *Mips16TargetLowering::emitSeliT16 } -MachineBasicBlock - *Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, - MachineInstr *MI, - MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, + MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned regX = MI->getOperand(0).getReg(); unsigned regY = MI->getOperand(1).getReg(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); @@ -729,12 +726,11 @@ MachineBasicBlock } MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( - unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, - MachineInstr *MI, MachineBasicBlock *BB) const { + unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, + MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned regX = MI->getOperand(0).getReg(); int64_t imm = MI->getOperand(1).getImm(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); @@ -763,13 +759,12 @@ static unsigned Mips16WhichOp8uOr16simm llvm_unreachable("immediate field not usable"); } -MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins( - unsigned SltOpc, - MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned CC = MI->getOperand(0).getReg(); unsigned regX = MI->getOperand(1).getReg(); unsigned regY = MI->getOperand(2).getReg(); @@ -781,13 +776,13 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins( return BB; } -MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRXI16_ins( - unsigned SltiOpc, unsigned SltiXOpc, - MachineInstr *MI, MachineBasicBlock *BB )const { +MachineBasicBlock * +Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc, + MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned CC = MI->getOperand(0).getReg(); unsigned regX = MI->getOperand(1).getReg(); int64_t Imm = MI->getOperand(2).getImm(); diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index 4dd9af2..976becc 100644 --- a/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/lib/Target/Mips/Mips16InstrInfo.cpp @@ -144,7 +144,6 @@ bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { /// opcode, e.g. turning BEQ to BNE. unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const { switch (Opc) { - default: llvm_unreachable("Illegal opcode!"); case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16; case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16; case Mips::BeqzRxImm16: return Mips::BnezRxImm16; @@ -166,8 +165,7 @@ unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BtnezT8SltX16: return Mips::BteqzT8SltX16; case Mips::BtnezT8SltiX16: return Mips::BteqzT8SltiX16; } - assert(false && "Implement this function."); - return 0; + llvm_unreachable("Illegal opcode!"); } static void addSaveRestoreRegs(MachineInstrBuilder &MIB, @@ -288,7 +286,7 @@ void Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount, void Mips16InstrInfo::adjustStackPtrBigUnrestricted( unsigned SP, int64_t Amount, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { - assert(false && "adjust stack pointer amount exceeded"); + llvm_unreachable("adjust stack pointer amount exceeded"); } /// Adjust SP by Amount bytes. diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index 2364f4d..10fff03 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -502,7 +502,7 @@ class ArithLogic16Defs<bit isCom=0> { bits<5> shamt = 0; bit isCommutable = isCom; bit isReMaterializable = 1; - bit neverHasSideEffects = 1; + bit hasSideEffects = 0; } class branch16 { @@ -879,7 +879,7 @@ def MoveR3216: FI8_MOVR3216_ins<"move", IIAlu>; // def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIAlu> { let Uses = [HI0]; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } // @@ -889,7 +889,7 @@ def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIAlu> { // def Mflo16: FRR16_M_ins<0b10010, "mflo", IIAlu> { let Uses = [LO0]; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } // @@ -897,13 +897,13 @@ def Mflo16: FRR16_M_ins<0b10010, "mflo", IIAlu> { // def MultRxRy16: FMULT16_ins<"mult", IIAlu> { let isCommutable = 1; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let Defs = [HI0, LO0]; } def MultuRxRy16: FMULT16_ins<"multu", IIAlu> { let isCommutable = 1; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let Defs = [HI0, LO0]; } @@ -914,7 +914,7 @@ def MultuRxRy16: FMULT16_ins<"multu", IIAlu> { // def MultRxRyRz16: FMULT16_LO_ins<"mult", IIAlu> { let isCommutable = 1; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let Defs = [HI0, LO0]; } @@ -925,7 +925,7 @@ def MultRxRyRz16: FMULT16_LO_ins<"mult", IIAlu> { // def MultuRxRyRz16: FMULT16_LO_ins<"multu", IIAlu> { let isCommutable = 1; - let neverHasSideEffects = 1; + let hasSideEffects = 0; let Defs = [HI0, LO0]; } @@ -1910,7 +1910,7 @@ def cpinst_operand : Operand<i32> { // is the index into the MachineConstantPool that this is, the third is the // size in bytes of this constant pool entry. // -let neverHasSideEffects = 1, isNotDuplicable = 1 in +let hasSideEffects = 0, isNotDuplicable = 1 in def CONSTPOOL_ENTRY : MipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), "foo", []>; diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp index 0bb452a..c45acc4 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -65,7 +65,7 @@ bool Mips16RegisterInfo::saveScavengerRegister const TargetRegisterClass *RC, unsigned Reg) const { DebugLoc DL; - const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); TII.copyPhysReg(MBB, I, DL, Mips::T0, Reg, true); TII.copyPhysReg(MBB, UseMI, DL, Reg, Mips::T0, true); return true; @@ -106,7 +106,7 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) FrameReg = Mips::SP; else { - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); if (TFI->hasFP(MF)) { FrameReg = Mips::S0; } @@ -140,8 +140,7 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, DebugLoc DL = II->getDebugLoc(); unsigned NewImm; const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>( - MBB.getParent()->getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(Subtarget.getInstrInfo()); FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm); Offset = SignExtend64<16>(NewImm); IsKill = true; diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td index 6d6735b..49c6322 100644 --- a/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/lib/Target/Mips/Mips32r6InstrInfo.td @@ -379,7 +379,6 @@ class JMP_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd, list<dag> Pattern = []; bit isTerminator = 1; bit hasDelaySlot = 0; - string DecoderMethod = "DecodeSimm16"; } class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, @@ -550,6 +549,7 @@ class CACHE_HINT_DESC<string instr_asm, Operand MemOpnd, dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); list<dag> Pattern = []; + string DecoderMethod = "DecodeCacheOpR6"; } class CACHE_DESC : CACHE_HINT_DESC<"cache", mem_simm9, GPR32Opnd>; @@ -561,6 +561,7 @@ class COP2LD_DESC_BASE<string instr_asm, RegisterOperand COPOpnd> { string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; bit mayLoad = 1; + string DecoderMethod = "DecodeFMemCop2R6"; } class LDC2_R6_DESC : COP2LD_DESC_BASE<"ldc2", COP2Opnd>; @@ -572,6 +573,7 @@ class COP2ST_DESC_BASE<string instr_asm, RegisterOperand COPOpnd> { string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; bit mayStore = 1; + string DecoderMethod = "DecodeFMemCop2R6"; } class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd>; @@ -756,7 +758,7 @@ def : MipsPat<(setge f32:$lhs, f32:$rhs), (CMP_LT_S f32:$rhs, f32:$lhs)>, ISA_MIPS32R6; def : MipsPat<(setlt f32:$lhs, f32:$rhs), (CMP_LT_S f32:$lhs, f32:$rhs)>, ISA_MIPS32R6; -def : MipsPat<(setlt f32:$lhs, f32:$rhs), (CMP_LE_S f32:$lhs, f32:$rhs)>, +def : MipsPat<(setle f32:$lhs, f32:$rhs), (CMP_LE_S f32:$lhs, f32:$rhs)>, ISA_MIPS32R6; def : MipsPat<(setne f32:$lhs, f32:$rhs), (NOR (CMP_EQ_S f32:$lhs, f32:$rhs), ZERO)>, ISA_MIPS32R6; @@ -776,7 +778,7 @@ def : MipsPat<(setge f64:$lhs, f64:$rhs), (CMP_LT_D f64:$rhs, f64:$lhs)>, ISA_MIPS32R6; def : MipsPat<(setlt f64:$lhs, f64:$rhs), (CMP_LT_D f64:$lhs, f64:$rhs)>, ISA_MIPS32R6; -def : MipsPat<(setlt f64:$lhs, f64:$rhs), (CMP_LE_D f64:$lhs, f64:$rhs)>, +def : MipsPat<(setle f64:$lhs, f64:$rhs), (CMP_LE_D f64:$lhs, f64:$rhs)>, ISA_MIPS32R6; def : MipsPat<(setne f64:$lhs, f64:$rhs), (NOR (CMP_EQ_D f64:$lhs, f64:$rhs), ZERO)>, ISA_MIPS32R6; diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 4e2dcd8..776e473 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -16,6 +16,10 @@ //===----------------------------------------------------------------------===// // Unsigned Operand +def uimm5_64 : Operand<i64> { + let PrintMethod = "printUnsignedImm"; +} + def uimm16_64 : Operand<i64> { let PrintMethod = "printUnsignedImm"; } @@ -41,6 +45,38 @@ def immSExt10_64 : PatLeaf<(i64 imm), def immZExt16_64 : PatLeaf<(i64 imm), [{ return isInt<16>(N->getZExtValue()); }]>; +def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>; + +// Transformation function: get log2 of low 32 bits of immediate +def Log2LO : SDNodeXForm<imm, [{ + return getImm(N, Log2_64((unsigned) N->getZExtValue())); +}]>; + +// Transformation function: get log2 of high 32 bits of immediate +def Log2HI : SDNodeXForm<imm, [{ + return getImm(N, Log2_64((unsigned) (N->getZExtValue() >> 32))); +}]>; + +// Predicate: True if immediate is a power of 2 and fits 32 bits +def PowerOf2LO : PatLeaf<(imm), [{ + if (N->getValueType(0) == MVT::i64) { + uint64_t Imm = N->getZExtValue(); + return isPowerOf2_64(Imm) && (Imm & 0xffffffff) == Imm; + } + else + return false; +}]>; + +// Predicate: True if immediate is a power of 2 and exceeds 32 bits +def PowerOf2HI : PatLeaf<(imm), [{ + if (N->getValueType(0) == MVT::i64) { + uint64_t Imm = N->getZExtValue(); + return isPowerOf2_64(Imm) && (Imm & 0xffffffff00000000) == Imm; + } + else + return false; +}]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -290,7 +326,8 @@ class ExtsCins<string opstr, SDPatternOperator Op = null_frag>: class SetCC64_R<string opstr, PatFrag cond_op> : InstSE<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, GPR64Opnd:$rt), !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set GPR64Opnd:$rd, (cond_op GPR64Opnd:$rs, GPR64Opnd:$rt))], + [(set GPR64Opnd:$rd, (zext (cond_op GPR64Opnd:$rs, + GPR64Opnd:$rt)))], II_SEQ_SNE, FrmR, opstr> { let TwoOperandAliasConstraint = "$rd = $rs"; } @@ -298,17 +335,40 @@ class SetCC64_R<string opstr, PatFrag cond_op> : class SetCC64_I<string opstr, PatFrag cond_op>: InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, simm10_64:$imm10), !strconcat(opstr, "\t$rt, $rs, $imm10"), - [(set GPR64Opnd:$rt, (cond_op GPR64Opnd:$rs, immSExt10_64:$imm10))], + [(set GPR64Opnd:$rt, (zext (cond_op GPR64Opnd:$rs, + immSExt10_64:$imm10)))], II_SEQI_SNEI, FrmI, opstr> { let TwoOperandAliasConstraint = "$rt = $rs"; } +class CBranchBitNum<string opstr, DAGOperand opnd, PatFrag cond_op, + RegisterOperand RO, bits<64> shift = 1> : + InstSE<(outs), (ins RO:$rs, uimm5_64:$p, opnd:$offset), + !strconcat(opstr, "\t$rs, $p, $offset"), + [(brcond (i32 (cond_op (and RO:$rs, (shl shift, immZExt5_64:$p)), 0)), + bb:$offset)], IIBranch, FrmI, opstr> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; + let Defs = [AT]; +} + // Unsigned Byte Add let Pattern = [(set GPR64Opnd:$rd, (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))] in def BADDu : ArithLogicR<"baddu", GPR64Opnd, 1, II_BADDU>, ADD_FM<0x1c, 0x28>; +// Branch on Bit Clear /+32 +def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd>, BBIT_FM<0x32>; +def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, 0x100000000>, + BBIT_FM<0x36>; + +// Branch on Bit Set /+32 +def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd>, BBIT_FM<0x3a>; +def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, 0x100000000>, + BBIT_FM<0x3e>; + // Multiply Doubleword to GPR let Defs = [HI0, LO0, P0, P1, P2] in def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, @@ -359,6 +419,14 @@ def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, } +/// Move between CPU and coprocessor registers +let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { +def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd>, MFC3OP_FM<0x10, 1>; +def DMTC0 : MFC3OP<"dmtc0", GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3; +def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3; +def DMTC2 : MFC3OP<"dmtc2", GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3; +} + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// @@ -426,6 +494,14 @@ def : MipsPat<(trunc (assertzext GPR64:$src)), def : MipsPat<(i32 (trunc GPR64:$src)), (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; +// Bypass trunc nodes for bitwise ops. +def : MipsPat<(i32 (trunc (and GPR64:$lhs, GPR64:$rhs))), + (EXTRACT_SUBREG (AND64 GPR64:$lhs, GPR64:$rhs), sub_32)>; +def : MipsPat<(i32 (trunc (or GPR64:$lhs, GPR64:$rhs))), + (EXTRACT_SUBREG (OR64 GPR64:$lhs, GPR64:$rhs), sub_32)>; +def : MipsPat<(i32 (trunc (xor GPR64:$lhs, GPR64:$rhs))), + (EXTRACT_SUBREG (XOR64 GPR64:$lhs, GPR64:$rhs), sub_32)>; + // 32-to-64-bit extension def : MipsPat<(i64 (anyext GPR32:$src)), (SLL64_32 GPR32:$src)>; def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>; @@ -438,6 +514,28 @@ def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), // bswap MipsPattern def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>; +// Carry pattern +def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), + (DSUBu GPR64:$lhs, GPR64:$rhs)>; +let AdditionalPredicates = [NotDSP] in { + def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), + (DADDu GPR64:$lhs, GPR64:$rhs)>; + def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm), + (DADDiu GPR64:$lhs, imm:$imm)>; +} + +// Octeon bbit0/bbit1 MipsPattern +let Predicates = [HasMips64, HasCnMips] in { +def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), + (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; +def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), + (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; +def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), + (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; +def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), + (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; +} + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// @@ -489,19 +587,6 @@ def : MipsInstAlias<"dsrl $rd, $rt, $rs", (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; -class LoadImm64< string instr_asm, Operand Od, RegisterOperand RO> : - MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm64), - !strconcat(instr_asm, "\t$rt, $imm64")> ; -def LoadImm64Reg : LoadImm64<"dli", imm64, GPR64Opnd>; - -/// Move between CPU and coprocessor registers -let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { -def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd>, MFC3OP_FM<0x10, 1>; -def DMTC0 : MFC3OP<"dmtc0", GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3; -def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3; -def DMTC2 : MFC3OP<"dmtc2", GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3; -} - // Two operand (implicit 0 selector) versions: def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>; @@ -514,3 +599,12 @@ def : MipsInstAlias<"syncs", (SYNC 0x6), 0>; def : MipsInstAlias<"syncw", (SYNC 0x4), 0>; def : MipsInstAlias<"syncws", (SYNC 0x5), 0>; } + +//===----------------------------------------------------------------------===// +// Assembler Pseudo Instructions +//===----------------------------------------------------------------------===// + +class LoadImm64<string instr_asm, Operand Od, RegisterOperand RO> : + MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm64), + !strconcat(instr_asm, "\t$rt, $imm64")> ; +def LoadImm64Reg : LoadImm64<"dli", imm64, GPR64Opnd>; diff --git a/lib/Target/Mips/MipsABIInfo.cpp b/lib/Target/Mips/MipsABIInfo.cpp deleted file mode 100644 index f885369..0000000 --- a/lib/Target/Mips/MipsABIInfo.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MipsABIInfo.h" -#include "MipsRegisterInfo.h" - -using namespace llvm; - -namespace { -static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; - -static const MCPhysReg Mips64IntRegs[8] = { - Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, - Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64}; -} - -const ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const { - if (IsO32()) - return makeArrayRef(O32IntRegs); - if (IsN32() || IsN64()) - return makeArrayRef(Mips64IntRegs); - llvm_unreachable("Unhandled ABI"); -} - -const ArrayRef<MCPhysReg> MipsABIInfo::GetVarArgRegs() const { - if (IsO32()) - return makeArrayRef(O32IntRegs); - if (IsN32() || IsN64()) - return makeArrayRef(Mips64IntRegs); - llvm_unreachable("Unhandled ABI"); -} - -unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { - if (IsO32()) - return CC != CallingConv::Fast ? 16 : 0; - if (IsN32() || IsN64() || IsEABI()) - return 0; - llvm_unreachable("Unhandled ABI"); -} diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 832fa05..c662e13 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -19,6 +19,7 @@ #include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" #include "MipsMCInstLower.h" +#include "MipsTargetMachine.h" #include "MipsTargetStreamer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -53,12 +54,12 @@ using namespace llvm; #define DEBUG_TYPE "mips-asm-printer" -MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() { +MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { return static_cast<MipsTargetStreamer &>(*OutStreamer.getTargetStreamer()); } bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &MF.getSubtarget<MipsSubtarget>(); // Initialize TargetLoweringObjectFile. const_cast<TargetLoweringObjectFile &>(getObjFileLowering()) @@ -319,7 +320,7 @@ void MipsAsmPrinter::emitFrameDirective() { /// Emit Set directives. const char *MipsAsmPrinter::getCurrentABIString() const { - switch (Subtarget->getABI().GetEnumValue()) { + switch (static_cast<MipsTargetMachine &>(TM).getABI().GetEnumValue()) { case MipsABIInfo::ABI::O32: return "abi32"; case MipsABIInfo::ABI::N32: return "abiN32"; case MipsABIInfo::ABI::N64: return "abi64"; @@ -357,10 +358,7 @@ void MipsAsmPrinter::EmitFunctionBodyStart() { MCInstLowering.Initialize(&MF->getContext()); - bool IsNakedFunction = - MF->getFunction()-> - getAttributes().hasAttribute(AttributeSet::FunctionIndex, - Attribute::Naked); + bool IsNakedFunction = MF->getFunction()->hasFnAttribute(Attribute::Naked); if (!IsNakedFunction) emitFrameDirective(); @@ -560,7 +558,7 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { - const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); + const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand(opNum); bool closeP = false; @@ -689,7 +687,21 @@ printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { } void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { - bool IsABICalls = Subtarget->isABICalls(); + + // Compute MIPS architecture attributes based on the default subtarget + // that we'd have constructed. Module level directives aren't LTO + // clean anyhow. + // FIXME: For ifunc related functions we could iterate over and look + // for a feature string that doesn't match the default one. + StringRef TT = TM.getTargetTriple(); + StringRef CPU = + MIPS_MC::selectMipsCPU(TM.getTargetTriple(), TM.getTargetCPU()); + StringRef FS = TM.getTargetFeatureString(); + const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM); + const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM); + + bool IsABICalls = STI.isABICalls(); + const MipsABIInfo &ABI = MTM.getABI(); if (IsABICalls) { getTargetStreamer().emitDirectiveAbiCalls(); Reloc::Model RM = TM.getRelocationModel(); @@ -697,68 +709,88 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // Ideally it should test for properties of the ABI and not the ABI // itself. // For the moment, I'm only correcting enough to make MIPS-IV work. - if (RM == Reloc::Static && !Subtarget->isABI_N64()) + if (RM == Reloc::Static && !ABI.IsN64()) getTargetStreamer().emitDirectiveOptionPic0(); } // Tell the assembler which ABI we are using std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); - OutStreamer.SwitchSection(OutContext.getELFSection( - SectionName, ELF::SHT_PROGBITS, 0, SectionKind::getDataRel())); + OutStreamer.SwitchSection( + OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0)); // NaN: At the moment we only support: // 1. .nan legacy (default) // 2. .nan 2008 - Subtarget->isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008() - : getTargetStreamer().emitDirectiveNaNLegacy(); + STI.isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008() + : getTargetStreamer().emitDirectiveNaNLegacy(); // TODO: handle O64 ABI - if (Subtarget->isABI_EABI()) { - if (Subtarget->isGP32bit()) - OutStreamer.SwitchSection( - OutContext.getELFSection(".gcc_compiled_long32", ELF::SHT_PROGBITS, 0, - SectionKind::getDataRel())); + if (ABI.IsEABI()) { + if (STI.isGP32bit()) + OutStreamer.SwitchSection(OutContext.getELFSection(".gcc_compiled_long32", + ELF::SHT_PROGBITS, 0)); else - OutStreamer.SwitchSection( - OutContext.getELFSection(".gcc_compiled_long64", ELF::SHT_PROGBITS, 0, - SectionKind::getDataRel())); + OutStreamer.SwitchSection(OutContext.getELFSection(".gcc_compiled_long64", + ELF::SHT_PROGBITS, 0)); } - getTargetStreamer().updateABIInfo(*Subtarget); + getTargetStreamer().updateABIInfo(STI); // We should always emit a '.module fp=...' but binutils 2.24 does not accept // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or // -mfp64) and omit it otherwise. - if (Subtarget->isABI_O32() && (Subtarget->isABI_FPXX() || - Subtarget->isFP64bit())) + if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) getTargetStreamer().emitDirectiveModuleFP(); // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not // accept it. We therefore emit it when it contradicts the default or an // option has changed the default (i.e. FPXX) and omit it otherwise. - if (Subtarget->isABI_O32() && (!Subtarget->useOddSPReg() || - Subtarget->isABI_FPXX())) - getTargetStreamer().emitDirectiveModuleOddSPReg(Subtarget->useOddSPReg(), - Subtarget->isABI_O32()); + if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) + getTargetStreamer().emitDirectiveModuleOddSPReg(STI.useOddSPReg(), + ABI.IsO32()); +} + +void MipsAsmPrinter::emitInlineAsmStart() const { + MipsTargetStreamer &TS = getTargetStreamer(); + + // GCC's choice of assembler options for inline assembly code ('at', 'macro' + // and 'reorder') is different from LLVM's choice for generated code ('noat', + // 'nomacro' and 'noreorder'). + // In order to maintain compatibility with inline assembly code which depends + // on GCC's assembler options being used, we have to switch to those options + // for the duration of the inline assembly block and then switch back. + TS.emitDirectiveSetPush(); + TS.emitDirectiveSetAt(); + TS.emitDirectiveSetMacro(); + TS.emitDirectiveSetReorder(); + OutStreamer.AddBlankLine(); } -void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) { +void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, + const MCSubtargetInfo *EndInfo) const { + OutStreamer.AddBlankLine(); + getTargetStreamer().emitDirectiveSetPop(); +} + +void MipsAsmPrinter::EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol) { MCInst I; I.setOpcode(Mips::JAL); I.addOperand( MCOperand::CreateExpr(MCSymbolRefExpr::Create(Symbol, OutContext))); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + OutStreamer.EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitInstrReg(unsigned Opcode, unsigned Reg) { +void MipsAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, + unsigned Reg) { MCInst I; I.setOpcode(Opcode); I.addOperand(MCOperand::CreateReg(Reg)); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + OutStreamer.EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitInstrRegReg(unsigned Opcode, unsigned Reg1, +void MipsAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, + unsigned Opcode, unsigned Reg1, unsigned Reg2) { MCInst I; // @@ -774,20 +806,22 @@ void MipsAsmPrinter::EmitInstrRegReg(unsigned Opcode, unsigned Reg1, I.setOpcode(Opcode); I.addOperand(MCOperand::CreateReg(Reg1)); I.addOperand(MCOperand::CreateReg(Reg2)); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + OutStreamer.EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitInstrRegRegReg(unsigned Opcode, unsigned Reg1, +void MipsAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, + unsigned Opcode, unsigned Reg1, unsigned Reg2, unsigned Reg3) { MCInst I; I.setOpcode(Opcode); I.addOperand(MCOperand::CreateReg(Reg1)); I.addOperand(MCOperand::CreateReg(Reg2)); I.addOperand(MCOperand::CreateReg(Reg3)); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + OutStreamer.EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, +void MipsAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, + unsigned MovOpc, unsigned Reg1, unsigned Reg2, unsigned FPReg1, unsigned FPReg2, bool LE) { if (!LE) { @@ -795,59 +829,60 @@ void MipsAsmPrinter::EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, Reg1 = Reg2; Reg2 = temp; } - EmitInstrRegReg(MovOpc, Reg1, FPReg1); - EmitInstrRegReg(MovOpc, Reg2, FPReg2); + EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); + EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); } -void MipsAsmPrinter::EmitSwapFPIntParams(Mips16HardFloatInfo::FPParamVariant PV, +void MipsAsmPrinter::EmitSwapFPIntParams(const MCSubtargetInfo &STI, + Mips16HardFloatInfo::FPParamVariant PV, bool LE, bool ToFP) { using namespace Mips16HardFloatInfo; unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1; switch (PV) { case FSig: - EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12); + EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); break; case FFSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); break; case FDSig: - EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12); - EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); + EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); + EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); break; case DSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); break; case DDSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); break; case DFSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - EmitInstrRegReg(MovOpc, Mips::A2, Mips::F14); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); + EmitInstrRegReg(STI, MovOpc, Mips::A2, Mips::F14); break; case NoSig: return; } } -void -MipsAsmPrinter::EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant RV, - bool LE) { +void MipsAsmPrinter::EmitSwapFPIntRetval( + const MCSubtargetInfo &STI, Mips16HardFloatInfo::FPReturnVariant RV, + bool LE) { using namespace Mips16HardFloatInfo; unsigned MovOpc = Mips::MFC1; switch (RV) { case FRet: - EmitInstrRegReg(MovOpc, Mips::V0, Mips::F0); + EmitInstrRegReg(STI, MovOpc, Mips::V0, Mips::F0); break; case DRet: - EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); break; case CFRet: - EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); break; case CDRet: - EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); break; case NoFPRet: break; @@ -858,7 +893,14 @@ void MipsAsmPrinter::EmitFPCallStub( const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) { MCSymbol *MSymbol = OutContext.GetOrCreateSymbol(StringRef(Symbol)); using namespace Mips16HardFloatInfo; - bool LE = Subtarget->isLittle(); + bool LE = getDataLayout().isLittleEndian(); + // Construct a local MCSubtargetInfo here. + // This is because the MachineFunction won't exist (but have not yet been + // freed) and since we're at the global level we can use the default + // constructed subtarget. + std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( + TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); + // // .global xxxx // @@ -921,7 +963,7 @@ void MipsAsmPrinter::EmitFPCallStub( // const MCSectionELF *M = OutContext.getELFSection( ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_EXECINSTR, SectionKind::getText()); + ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); OutStreamer.SwitchSection(M, nullptr); // // .align 2 @@ -946,13 +988,10 @@ void MipsAsmPrinter::EmitFPCallStub( OutContext.GetOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); OutStreamer.EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); OutStreamer.EmitLabel(Stub); - // - // we just handle non pic for now. these function will not be - // called otherwise. when the full stub generation is moved here - // we need to deal with pic. - // - if (Subtarget->getRelocationModel() == Reloc::PIC_) - llvm_unreachable("should not be here if we are compiling pic"); + + // Only handle non-pic for now. + assert(TM.getRelocationModel() != Reloc::PIC_ && + "should not be here if we are compiling pic"); TS.emitDirectiveSetReorder(); // // We need to add a MipsMCExpr class to MCTargetDesc to fully implement @@ -969,22 +1008,22 @@ void MipsAsmPrinter::EmitFPCallStub( // // Mov $18, $31 - EmitInstrRegRegReg(Mips::ADDu, Mips::S2, Mips::RA, Mips::ZERO); + EmitInstrRegRegReg(*STI, Mips::ADDu, Mips::S2, Mips::RA, Mips::ZERO); - EmitSwapFPIntParams(Signature->ParamSig, LE, true); + EmitSwapFPIntParams(*STI, Signature->ParamSig, LE, true); // Jal xxxx // - EmitJal(MSymbol); + EmitJal(*STI, MSymbol); // fix return values - EmitSwapFPIntRetval(Signature->RetSig, LE); + EmitSwapFPIntRetval(*STI, Signature->RetSig, LE); // // do the return // if (Signature->RetSig == NoFPRet) // llvm_unreachable("should not be any stubs here with no return value"); // else - EmitInstrReg(Mips::JR, Mips::S2); + EmitInstrReg(*STI, Mips::JR, Mips::S2); MCSymbol *Tmp = OutContext.CreateTempSymbol(); OutStreamer.EmitLabel(Tmp); diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index 0582e21..d4c5b80 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -31,7 +31,7 @@ class Module; class raw_ostream; class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter { - MipsTargetStreamer &getTargetStreamer(); + MipsTargetStreamer &getTargetStreamer() const; void EmitInstrWithMacroNoAT(const MachineInstr *MI); @@ -60,22 +60,31 @@ private: std::map<const char *, const llvm::Mips16HardFloatInfo::FuncSignature *> StubsNeeded; - void EmitJal(MCSymbol *Symbol); + void emitInlineAsmStart() const override; - void EmitInstrReg(unsigned Opcode, unsigned Reg); + void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, + const MCSubtargetInfo *EndInfo) const override; - void EmitInstrRegReg(unsigned Opcode, unsigned Reg1, unsigned Reg2); + void EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol); - void EmitInstrRegRegReg(unsigned Opcode, unsigned Reg1, unsigned Reg2, - unsigned Reg3); + void EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, unsigned Reg); - void EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, unsigned Reg2, - unsigned FPReg1, unsigned FPReg2, bool LE); + void EmitInstrRegReg(const MCSubtargetInfo &STI, unsigned Opcode, + unsigned Reg1, unsigned Reg2); - void EmitSwapFPIntParams(Mips16HardFloatInfo::FPParamVariant, bool LE, + void EmitInstrRegRegReg(const MCSubtargetInfo &STI, unsigned Opcode, + unsigned Reg1, unsigned Reg2, unsigned Reg3); + + void EmitMovFPIntPair(const MCSubtargetInfo &STI, unsigned MovOpc, + unsigned Reg1, unsigned Reg2, unsigned FPReg1, + unsigned FPReg2, bool LE); + + void EmitSwapFPIntParams(const MCSubtargetInfo &STI, + Mips16HardFloatInfo::FPParamVariant, bool LE, bool ToFP); - void EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant, bool LE); + void EmitSwapFPIntRetval(const MCSubtargetInfo &STI, + Mips16HardFloatInfo::FPReturnVariant, bool LE); void EmitFPCallStub(const char *, const Mips16HardFloatInfo::FuncSignature *); @@ -89,14 +98,10 @@ public: const MipsFunctionInfo *MipsFI; MipsMCInstLower MCInstLowering; - // We initialize the subtarget here and in runOnMachineFunction - // since there are certain target specific flags (ABI) that could - // reside on the TargetMachine, but are on the subtarget currently - // and we need them for the beginning of file output before we've - // seen a single function. - explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer), MCP(nullptr), InConstantPool(false), - Subtarget(&TM.getSubtarget<MipsSubtarget>()), MCInstLowering(*this) {} + explicit MipsAsmPrinter(TargetMachine &TM, + std::unique_ptr<MCStreamer> Streamer) + : AsmPrinter(TM, std::move(Streamer)), MCP(nullptr), + InConstantPool(false), MCInstLowering(*this) {} const char *getPassName() const override { return "Mips Assembly Printer"; diff --git a/lib/Target/Mips/MipsCCState.cpp b/lib/Target/Mips/MipsCCState.cpp index e18cc8b..b808129 100644 --- a/lib/Target/Mips/MipsCCState.cpp +++ b/lib/Target/Mips/MipsCCState.cpp @@ -132,8 +132,8 @@ void MipsCCState::PreAnalyzeFormalArgumentsForF128( continue; } - assert(Ins[i].OrigArgIndex < MF.getFunction()->arg_size()); - std::advance(FuncArg, Ins[i].OrigArgIndex); + assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size()); + std::advance(FuncArg, Ins[i].getOrigArgIndex()); OriginalArgWasF128.push_back( originalTypeIsF128(FuncArg->getType(), nullptr)); diff --git a/lib/Target/Mips/MipsCCState.h b/lib/Target/Mips/MipsCCState.h index cc4531d..081c393 100644 --- a/lib/Target/Mips/MipsCCState.h +++ b/lib/Target/Mips/MipsCCState.h @@ -10,9 +10,9 @@ #ifndef MIPSCCSTATE_H #define MIPSCCSTATE_H +#include "MipsISelLowering.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" -#include "MipsISelLowering.h" namespace llvm { class SDNode; @@ -85,10 +85,10 @@ public: // provide a means of accessing ArgListEntry::IsFixed. Delete them from this // class. This doesn't stop them being used via the base class though. void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, - CCAssignFn Fn) LLVM_DELETED_FUNCTION; + CCAssignFn Fn) = delete; void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs, SmallVectorImpl<ISD::ArgFlagsTy> &Flags, - CCAssignFn Fn) LLVM_DELETED_FUNCTION; + CCAssignFn Fn) = delete; void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, CCAssignFn Fn) { diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 7318de2..abee185 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -20,6 +20,29 @@ class CCIfSubtarget<string F, CCAction A, string Invert = ""> // The inverse of CCIfSubtarget class CCIfSubtargetNot<string F, CCAction A> : CCIfSubtarget<F, A, "!">; +/// Match if the original argument (before lowering) was a float. +/// For example, this is true for i32's that were lowered from soft-float. +class CCIfOrigArgWasNotFloat<CCAction A> + : CCIf<"!static_cast<MipsCCState *>(&State)->WasOriginalArgFloat(ValNo)", + A>; + +/// Match if the original argument (before lowering) was a 128-bit float (i.e. +/// long double). +class CCIfOrigArgWasF128<CCAction A> + : CCIf<"static_cast<MipsCCState *>(&State)->WasOriginalArgF128(ValNo)", A>; + +/// Match if this specific argument is a vararg. +/// This is slightly different fro CCIfIsVarArg which matches if any argument is +/// a vararg. +class CCIfArgIsVarArg<CCAction A> + : CCIf<"!static_cast<MipsCCState *>(&State)->IsCallOperandFixed(ValNo)", A>; + + +/// Match if the special calling conv is the specified value. +class CCIfSpecialCallingConv<string CC, CCAction A> + : CCIf<"static_cast<MipsCCState *>(&State)->getSpecialCallingConv() == " + "MipsCCState::" # CC, A>; + // For soft-float, f128 values are returned in A0_64 rather than V1_64. def RetCC_F128SoftFloat : CallingConv<[ CCAssignToReg<[V0_64, A0_64]> @@ -105,9 +128,7 @@ def CC_MipsN : CallingConv<[ CCIfInReg<CCPromoteToUpperBitsInType<i64>>>>, // All integers (except soft-float integers) are promoted to 64-bit. - CCIfType<[i8, i16, i32], - CCIf<"!static_cast<MipsCCState *>(&State)->WasOriginalArgFloat(ValNo)", - CCPromoteToType<i64>>>, + CCIfType<[i8, i16, i32], CCIfOrigArgWasNotFloat<CCPromoteToType<i64>>>, // The only i32's we have left are soft-float arguments. CCIfSubtarget<"abiUsesSoftFloat()", CCIfType<[i32], CCDelegateTo<CC_MipsN_SoftFloat>>>, @@ -138,6 +159,10 @@ def CC_MipsN : CallingConv<[ // N32/64 variable arguments. // All arguments are passed in integer registers. def CC_MipsN_VarArg : CallingConv<[ + CCIfType<[i8, i16, i32, i64], + CCIfSubtargetNot<"isLittle()", + CCIfInReg<CCPromoteToUpperBitsInType<i64>>>>, + // All integers are promoted to 64-bit. CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, @@ -162,9 +187,7 @@ def RetCC_MipsN : CallingConv<[ // // f128 should only occur for the N64 ABI where long double is 128-bit. On // N32, long double is equivalent to double. - CCIfType<[i64], - CCIf<"static_cast<MipsCCState *>(&State)->WasOriginalArgF128(ValNo)", - CCDelegateTo<RetCC_F128>>>, + CCIfType<[i64], CCIfOrigArgWasF128<CCDelegateTo<RetCC_F128>>>, // Aggregate returns are positioned at the lowest address in the slot for // both little and big-endian targets. When passing in registers, this @@ -330,8 +353,7 @@ def CC_Mips16RetHelper : CallingConv<[ def CC_Mips_FixedArg : CallingConv<[ // Mips16 needs special handling on some functions. CCIf<"State.getCallingConv() != CallingConv::Fast", - CCIf<"static_cast<MipsCCState *>(&State)->getSpecialCallingConv() == " - "MipsCCState::Mips16RetHelperConv", + CCIfSpecialCallingConv<"Mips16RetHelperConv", CCDelegateTo<CC_Mips16RetHelper>>>, CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>, @@ -348,8 +370,7 @@ def CC_Mips_FixedArg : CallingConv<[ // N32, long double is equivalent to double. CCIfType<[i64], CCIfSubtargetNot<"abiUsesSoftFloat()", - CCIf<"static_cast<MipsCCState *>(&State)->WasOriginalArgF128(ValNo)", - CCBitConvertToType<f64>>>>, + CCIfOrigArgWasF128<CCBitConvertToType<f64>>>>, CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_Mips_FastCC>>, @@ -369,9 +390,7 @@ def CC_Mips_VarArg : CallingConv<[ ]>; def CC_Mips : CallingConv<[ - CCIfVarArg< - CCIf<"!static_cast<MipsCCState *>(&State)->IsCallOperandFixed(ValNo)", - CCDelegateTo<CC_Mips_VarArg>>>, + CCIfVarArg<CCIfArgIsVarArg<CCDelegateTo<CC_Mips_VarArg>>>, CCDelegateTo<CC_Mips_FixedArg> ]>; diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index 690f626..af10cd4 100644 --- a/lib/Target/Mips/MipsCondMov.td +++ b/lib/Target/Mips/MipsCondMov.td @@ -263,3 +263,40 @@ defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + +// For targets that don't have conditional-move instructions +// we have to match SELECT nodes with pseudo instructions. +let usesCustomInserter = 1 in { + class Select_Pseudo<RegisterOperand RC> : + PseudoSE<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), + [(set RC:$dst, (select GPR32Opnd:$cond, RC:$T, RC:$F))]>, + ISA_MIPS1_NOT_4_32; + + class SelectFP_Pseudo_T<RegisterOperand RC> : + PseudoSE<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), + [(set RC:$dst, (MipsCMovFP_T RC:$T, GPR32Opnd:$cond, RC:$F))]>, + ISA_MIPS1_NOT_4_32; + + class SelectFP_Pseudo_F<RegisterOperand RC> : + PseudoSE<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), + [(set RC:$dst, (MipsCMovFP_F RC:$T, GPR32Opnd:$cond, RC:$F))]>, + ISA_MIPS1_NOT_4_32; +} + +def PseudoSELECT_I : Select_Pseudo<GPR32Opnd>; +def PseudoSELECT_I64 : Select_Pseudo<GPR64Opnd>; +def PseudoSELECT_S : Select_Pseudo<FGR32Opnd>; +def PseudoSELECT_D32 : Select_Pseudo<AFGR64Opnd>, FGR_32; +def PseudoSELECT_D64 : Select_Pseudo<FGR64Opnd>, FGR_64; + +def PseudoSELECTFP_T_I : SelectFP_Pseudo_T<GPR32Opnd>; +def PseudoSELECTFP_T_I64 : SelectFP_Pseudo_T<GPR64Opnd>; +def PseudoSELECTFP_T_S : SelectFP_Pseudo_T<FGR32Opnd>; +def PseudoSELECTFP_T_D32 : SelectFP_Pseudo_T<AFGR64Opnd>, FGR_32; +def PseudoSELECTFP_T_D64 : SelectFP_Pseudo_T<FGR64Opnd>, FGR_64; + +def PseudoSELECTFP_F_I : SelectFP_Pseudo_F<GPR32Opnd>; +def PseudoSELECTFP_F_I64 : SelectFP_Pseudo_F<GPR64Opnd>; +def PseudoSELECTFP_F_S : SelectFP_Pseudo_F<FGR32Opnd>; +def PseudoSELECTFP_F_D32 : SelectFP_Pseudo_F<AFGR64Opnd>, FGR_32; +def PseudoSELECTFP_F_D64 : SelectFP_Pseudo_F<FGR64Opnd>, FGR_64; diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index c4e5ac0..96553d2 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -448,14 +448,12 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { // FIXME: MF = &mf; MCP = mf.getConstantPool(); - STI = &mf.getTarget().getSubtarget<MipsSubtarget>(); + STI = &static_cast<const MipsSubtarget &>(mf.getSubtarget()); DEBUG(dbgs() << "constant island machine function " << "\n"); if (!STI->inMips16Mode() || !MipsSubtarget::useConstantIslands()) { return false; } - TII = (const Mips16InstrInfo *)MF->getTarget() - .getSubtargetImpl() - ->getInstrInfo(); + TII = (const Mips16InstrInfo *)STI->getInstrInfo(); MFI = MF->getInfo<MipsFunctionInfo>(); DEBUG(dbgs() << "constant island processing " << "\n"); // @@ -562,7 +560,7 @@ MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { // identity mapping of CPI's to CPE's. const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants(); - const DataLayout &TD = *MF->getSubtarget().getDataLayout(); + const DataLayout &TD = *MF->getTarget().getDataLayout(); for (unsigned i = 0, e = CPs.size(); i != e; ++i) { unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); assert(Size >= 4 && "Too small constant pool entry"); diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index d7ba6d4..ac03c0b 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -69,7 +69,7 @@ namespace { class RegDefsUses { public: - RegDefsUses(TargetMachine &TM); + RegDefsUses(const TargetRegisterInfo &TRI); void init(const MachineInstr &MI); /// This function sets all caller-saved registers in Defs. @@ -196,6 +196,12 @@ namespace { private: bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + Iter replaceWithCompactBranch(MachineBasicBlock &MBB, + Iter Branch, DebugLoc DL); + + Iter replaceWithCompactJump(MachineBasicBlock &MBB, + Iter Jump, DebugLoc DL); + /// This function checks if it is valid to move Candidate to the delay slot /// and returns true if it isn't. It also updates memory and register /// dependence information. @@ -207,7 +213,7 @@ namespace { template<typename IterTy> bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, RegDefsUses &RegDU, InspectMemInstr &IM, - IterTy &Filler) const; + IterTy &Filler, Iter Slot) const; /// This function searches in the backward direction for an instruction that /// can be moved to the delay slot. Returns true on success. @@ -275,11 +281,7 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { #ifndef NDEBUG const MachineFunction &MF = *MBB.getParent(); - assert(MF.getTarget() - .getSubtargetImpl() - ->getRegisterInfo() - ->getAllocatableSet(MF) - .test(R) && + assert(MF.getSubtarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && "Shouldn't move an instruction with unallocatable registers across " "basic block boundaries."); #endif @@ -289,9 +291,8 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { } } -RegDefsUses::RegDefsUses(TargetMachine &TM) - : TRI(*TM.getSubtargetImpl()->getRegisterInfo()), - Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} +RegDefsUses::RegDefsUses(const TargetRegisterInfo &TRI) + : TRI(TRI), Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} void RegDefsUses::init(const MachineInstr &MI) { // Add all register operands which are explicit and non-variadic. @@ -494,42 +495,135 @@ getUnderlyingObjects(const MachineInstr &MI, return true; } +// Replace Branch with the compact branch instruction. +Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, + Iter Branch, DebugLoc DL) { + const MipsInstrInfo *TII = + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); + + unsigned NewOpcode = + (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM + : Mips::BNEZC_MM; + + const MCInstrDesc &NewDesc = TII->get(NewOpcode); + MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc); + + MIB.addReg(Branch->getOperand(0).getReg()); + MIB.addMBB(Branch->getOperand(2).getMBB()); + + Iter tmpIter = Branch; + Branch = std::prev(Branch); + MBB.erase(tmpIter); + + return Branch; +} + +// Replace Jumps with the compact jump instruction. +Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB, + Iter Jump, DebugLoc DL) { + const MipsInstrInfo *TII = + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); + + const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM); + MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc); + + MIB.addReg(Jump->getOperand(0).getReg()); + + Iter tmpIter = Jump; + Jump = std::prev(Jump); + MBB.erase(tmpIter); + + return Jump; +} + +// For given opcode returns opcode of corresponding instruction with short +// delay slot. +static int getEquivalentCallShort(int Opcode) { + switch (Opcode) { + case Mips::BGEZAL: + return Mips::BGEZALS_MM; + case Mips::BLTZAL: + return Mips::BLTZALS_MM; + case Mips::JAL: + return Mips::JALS_MM; + case Mips::JALR: + return Mips::JALRS_MM; + case Mips::JALR16_MM: + return Mips::JALRS16_MM; + default: + llvm_unreachable("Unexpected call instruction for microMIPS."); + } +} + /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. /// We assume there is only one delay slot per delayed instruction. bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); + const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); + bool InMicroMipsMode = STI.inMicroMipsMode(); + const MipsInstrInfo *TII = STI.getInstrInfo(); for (Iter I = MBB.begin(); I != MBB.end(); ++I) { if (!hasUnoccupiedSlot(&*I)) continue; - // For microMIPS, at the moment, do not fill delay slots of call - // instructions. - // - // TODO: Support for replacing regular call instructions with corresponding - // short delay slot instructions should be implemented. - if (!InMicroMipsMode || !I->isCall()) { - ++FilledSlots; - Changed = true; - - // Delay slot filling is disabled at -O0. - if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { - if (searchBackward(MBB, I)) - continue; + ++FilledSlots; + Changed = true; - if (I->isTerminator()) { - if (searchSuccBBs(MBB, I)) - continue; - } else if (searchForward(MBB, I)) { - continue; + // Delay slot filling is disabled at -O0. + if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { + bool Filled = false; + + if (searchBackward(MBB, I)) { + Filled = true; + } else if (I->isTerminator()) { + if (searchSuccBBs(MBB, I)) { + Filled = true; + } + } else if (searchForward(MBB, I)) { + Filled = true; + } + + if (Filled) { + // Get instruction with delay slot. + MachineBasicBlock::instr_iterator DSI(I); + + if (InMicroMipsMode && TII->GetInstSizeInBytes(std::next(DSI)) == 2 && + DSI->isCall()) { + // If instruction in delay slot is 16b change opcode to + // corresponding instruction with short delay slot. + DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); } + + continue; } } + // If instruction is BEQ or BNE with one ZERO register, then instead of + // adding NOP replace this instruction with the corresponding compact + // branch instruction, i.e. BEQZC or BNEZC. + unsigned Opcode = I->getOpcode(); + if (InMicroMipsMode) { + switch (Opcode) { + case Mips::BEQ: + case Mips::BNE: + if (((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { + I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); + continue; + } + break; + case Mips::JR: + case Mips::PseudoReturn: + case Mips::PseudoIndirectBranch: + // For microMIPS the PseudoReturn and PseudoIndirectBranch are allways + // expanded to JR_MM, so they can be replaced with JRC16_MM. + I = replaceWithCompactJump(MBB, I, I->getDebugLoc()); + continue; + default: + break; + } + } // Bundle the NOP to the instruction with the delay slot. - const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); MIBundleBuilder(MBB, I, std::next(I, 2)); } @@ -546,7 +640,7 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { template<typename IterTy> bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, RegDefsUses &RegDU, InspectMemInstr& IM, - IterTy &Filler) const { + IterTy &Filler, Iter Slot) const { for (IterTy I = Begin; I != End; ++I) { // skip debug value if (I->isDebugValue()) @@ -561,7 +655,8 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, if (delayHasHazard(*I, RegDU, IM)) continue; - if (TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); + if (STI.isTargetNaCl()) { // In NaCl, instructions that must be masked are forbidden in delay slots. // We only check for loads, stores and SP changes. Calls, returns and // branches are not checked because non-NaCl targets never put them in @@ -569,11 +664,18 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, unsigned AddrIdx; if ((isBasePlusOffsetMemoryAccess(I->getOpcode(), &AddrIdx) && baseRegNeedsLoadStoreMask(I->getOperand(AddrIdx).getReg())) || - I->modifiesRegister(Mips::SP, - TM.getSubtargetImpl()->getRegisterInfo())) + I->modifiesRegister(Mips::SP, STI.getRegisterInfo())) continue; } + bool InMicroMipsMode = STI.inMicroMipsMode(); + const MipsInstrInfo *TII = STI.getInstrInfo(); + unsigned Opcode = (*Slot).getOpcode(); + if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*I)) == 2 && + (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || + Opcode == Mips::PseudoReturn)) + continue; + Filler = I; return true; } @@ -585,13 +687,14 @@ bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot) const { if (DisableBackwardSearch) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); MemDefsUses MemDU(MBB.getParent()->getFrameInfo()); ReverseIter Filler; RegDU.init(*Slot); - if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler)) + if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler, + Slot)) return false; MBB.splice(std::next(Slot), &MBB, std::next(Filler).base()); @@ -605,13 +708,13 @@ bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { if (DisableForwardSearch || !Slot->isCall()) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); NoMemInstr NM; Iter Filler; RegDU.setCallerSaved(*Slot); - if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Filler)) + if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Filler, Slot)) return false; MBB.splice(std::next(Slot), &MBB, Filler); @@ -629,7 +732,7 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { if (!SuccBB) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); bool HasMultipleSuccs = false; BB2BrMap BrMap; std::unique_ptr<InspectMemInstr> IM; @@ -654,7 +757,8 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { IM.reset(new MemDefsUses(MFI)); } - if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Filler)) + if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Filler, + Slot)) return false; insertDelayFiller(Filler, BrMap); @@ -681,7 +785,7 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { std::pair<MipsInstrInfo::BranchType, MachineInstr *> Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr; SmallVector<MachineInstr*, 2> BranchInstrs; SmallVector<MachineOperand, 2> Cond; diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp index 2bb16e3..7d69659 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -1,19 +1,21 @@ //===-- MipsastISel.cpp - Mips FastISel implementation //---------------------===// -#include "llvm/CodeGen/FunctionLoweringInfo.h" -#include "llvm/CodeGen/FastISel.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/IR/GlobalAlias.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetLibraryInfo.h" #include "MipsCCState.h" -#include "MipsRegisterInfo.h" +#include "MipsInstrInfo.h" #include "MipsISelLowering.h" #include "MipsMachineFunction.h" +#include "MipsRegisterInfo.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/Target/TargetInstrInfo.h" using namespace llvm; @@ -43,6 +45,7 @@ class MipsFastISel final : public FastISel { void setKind(BaseKind K) { Kind = K; } BaseKind getKind() const { return Kind; } bool isRegBase() const { return Kind == RegBase; } + bool isFIBase() const { return Kind == FrameIndexBase; } void setReg(unsigned Reg) { assert(isRegBase() && "Invalid base register access!"); Base.Reg = Reg; @@ -51,6 +54,15 @@ class MipsFastISel final : public FastISel { assert(isRegBase() && "Invalid base register access!"); return Base.Reg; } + void setFI(unsigned FI) { + assert(isFIBase() && "Invalid base frame index access!"); + Base.FI = FI; + } + unsigned getFI() const { + assert(isFIBase() && "Invalid base frame index access!"); + return Base.FI; + } + void setOffset(int64_t Offset_) { Offset = Offset_; } int64_t getOffset() const { return Offset; } void setGlobalValue(const GlobalValue *G) { GV = G; } @@ -59,11 +71,10 @@ class MipsFastISel final : public FastISel { /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can /// make the right decision when generating code for different targets. - Module &M; const TargetMachine &TM; + const MipsSubtarget *Subtarget; const TargetInstrInfo &TII; const TargetLowering &TLI; - const MipsSubtarget *Subtarget; MipsFunctionInfo *MFI; // Convenience variables to avoid some queries. @@ -94,6 +105,7 @@ private: bool isLoadTypeLegal(Type *Ty, MVT &VT); bool computeAddress(const Value *Obj, Address &Addr); bool computeCallAddress(const Value *V, Address &Addr); + void simplifyAddress(Address &Addr); // Emit helper routines. bool emitCmp(unsigned DestReg, const CmpInst *CI); @@ -157,17 +169,15 @@ public: // Backend specific FastISel code. explicit MipsFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) - : FastISel(funcInfo, libInfo), - M(const_cast<Module &>(*funcInfo.Fn->getParent())), - TM(funcInfo.MF->getTarget()), - TII(*TM.getSubtargetImpl()->getInstrInfo()), - TLI(*TM.getSubtargetImpl()->getTargetLowering()), - Subtarget(&TM.getSubtarget<MipsSubtarget>()) { + : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()), + Subtarget(&funcInfo.MF->getSubtarget<MipsSubtarget>()), + TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) { MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); Context = &funcInfo.Fn->getContext(); - TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) && - ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) && - (Subtarget->isABI_O32()))); + TargetSupported = + ((TM.getRelocationModel() == Reloc::PIC_) && + ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) && + (static_cast<const MipsTargetMachine &>(TM).getABI().IsO32()))); UnsupportedFPMode = Subtarget->isFP64bit(); } @@ -188,9 +198,9 @@ static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, llvm_unreachable("should not be called"); } -bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State) { +static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { llvm_unreachable("should not be called"); } @@ -306,14 +316,82 @@ unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { } bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { - // This construct looks a big awkward but it is how other ports handle this - // and as this function is more fully completed, these cases which - // return false will have additional code in them. - // - if (isa<Instruction>(Obj)) - return false; - else if (isa<ConstantExpr>(Obj)) + + const User *U = nullptr; + unsigned Opcode = Instruction::UserOp1; + if (const Instruction *I = dyn_cast<Instruction>(Obj)) { + // Don't walk into other basic blocks unless the object is an alloca from + // another block, otherwise it may not have a virtual register assigned. + if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) || + FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { + Opcode = I->getOpcode(); + U = I; + } + } else if (isa<ConstantExpr>(Obj)) return false; + switch (Opcode) { + default: + break; + case Instruction::BitCast: { + // Look through bitcasts. + return computeAddress(U->getOperand(0), Addr); + } + case Instruction::GetElementPtr: { + Address SavedAddr = Addr; + uint64_t TmpOffset = Addr.getOffset(); + // Iterate through the GEP folding the constants into offsets where + // we can. + gep_type_iterator GTI = gep_type_begin(U); + for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; + ++i, ++GTI) { + const Value *Op = *i; + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + const StructLayout *SL = DL.getStructLayout(STy); + unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); + TmpOffset += SL->getElementOffset(Idx); + } else { + uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); + for (;;) { + if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { + // Constant-offset addressing. + TmpOffset += CI->getSExtValue() * S; + break; + } + if (canFoldAddIntoGEP(U, Op)) { + // A compatible add with a constant operand. Fold the constant. + ConstantInt *CI = + cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); + TmpOffset += CI->getSExtValue() * S; + // Iterate on the other operand. + Op = cast<AddOperator>(Op)->getOperand(0); + continue; + } + // Unsupported + goto unsupported_gep; + } + } + } + // Try to grab the base operand now. + Addr.setOffset(TmpOffset); + if (computeAddress(U->getOperand(0), Addr)) + return true; + // We failed, restore everything and try the other options. + Addr = SavedAddr; + unsupported_gep: + break; + } + case Instruction::Alloca: { + const AllocaInst *AI = cast<AllocaInst>(Obj); + DenseMap<const AllocaInst *, int>::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) { + Addr.setKind(Address::FrameIndexBase); + Addr.setFI(SI->second); + return true; + } + break; + } + } Addr.setReg(getRegForValue(Obj)); return Addr.getReg() != 0; } @@ -519,8 +597,26 @@ bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, default: return false; } - emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); - return true; + if (Addr.isRegBase()) { + simplifyAddress(Addr); + emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); + return true; + } + if (Addr.isFIBase()) { + unsigned FI = Addr.getFI(); + unsigned Align = 4; + unsigned Offset = Addr.getOffset(); + MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = MF->getMachineMemOperand( + MachinePointerInfo::getFixedStack(FI), MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), Align); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) + .addFrameIndex(FI) + .addImm(Offset) + .addMemOperand(MMO); + return true; + } + return false; } bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, @@ -552,8 +648,27 @@ bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, default: return false; } - emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); - return true; + if (Addr.isRegBase()) { + simplifyAddress(Addr); + emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); + return true; + } + if (Addr.isFIBase()) { + unsigned FI = Addr.getFI(); + unsigned Align = 4; + unsigned Offset = Addr.getOffset(); + MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = MF->getMachineMemOperand( + MachinePointerInfo::getFixedStack(FI), MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), Align); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) + .addReg(SrcReg) + .addFrameIndex(FI) + .addImm(Offset) + .addMemOperand(MMO); + return true; + } + return false; } bool MipsFastISel::selectLoad(const Instruction *I) { @@ -972,28 +1087,93 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { CLI.Call = MIB; - // Add implicit physical register uses to the call. - for (auto Reg : CLI.OutRegs) - MIB.addReg(Reg, RegState::Implicit); - - // Add a register mask with the call-preserved registers. Proper - // defs for return values will be added by setPhysRegsDeadExcept(). - MIB.addRegMask(TRI.getCallPreservedMask(CC)); - - CLI.Call = MIB; // Finish off the call including any return values. return finishCall(CLI, RetVT, NumBytes); } bool MipsFastISel::selectRet(const Instruction *I) { + const Function &F = *I->getParent()->getParent(); const ReturnInst *Ret = cast<ReturnInst>(I); if (!FuncInfo.CanLowerReturn) return false; + + // Build a list of return value registers. + SmallVector<unsigned, 4> RetRegs; + if (Ret->getNumOperands() > 0) { - return false; + CallingConv::ID CC = F.getCallingConv(); + SmallVector<ISD::OutputArg, 4> Outs; + GetReturnInfo(F.getReturnType(), F.getAttributes(), Outs, TLI); + // Analyze operands of the call, assigning locations to each operand. + SmallVector<CCValAssign, 16> ValLocs; + MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, + I->getContext()); + CCAssignFn *RetCC = RetCC_Mips; + CCInfo.AnalyzeReturn(Outs, RetCC); + + // Only handle a single return value for now. + if (ValLocs.size() != 1) + return false; + + CCValAssign &VA = ValLocs[0]; + const Value *RV = Ret->getOperand(0); + + // Don't bother handling odd stuff for now. + if ((VA.getLocInfo() != CCValAssign::Full) && + (VA.getLocInfo() != CCValAssign::BCvt)) + return false; + + // Only handle register returns for now. + if (!VA.isRegLoc()) + return false; + + unsigned Reg = getRegForValue(RV); + if (Reg == 0) + return false; + + unsigned SrcReg = Reg + VA.getValNo(); + unsigned DestReg = VA.getLocReg(); + // Avoid a cross-class copy. This is very unlikely. + if (!MRI.getRegClass(SrcReg)->contains(DestReg)) + return false; + + EVT RVEVT = TLI.getValueType(RV->getType()); + if (!RVEVT.isSimple()) + return false; + + if (RVEVT.isVector()) + return false; + + MVT RVVT = RVEVT.getSimpleVT(); + if (RVVT == MVT::f128) + return false; + + MVT DestVT = VA.getValVT(); + // Special handling for extended integers. + if (RVVT != DestVT) { + if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16) + return false; + + if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt()) + return false; + + bool IsZExt = Outs[0].Flags.isZExt(); + SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt); + if (SrcReg == 0) + return false; + } + + // Make the copy. + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg); + + // Add register to return instruction. + RetRegs.push_back(VA.getLocReg()); } - emitInst(Mips::RetRA); + MachineInstrBuilder MIB = emitInst(Mips::RetRA); + for (unsigned i = 0, e = RetRegs.size(); i != e; ++i) + MIB.addReg(RetRegs[i], RegState::Implicit); return true; } @@ -1118,7 +1298,8 @@ bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt) { unsigned DestReg = createResultReg(&Mips::GPR32RegClass); - return emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); + bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); + return Success ? DestReg : 0; } bool MipsFastISel::fastSelectInstruction(const Instruction *I) { @@ -1170,6 +1351,17 @@ unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, return VReg; } +void MipsFastISel::simplifyAddress(Address &Addr) { + if (!isInt<16>(Addr.getOffset())) { + unsigned TempReg = + materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass); + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg()); + Addr.setReg(DestReg); + Addr.setOffset(0); + } +} + namespace llvm { FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) { diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index 3014a0d..8b8b019 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -100,7 +100,7 @@ bool MipsFrameLowering::hasFP(const MachineFunction &MF) const { uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); int64_t Offset = 0; diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 0bdabf3..21fc8ce 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -47,7 +47,7 @@ using namespace llvm; //===----------------------------------------------------------------------===// bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); bool Ret = SelectionDAGISel::runOnMachineFunction(MF); processFunctionAfterISel(MF); @@ -95,6 +95,12 @@ bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, return false; } +bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const { llvm_unreachable("Unimplemented function."); @@ -230,12 +236,3 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, OutOps.push_back(Op); return false; } - -/// createMipsISelDag - This pass converts a legalized DAG into a -/// MIPS-specific DAG, ready for instruction scheduling. -FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { - if (TM.getSubtargetImpl()->inMips16Mode()) - return llvm::createMips16ISelDag(TM); - - return llvm::createMipsSEISelDag(TM); -} diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h index ff8760d..6b72877 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/lib/Target/Mips/MipsISelDAGToDAG.h @@ -73,6 +73,9 @@ private: virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const; + virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + /// Match addr+simm10 and addr virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const; @@ -125,11 +128,6 @@ private: char ConstraintCode, std::vector<SDValue> &OutOps) override; }; - -/// createMipsISelDag - This pass converts a legalized DAG into a -/// MIPS-specific DAG, ready for instruction scheduling. -FunctionPass *createMipsISelDag(MipsTargetMachine &TM); - } #endif diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index ff2bfb3..9253b2e 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -70,7 +70,7 @@ static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { if (!isShiftedMask_64(I)) return false; - Size = CountPopulation_64(I); + Size = countPopulation(I); Pos = countTrailingZeros(I); return true; } @@ -203,7 +203,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) - : TargetLowering(TM), Subtarget(STI) { + : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) { // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); @@ -215,12 +215,15 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, ZeroOrNegativeOneBooleanContent); // Load extented operations for i1 types must be promoted - setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + for (MVT VT : MVT::integer_valuetypes()) { + setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); + } // MIPS doesn't have extending float->double load/store - setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + for (MVT VT : MVT::fp_valuetypes()) + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); setTruncStoreAction(MVT::f64, MVT::f32, Expand); // Used by legalize types to correctly generate the setcc result. @@ -258,6 +261,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::LOAD, MVT::i64, Custom); setOperationAction(ISD::STORE, MVT::i64, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); + setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); } if (!Subtarget.isGP64bit()) { @@ -368,9 +374,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::BSWAP, MVT::i64, Expand); if (Subtarget.isGP64bit()) { - setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Custom); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Custom); - setLoadExtAction(ISD::EXTLOAD, MVT::i32, Custom); + setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom); + setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); setTruncStoreAction(MVT::i64, MVT::i32, Custom); } @@ -387,14 +393,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, // The arguments on the stack are defined in terms of 4-byte slots on O32 // and 8-byte slots on N32/N64. - setMinStackArgumentAlignment( - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4); + setMinStackArgumentAlignment((ABI.IsN32() || ABI.IsN64()) ? 8 : 4); - setStackPointerRegisterToSaveRestore(Subtarget.isABI_N64() ? Mips::SP_64 - : Mips::SP); + setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP); - setExceptionPointerRegister(Subtarget.isABI_N64() ? Mips::A0_64 : Mips::A0); - setExceptionSelectorRegister(Subtarget.isABI_N64() ? Mips::A1_64 : Mips::A1); + setExceptionPointerRegister(ABI.IsN64() ? Mips::A0_64 : Mips::A0); + setExceptionSelectorRegister(ABI.IsN64() ? Mips::A1_64 : Mips::A1); MaxStoresPerMemcpy = 16; @@ -933,18 +937,35 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case Mips::DIVU: case Mips::MOD: case Mips::MODU: - return insertDivByZeroTrap( - MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), false); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false); case Mips::PseudoDSDIV: case Mips::PseudoDUDIV: case Mips::DDIV: case Mips::DDIVU: case Mips::DMOD: case Mips::DMODU: - return insertDivByZeroTrap( - MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), true); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true); case Mips::SEL_D: return emitSEL_D(MI, BB); + + case Mips::PseudoSELECT_I: + case Mips::PseudoSELECT_I64: + case Mips::PseudoSELECT_S: + case Mips::PseudoSELECT_D32: + case Mips::PseudoSELECT_D64: + return emitPseudoSELECT(MI, BB, false, Mips::BNE); + case Mips::PseudoSELECTFP_F_I: + case Mips::PseudoSELECTFP_F_I64: + case Mips::PseudoSELECTFP_F_S: + case Mips::PseudoSELECTFP_F_D32: + case Mips::PseudoSELECTFP_F_D64: + return emitPseudoSELECT(MI, BB, true, Mips::BC1F); + case Mips::PseudoSELECTFP_T_I: + case Mips::PseudoSELECTFP_T_I64: + case Mips::PseudoSELECTFP_T_S: + case Mips::PseudoSELECTFP_T_D32: + case Mips::PseudoSELECTFP_T_D64: + return emitPseudoSELECT(MI, BB, true, Mips::BC1T); } } @@ -959,8 +980,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, AND, NOR, ZERO, BEQ; @@ -1043,8 +1063,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, unsigned SrcReg) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); if (Subtarget.hasMips32r2() && Size == 1) { @@ -1080,8 +1099,7 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1178,7 +1196,8 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( // beq success,$0,loopMBB BB = loopMBB; - BuildMI(BB, DL, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; + BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); if (Nand) { // and andres, oldval, incr2 // nor binopres, $0, andres @@ -1201,7 +1220,8 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( .addReg(OldVal).addReg(Mask2); BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal0).addReg(NewVal); - BuildMI(BB, DL, TII->get(Mips::SC), Success) + unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; + BuildMI(BB, DL, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::BEQ)) .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); @@ -1231,8 +1251,7 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, ZERO, BNE, BEQ; @@ -1314,8 +1333,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1412,7 +1430,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, // and maskedoldval0,oldval,mask // bne maskedoldval0,shiftedcmpval,sinkMBB BB = loop1MBB; - BuildMI(BB, DL, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; + BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) .addReg(OldVal).addReg(Mask); BuildMI(BB, DL, TII->get(Mips::BNE)) @@ -1428,7 +1447,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, .addReg(OldVal).addReg(Mask2); BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal1).addReg(ShiftedNewVal); - BuildMI(BB, DL, TII->get(Mips::SC), Success) + unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; + BuildMI(BB, DL, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::BEQ)) .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); @@ -1450,10 +1470,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const { MachineFunction *MF = BB->getParent(); - const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); MachineBasicBlock::iterator II(MI); @@ -1497,8 +1515,7 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { false, 0); Chain = Addr.getValue(1); - if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || - Subtarget.isABI_N64()) { + if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || ABI.IsN64()) { // For PIC, the sequence is: // BRIND(load(Jumptable + index) + RelocBase) // RelocBase can be JumpTable, GOT or some sort of global base. @@ -1580,32 +1597,29 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = N->getGlobal(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) { - const MipsTargetObjectFile &TLOF = - (const MipsTargetObjectFile&)getObjFileLowering(); - - if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + const MipsTargetObjectFile *TLOF = + static_cast<const MipsTargetObjectFile *>( + getTargetMachine().getObjFileLowering()); + if (TLOF->IsGlobalInSmallSection(GV, getTargetMachine())) // %gp_rel relocation - return getAddrGPRel(N, Ty, DAG); + return getAddrGPRel(N, SDLoc(N), Ty, DAG); // %hi/%lo relocation - return getAddrNonPIC(N, Ty, DAG); + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); } if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))) - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); if (LargeGOT) - return getAddrGlobalLargeGOT(N, Ty, DAG, MipsII::MO_GOT_HI16, + return getAddrGlobalLargeGOT(N, SDLoc(N), Ty, DAG, MipsII::MO_GOT_HI16, MipsII::MO_GOT_LO16, DAG.getEntryNode(), MachinePointerInfo::getGOT()); - return getAddrGlobal(N, Ty, DAG, - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) - ? MipsII::MO_GOT_DISP - : MipsII::MO_GOT16, + return getAddrGlobal(N, SDLoc(N), Ty, DAG, + (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP + : MipsII::MO_GOT16, DAG.getEntryNode(), MachinePointerInfo::getGOT()); } @@ -1614,12 +1628,10 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) - return getAddrNonPIC(N, Ty, DAG); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering:: @@ -1707,12 +1719,10 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const JumpTableSDNode *N = cast<JumpTableSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) - return getAddrNonPIC(N, Ty, DAG); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering:: @@ -1721,20 +1731,19 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) { - const MipsTargetObjectFile &TLOF = - (const MipsTargetObjectFile&)getObjFileLowering(); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + const MipsTargetObjectFile *TLOF = + static_cast<const MipsTargetObjectFile *>( + getTargetMachine().getObjFileLowering()); - if (TLOF.IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) + if (TLOF->IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) // %gp_rel relocation - return getAddrGPRel(N, Ty, DAG); + return getAddrGPRel(N, SDLoc(N), Ty, DAG); - return getAddrNonPIC(N, Ty, DAG); + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); } - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { @@ -1760,8 +1769,7 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { unsigned Align = Node->getConstantOperandVal(3); const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); SDLoc DL(Node); - unsigned ArgSlotSizeInBytes = - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4; + unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4; SDValue VAListLoad = DAG.getLoad(getPointerTy(), DL, Chain, VAListPtr, MachinePointerInfo(SV), false, false, false, @@ -1924,9 +1932,8 @@ lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc DL(Op); - SDValue FrameAddr = - DAG.getCopyFromReg(DAG.getEntryNode(), DL, - Subtarget.isABI_N64() ? Mips::FP_64 : Mips::FP, VT); + SDValue FrameAddr = DAG.getCopyFromReg( + DAG.getEntryNode(), DL, ABI.IsN64() ? Mips::FP_64 : Mips::FP, VT); return FrameAddr; } @@ -1942,7 +1949,7 @@ SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MVT VT = Op.getSimpleValueType(); - unsigned RA = Subtarget.isABI_N64() ? Mips::RA_64 : Mips::RA; + unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA; MFI->setReturnAddressIsTaken(true); // Return RA, which contains the return address. Mark it an implicit live-in. @@ -1964,12 +1971,12 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) SDValue Offset = Op.getOperand(1); SDValue Handler = Op.getOperand(2); SDLoc DL(Op); - EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; + EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; // Store stack offset in V1, store jump target in V0. Glue CopyToReg and // EH_RETURN nodes, so that instructions are emitted back-to-back. - unsigned OffsetReg = Subtarget.isABI_N64() ? Mips::V1_64 : Mips::V1; - unsigned AddrReg = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; + unsigned OffsetReg = ABI.IsN64() ? Mips::V1_64 : Mips::V1; + unsigned AddrReg = ABI.IsN64() ? Mips::V0_64 : Mips::V0; Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain, @@ -1991,10 +1998,11 @@ SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op, SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); + MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32; + SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); SDValue Shamt = Op.getOperand(2); - - // if shamt < 32: + // if shamt < (VT.bits): // lo = (shl lo, shamt) // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) // else: @@ -2002,18 +2010,17 @@ SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, // hi = (shl lo, shamt[4:0]) SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, DAG.getConstant(-1, MVT::i32)); - SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, - DAG.getConstant(1, MVT::i32)); - SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, ShiftRight1Lo, - Not); - SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, Shamt); - SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); - SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, MVT::i32, Lo, Shamt); + SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, + DAG.getConstant(1, VT)); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); + SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, DAG.getConstant(0x20, MVT::i32)); - Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, - DAG.getConstant(0, MVT::i32), ShiftLeftLo); - Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftLeftLo, Or); + Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, + DAG.getConstant(0, VT), ShiftLeftLo); + Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or); SDValue Ops[2] = {Lo, Hi}; return DAG.getMergeValues(Ops, DL); @@ -2024,8 +2031,9 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, SDLoc DL(Op); SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); SDValue Shamt = Op.getOperand(2); + MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32; - // if shamt < 32: + // if shamt < (VT.bits): // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) // if isSRA: // hi = (sra hi, shamt) @@ -2040,21 +2048,19 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, // hi = 0 SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, DAG.getConstant(-1, MVT::i32)); - SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, - DAG.getConstant(1, MVT::i32)); - SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, ShiftLeft1Hi, Not); - SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, Shamt); - SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); - SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, MVT::i32, - Hi, Shamt); + SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, + DAG.getConstant(1, VT)); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); + SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, + DL, VT, Hi, Shamt); SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, DAG.getConstant(0x20, MVT::i32)); - SDValue Shift31 = DAG.getNode(ISD::SRA, DL, MVT::i32, Hi, - DAG.getConstant(31, MVT::i32)); - Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftRightHi, Or); - Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, - IsSRA ? Shift31 : DAG.getConstant(0, MVT::i32), - ShiftRightHi); + SDValue Shift31 = DAG.getNode(ISD::SRA, DL, VT, Hi, DAG.getConstant(31, VT)); + Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or); + Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, + IsSRA ? Shift31 : DAG.getConstant(0, VT), ShiftRightHi); SDValue Ops[2] = {Lo, Hi}; return DAG.getMergeValues(Ops, DL); @@ -2266,9 +2272,9 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State, const MCPhysReg *F64Regs) { - - static const unsigned IntRegsSize = 4, FloatRegsSize = 2; + CCState &State, ArrayRef<MCPhysReg> F64Regs) { + const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>( + State.getMachineFunction().getSubtarget()); static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 }; @@ -2278,6 +2284,19 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, return true; // Promote i8 and i16 + if (ArgFlags.isInReg() && !Subtarget.isLittle()) { + if (LocVT == MVT::i8 || LocVT == MVT::i16 || LocVT == MVT::i32) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExtUpper; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExtUpper; + else + LocInfo = CCValAssign::AExtUpper; + } + } + + // Promote i8 and i16 if (LocVT == MVT::i8 || LocVT == MVT::i16) { LocVT = MVT::i32; if (ArgFlags.isSExt()) @@ -2293,39 +2312,39 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following // is true: function is vararg, argument is 3rd or higher, there is previous // argument which is not f32 or f64. - bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 - || State.getFirstUnallocated(F32Regs, FloatRegsSize) != ValNo; + bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || + State.getFirstUnallocated(F32Regs) != ValNo; unsigned OrigAlign = ArgFlags.getOrigAlign(); bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8); if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); // If this is the first part of an i64 arg, // the allocated register must be either A0 or A2. if (isI64 && (Reg == Mips::A1 || Reg == Mips::A3)) - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { // Allocate int register and shadow next int register. If first // available register is Mips::A1 or Mips::A3, shadow it too. - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); if (Reg == Mips::A1 || Reg == Mips::A3) - Reg = State.AllocateReg(IntRegs, IntRegsSize); - State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); + State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { // we are guaranteed to find an available float register if (ValVT == MVT::f32) { - Reg = State.AllocateReg(F32Regs, FloatRegsSize); + Reg = State.AllocateReg(F32Regs); // Shadow int register - State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs); } else { - Reg = State.AllocateReg(F64Regs, FloatRegsSize); + Reg = State.AllocateReg(F64Regs); // Shadow int registers - unsigned Reg2 = State.AllocateReg(IntRegs, IntRegsSize); + unsigned Reg2 = State.AllocateReg(IntRegs); if (Reg2 == Mips::A1 || Reg2 == Mips::A3) - State.AllocateReg(IntRegs, IntRegsSize); - State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs); + State.AllocateReg(IntRegs); } } else llvm_unreachable("Cannot handle this ValVT."); @@ -2407,8 +2426,8 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, // used for the function (that is, Mips linker doesn't generate lazy binding // stub for a function whose address is taken in the program). if (IsPICCall && !InternalLinkage && IsCallReloc) { - unsigned GPReg = Subtarget.isABI_N64() ? Mips::GP_64 : Mips::GP; - EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; + unsigned GPReg = ABI.IsN64() ? Mips::GP_64 : Mips::GP; + EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); } @@ -2431,8 +2450,7 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); assert(Mask && "Missing call preserved mask for calling convention"); if (Subtarget.inMips16HardFloat()) { @@ -2468,7 +2486,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; @@ -2480,7 +2498,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Allocate the reserved argument area. It seems strange to do this from the // caller side but removing it breaks the frame size calculation. - const MipsABIInfo &ABI = Subtarget.getABI(); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), Callee.getNode()); @@ -2511,8 +2528,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, Chain = DAG.getCALLSEQ_START(Chain, NextStackOffsetVal, DL); SDValue StackPtr = DAG.getCopyFromReg( - Chain, DL, Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP, - getPointerTy()); + Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP, getPointerTy()); // With EABI is it possible to have 16 args on registers. std::deque< std::pair<unsigned, SDValue> > RegsToPass; @@ -2626,9 +2642,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - bool IsPICCall = - (Subtarget.isABI_N64() || IsPIC); // true if calls are translated to - // jalr $25 + bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to + // jalr $25 bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false; SDValue CalleeLo; EVT Ty = Callee.getValueType(); @@ -2639,15 +2654,14 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, InternalLinkage = Val->hasInternalLinkage(); if (InternalLinkage) - Callee = getAddrLocal(G, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + Callee = getAddrLocal(G, DL, Ty, DAG, ABI.IsN32() || ABI.IsN64()); else if (LargeGOT) { - Callee = getAddrGlobalLargeGOT(G, Ty, DAG, MipsII::MO_CALL_HI16, + Callee = getAddrGlobalLargeGOT(G, DL, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Val)); IsCallReloc = true; } else { - Callee = getAddrGlobal(G, Ty, DAG, MipsII::MO_GOT_CALL, Chain, + Callee = getAddrGlobal(G, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Val)); IsCallReloc = true; } @@ -2659,16 +2673,16 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { const char *Sym = S->getSymbol(); - if (!Subtarget.isABI_N64() && !IsPIC) // !N64 && static - Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), - MipsII::MO_NO_FLAG); + if (!ABI.IsN64() && !IsPIC) // !N64 && static + Callee = + DAG.getTargetExternalSymbol(Sym, getPointerTy(), MipsII::MO_NO_FLAG); else if (LargeGOT) { - Callee = getAddrGlobalLargeGOT(S, Ty, DAG, MipsII::MO_CALL_HI16, + Callee = getAddrGlobalLargeGOT(S, DL, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; } else { // N64 || PIC - Callee = getAddrGlobal(S, Ty, DAG, MipsII::MO_GOT_CALL, Chain, + Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; } @@ -2844,7 +2858,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, SmallVector<CCValAssign, 16> ArgLocs; MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); - const MipsABIInfo &ABI = Subtarget.getABI(); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); Function::const_arg_iterator FuncArg = DAG.getMachineFunction().getFunction()->arg_begin(); @@ -2858,13 +2871,16 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; - std::advance(FuncArg, Ins[i].OrigArgIndex - CurArgIdx); - CurArgIdx = Ins[i].OrigArgIndex; + if (Ins[i].isOrigArg()) { + std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx); + CurArgIdx = Ins[i].getOrigArgIndex(); + } EVT ValVT = VA.getValVT(); ISD::ArgFlagsTy Flags = Ins[i].Flags; bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { + assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit"); unsigned FirstByValReg, LastByValReg; unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); @@ -2897,7 +2913,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, (RegVT == MVT::i64 && ValVT == MVT::f64) || (RegVT == MVT::f64 && ValVT == MVT::i64)) ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - else if (Subtarget.isABI_O32() && RegVT == MVT::i32 && + else if (ABI.IsO32() && RegVT == MVT::i32 && ValVT == MVT::f64) { unsigned Reg2 = addLiveIn(DAG.getMachineFunction(), getNextIntArgReg(ArgReg), RC); @@ -2912,7 +2928,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, } else { // VA.isRegLoc() MVT LocVT = VA.getLocVT(); - if (Subtarget.isABI_O32()) { + if (ABI.IsO32()) { // We ought to be able to use LocVT directly but O32 sets it to i32 // when allocating floating point values to integer registers. // This shouldn't influence how we load the value into registers unless @@ -2949,7 +2965,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, unsigned Reg = MipsFI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister( - getRegClassFor(Subtarget.isABI_N64() ? MVT::i64 : MVT::i32)); + getRegClassFor(ABI.IsN64() ? MVT::i64 : MVT::i32)); MipsFI->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); @@ -3066,7 +3082,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, if (!Reg) llvm_unreachable("sret virtual register not created in the entry block"); SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy()); - unsigned V0 = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; + unsigned V0 = ABI.IsN64() ? Mips::V0_64 : Mips::V0; Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Flag); Flag = Chain.getValue(1); @@ -3201,7 +3217,7 @@ parsePhysicalReg(StringRef C, std::string &Prefix, std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering:: parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); + Subtarget.getRegisterInfo(); const TargetRegisterClass *RC; std::string Prefix; unsigned long long Reg; @@ -3275,9 +3291,10 @@ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { /// Given a register class constraint, like 'r', if this corresponds directly /// to an LLVM register class, return a register of 0 and the register class /// pointer. -std::pair<unsigned, const TargetRegisterClass*> MipsTargetLowering:: -getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const -{ +std::pair<unsigned, const TargetRegisterClass *> +MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + const std::string &Constraint, + MVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'd': // Address register. Same as 'r' unless generating MIPS16 code. @@ -3333,7 +3350,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const if (R.second) return R; - return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); + return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops @@ -3477,7 +3494,7 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { } unsigned MipsTargetLowering::getJumpTableEncoding() const { - if (Subtarget.isABI_N64()) + if (ABI.IsN64()) return MachineJumpTableInfo::EK_GPRel64BlockAddress; return TargetLowering::getJumpTableEncoding(); @@ -3495,7 +3512,6 @@ void MipsTargetLowering::copyByValRegs( unsigned RegAreaSize = NumRegs * GPRSizeInBytes; unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); int FrameObjOffset; - const MipsABIInfo &ABI = Subtarget.getABI(); ArrayRef<MCPhysReg> ByValArgRegs = ABI.GetByValArgRegs(); if (RegAreaSize) @@ -3547,7 +3563,7 @@ void MipsTargetLowering::passByValArg( unsigned NumRegs = LastReg - FirstReg; if (NumRegs) { - const ArrayRef<MCPhysReg> ArgRegs = Subtarget.getABI().GetByValArgRegs(); + const ArrayRef<MCPhysReg> ArgRegs = ABI.GetByValArgRegs(); bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); unsigned I = 0; @@ -3630,8 +3646,8 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain, SDLoc DL, SelectionDAG &DAG, CCState &State) const { - const ArrayRef<MCPhysReg> ArgRegs = Subtarget.getABI().GetVarArgRegs(); - unsigned Idx = State.getFirstUnallocated(ArgRegs.data(), ArgRegs.size()); + const ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); + unsigned Idx = State.getFirstUnallocated(ArgRegs); unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); const TargetRegisterClass *RC = getRegClassFor(RegTy); @@ -3646,7 +3662,6 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, VaArgOffset = RoundUpToAlignment(State.getNextStackOffset(), RegSizeInBytes); else { - const MipsABIInfo &ABI = Subtarget.getABI(); VaArgOffset = (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); @@ -3677,8 +3692,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, unsigned Align) const { - MachineFunction &MF = State->getMachineFunction(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); assert(Size && "Byval argument's size shouldn't be 0."); @@ -3689,10 +3703,10 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, if (State->getCallingConv() != CallingConv::Fast) { unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - const ArrayRef<MCPhysReg> IntArgRegs = Subtarget.getABI().GetByValArgRegs(); + const ArrayRef<MCPhysReg> IntArgRegs = ABI.GetByValArgRegs(); // FIXME: The O32 case actually describes no shadow registers. const MCPhysReg *ShadowRegs = - Subtarget.isABI_O32() ? IntArgRegs.data() : Mips64DPRegs; + ABI.IsO32() ? IntArgRegs.data() : Mips64DPRegs; // We used to check the size as well but we can't do that anymore since // CCState::HandleByVal() rounds up the size after calling this function. @@ -3700,7 +3714,7 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, "Byval argument's alignment should be a multiple of" "RegSizeInBytes."); - FirstReg = State->getFirstUnallocated(IntArgRegs.data(), IntArgRegs.size()); + FirstReg = State->getFirstUnallocated(IntArgRegs); // If Align > RegSizeInBytes, the first arg register must be even. // FIXME: This condition happens to do the right thing but it's not the @@ -3720,3 +3734,102 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); } + +MachineBasicBlock * +MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, + bool isFPCmp, unsigned Opc) const { + assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && + "Subtarget already supports SELECT nodes with the use of" + "conditional-move instructions."); + + const TargetInstrInfo *TII = + Subtarget.getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + + // To "insert" a SELECT instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + std::next(MachineBasicBlock::iterator(MI)), BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + if (isFPCmp) { + // bc1[tf] cc, sinkMBB + BuildMI(BB, DL, TII->get(Opc)) + .addReg(MI->getOperand(1).getReg()) + .addMBB(sinkMBB); + } else { + // bne rs, $0, sinkMBB + BuildMI(BB, DL, TII->get(Opc)) + .addReg(MI->getOperand(1).getReg()) + .addReg(Mips::ZERO) + .addMBB(sinkMBB); + } + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] + // ... + BB = sinkMBB; + + BuildMI(*BB, BB->begin(), DL, + TII->get(Mips::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB) + .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + + return BB; +} + +// FIXME? Maybe this could be a TableGen attribute on some registers and +// this table could be generated automatically from RegInfo. +unsigned MipsTargetLowering::getRegisterByName(const char* RegName, + EVT VT) const { + // Named registers is expected to be fairly rare. For now, just support $28 + // since the linux kernel uses it. + if (Subtarget.isGP64bit()) { + unsigned Reg = StringSwitch<unsigned>(RegName) + .Case("$28", Mips::GP_64) + .Default(0); + if (Reg) + return Reg; + } else { + unsigned Reg = StringSwitch<unsigned>(RegName) + .Case("$28", Mips::GP) + .Default(0); + if (Reg) + return Reg; + } + report_fatal_error("Invalid register name global variable"); +} diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 60e53da..9f86a43 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -15,6 +15,7 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H #define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H +#include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "Mips.h" #include "llvm/CodeGen/CallingConvLower.h" @@ -262,6 +263,8 @@ namespace llvm { void HandleByVal(CCState *, unsigned &, unsigned) const override; + unsigned getRegisterByName(const char* RegName, EVT VT) const override; + protected: SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; @@ -270,9 +273,8 @@ namespace llvm { // // (add (load (wrapper $gp, %got(sym)), %lo(sym)) template <class NodeTy> - SDValue getAddrLocal(NodeTy *N, EVT Ty, SelectionDAG &DAG, + SDValue getAddrLocal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG, bool IsN32OrN64) const { - SDLoc DL(N); unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), getTargetNode(N, Ty, DAG, GOTFlag)); @@ -289,11 +291,10 @@ namespace llvm { // computing a global symbol's address: // // (load (wrapper $gp, %got(sym))) - template<class NodeTy> - SDValue getAddrGlobal(NodeTy *N, EVT Ty, SelectionDAG &DAG, + template <class NodeTy> + SDValue getAddrGlobal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG, unsigned Flag, SDValue Chain, const MachinePointerInfo &PtrInfo) const { - SDLoc DL(N); SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), getTargetNode(N, Ty, DAG, Flag)); return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo, false, false, false, 0); @@ -303,14 +304,13 @@ namespace llvm { // computing a global symbol's address in large-GOT mode: // // (load (wrapper (add %hi(sym), $gp), %lo(sym))) - template<class NodeTy> - SDValue getAddrGlobalLargeGOT(NodeTy *N, EVT Ty, SelectionDAG &DAG, - unsigned HiFlag, unsigned LoFlag, - SDValue Chain, + template <class NodeTy> + SDValue getAddrGlobalLargeGOT(NodeTy *N, SDLoc DL, EVT Ty, + SelectionDAG &DAG, unsigned HiFlag, + unsigned LoFlag, SDValue Chain, const MachinePointerInfo &PtrInfo) const { - SDLoc DL(N); - SDValue Hi = DAG.getNode(MipsISD::Hi, DL, Ty, - getTargetNode(N, Ty, DAG, HiFlag)); + SDValue Hi = + DAG.getNode(MipsISD::Hi, DL, Ty, getTargetNode(N, Ty, DAG, HiFlag)); Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, getTargetNode(N, Ty, DAG, LoFlag)); @@ -322,9 +322,9 @@ namespace llvm { // computing a symbol's address in non-PIC mode: // // (add %hi(sym), %lo(sym)) - template<class NodeTy> - SDValue getAddrNonPIC(NodeTy *N, EVT Ty, SelectionDAG &DAG) const { - SDLoc DL(N); + template <class NodeTy> + SDValue getAddrNonPIC(NodeTy *N, SDLoc DL, EVT Ty, + SelectionDAG &DAG) const { SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); return DAG.getNode(ISD::ADD, DL, Ty, @@ -336,9 +336,8 @@ namespace llvm { // computing a symbol's address using gp-relative addressing: // // (add $gp, %gp_rel(sym)) - template<class NodeTy> - SDValue getAddrGPRel(NodeTy *N, EVT Ty, SelectionDAG &DAG) const { - SDLoc DL(N); + template <class NodeTy> + SDValue getAddrGPRel(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG) const { assert(Ty == MVT::i32); SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); return DAG.getNode(ISD::ADD, DL, Ty, @@ -363,6 +362,8 @@ namespace llvm { // Subtarget Info const MipsSubtarget &Subtarget; + // Cache the ABI from the TargetMachine, we use it everywhere. + const MipsABIInfo &ABI; private: // Create a TargetGlobalAddress node. @@ -488,9 +489,10 @@ namespace llvm { std::pair<unsigned, const TargetRegisterClass *> parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; - std::pair<unsigned, const TargetRegisterClass*> - getRegForInlineAsmConstraint(const std::string &Constraint, - MVT VT) const override; + std::pair<unsigned, const TargetRegisterClass *> + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + const std::string &Constraint, + MVT VT) const override; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. If hasMemory is @@ -534,6 +536,9 @@ namespace llvm { MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr *MI, MachineBasicBlock *BB, unsigned Size) const; MachineBasicBlock *emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const; + MachineBasicBlock *emitPseudoSELECT(MachineInstr *MI, + MachineBasicBlock *BB, bool isFPCmp, + unsigned Opc) const; }; /// Create MipsTargetLowering objects. diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 2aa8328..ed97cb4 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -458,42 +458,42 @@ def FSUB_S : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>, defm FSUB : ADDS_M<"sub.d", II_SUB_D, 0, fsub>, ADDS_FM<0x01, 17>; def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, - MADDS_FM<4, 0>, ISA_MIPS32R2_NOT_32R6_64R6; + MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>, - MADDS_FM<5, 0>, ISA_MIPS32R2_NOT_32R6_64R6; + MADDS_FM<5, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; let AdditionalPredicates = [NoNaNsFPMath] in { def NMADD_S : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, fadd>, - MADDS_FM<6, 0>, ISA_MIPS32R2_NOT_32R6_64R6; + MADDS_FM<6, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; def NMSUB_S : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, fsub>, - MADDS_FM<7, 0>, ISA_MIPS32R2_NOT_32R6_64R6; + MADDS_FM<7, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; } def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>, - MADDS_FM<4, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_32; + MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM<5, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_32; + MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; let AdditionalPredicates = [NoNaNsFPMath] in { def NMADD_D32 : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D, fadd>, - MADDS_FM<6, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_32; + MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; def NMSUB_D32 : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D, fsub>, - MADDS_FM<7, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_32; + MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; } -let isCodeGenOnly=1 in { +let DecoderNamespace = "Mips64" in { def MADD_D64 : MADDS_FT<"madd.d", FGR64Opnd, II_MADD_D, fadd>, - MADDS_FM<4, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; + MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; def MSUB_D64 : MADDS_FT<"msub.d", FGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM<5, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; + MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; } let AdditionalPredicates = [NoNaNsFPMath], - isCodeGenOnly=1 in { + DecoderNamespace = "Mips64" in { def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64Opnd, II_NMADD_D, fadd>, - MADDS_FM<6, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; + MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64Opnd, II_NMSUB_D, fsub>, - MADDS_FM<7, 1>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; + MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 5c91fbc..8cc1603 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -297,6 +297,19 @@ class BGEZ_FM<bits<6> op, bits<5> funct> : StdArch { let Inst{15-0} = offset; } +class BBIT_FM<bits<6> op> : StdArch { + bits<5> rs; + bits<5> p; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rs; + let Inst{20-16} = p; + let Inst{15-0} = offset; +} + class SLTI_FM<bits<6> op> : StdArch { bits<5> rt; bits<5> rs; @@ -411,6 +424,20 @@ class SYNC_FM : StdArch { let Inst{5-0} = 0xf; } +class SYNCI_FM : StdArch { + // Produced by the mem_simm16 address as reg << 16 | imm (see getMemEncoding). + bits<21> addr; + bits<5> rs = addr{20-16}; + bits<16> offset = addr{15-0}; + + bits<32> Inst; + + let Inst{31-26} = 0b000001; + let Inst{25-21} = rs; + let Inst{20-16} = 0b11111; + let Inst{15-0} = offset; +} + class MULT_FM<bits<6> op, bits<6> funct> : StdArch { bits<5> rs; bits<5> rt; diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index dcc0e24..0839147 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -15,7 +15,7 @@ #include "InstPrinter/MipsInstPrinter.h" #include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" -#include "MipsTargetMachine.h" +#include "MipsSubtarget.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index aebac34..04a16b3 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -156,6 +156,8 @@ def HasMips3 : Predicate<"Subtarget->hasMips3()">, AssemblerPredicate<"FeatureMips3">; def HasMips4_32 : Predicate<"Subtarget->hasMips4_32()">, AssemblerPredicate<"FeatureMips4_32">; +def NotMips4_32 : Predicate<"!Subtarget->hasMips4_32()">, + AssemblerPredicate<"FeatureMips4_32">; def HasMips4_32r2 : Predicate<"Subtarget->hasMips4_32r2()">, AssemblerPredicate<"FeatureMips4_32r2">; def HasMips5_32r2 : Predicate<"Subtarget->hasMips5_32r2()">, @@ -180,8 +182,6 @@ def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">, AssemblerPredicate<"FeatureMips64r6">; def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">, AssemblerPredicate<"!FeatureMips64r6">; -def IsN64 : Predicate<"Subtarget->isABI_N64()">, - AssemblerPredicate<"FeatureN64">; def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; def HasCnMips : Predicate<"Subtarget->hasCnMips()">, @@ -220,6 +220,9 @@ class GPR_64 { list<Predicate> GPRPredicates = [IsGP64bit]; } // subtractive predicate will hopefully keep us under the 32 predicate // limit long enough to develop an alternative way to handle P1||P2 // predicates. +class ISA_MIPS1_NOT_4_32 { + list<Predicate> InsnPredicates = [NotMips4_32]; +} class ISA_MIPS1_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6]; } @@ -316,7 +319,7 @@ class IsAsCheapAsAMove { } class NeverHasSideEffects { - bit neverHasSideEffects = 1; + bit hasSideEffects = 0; } //===----------------------------------------------------------------------===// @@ -425,7 +428,14 @@ def MipsMemSimm11AsmOperand : AsmOperandClass { let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<11>"; - //let DiagnosticType = "Simm11"; +} + +def MipsMemSimm16AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm16"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<16>"; } def MipsInvertedImmoperand : AsmOperandClass { @@ -470,6 +480,12 @@ def mem_simm11 : mem_generic { let ParserMatchClass = MipsMemSimm11AsmOperand; } +def mem_simm16 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm16); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm16AsmOperand; +} + def mem_ea : Operand<iPTR> { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -632,7 +648,7 @@ class shift_rotate_reg<string opstr, RegisterOperand RO, InstrItinClass itin, class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>: InstSE<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), [], II_LUI, FrmI, opstr>, IsAsCheapAsAMove { - let neverHasSideEffects = 1; + let hasSideEffects = 0; let isReMaterializable = 1; } @@ -860,6 +876,13 @@ class SYNC_FT<string opstr> : InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)], NoItinerary, FrmOther, opstr>; +class SYNCI_FT<string opstr> : + InstSE<(outs), (ins mem_simm16:$addr), !strconcat(opstr, "\t$addr"), [], + NoItinerary, FrmOther, opstr> { + let hasSideEffects = 1; + let DecoderMethod = "DecodeSyncI"; +} + let hasSideEffects = 1 in class TEQ_FT<string opstr, RegisterOperand RO> : InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_), @@ -876,7 +899,7 @@ class Mult<string opstr, InstrItinClass itin, RegisterOperand RO, itin, FrmR, opstr> { let isCommutable = 1; let Defs = DefRegs; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } // Pseudo multiply/divide instruction with explicit accumulator register @@ -922,7 +945,7 @@ class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>: InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], II_MFHI_MFLO, FrmR, opstr> { let Uses = [UseReg]; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } class PseudoMTLOHI<RegisterClass DstRC, RegisterClass SrcRC> @@ -934,7 +957,7 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>: InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], II_MTHI_MTLO, FrmR, opstr> { let Defs = DefRegs; - let neverHasSideEffects = 1; + let hasSideEffects = 0; } class EffectiveAddress<string opstr, RegisterOperand RO> : @@ -964,7 +987,7 @@ class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO, class SubwordSwap<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [], NoItinerary, FrmR, opstr> { - let neverHasSideEffects = 1; + let hasSideEffects = 0; } // Read Hardware @@ -1130,12 +1153,14 @@ def ADD : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>; def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>; def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>; +let AdditionalPredicates = [NotInMicroMips] in { def AND : MMRel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>; def OR : MMRel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; +} def NOR : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; /// Shift Instructions @@ -1169,11 +1194,15 @@ def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel, def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel, LW_FM<0x21>; def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; +let AdditionalPredicates = [NotInMicroMips] in { def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, LW_FM<0x23>; +} def SB : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>; def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; +let AdditionalPredicates = [NotInMicroMips] in { def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>; +} /// load/store left/right let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug @@ -1188,6 +1217,7 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, ISA_MIPS1_NOT_32R6_64R6; } +let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; @@ -1207,8 +1237,10 @@ let DecoderNamespace = "COP3_" in { def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, ISA_MIPS2; } +} def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; +def SYNCI : MMRel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>, ISA_MIPS2; def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>, ISA_MIPS2; @@ -1284,8 +1316,8 @@ let AdditionalPredicates = [NotInMicroMips] in { def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>; } -// FIXME: JALX really requires either MIPS16 or microMIPS in addition to MIPS32. -def JALX : JumpLink<"jalx", calltarget>, FJ<0x1D>, ISA_MIPS32_NOT_32R6_64R6; +def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>, + ISA_MIPS32_NOT_32R6_64R6; def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, ISA_MIPS1_NOT_32R6_64R6; def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd, 0>, @@ -1440,10 +1472,10 @@ def MFC2 : MFC3OP<"mfc2", GPR32Opnd>, MFC3OP_FM<0x12, 0>; def MTC2 : MFC3OP<"mtc2", GPR32Opnd>, MFC3OP_FM<0x12, 4>; class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary, - FrmOther>; -def SSNOP : Barrier<"ssnop">, BARRIER_FM<1>; -def EHB : Barrier<"ehb">, BARRIER_FM<3>; -def PAUSE : Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; + FrmOther, asmstr>; +def SSNOP : MMRel, Barrier<"ssnop">, BARRIER_FM<1>; +def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>; +def PAUSE : MMRel, Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; // JR_HB and JALR_HB are defined here using the new style naming // scheme because some of this code is shared with Mips32r6InstrInfo.td @@ -1494,13 +1526,14 @@ def TLBWR : MMRel, TLB<"tlbwr">, COP0_TLB_FM<0x06>; class CacheOp<string instr_asm, Operand MemOpnd> : InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), - !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther> { + !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther, + instr_asm> { let DecoderMethod = "DecodeCacheOp"; } -def CACHE : CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, +def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, INSN_MIPS3_32_NOT_32R6_64R6; -def PREF : CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, +def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, INSN_MIPS3_32_NOT_32R6_64R6; //===----------------------------------------------------------------------===// @@ -1531,8 +1564,6 @@ def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; let Predicates = [NotInMicroMips] in { def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; } -def : MipsInstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>; -def : MipsInstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32; def : MipsInstAlias<"not $rt, $rs", (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; @@ -1557,7 +1588,9 @@ def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; +let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; +} def : MipsInstAlias<"bnez $rs,$offset", (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; def : MipsInstAlias<"beqz $rs,$offset", @@ -1606,7 +1639,7 @@ def : MipsInstAlias<"sync", // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// -class LoadImm32< string instr_asm, Operand Od, RegisterOperand RO> : +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", uimm5, GPR32Opnd>; @@ -1621,6 +1654,11 @@ class LoadAddressImm<string instr_asm, Operand Od, RegisterOperand RO> : !strconcat(instr_asm, "\t$rt, $imm32")> ; def LoadAddr32Imm : LoadAddressImm<"la", uimm5, GPR32Opnd>; +def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), + "jal\t$rd, $rs"> ; +def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), + "jal\t$rs"> ; + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// @@ -1633,10 +1671,12 @@ class StoreRegImmPat<Instruction StoreInst, ValueType ValTy> : MipsPat<(store ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>; // Small immediates +let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(i32 immSExt16:$in), (ADDiu ZERO, imm:$in)>; def : MipsPat<(i32 immZExt16:$in), (ORi ZERO, imm:$in)>; +} def : MipsPat<(i32 immLow16Zero:$in), (LUi (HI16 imm:$in))>; @@ -1826,7 +1866,9 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; let AddedComplexity = 40 in { def : LoadRegImmPat<LBu, i32, zextloadi8>; def : LoadRegImmPat<LH, i32, sextloadi16>; + let AdditionalPredicates = [NotInMicroMips] in { def : LoadRegImmPat<LW, i32, load>; + } } //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index e44d6ee..90f8cc0 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -63,11 +63,9 @@ namespace { public: static char ID; MipsLongBranch(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), - IsPIC(TM.getRelocationModel() == Reloc::PIC_), - ABI(TM.getSubtarget<MipsSubtarget>().getABI()), - LongBranchSeqSize(!IsPIC ? 2 : (ABI.IsN64() ? 10 : - (!TM.getSubtarget<MipsSubtarget>().isTargetNaCl() ? 9 : 10))) {} + : MachineFunctionPass(ID), TM(tm), + IsPIC(TM.getRelocationModel() == Reloc::PIC_), + ABI(static_cast<const MipsTargetMachine &>(TM).getABI()) {} const char *getPassName() const override { return "Mips Long Branch"; @@ -110,8 +108,7 @@ static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) { return MO.getMBB(); } - assert(false && "This instruction does not have an MBB operand."); - return nullptr; + llvm_unreachable("This instruction does not have an MBB operand."); } // Traverse the list of instructions backwards until a non-debug instruction is @@ -171,7 +168,7 @@ void MipsLongBranch::initMBBInfo() { MBBInfos.resize(MF->size()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + static_cast<const MipsInstrInfo *>(MF->getSubtarget().getInstrInfo()); for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { MachineBasicBlock *MBB = MF->getBlockNumbered(I); @@ -217,8 +214,8 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { // MachineBasicBlock operand MBBOpnd. void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, MachineBasicBlock *MBBOpnd) { - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( + MBB.getParent()->getSubtarget().getInstrInfo()); unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); const MCInstrDesc &NewDesc = TII->get(NewOpc); @@ -237,15 +234,21 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, MIB.addMBB(MBBOpnd); - // Bundle the instruction in the delay slot to the newly created branch - // and erase the original branch. - assert(Br->isBundledWithSucc()); - MachineBasicBlock::instr_iterator II(Br); - MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); + if (Br->hasDelaySlot()) { + // Bundle the instruction in the delay slot to the newly created branch + // and erase the original branch. + assert(Br->isBundledWithSucc()); + MachineBasicBlock::instr_iterator II(Br); + MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); + } Br->eraseFromParent(); } // Expand branch instructions to long branches. +// TODO: This function has to be fixed for beqz16 and bnez16, because it +// currently assumes that all branches have 16-bit offsets, and will produce +// wrong code if branches whose allowed offsets are [-128, -126, ..., 126] +// are present. void MipsLongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); @@ -253,9 +256,10 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); - + const MipsSubtarget &Subtarget = + static_cast<const MipsSubtarget &>(MF->getSubtarget()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + static_cast<const MipsInstrInfo *>(Subtarget.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->removeSuccessor(TgtMBB); @@ -270,8 +274,6 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { // We must select between the MIPS32r6/MIPS64r6 BAL (which is a normal // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an // pseudo-instruction wrapping BGEZAL). - - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); unsigned BalOp = Subtarget.hasMips32r6() ? Mips::BAL : Mips::BAL_BR; if (!ABI.IsN64()) { @@ -328,7 +330,7 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) .addReg(Mips::SP).addImm(0); - if (!TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + if (!Subtarget.isTargetNaCl()) { MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) @@ -447,14 +449,17 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { } bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { + const MipsSubtarget &STI = + static_cast<const MipsSubtarget &>(F.getSubtarget()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + static_cast<const MipsInstrInfo *>(STI.getInstrInfo()); + LongBranchSeqSize = + !IsPIC ? 2 : (ABI.IsN64() ? 10 : (!STI.isTargetNaCl() ? 9 : 10)); - const MipsSubtarget &STI = TM.getSubtarget<MipsSubtarget>(); if (STI.inMips16Mode() || !STI.enableLongBranchPass()) return false; if ((TM.getRelocationModel() == Reloc::PIC_) && - TM.getSubtarget<MipsSubtarget>().isABI_O32() && + static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() && F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) emitGPDisp(F, TII); @@ -476,10 +481,10 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { if (!I->Br || I->HasLongBranch) continue; - int ShVal = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode() ? 2 : 4; + int ShVal = STI.inMicroMipsMode() ? 2 : 4; int64_t Offset = computeOffset(I->Br) / ShVal; - if (TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + if (STI.isTargetNaCl()) { // The offset calculation does not include sandboxing instructions // that will be added later in the MC layer. Since at this point we // don't know the exact amount of code that "sandboxing" will add, we diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index a89718a..30b93dc 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "MipsMachineFunction.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "MipsInstrInfo.h" +#include "MipsMachineFunction.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/Function.h" @@ -78,15 +79,14 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { if (GlobalBaseReg) return GlobalBaseReg; - const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>(); - - const TargetRegisterClass *RC; - if (ST.inMips16Mode()) - RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass; - else - RC = ST.isABI_N64() ? - (const TargetRegisterClass*)&Mips::GPR64RegClass : - (const TargetRegisterClass*)&Mips::GPR32RegClass; + const TargetRegisterClass *RC = + static_cast<const MipsSubtarget &>(MF.getSubtarget()).inMips16Mode() + ? &Mips::CPU16RegsRegClass + : static_cast<const MipsTargetMachine &>(MF.getTarget()) + .getABI() + .IsN64() + ? &Mips::GPR64RegClass + : &Mips::GPR32RegClass; return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); } @@ -98,16 +98,16 @@ unsigned MipsFunctionInfo::getMips16SPAliasReg() { if (Mips16SPAliasReg) return Mips16SPAliasReg; - const TargetRegisterClass *RC; - RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass; + const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; return Mips16SPAliasReg = MF.getRegInfo().createVirtualRegister(RC); } void MipsFunctionInfo::createEhDataRegsFI() { for (int I = 0; I < 4; ++I) { - const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>(); - const TargetRegisterClass *RC = ST.isABI_N64() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; + const TargetRegisterClass *RC = + static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64() + ? &Mips::GPR64RegClass + : &Mips::GPR32RegClass; EhDataRegFI[I] = MF.getFrameInfo()->CreateStackObject(RC->getSize(), RC->getAlignment(), false); diff --git a/lib/Target/Mips/MipsOptimizePICCall.cpp b/lib/Target/Mips/MipsOptimizePICCall.cpp index 22c524e..7c940ee 100644 --- a/lib/Target/Mips/MipsOptimizePICCall.cpp +++ b/lib/Target/Mips/MipsOptimizePICCall.cpp @@ -174,7 +174,7 @@ void MBBInfo::postVisit() { // OptimizePICCall methods. bool OptimizePICCall::runOnMachineFunction(MachineFunction &F) { - if (F.getTarget().getSubtarget<MipsSubtarget>().inMips16Mode()) + if (static_cast<const MipsSubtarget &>(F.getSubtarget()).inMips16Mode()) return false; // Do a pre-order traversal of the dominator tree. diff --git a/lib/Target/Mips/MipsOptionRecord.h b/lib/Target/Mips/MipsOptionRecord.h index f82544a..dc29cbd 100644 --- a/lib/Target/Mips/MipsOptionRecord.h +++ b/lib/Target/Mips/MipsOptionRecord.h @@ -36,9 +36,8 @@ public: class MipsRegInfoRecord : public MipsOptionRecord { public: - MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context, - const MCSubtargetInfo &STI) - : Streamer(S), Context(Context), STI(STI) { + MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context) + : Streamer(S), Context(Context) { ri_gprmask = 0; ri_cprmask[0] = ri_cprmask[1] = ri_cprmask[2] = ri_cprmask[3] = 0; ri_gp_value = 0; @@ -61,7 +60,6 @@ public: private: MipsELFStreamer *Streamer; MCContext &Context; - const MCSubtargetInfo &STI; const MCRegisterClass *GPR32RegClass; const MCRegisterClass *GPR64RegClass; const MCRegisterClass *FGR32RegClass; diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 20ef3f3..2110c03 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -17,6 +17,7 @@ #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -62,7 +63,7 @@ MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, case Mips::GPR32RegClassID: case Mips::GPR64RegClassID: case Mips::DSPRRegClassID: { - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); return 28 - TFI->hasFP(MF); } case Mips::FGR32RegClassID: @@ -167,7 +168,7 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(*Reg); } // Reserve FP if this function should have a dedicated frame pointer register. - if (MF.getSubtarget().getFrameLowering()->hasFP(MF)) { + if (Subtarget.getFrameLowering()->hasFP(MF)) { if (Subtarget.inMips16Mode()) Reserved.set(Mips::S0); else { @@ -256,8 +257,9 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); - bool IsN64 = Subtarget.isABI_N64(); + const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); + bool IsN64 = + static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64(); if (Subtarget.inMips16Mode()) return TFI->hasFP(MF) ? Mips::S0 : Mips::SP; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 42fe76b..7497a25 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -289,10 +289,28 @@ def GPR32 : GPR32Class<[i32]>; def DSPR : GPR32Class<[v4i8, v2i16]>; def GPRMM16 : RegisterClass<"Mips", [i32], 32, (add + // Callee save + S0, S1, // Return Values and Arguments - V0, V1, A0, A1, A2, A3, + V0, V1, A0, A1, A2, A3)>; + +def GPRMM16Zero : RegisterClass<"Mips", [i32], 32, (add + // Reserved + ZERO, // Callee save - S0, S1)>; + S1, + // Return Values and Arguments + V0, V1, A0, A1, A2, A3)>; + +def GPRMM16MoveP : RegisterClass<"Mips", [i32], 32, (add + // Reserved + ZERO, + // Callee save + S1, + // Return Values and Arguments + V0, V1, + // Callee save + S0, S2, S3, S4)>; def GPR64 : RegisterClass<"Mips", [i64], 64, (add // Reserved @@ -380,6 +398,8 @@ def MSA128W: RegisterClass<"Mips", [v4i32, v4f32], 128, (sequence "W%u", 0, 31)>; def MSA128D: RegisterClass<"Mips", [v2i64, v2f64], 128, (sequence "W%u", 0, 31)>; +def MSA128WEvens: RegisterClass<"Mips", [v4i32, v4f32], 128, + (decimate (sequence "W%u", 0, 31), 2)>; def MSACtrl: RegisterClass<"Mips", [i32], 32, (add MSAIR, MSACSR, MSAAccess, MSASave, MSAModify, MSARequest, MSAMap, MSAUnmap)>; @@ -446,6 +466,16 @@ def GPRMM16AsmOperand : MipsAsmRegOperand { let PredicateMethod = "isMM16AsmReg"; } +def GPRMM16AsmOperandZero : MipsAsmRegOperand { + let Name = "GPRMM16AsmRegZero"; + let PredicateMethod = "isMM16AsmRegZero"; +} + +def GPRMM16AsmOperandMoveP : MipsAsmRegOperand { + let Name = "GPRMM16AsmRegMoveP"; + let PredicateMethod = "isMM16AsmRegMoveP"; +} + def ACC64DSPAsmOperand : MipsAsmRegOperand { let Name = "ACC64DSPAsmReg"; let PredicateMethod = "isACCAsmReg"; @@ -505,6 +535,14 @@ def GPRMM16Opnd : RegisterOperand<GPRMM16> { let ParserMatchClass = GPRMM16AsmOperand; } +def GPRMM16OpndZero : RegisterOperand<GPRMM16Zero> { + let ParserMatchClass = GPRMM16AsmOperandZero; +} + +def GPRMM16OpndMoveP : RegisterOperand<GPRMM16MoveP> { + let ParserMatchClass = GPRMM16AsmOperandMoveP; +} + def GPR64Opnd : RegisterOperand<GPR64> { let ParserMatchClass = GPR64AsmOperand; } diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index 97d9edf..7c79c4c 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -71,11 +71,17 @@ private: MachineFunction &MF; MachineRegisterInfo &MRI; + const MipsSubtarget &Subtarget; + const MipsSEInstrInfo &TII; + const MipsRegisterInfo &RegInfo; }; } ExpandPseudo::ExpandPseudo(MachineFunction &MF_) - : MF(MF_), MRI(MF.getRegInfo()) {} + : MF(MF_), MRI(MF.getRegInfo()), + Subtarget(static_cast<const MipsSubtarget &>(MF.getSubtarget())), + TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())), + RegInfo(*Subtarget.getRegisterInfo()) {} bool ExpandPseudo::expand() { bool Expanded = false; @@ -146,11 +152,6 @@ void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(4); unsigned VR = MRI.createVirtualRegister(RC); unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); @@ -166,11 +167,6 @@ void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(4); unsigned VR = MRI.createVirtualRegister(RC); unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); @@ -189,11 +185,6 @@ void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); @@ -219,11 +210,6 @@ void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); @@ -254,11 +240,6 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, // mfhi $vr1, src // copy dst_hi, $vr1 - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2; const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize); @@ -298,16 +279,8 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, // register). Unfortunately, we have to make this decision before register // allocation so for now we use a spill/reload sequence for all // double-precision values in regardless of being an odd/even register. - - const TargetMachine &TM = MF.getTarget(); - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || (FP64 && !Subtarget.useOddSPReg())) { - const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); - const MipsRegisterInfo &TRI = *static_cast<const MipsRegisterInfo *>( - TM.getSubtargetImpl()->getRegisterInfo()); - unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(); unsigned HiReg = I->getOperand(2).getReg(); @@ -327,11 +300,11 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC2); if (!Subtarget.isLittle()) std::swap(LoReg, HiReg); - TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC, &TRI, - 0); - TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC, &TRI, - 4); - TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &TRI, 0); + TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC, + &RegInfo, 0); + TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC, + &RegInfo, 4); + TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, 0); return true; } @@ -359,15 +332,8 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, // allocation so for now we use a spill/reload sequence for all // double-precision values in regardless of being an odd/even register. - const TargetMachine &TM = MF.getTarget(); - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || (FP64 && !Subtarget.useOddSPReg())) { - const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); - const MipsRegisterInfo &TRI = *static_cast<const MipsRegisterInfo *>( - TM.getSubtargetImpl()->getRegisterInfo()); - unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = I->getOperand(1).getReg(); unsigned N = I->getOperand(2).getImm(); @@ -386,9 +352,9 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, // We re-use the same spill slot each time so that the stack frame doesn't // grow too much in functions with a large number of moves. int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC); - TII.storeRegToStack(MBB, I, SrcReg, I->getOperand(1).isKill(), FI, RC, &TRI, - 0); - TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &TRI, Offset); + TII.storeRegToStack(MBB, I, SrcReg, I->getOperand(1).isKill(), FI, RC, + &RegInfo, 0); + TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, Offset); return true; } @@ -415,9 +381,9 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); + *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); + const MipsRegisterInfo &RegInfo = + *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); @@ -550,9 +516,9 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); + *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); + const MipsRegisterInfo &RegInfo = + *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; @@ -605,7 +571,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); MachineBasicBlock *EntryBlock = MF->begin(); - const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *STI.getInstrInfo(); for (unsigned i = 0, e = CSI.size(); i != e; ++i) { // Add the callee-saved register as live-in. Do not add if the register is @@ -646,7 +612,7 @@ void MipsSEFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); if (!hasReservedCallFrame(MF)) { int64_t Amount = I->getOperand(0).getImm(); diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index f759905..0761ded 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -37,7 +37,7 @@ using namespace llvm; #define DEBUG_TYPE "mips-isel" bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); if (Subtarget->inMips16Mode()) return false; return MipsDAGToDAGISel::runOnMachineFunction(MF); @@ -130,20 +130,17 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); const TargetRegisterClass *RC; - - if (Subtarget->isABI_N64()) - RC = (const TargetRegisterClass*)&Mips::GPR64RegClass; - else - RC = (const TargetRegisterClass*)&Mips::GPR32RegClass; + const MipsABIInfo &ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); + RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); - if (Subtarget->isABI_N64()) { + if (ABI.IsN64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); MBB.addLiveIn(Mips::T9_64); @@ -175,7 +172,7 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MF.getRegInfo().addLiveIn(Mips::T9); MBB.addLiveIn(Mips::T9); - if (Subtarget->isABI_N32()) { + if (ABI.IsN32()) { // lui $v0, %hi(%neg(%gp_rel(fname))) // addu $v1, $v0, $t9 // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) @@ -188,7 +185,7 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { return; } - assert(Subtarget->isABI_O32()); + assert(ABI.IsO32()); // For O32 ABI, the following instruction sequence is emitted to initialize // the global base register: @@ -239,13 +236,31 @@ SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, (Opc == ISD::SUBC || Opc == ISD::SUBE)) && "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); + unsigned SLTuOp = Mips::SLTu, ADDuOp = Mips::ADDu; + if (Subtarget->isGP64bit()) { + SLTuOp = Mips::SLTu64; + ADDuOp = Mips::DADDu; + } + SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1); EVT VT = LHS.getValueType(); - SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, DL, VT, Ops); - SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, DL, VT, + SDNode *Carry = CurDAG->getMachineNode(SLTuOp, DL, VT, Ops); + + if (Subtarget->isGP64bit()) { + // On 64-bit targets, sltu produces an i64 but our backend currently says + // that SLTu64 produces an i32. We need to fix this in the long run but for + // now, just make the DAG type-correct by asserting the upper bits are zero. + Carry = CurDAG->getMachineNode(Mips::SUBREG_TO_REG, DL, VT, + CurDAG->getTargetConstant(0, VT), + SDValue(Carry, 0), + CurDAG->getTargetConstant(Mips::sub_32, VT)); + } + + SDNode *AddCarry = CurDAG->getMachineNode(ADDuOp, DL, VT, SDValue(Carry, 0), RHS); + return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0)); } @@ -392,6 +407,28 @@ bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, selectAddrDefault(Addr, Base, Offset); } +bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) { + if (isa<FrameIndexSDNode>(Base)) + return false; + + if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Offset)) { + unsigned CnstOff = CN->getZExtValue(); + return (CnstOff == (CnstOff & 0x3c)); + } + + return false; + } + + // For all other cases where "lw" would be selected, don't select "lw16" + // because it would result in additional instructions to prepare operands. + if (selectAddrRegImm(Addr, Base, Offset)) + return false; + + return selectAddrDefault(Addr, Base, Offset); +} + bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const { if (selectAddrRegImm10(Addr, Base, Offset)) @@ -644,7 +681,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { case ISD::SUBE: { SDValue InFlag = Node->getOperand(2); - Result = selectAddESubE(Mips::SUBu, InFlag, InFlag.getOperand(0), DL, Node); + unsigned Opc = Subtarget->isGP64bit() ? Mips::DSUBu : Mips::SUBu; + Result = selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node); return std::make_pair(true, Result); } @@ -652,7 +690,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { if (Subtarget->hasDSP()) // Select DSP instructions, ADDSC and ADDWC. break; SDValue InFlag = Node->getOperand(2); - Result = selectAddESubE(Mips::ADDu, InFlag, InFlag.getValue(0), DL, Node); + unsigned Opc = Subtarget->isGP64bit() ? Mips::DADDu : Mips::ADDu; + Result = selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node); return std::make_pair(true, Result); } diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index 2e11fa7..2d24eb4 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -65,6 +65,9 @@ private: bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const override; + bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const override; + bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const override; diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 4a0ce09..09ff4f9 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -46,17 +46,13 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, if (Subtarget.hasDSP() || Subtarget.hasMSA()) { // Expand all truncating stores and extending loads. - unsigned FirstVT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; - unsigned LastVT = (unsigned)MVT::LAST_VECTOR_VALUETYPE; - - for (unsigned VT0 = FirstVT; VT0 <= LastVT; ++VT0) { - for (unsigned VT1 = FirstVT; VT1 <= LastVT; ++VT1) - setTruncStoreAction((MVT::SimpleValueType)VT0, - (MVT::SimpleValueType)VT1, Expand); - - setLoadExtAction(ISD::SEXTLOAD, (MVT::SimpleValueType)VT0, Expand); - setLoadExtAction(ISD::ZEXTLOAD, (MVT::SimpleValueType)VT0, Expand); - setLoadExtAction(ISD::EXTLOAD, (MVT::SimpleValueType)VT0, Expand); + for (MVT VT0 : MVT::vector_valuetypes()) { + for (MVT VT1 : MVT::vector_valuetypes()) { + setTruncStoreAction(VT0, VT1, Expand); + setLoadExtAction(ISD::SEXTLOAD, VT0, VT1, Expand); + setLoadExtAction(ISD::ZEXTLOAD, VT0, VT1, Expand); + setLoadExtAction(ISD::EXTLOAD, VT0, VT1, Expand); + } } } @@ -126,6 +122,8 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::MUL, MVT::i64, Custom); if (Subtarget.isGP64bit()) { + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom); setOperationAction(ISD::MULHS, MVT::i64, Custom); setOperationAction(ISD::MULHU, MVT::i64, Custom); setOperationAction(ISD::SDIVREM, MVT::i64, Custom); @@ -204,6 +202,8 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, if (Subtarget.hasMips64r6()) { // MIPS64r6 replaces the accumulator-based multiplies with a three register // instruction + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); setOperationAction(ISD::MUL, MVT::i64, Legal); setOperationAction(ISD::MULHS, MVT::i64, Legal); setOperationAction(ISD::MULHU, MVT::i64, Legal); @@ -224,7 +224,7 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); } - computeRegisterProperties(); + computeRegisterProperties(Subtarget.getRegisterInfo()); } const MipsTargetLowering * @@ -1836,11 +1836,9 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_fill_h: case Intrinsic::mips_fill_w: case Intrinsic::mips_fill_d: { - SmallVector<SDValue, 16> Ops; EVT ResTy = Op->getValueType(0); - - for (unsigned i = 0; i < ResTy.getVectorNumElements(); ++i) - Ops.push_back(Op->getOperand(1)); + SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(), + Op->getOperand(1)); // If ResTy is v2i64 then the type legalizer will break this node down into // an equivalent v4i32. @@ -2291,9 +2289,9 @@ lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { static bool isConstantOrUndef(const SDValue Op) { if (Op->getOpcode() == ISD::UNDEF) return true; - if (dyn_cast<ConstantSDNode>(Op)) + if (isa<ConstantSDNode>(Op)) return true; - if (dyn_cast<ConstantFPSDNode>(Op)) + if (isa<ConstantFPSDNode>(Op)) return true; return false; } @@ -2747,8 +2745,7 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ // $vr0 = phi($vr2, $fbb, $vr1, $tbb) MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; DebugLoc DL = MI->getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -2813,8 +2810,7 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // $rd = phi($rd1, $fbb, $rd2, $tbb) MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; DebugLoc DL = MI->getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -2875,18 +2871,28 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // for lane 1 because it would require FR=0 mode which isn't supported by MSA. MachineBasicBlock * MipsSETargetLowering:: emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{ - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Fd = MI->getOperand(0).getReg(); unsigned Ws = MI->getOperand(1).getReg(); unsigned Lane = MI->getOperand(2).getImm(); - if (Lane == 0) - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_lo); - else { - unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); + if (Lane == 0) { + unsigned Wt = Ws; + if (!Subtarget.useOddSPReg()) { + // We must copy to an even-numbered MSA register so that the + // single-precision sub-register is also guaranteed to be even-numbered. + Wt = RegInfo.createVirtualRegister(&Mips::MSA128WEvensRegClass); + + BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Wt).addReg(Ws); + } + + BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo); + } else { + unsigned Wt = RegInfo.createVirtualRegister( + Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass : + &Mips::MSA128WEvensRegClass); BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wt).addReg(Ws).addImm(Lane); BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo); @@ -2910,8 +2916,7 @@ MachineBasicBlock * MipsSETargetLowering:: emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); unsigned Fd = MI->getOperand(0).getReg(); unsigned Ws = MI->getOperand(1).getReg(); @@ -2940,15 +2945,16 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ MachineBasicBlock * MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); unsigned Wd_in = MI->getOperand(1).getReg(); unsigned Lane = MI->getOperand(2).getImm(); unsigned Fs = MI->getOperand(3).getReg(); - unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); + unsigned Wt = RegInfo.createVirtualRegister( + Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass : + &Mips::MSA128WEvensRegClass); BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt) .addImm(0) @@ -2975,8 +2981,7 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3024,8 +3029,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, bool IsFP) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3135,8 +3139,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFILL_FW(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3167,8 +3170,7 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3196,8 +3198,7 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128WRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); @@ -3226,8 +3227,7 @@ MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFEXP2_D_1(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128DRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index 16bea8b..74f291f 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -27,7 +27,7 @@ using namespace llvm; MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J), - RI(STI), IsN64(STI.isABI_N64()) {} + RI(STI) {} const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { return RI; @@ -38,9 +38,8 @@ const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. -unsigned MipsSEInstrInfo:: -isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const -{ +unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { unsigned Opc = MI->getOpcode(); if ((Opc == Mips::LW) || (Opc == Mips::LD) || @@ -61,9 +60,8 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. -unsigned MipsSEInstrInfo:: -isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const -{ +unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { unsigned Opc = MI->getOpcode(); if ((Opc == Mips::SW) || (Opc == Mips::SD) || @@ -352,6 +350,8 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BLEZ64: return Mips::BGTZ64; case Mips::BC1T: return Mips::BC1F; case Mips::BC1F: return Mips::BC1T; + case Mips::BEQZC_MM: return Mips::BNEZC_MM; + case Mips::BNEZC_MM: return Mips::BEQZC_MM; } } @@ -422,7 +422,7 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || - Opc == Mips::J) ? + Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ? Opc : 0; } @@ -620,18 +620,13 @@ void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, // jr $ra (via RetRA) const TargetMachine &TM = MBB.getParent()->getTarget(); if (TM.getRelocationModel() == Reloc::PIC_) - BuildMI(MBB, I, I->getDebugLoc(), - TM.getSubtargetImpl()->getInstrInfo()->get(ADDU), T9) + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9) .addReg(TargetReg) .addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), - TM.getSubtargetImpl()->getInstrInfo()->get(ADDU), RA) + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA) .addReg(TargetReg) .addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), - TM.getSubtargetImpl()->getInstrInfo()->get(ADDU), SP) - .addReg(SP) - .addReg(OffsetReg); + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), SP).addReg(SP).addReg(OffsetReg); expandRetRA(MBB, I); } diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h index b2d2301..d16fab2 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.h +++ b/lib/Target/Mips/MipsSEInstrInfo.h @@ -21,7 +21,6 @@ namespace llvm { class MipsSEInstrInfo : public MipsInstrInfo { const MipsSERegisterInfo RI; - bool IsN64; public: explicit MipsSEInstrInfo(const MipsSubtarget &STI); diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 8768b12..26f39a2 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -33,120 +33,61 @@ using namespace llvm; // FIXME: Maybe this should be on by default when Mips16 is specified // -static cl::opt<bool> Mixed16_32( - "mips-mixed-16-32", - cl::init(false), - cl::desc("Allow for a mixture of Mips16 " - "and Mips32 code in a single source file"), - cl::Hidden); - -static cl::opt<bool> Mips_Os16( - "mips-os16", - cl::init(false), - cl::desc("Compile all functions that don' use " - "floating point as Mips 16"), - cl::Hidden); - static cl::opt<bool> -Mips16HardFloat("mips16-hard-float", cl::NotHidden, - cl::desc("MIPS: mips16 hard float enable."), - cl::init(false)); + Mixed16_32("mips-mixed-16-32", cl::init(false), + cl::desc("Allow for a mixture of Mips16 " + "and Mips32 code in a single output file"), + cl::Hidden); + +static cl::opt<bool> Mips_Os16("mips-os16", cl::init(false), + cl::desc("Compile all functions that don't use " + "floating point as Mips 16"), + cl::Hidden); + +static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden, + cl::desc("Enable mips16 hard float."), + cl::init(false)); static cl::opt<bool> -Mips16ConstantIslands( - "mips16-constant-islands", cl::NotHidden, - cl::desc("MIPS: mips16 constant islands enable."), - cl::init(true)); + Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden, + cl::desc("Enable mips16 constant islands."), + cl::init(true)); static cl::opt<bool> -GPOpt("mgpopt", cl::Hidden, - cl::desc("MIPS: Enable gp-relative addressing of small data items")); - -/// Select the Mips CPU for the given triple and cpu name. -/// FIXME: Merge with the copy in MipsMCTargetDesc.cpp -static StringRef selectMipsCPU(Triple TT, StringRef CPU) { - if (CPU.empty() || CPU == "generic") { - if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel) - CPU = "mips32"; - else - CPU = "mips64"; - } - return CPU; -} + GPOpt("mgpopt", cl::Hidden, + cl::desc("Enable gp-relative addressing of mips small data items")); void MipsSubtarget::anchor() { } -static std::string computeDataLayout(const MipsSubtarget &ST) { - std::string Ret = ""; - - // There are both little and big endian mips. - if (ST.isLittle()) - Ret += "e"; - else - Ret += "E"; - - Ret += "-m:m"; - - // Pointers are 32 bit on some ABIs. - if (!ST.isABI_N64()) - Ret += "-p:32:32"; - - // 8 and 16 bit integers only need no have natural alignment, but try to - // align them to 32 bits. 64 bit integers have natural alignment. - Ret += "-i8:8:32-i16:16:32-i64:64"; - - // 32 bit registers are always available and the stack is at least 64 bit - // aligned. On N64 64 bit registers are also available and the stack is - // 128 bit aligned. - if (ST.isABI_N64() || ST.isABI_N32()) - Ret += "-n32:64-S128"; - else - Ret += "-n32-S64"; - - return Ret; -} - MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little, - const MipsTargetMachine *_TM) + const MipsTargetMachine &TM) : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(MipsDefault), - ABI(MipsABIInfo::Unknown()), IsLittle(little), IsSingleFloat(false), - IsFPXX(false), NoABICalls(false), IsFP64bit(false), UseOddSPReg(true), - IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), - IsLinux(true), HasMips3_32(false), HasMips3_32r2(false), - HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false), - InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), - InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), - AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), - HasMSA(false), TM(_TM), TargetTriple(TT), - DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS, TM))), - TSInfo(DL), InstrInfo(MipsInstrInfo::create(*this)), + IsLittle(little), IsSingleFloat(false), IsFPXX(false), NoABICalls(false), + IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false), + IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasMips3_32(false), + HasMips3_32r2(false), HasMips4_32(false), HasMips4_32r2(false), + HasMips5_32r2(false), InMips16Mode(false), + InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), + HasDSPR2(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), + HasMSA(false), TM(TM), TargetTriple(TT), TSInfo(*TM.getDataLayout()), + InstrInfo( + MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), FrameLowering(MipsFrameLowering::create(*this)), - TLInfo(MipsTargetLowering::create(*TM, *this)) { + TLInfo(MipsTargetLowering::create(TM, *this)) { PreviousInMips16Mode = InMips16Mode; if (MipsArchVersion == MipsDefault) MipsArchVersion = Mips32; - // Don't even attempt to generate code for MIPS-I, MIPS-III and MIPS-V. - // They have not been tested and currently exist for the integrated - // assembler only. + // Don't even attempt to generate code for MIPS-I and MIPS-V. They have not + // been tested and currently exist for the integrated assembler only. if (MipsArchVersion == Mips1) report_fatal_error("Code generation for MIPS-I is not implemented", false); - if (MipsArchVersion == Mips3) - report_fatal_error("Code generation for MIPS-III is not implemented", - false); if (MipsArchVersion == Mips5) report_fatal_error("Code generation for MIPS-V is not implemented", false); - // Assert exactly one ABI was chosen. - assert(ABI.IsKnown()); - assert((((getFeatureBits() & Mips::FeatureO32) != 0) + - ((getFeatureBits() & Mips::FeatureEABI) != 0) + - ((getFeatureBits() & Mips::FeatureN32) != 0) + - ((getFeatureBits() & Mips::FeatureN64) != 0)) == 1); - // Check if Architecture and ABI are compatible. assert(((!isGP64bit() && (isABI_O32() || isABI_EABI())) || (isGP64bit() && (isABI_N32() || isABI_N64()))) && @@ -172,11 +113,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, report_fatal_error(ISA + " is not compatible with the DSP ASE", false); } - // Is the target system Linux ? - if (TT.find("linux") == std::string::npos) - IsLinux = false; - - if (NoABICalls && TM->getRelocationModel() == Reloc::PIC_) + if (NoABICalls && TM.getRelocationModel() == Reloc::PIC_) report_fatal_error("position-independent code requires '-mabicalls'"); // Set UseSmallSection. @@ -203,22 +140,22 @@ CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const { MipsSubtarget & MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine *TM) { - std::string CPUName = selectMipsCPU(TargetTriple, CPU); - + const TargetMachine &TM) { + std::string CPUName = MIPS_MC::selectMipsCPU(TM.getTargetTriple(), CPU); + // Parse features string. ParseSubtargetFeatures(CPUName, FS); // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); - if (InMips16Mode && !TM->Options.UseSoftFloat) + if (InMips16Mode && !TM.Options.UseSoftFloat) InMips16HardFloat = true; return *this; } bool MipsSubtarget::abiUsesSoftFloat() const { - return TM->Options.UseSoftFloat && !InMips16HardFloat; + return TM.Options.UseSoftFloat && !InMips16HardFloat; } bool MipsSubtarget::useConstantIslands() { @@ -227,5 +164,11 @@ bool MipsSubtarget::useConstantIslands() { } Reloc::Model MipsSubtarget::getRelocationModel() const { - return TM->getRelocationModel(); + return TM.getRelocationModel(); } + +bool MipsSubtarget::isABI_EABI() const { return getABI().IsEABI(); } +bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); } +bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); } +bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); } +const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); } diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index bff9013..faded8a 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -14,6 +14,7 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSSUBTARGET_H #define LLVM_LIB_TARGET_MIPS_MIPSSUBTARGET_H +#include "MCTargetDesc/MipsABIInfo.h" #include "MipsFrameLowering.h" #include "MipsISelLowering.h" #include "MipsInstrInfo.h" @@ -22,7 +23,6 @@ #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetSubtargetInfo.h" -#include "MipsABIInfo.h" #include <string> #define GET_SUBTARGETINFO_HEADER @@ -38,16 +38,13 @@ class MipsSubtarget : public MipsGenSubtargetInfo { enum MipsArchEnum { MipsDefault, - Mips1, Mips2, Mips32, Mips32r2, Mips32r6, Mips3, Mips4, Mips5, Mips64, - Mips64r2, Mips64r6 + Mips1, Mips2, Mips32, Mips32r2, Mips32r3, Mips32r5, Mips32r6, Mips32Max, + Mips3, Mips4, Mips5, Mips64, Mips64r2, Mips64r3, Mips64r5, Mips64r6 }; // Mips architecture version MipsArchEnum MipsArchVersion; - // Selected ABI - MipsABIInfo ABI; - // IsLittle - The target is Little Endian bool IsLittle; @@ -136,11 +133,10 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // as from the command line enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode; - const MipsTargetMachine *TM; + const MipsTargetMachine &TM; Triple TargetTriple; - const DataLayout DL; // Calculates type size & alignment const MipsSelectionDAGInfo TSInfo; std::unique_ptr<const MipsInstrInfo> InstrInfo; std::unique_ptr<const MipsFrameLowering> FrameLowering; @@ -153,18 +149,18 @@ public: CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override; /// Only O32 and EABI supported right now. - bool isABI_EABI() const { return ABI.IsEABI(); } - bool isABI_N64() const { return ABI.IsN64(); } - bool isABI_N32() const { return ABI.IsN32(); } - bool isABI_O32() const { return ABI.IsO32(); } + bool isABI_EABI() const; + bool isABI_N64() const; + bool isABI_N32() const; + bool isABI_O32() const; + const MipsABIInfo &getABI() const; bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } - const MipsABIInfo &getABI() const { return ABI; } /// This constructor initializes the data members to match that /// of the specified triple. MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little, - const MipsTargetMachine *TM); + const MipsTargetMachine &TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. @@ -178,21 +174,30 @@ public: bool hasMips4_32() const { return HasMips4_32; } bool hasMips4_32r2() const { return HasMips4_32r2; } bool hasMips32() const { - return MipsArchVersion >= Mips32 && MipsArchVersion != Mips3 && - MipsArchVersion != Mips4 && MipsArchVersion != Mips5; + return (MipsArchVersion >= Mips32 && MipsArchVersion < Mips32Max) || + hasMips64(); } bool hasMips32r2() const { - return MipsArchVersion == Mips32r2 || MipsArchVersion == Mips32r6 || - MipsArchVersion == Mips64r2 || MipsArchVersion == Mips64r6; + return (MipsArchVersion >= Mips32r2 && MipsArchVersion < Mips32Max) || + hasMips64r2(); + } + bool hasMips32r3() const { + return (MipsArchVersion >= Mips32r3 && MipsArchVersion < Mips32Max) || + hasMips64r2(); + } + bool hasMips32r5() const { + return (MipsArchVersion >= Mips32r5 && MipsArchVersion < Mips32Max) || + hasMips64r2(); } bool hasMips32r6() const { - return MipsArchVersion == Mips32r6 || MipsArchVersion == Mips64r6; + return (MipsArchVersion >= Mips32r6 && MipsArchVersion < Mips32Max) || + hasMips64r6(); } bool hasMips64() const { return MipsArchVersion >= Mips64; } - bool hasMips64r2() const { - return MipsArchVersion == Mips64r2 || MipsArchVersion == Mips64r6; - } - bool hasMips64r6() const { return MipsArchVersion == Mips64r6; } + bool hasMips64r2() const { return MipsArchVersion >= Mips64r2; } + bool hasMips64r3() const { return MipsArchVersion >= Mips64r3; } + bool hasMips64r5() const { return MipsArchVersion >= Mips64r5; } + bool hasMips64r6() const { return MipsArchVersion >= Mips64r6; } bool hasCnMips() const { return HasCnMips; } @@ -223,7 +228,6 @@ public: bool hasDSP() const { return HasDSP; } bool hasDSPR2() const { return HasDSPR2; } bool hasMSA() const { return HasMSA; } - bool isLinux() const { return IsLinux; } bool useSmallSection() const { return UseSmallSection; } bool hasStandardEncoding() const { return !inMips16Mode(); } @@ -239,9 +243,9 @@ public: bool hasMTHC1() const { return hasMips32r2(); } bool allowMixed16_32() const { return inMips16ModeDefault() | - AllowMixed16_32;} + AllowMixed16_32; } - bool os16() const { return Os16;}; + bool os16() const { return Os16; } bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } @@ -255,7 +259,7 @@ public: Reloc::Model getRelocationModel() const; MipsSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine *TM); + const TargetMachine &TM); /// Does the system support unaligned memory access. /// @@ -271,7 +275,6 @@ public: const MipsSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; } - const DataLayout *getDataLayout() const override { return &DL; } const MipsInstrInfo *getInstrInfo() const override { return InstrInfo.get(); } const TargetFrameLowering *getFrameLowering() const override { return FrameLowering.get(); diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 33280e3..86c8931 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -29,7 +29,7 @@ #include "MipsTargetObjectFile.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" @@ -46,6 +46,36 @@ extern "C" void LLVMInitializeMipsTarget() { RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget); } +static std::string computeDataLayout(bool isLittle, MipsABIInfo &ABI) { + std::string Ret = ""; + + // There are both little and big endian mips. + if (isLittle) + Ret += "e"; + else + Ret += "E"; + + Ret += "-m:m"; + + // Pointers are 32 bit on some ABIs. + if (!ABI.IsN64()) + Ret += "-p:32:32"; + + // 8 and 16 bit integers only need no have natural alignment, but try to + // align them to 32 bits. 64 bit integers have natural alignment. + Ret += "-i8:8:32-i16:16:32-i64:64"; + + // 32 bit registers are always available and the stack is at least 64 bit + // aligned. On N64 64 bit registers are also available and the stack is + // 128 bit aligned. + if (ABI.IsN64() || ABI.IsN32()) + Ret += "-n32:64-S128"; + else + Ret += "-n32-S64"; + + return Ret; +} + // On function prologue, the stack is created by decrementing // its pointer. Once decremented, all references are done with positive // offset from the stack/frame pointer, using StackGrowsUp enables @@ -57,14 +87,14 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle) : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - isLittle(isLittle), - TLOF(make_unique<MipsTargetObjectFile>()), - Subtarget(nullptr), - DefaultSubtarget(TT, CPU, FS, isLittle, this), + isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()), + ABI(MipsABIInfo::computeTargetABI(Triple(TT), CPU, Options.MCOptions)), + DL(computeDataLayout(isLittle, ABI)), Subtarget(nullptr), + DefaultSubtarget(TT, CPU, FS, isLittle, *this), NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", - isLittle, this), + isLittle, *this), Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", - isLittle, this) { + isLittle, *this) { Subtarget = &DefaultSubtarget; initAsmInfo(); } @@ -91,11 +121,8 @@ MipselTargetMachine(const Target &T, StringRef TT, const MipsSubtarget * MipsTargetMachine::getSubtargetImpl(const Function &F) const { - AttributeSet FnAttrs = F.getAttributes(); - Attribute CPUAttr = - FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu"); - Attribute FSAttr = - FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features"); + Attribute CPUAttr = F.getFnAttribute("target-cpu"); + Attribute FSAttr = F.getFnAttribute("target-features"); std::string CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString().str() @@ -104,19 +131,16 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const { ? FSAttr.getValueAsString().str() : TargetFS; bool hasMips16Attr = - !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "mips16") - .hasAttribute(Attribute::None); + !F.getFnAttribute("mips16").hasAttribute(Attribute::None); bool hasNoMips16Attr = - !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "nomips16") - .hasAttribute(Attribute::None); + !F.getFnAttribute("nomips16").hasAttribute(Attribute::None); // FIXME: This is related to the code below to reset the target options, // we need to know whether or not the soft float flag is set on the // function before we can generate a subtarget. We also need to use // it as a key for the subtarget since that can be the only difference // between two functions. - Attribute SFAttr = - FnAttrs.getAttribute(AttributeSet::FunctionIndex, "use-soft-float"); + Attribute SFAttr = F.getFnAttribute("use-soft-float"); bool softFloat = !SFAttr.hasAttribute(Attribute::None) ? SFAttr.getValueAsString() == "true" : Options.UseSoftFloat; @@ -133,7 +157,7 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const { // creation will depend on the TM and the code generation flags on the // function that reside in TargetOptions. resetTargetOptions(F); - I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, this); + I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, *this); } return I.get(); } @@ -170,9 +194,9 @@ public: void addIRPasses() override; bool addInstSelector() override; void addMachineSSAOptimization() override; - bool addPreEmitPass() override; + void addPreEmitPass() override; - bool addPreRegAlloc() override; + void addPreRegAlloc() override; }; } // namespace @@ -203,35 +227,30 @@ void MipsPassConfig::addMachineSSAOptimization() { TargetPassConfig::addMachineSSAOptimization(); } -bool MipsPassConfig::addPreRegAlloc() { - if (getOptLevel() == CodeGenOpt::None) { +void MipsPassConfig::addPreRegAlloc() { + if (getOptLevel() == CodeGenOpt::None) addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); - return true; - } - else - return false; } -void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) { - if (Subtarget->allowMixed16_32()) { - DEBUG(errs() << "No "); - //FIXME: The Basic Target Transform Info - // pass needs to become a function pass instead of - // being an immutable pass and then this method as it exists now - // would be unnecessary. - PM.add(createNoTargetTransformInfoPass()); - } else - LLVMTargetMachine::addAnalysisPasses(PM); - DEBUG(errs() << "Target Transform Info Pass Added\n"); +TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() { + return TargetIRAnalysis([this](Function &F) { + if (Subtarget->allowMixed16_32()) { + DEBUG(errs() << "No Target Transform Info Pass Added\n"); + // FIXME: This is no longer necessary as the TTI returned is per-function. + return TargetTransformInfo(getDataLayout()); + } + + DEBUG(errs() << "Target Transform Info Pass Added\n"); + return TargetTransformInfo(BasicTTIImpl(this, F)); + }); } // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. -bool MipsPassConfig::addPreEmitPass() { +void MipsPassConfig::addPreEmitPass() { MipsTargetMachine &TM = getMipsTargetMachine(); addPass(createMipsDelaySlotFillerPass(TM)); addPass(createMipsLongBranchPass(TM)); addPass(createMipsConstantIslandPass(TM)); - return true; } diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 1349f82..afd0cea 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -14,7 +14,9 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H #define LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H +#include "MCTargetDesc/MipsABIInfo.h" #include "MipsSubtarget.h" +#include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Target/TargetFrameLowering.h" @@ -27,6 +29,9 @@ class MipsRegisterInfo; class MipsTargetMachine : public LLVMTargetMachine { bool isLittle; std::unique_ptr<TargetLoweringObjectFile> TLOF; + // Selected ABI + MipsABIInfo ABI; + const DataLayout DL; // Calculates type size & alignment MipsSubtarget *Subtarget; MipsSubtarget DefaultSubtarget; MipsSubtarget NoMips16Subtarget; @@ -40,8 +45,9 @@ public: CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle); ~MipsTargetMachine() override; - void addAnalysisPasses(PassManagerBase &PM) override; + TargetIRAnalysis getTargetIRAnalysis() override; + const DataLayout *getDataLayout() const override { return &DL; } const MipsSubtarget *getSubtargetImpl() const override { if (Subtarget) return Subtarget; @@ -59,6 +65,9 @@ public: TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } + + bool isLittleEndian() const { return isLittle; } + const MipsABIInfo &getABI() const { return ABI; } }; /// MipsebTargetMachine - Mips32/64 big endian target machine. diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index b56c39b..c07693e 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -39,15 +39,11 @@ void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); InitializeELF(TM.Options.UseInitArray); - SmallDataSection = - getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getDataRel()); - - SmallBSSSection = - getContext().getELFSection(".sbss", ELF::SHT_NOBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getBSS()); + SmallDataSection = getContext().getELFSection( + ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); + + SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC); this->TM = &TM; } @@ -109,8 +105,7 @@ IsGlobalInSmallSectionImpl(const GlobalValue *GV, return false; Type *Ty = GV->getType()->getElementType(); - return IsInSmallSection( - TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(Ty)); + return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty)); } const MCSection *MipsTargetObjectFile:: @@ -132,10 +127,9 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, /// Return true if this constant should be placed into small data section. bool MipsTargetObjectFile:: IsConstantInSmallSection(const Constant *CN, const TargetMachine &TM) const { - return (TM.getSubtarget<MipsSubtarget>().useSmallSection() && - LocalSData && - IsInSmallSection(TM.getSubtargetImpl()->getDataLayout() - ->getTypeAllocSize(CN->getType()))); + return ( + TM.getSubtarget<MipsSubtarget>().useSmallSection() && LocalSData && + IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(CN->getType()))); } const MCSection *MipsTargetObjectFile:: diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index c1f17933..b3b8296 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -10,10 +10,11 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H #define LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H +#include "MCTargetDesc/MipsABIFlagsSection.h" +#include "MCTargetDesc/MipsABIInfo.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" -#include "MCTargetDesc/MipsABIFlagsSection.h" namespace llvm { @@ -34,6 +35,7 @@ public: virtual void emitDirectiveSetMsa(); virtual void emitDirectiveSetNoMsa(); virtual void emitDirectiveSetAt(); + virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); virtual void emitDirectiveEnd(StringRef Name); @@ -57,9 +59,13 @@ public: virtual void emitDirectiveSetMips5(); virtual void emitDirectiveSetMips32(); virtual void emitDirectiveSetMips32R2(); + virtual void emitDirectiveSetMips32R3(); + virtual void emitDirectiveSetMips32R5(); virtual void emitDirectiveSetMips32R6(); virtual void emitDirectiveSetMips64(); virtual void emitDirectiveSetMips64R2(); + virtual void emitDirectiveSetMips64R3(); + virtual void emitDirectiveSetMips64R5(); virtual void emitDirectiveSetMips64R6(); virtual void emitDirectiveSetDsp(); virtual void emitDirectiveSetNoDsp(); @@ -95,12 +101,18 @@ public: // structure values. template <class PredicateLibrary> void updateABIInfo(const PredicateLibrary &P) { + ABI = &P.getABI(); ABIFlagsSection.setAllFromPredicates(P); } MipsABIFlagsSection &getABIFlagsSection() { return ABIFlagsSection; } + const MipsABIInfo &getABI() const { + assert(ABI && "ABI hasn't been set!"); + return *ABI; + } protected: + const MipsABIInfo *ABI; MipsABIFlagsSection ABIFlagsSection; bool GPRInfoSet; @@ -138,6 +150,7 @@ public: void emitDirectiveSetMsa() override; void emitDirectiveSetNoMsa() override; void emitDirectiveSetAt() override; + void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; void emitDirectiveEnd(StringRef Name) override; @@ -161,9 +174,13 @@ public: void emitDirectiveSetMips5() override; void emitDirectiveSetMips32() override; void emitDirectiveSetMips32R2() override; + void emitDirectiveSetMips32R3() override; + void emitDirectiveSetMips32R5() override; void emitDirectiveSetMips32R6() override; void emitDirectiveSetMips64() override; void emitDirectiveSetMips64R2() override; + void emitDirectiveSetMips64R3() override; + void emitDirectiveSetMips64R5() override; void emitDirectiveSetMips64R6() override; void emitDirectiveSetDsp() override; void emitDirectiveSetNoDsp() override; @@ -224,11 +241,6 @@ public: // ABI Flags void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI) override; void emitMipsAbiFlags() override; - -protected: - bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; } - bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; } - bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; } }; } #endif |