diff options
Diffstat (limited to 'lib/Target/Mips')
105 files changed, 5369 insertions, 2200 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 2d65b08846c7..7db5b34204c3 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -12,6 +12,7 @@ #include "MipsRegisterInfo.h" #include "MipsTargetStreamer.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -25,7 +26,9 @@ #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" +#include <memory> using namespace llvm; @@ -38,36 +41,69 @@ class MCInstrInfo; namespace { class MipsAssemblerOptions { public: - MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {} + MipsAssemblerOptions(uint64_t Features_) : + ATReg(1), Reorder(true), Macro(true), Features(Features_) {} - unsigned getATRegNum() { return aTReg; } - bool setATReg(unsigned Reg); + MipsAssemblerOptions(const MipsAssemblerOptions *Opts) { + ATReg = Opts->getATRegNum(); + Reorder = Opts->isReorder(); + Macro = Opts->isMacro(); + Features = Opts->getFeatures(); + } - bool isReorder() { return reorder; } - void setReorder() { reorder = true; } - void setNoreorder() { reorder = false; } + unsigned getATRegNum() const { return ATReg; } + bool setATReg(unsigned Reg); - bool isMacro() { return macro; } - void setMacro() { macro = true; } - void setNomacro() { macro = false; } + bool isReorder() const { return Reorder; } + void setReorder() { Reorder = true; } + void setNoReorder() { Reorder = false; } + + bool isMacro() const { return Macro; } + void setMacro() { Macro = true; } + void setNoMacro() { Macro = false; } + + uint64_t getFeatures() const { return Features; } + void setFeatures(uint64_t Features_) { Features = Features_; } + + // Set of features that are either architecture features or referenced + // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6). + // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). + // The reason we need this mask is explained in the selectArch function. + // FIXME: Ideally we would like TableGen to generate this information. + static const uint64_t AllArchRelatedMask = + Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 | + 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; private: - unsigned aTReg; - bool reorder; - bool macro; + unsigned ATReg; + bool Reorder; + bool Macro; + uint64_t Features; }; } namespace { class MipsAsmParser : public MCTargetAsmParser { MipsTargetStreamer &getTargetStreamer() { - MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer(); + MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); return static_cast<MipsTargetStreamer &>(TS); } MCSubtargetInfo &STI; - MCAsmParser &Parser; - MipsAssemblerOptions Options; + 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 + // selected. This usually happens after an '.end func' + // directive. + + // Print a warning along with its fix-it message at the given range. + void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, + SMRange Range, bool ShowColors = true); #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -76,15 +112,15 @@ class MipsAsmParser : public MCTargetAsmParser { bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) override; /// Parse a register as used in CFI directives bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - bool ParseParenSuffix(StringRef Name, OperandVector &Operands); + bool parseParenSuffix(StringRef Name, OperandVector &Operands); - bool ParseBracketSuffix(StringRef Name, OperandVector &Operands); + bool parseBracketSuffix(StringRef Name, OperandVector &Operands); bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -94,25 +130,31 @@ class MipsAsmParser : public MCTargetAsmParser { MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands); MipsAsmParser::OperandMatchResultTy - MatchAnyRegisterNameWithoutDollar(OperandVector &Operands, + matchAnyRegisterNameWithoutDollar(OperandVector &Operands, StringRef Identifier, SMLoc S); MipsAsmParser::OperandMatchResultTy - MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S); + matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S); - MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands); - MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands); - MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands); MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands); - MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands); + + MipsAsmParser::OperandMatchResultTy + parseRegisterPair (OperandVector &Operands); + + MipsAsmParser::OperandMatchResultTy + parseRegisterList (OperandVector &Operands); bool searchSymbolAlias(OperandVector &Operands); - bool ParseOperand(OperandVector &, StringRef Mnemonic); + bool parseOperand(OperandVector &, StringRef Mnemonic); bool needsExpansion(MCInst &Inst); @@ -130,6 +172,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); + void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd); @@ -142,8 +187,10 @@ class MipsAsmParser : public MCTargetAsmParser { const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); bool isEvaluated(const MCExpr *Expr); + bool parseSetMips0Directive(); + bool parseSetArchDirective(); bool parseSetFeature(uint64_t Feature); - bool parseDirectiveCPLoad(SMLoc Loc); + bool parseDirectiveCpLoad(SMLoc Loc); bool parseDirectiveCPSetup(); bool parseDirectiveNaN(); bool parseDirectiveSet(); @@ -153,10 +200,16 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetNoAtDirective(); bool parseSetMacroDirective(); bool parseSetNoMacroDirective(); + bool parseSetMsaDirective(); + bool parseSetNoMsaDirective(); + bool parseSetNoDspDirective(); bool parseSetReorderDirective(); bool parseSetNoReorderDirective(); + bool parseSetMips16Directive(); bool parseSetNoMips16Directive(); bool parseSetFpDirective(); + bool parseSetPopDirective(); + bool parseSetPushDirective(); bool parseSetAssignment(); @@ -174,6 +227,8 @@ class MipsAsmParser : public MCTargetAsmParser { int matchCPURegisterName(StringRef Symbol); + int matchHWRegsRegisterName(StringRef Symbol); + int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); int matchFPURegisterName(StringRef Name); @@ -200,11 +255,43 @@ class MipsAsmParser : public MCTargetAsmParser { // Example: INSERT.B $w0[n], $1 => 16 > n >= 0 bool validateMSAIndex(int Val, int RegKind); + // Selects a new architecture by updating the FeatureBits with the necessary + // info including implied dependencies. + // Internally, it clears all the feature bits related to *any* architecture + // and selects the new one using the ToggleFeature functionality of the + // MCSubtargetInfo object that handles implied dependencies. The reason we + // clear all the arch related bits manually is because ToggleFeature only + // clears the features that imply the feature being cleared and not the + // features implied by the feature being cleared. This is easier to see + // with an example: + // -------------------------------------------------- + // | Feature | Implies | + // | -------------------------------------------------| + // | FeatureMips1 | None | + // | FeatureMips2 | FeatureMips1 | + // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 | + // | FeatureMips4 | FeatureMips3 | + // | ... | | + // -------------------------------------------------- + // + // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 | + // FeatureMipsGP64 | FeatureMips1) + // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). + void selectArch(StringRef ArchFeature) { + uint64_t FeatureBits = STI.getFeatureBits(); + FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; + STI.setFeatureBits(FeatureBits); + setAvailableFeatures( + ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature))); + AssemblerOptions.back()->setFeatures(getAvailableFeatures()); + } + void setFeatureBits(uint64_t Feature, StringRef FeatureString) { if (!(STI.getFeatureBits() & Feature)) { setAvailableFeatures( ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); } + AssemblerOptions.back()->setFeatures(getAvailableFeatures()); } void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { @@ -212,6 +299,7 @@ class MipsAsmParser : public MCTargetAsmParser { setAvailableFeatures( ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); } + AssemblerOptions.back()->setFeatures(getAvailableFeatures()); } public: @@ -225,9 +313,19 @@ public: MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII, const MCTargetOptions &Options) - : MCTargetAsmParser(), STI(sti), Parser(parser) { + : MCTargetAsmParser(), STI(sti) { + MCAsmParserExtension::Initialize(parser); + // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + + // Remember the initial assembler options. The user can not modify these. + AssemblerOptions.push_back( + make_unique<MipsAssemblerOptions>(getAvailableFeatures())); + + // Create an assembler options environment for the user to modify. + AssemblerOptions.push_back( + make_unique<MipsAssemblerOptions>(getAvailableFeatures())); getTargetStreamer().updateABIInfo(*this); @@ -239,10 +337,9 @@ public: if (!isABI_O32() && !useOddSPReg() != 0) report_fatal_error("-mno-odd-spreg requires the O32 ABI"); - } - MCAsmParser &getParser() const { return Parser; } - MCAsmLexer &getLexer() const { return Parser.getLexer(); } + CurrentFn = nullptr; + } /// True if all of $fcc0 - $fcc7 exist for the current ISA. bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } @@ -295,7 +392,7 @@ public: bool abiUsesSoftFloat() const { return false; } /// Warn if RegNo is the current assembler temporary. - void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc); + void warnIfAssemblerTemporary(int RegNo, SMLoc Loc); }; } @@ -333,7 +430,9 @@ private: k_Memory, /// Base + Offset Memory Address 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_Token, /// A simple token + k_RegList, /// A physical register list + k_RegPair /// A pair of physical register } Kind; public: @@ -368,12 +467,17 @@ private: const MCExpr *Off; }; + struct RegListOp { + SmallVector<unsigned, 10> *List; + }; + union { struct Token Tok; struct PhysRegOp PhysReg; struct RegIdxOp RegIdx; struct ImmOp Imm; struct MemOp Mem; + struct RegListOp RegList; }; SMLoc StartLoc, EndLoc; @@ -397,7 +501,15 @@ public: /// target. unsigned getGPR32Reg() const { assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc); + AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc); + unsigned ClassID = Mips::GPR32RegClassID; + return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + } + + /// Coerce the register to GPR32 and return the real register for the current + /// target. + unsigned getGPRMM16Reg() const { + assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); unsigned ClassID = Mips::GPR32RegClassID; return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); } @@ -550,6 +662,16 @@ public: Inst.addOperand(MCOperand::CreateReg(getGPR32Reg())); } + void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg())); + } + + void addGPRMM16AsmRegZeroOperands(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 @@ -647,6 +769,29 @@ 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!"); + + for (auto RegNo : getRegList()) + 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)); + } + 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. @@ -672,6 +817,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()) @@ -679,11 +855,13 @@ public: int64_t Val = getConstantImm(); return 1 <= Val && Val <= 4; } + bool isRegList() const { return Kind == k_RegList; } 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 @@ -720,6 +898,16 @@ public: return static_cast<const MCConstantExpr *>(getMemOff())->getValue(); } + const SmallVectorImpl<unsigned> &getRegList() const { + assert((Kind == k_RegList) && "Invalid access!"); + 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); @@ -733,16 +921,16 @@ public: /// Create a numeric register (e.g. $1). The exact register remains /// unresolved until an instruction successfully matches static std::unique_ptr<MipsOperand> - CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, + createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n"); + DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser); } /// Create a register that is definitely a GPR. /// This is typically only used for named registers such as $gp. static std::unique_ptr<MipsOperand> - CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser); } @@ -750,15 +938,23 @@ public: /// Create a register that is definitely a FGR. /// This is typically only used for named registers such as $f0. static std::unique_ptr<MipsOperand> - CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser); } + /// Create a register that is definitely a HWReg. + /// This is typically only used for named registers such as $hwr_cpunum. + static std::unique_ptr<MipsOperand> + createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo, + SMLoc S, SMLoc E, MipsAsmParser &Parser) { + return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser); + } + /// Create a register that is definitely an FCC. /// This is typically only used for named registers such as $fcc0. static std::unique_ptr<MipsOperand> - CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser); } @@ -766,7 +962,7 @@ public: /// Create a register that is definitely an ACC. /// This is typically only used for named registers such as $ac0. static std::unique_ptr<MipsOperand> - CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser); } @@ -774,7 +970,7 @@ public: /// Create a register that is definitely an MSA128. /// This is typically only used for named registers such as $w0. static std::unique_ptr<MipsOperand> - CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, + createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser); } @@ -782,7 +978,7 @@ public: /// Create a register that is definitely an MSACtrl. /// This is typically only used for named registers such as $msaaccess. static std::unique_ptr<MipsOperand> - CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, + createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser); } @@ -807,9 +1003,45 @@ public: return Op; } + static std::unique_ptr<MipsOperand> + CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc, + MipsAsmParser &Parser) { + 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->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; } + bool isMM16AsmReg() const { + if (!(isRegIdx() && RegIdx.Kind)) + return false; + 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 isFGRAsmReg() const { // AFGR64 is $0-$15 but we handle this in getAFGR64() return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; @@ -855,9 +1087,12 @@ public: case k_Memory: delete Mem.Base; break; + case k_RegList: + delete RegList.List; case k_PhysRegister: case k_RegisterIndex: case k_Token: + case k_RegPair: break; } } @@ -885,6 +1120,15 @@ public: case k_Token: OS << Tok.Data; break; + case k_RegList: + OS << "RegList< "; + for (auto Reg : (*RegList.List)) + OS << Reg << " "; + OS << ">"; + break; + case k_RegPair: + OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; + break; } } }; // class MipsOperand @@ -897,6 +1141,19 @@ static const MCInstrDesc &getInstDesc(unsigned Opcode) { return MipsInsts[Opcode]; } +static bool hasShortDelaySlot(unsigned Opcode) { + switch (Opcode) { + case Mips::JALS_MM: + case Mips::JALRS_MM: + case Mips::JALRS16_MM: + case Mips::BGEZALS_MM: + case Mips::BLTZALS_MM: + return true; + default: + return false; + } +} + bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); @@ -950,6 +1207,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; } } @@ -961,15 +1229,21 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, "nop instruction"); } - if (MCID.hasDelaySlot() && Options.isReorder()) { + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { // If this instruction has a delay slot and .set reorder is active, // emit a NOP after it. Instructions.push_back(Inst); MCInst NopInst; - NopInst.setOpcode(Mips::SLL); - NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::CreateImm(0)); + if (hasShortDelaySlot(Inst.getOpcode())) { + NopInst.setOpcode(Mips::MOVE16_MM); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + } else { + 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; } @@ -1008,6 +1282,123 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } // for } // if load/store + // TODO: Handle this with the AsmOperandClass.PredicateMethod. + if (inMicroMipsMode()) { + MCOperand Opnd; + int Imm; + + switch (Inst.getOpcode()) { + default: + break; + case Mips::ADDIUS5_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -8 || Imm > 7) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::ADDIUSP_MM: + Opnd = Inst.getOperand(0); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) || + Imm % 4 != 0) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::SLL16_MM: + case Mips::SRL16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 1 || Imm > 8) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LI16_MM: + Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -1 || Imm > 126) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::ADDIUR2_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!(Imm == 1 || Imm == -1 || + ((Imm % 4 == 0) && Imm < 28 && Imm > 0))) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::ADDIUR1SP_MM: + Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (OffsetToAlignment(Imm, 4LL)) + return Error(IDLoc, "misaligned immediate operand value"); + if (Imm < 0 || Imm > 255) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::ANDI16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || + Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || + 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; + } + } + if (needsExpansion(Inst)) return expandInstruction(Inst, IDLoc, Instructions); else @@ -1032,14 +1423,12 @@ 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: if (!isGP64bit()) { - Error(IDLoc, "instruction requires a CPU feature not currently enabled"); + Error(IDLoc, "instruction requires a 64-bit architecture"); return true; } return expandLoadImm(Inst, IDLoc, Instructions); @@ -1051,8 +1440,8 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, } namespace { -template <int Shift, bool PerformShift> -void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc, +template <bool PerformShift> +void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; if (PerformShift) { @@ -1067,11 +1456,18 @@ void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc, tmpInst.setOpcode(Mips::ORi); tmpInst.addOperand(MCOperand::CreateReg(RegNo)); tmpInst.addOperand(MCOperand::CreateReg(RegNo)); - tmpInst.addOperand( - MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift))); + tmpInst.addOperand(Operand); tmpInst.setLoc(IDLoc); Instructions.push_back(tmpInst); } + +template <int Shift, bool PerformShift> +void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + createShiftOr<PerformShift>( + MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo, + IDLoc, Instructions); +} } bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, @@ -1114,7 +1510,7 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions); } else if ((ImmValue & (0xffffLL << 48)) == 0) { if (!isGP64bit()) { - Error(IDLoc, "instruction requires a CPU feature not currently enabled"); + Error(IDLoc, "instruction requires a 64-bit architecture"); return true; } @@ -1141,7 +1537,7 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions); } else { if (!isGP64bit()) { - Error(IDLoc, "instruction requires a CPU feature not currently enabled"); + Error(IDLoc, "instruction requires a 64-bit architecture"); return true; } @@ -1176,7 +1572,12 @@ MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(2); - assert(ImmOp.isImm() && "expected immediate operand kind"); + assert((ImmOp.isImm() || ImmOp.isExpr()) && + "expected immediate operand kind"); + if (!ImmOp.isImm()) { + expandLoadAddressSym(Inst, IDLoc, Instructions); + return false; + } const MCOperand &SrcRegOp = Inst.getOperand(1); assert(SrcRegOp.isReg() && "expected register operand kind"); const MCOperand &DstRegOp = Inst.getOperand(0); @@ -1220,7 +1621,12 @@ MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(1); - assert(ImmOp.isImm() && "expected immediate operand kind"); + assert((ImmOp.isImm() || ImmOp.isExpr()) && + "expected immediate operand kind"); + if (!ImmOp.isImm()) { + expandLoadAddressSym(Inst, IDLoc, Instructions); + return false; + } const MCOperand &RegOp = Inst.getOperand(0); assert(RegOp.isReg() && "expected register operand kind"); int ImmValue = ImmOp.getImm(); @@ -1250,6 +1656,71 @@ MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, return false; } +void +MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + // FIXME: If we do have a valid at register to use, we should generate a + // slightly shorter sequence here. + MCInst tmpInst; + int ExprOperandNo = 1; + // Sometimes the assembly parser will get the immediate expression as + // a $zero + an immediate. + if (Inst.getNumOperands() == 3) { + assert(Inst.getOperand(1).getReg() == + (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO)); + ExprOperandNo = 2; + } + const MCOperand &SymOp = Inst.getOperand(ExprOperandNo); + assert(SymOp.isExpr() && "expected symbol operand kind"); + const MCOperand &RegOp = Inst.getOperand(0); + unsigned RegNo = RegOp.getReg(); + const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr()); + const MCSymbolRefExpr *HiExpr = + MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::VK_Mips_ABS_HI, getContext()); + const MCSymbolRefExpr *LoExpr = + MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::VK_Mips_ABS_LO, getContext()); + if (isGP64bit()) { + // If it's a 64-bit architecture, expand to: + // la d,sym => lui d,highest(sym) + // ori d,d,higher(sym) + // dsll d,d,16 + // ori d,d,hi16(sym) + // dsll d,d,16 + // ori d,d,lo16(sym) + const MCSymbolRefExpr *HighestExpr = + MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::VK_Mips_HIGHEST, getContext()); + const MCSymbolRefExpr *HigherExpr = + MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::VK_Mips_HIGHER, getContext()); + + tmpInst.setOpcode(Mips::LUi); + tmpInst.addOperand(MCOperand::CreateReg(RegNo)); + tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr)); + Instructions.push_back(tmpInst); + + createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(), + Instructions); + createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(), + Instructions); + createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(), + Instructions); + } else { + // Otherwise, expand to: + // la d,sym => lui d,hi16(sym) + // ori d,d,lo16(sym) + tmpInst.setOpcode(Mips::LUi); + tmpInst.addOperand(MCOperand::CreateReg(RegNo)); + tmpInst.addOperand(MCOperand::CreateExpr(HiExpr)); + Instructions.push_back(tmpInst); + + createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(), + Instructions); + } +} + void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) { @@ -1381,7 +1852,7 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) { MCInst Inst; @@ -1390,8 +1861,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; @@ -1404,7 +1873,7 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return true; case Match_InvalidOperand: { SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0U) { + if (ErrorInfo != ~0ULL) { if (ErrorInfo >= Operands.size()) return Error(IDLoc, "too few operands for instruction"); @@ -1420,19 +1889,29 @@ 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) { - if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) { +void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) { + if ((RegIndex != 0) && + ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) { if (RegIndex == 1) - Warning(Loc, "Used $at without \".set noat\""); + Warning(Loc, "used $at without \".set noat\""); else - Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" + + Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" + Twine(RegIndex) + "\""); } } +void +MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, + SMRange Range, bool ShowColors) { + getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg, + Range, SMFixIt(Range, FixMsg), + ShowColors); +} + int MipsAsmParser::matchCPURegisterName(StringRef Name) { int CC; @@ -1472,23 +1951,55 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { .Case("t9", 25) .Default(-1); - if (isABI_N32() || isABI_N64()) { - // Although SGI documentation just cuts out t0-t3 for n32/n64, - // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 - // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. - if (8 <= CC && CC <= 11) - CC += 4; + if (!(isABI_N32() || isABI_N64())) + return CC; + + if (12 <= CC && CC <= 15) { + // Name is one of t4-t7 + AsmToken RegTok = getLexer().peekTok(); + SMRange RegRange = RegTok.getLocRange(); + + StringRef FixedName = StringSwitch<StringRef>(Name) + .Case("t4", "t0") + .Case("t5", "t1") + .Case("t6", "t2") + .Case("t7", "t3") + .Default(""); + assert(FixedName != "" && "Register name is not one of t4-t7."); + + printWarningWithFixIt("register names $t4-$t7 are only available in O32.", + "Did you mean $" + FixedName + "?", RegRange); + } + + // Although SGI documentation just cuts out t0-t3 for n32/n64, + // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 + // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. + if (8 <= CC && CC <= 11) + CC += 4; + + if (CC == -1) + CC = StringSwitch<unsigned>(Name) + .Case("a4", 8) + .Case("a5", 9) + .Case("a6", 10) + .Case("a7", 11) + .Case("kt0", 26) + .Case("kt1", 27) + .Default(-1); - if (CC == -1) - CC = StringSwitch<unsigned>(Name) - .Case("a4", 8) - .Case("a5", 9) - .Case("a6", 10) - .Case("a7", 11) - .Case("kt0", 26) - .Case("kt1", 27) - .Default(-1); - } + return CC; +} + +int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) { + int CC; + + CC = StringSwitch<unsigned>(Name) + .Case("hwr_cpunum", 0) + .Case("hwr_synci_step", 1) + .Case("hwr_cc", 2) + .Case("hwr_ccres", 3) + .Case("hwr_ulr", 29) + .Default(-1); return CC; } @@ -1568,15 +2079,15 @@ bool MipsAssemblerOptions::setATReg(unsigned Reg) { if (Reg > 31) return false; - aTReg = Reg; + ATReg = Reg; return true; } int MipsAsmParser::getATReg(SMLoc Loc) { - int AT = Options.getATRegNum(); + int AT = AssemblerOptions.back()->getATRegNum(); if (AT == 0) reportParseError(Loc, - "Pseudo instruction requires $at, which is not available"); + "pseudo-instruction requires $at, which is not available"); return AT; } @@ -1597,8 +2108,9 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { return getReg(RegClass, RegNum); } -bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) { - DEBUG(dbgs() << "ParseOperand\n"); +bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { + MCAsmParser &Parser = getParser(); + DEBUG(dbgs() << "parseOperand\n"); // Check if the current operand has a custom associated parser, if so, try to // custom parse the operand, or fallback to the general approach. @@ -1626,7 +2138,7 @@ bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) { // for div, divu, and similar instructions because it is not an operand // to the instruction definition but an explicit register. Special case // this situation for now. - if (ParseAnyRegister(Operands) != MatchOperand_NoMatch) + if (parseAnyRegister(Operands) != MatchOperand_NoMatch) return false; // Maybe it is a symbol reference. @@ -1651,7 +2163,7 @@ bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) { case AsmToken::Tilde: case AsmToken::String: { DEBUG(dbgs() << ".. generic integer\n"); - OperandMatchResultTy ResTy = ParseImm(Operands); + OperandMatchResultTy ResTy = parseImm(Operands); return ResTy != MatchOperand_Success; } case AsmToken::Percent: { @@ -1696,7 +2208,7 @@ const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff; break; default: - report_fatal_error("Unsupported reloc value!"); + report_fatal_error("unsupported reloc value"); } return MCConstantExpr::Create(Val, getContext()); } @@ -1753,6 +2265,7 @@ bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { } bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { + MCAsmParser &Parser = getParser(); Parser.Lex(); // Eat the % token. const AsmToken &Tok = Parser.getTok(); // Get next token, operation. if (Tok.isNot(AsmToken::Identifier)) @@ -1797,7 +2310,7 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; - OperandMatchResultTy ResTy = ParseAnyRegister(Operands); + OperandMatchResultTy ResTy = parseAnyRegister(Operands); if (ResTy == MatchOperand_Success) { assert(Operands.size() == 1); MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front()); @@ -1821,6 +2334,7 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, } bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { + MCAsmParser &Parser = getParser(); SMLoc S; bool Result = true; @@ -1850,6 +2364,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); DEBUG(dbgs() << "parseMemOperand\n"); const MCExpr *IdVal = nullptr; SMLoc S; @@ -1882,7 +2397,7 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { // Zero register assumed, add a memory operand with ZERO as its base. // "Base" will be managed by k_Memory. - auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(), + auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(), S, E, *this); Operands.push_back( MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this)); @@ -1895,7 +2410,7 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { Parser.Lex(); // Eat the '(' token. } - Res = ParseAnyRegister(Operands); + Res = parseAnyRegister(Operands); if (Res != MatchOperand_Success) return Res; @@ -1932,7 +2447,7 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { } bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { - + MCAsmParser &Parser = getParser(); MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); if (Sym) { SMLoc S = Parser.getTok().getLoc(); @@ -1943,10 +2458,10 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { return false; if (Expr->getKind() == MCExpr::SymbolRef) { const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); - const StringRef DefSymbol = Ref->getSymbol().getName(); + StringRef DefSymbol = Ref->getSymbol().getName(); if (DefSymbol.startswith("$")) { OperandMatchResultTy ResTy = - MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); + matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); if (ResTy == MatchOperand_Success) { Parser.Lex(); return true; @@ -1966,47 +2481,54 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands, +MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands, StringRef Identifier, SMLoc S) { int Index = matchCPURegisterName(Identifier); if (Index != -1) { - Operands.push_back(MipsOperand::CreateGPRReg( + Operands.push_back(MipsOperand::createGPRReg( + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + return MatchOperand_Success; + } + + Index = matchHWRegsRegisterName(Identifier); + if (Index != -1) { + Operands.push_back(MipsOperand::createHWRegsReg( Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchFPURegisterName(Identifier); if (Index != -1) { - Operands.push_back(MipsOperand::CreateFGRReg( + Operands.push_back(MipsOperand::createFGRReg( Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchFCCRegisterName(Identifier); if (Index != -1) { - Operands.push_back(MipsOperand::CreateFCCReg( + Operands.push_back(MipsOperand::createFCCReg( Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchACRegisterName(Identifier); if (Index != -1) { - Operands.push_back(MipsOperand::CreateACCReg( + Operands.push_back(MipsOperand::createACCReg( Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchMSA128RegisterName(Identifier); if (Index != -1) { - Operands.push_back(MipsOperand::CreateMSA128Reg( + Operands.push_back(MipsOperand::createMSA128Reg( Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchMSA128CtrlRegisterName(Identifier); if (Index != -1) { - Operands.push_back(MipsOperand::CreateMSACtrlReg( + Operands.push_back(MipsOperand::createMSACtrlReg( Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } @@ -2015,18 +2537,19 @@ MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands, } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { +MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { + MCAsmParser &Parser = getParser(); auto Token = Parser.getLexer().peekTok(false); if (Token.is(AsmToken::Identifier)) { DEBUG(dbgs() << ".. identifier\n"); StringRef Identifier = Token.getIdentifier(); OperandMatchResultTy ResTy = - MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S); + matchAnyRegisterNameWithoutDollar(Operands, Identifier, S); return ResTy; } else if (Token.is(AsmToken::Integer)) { DEBUG(dbgs() << ".. integer\n"); - Operands.push_back(MipsOperand::CreateNumericReg( + Operands.push_back(MipsOperand::createNumericReg( Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(), *this)); return MatchOperand_Success; @@ -2038,8 +2561,9 @@ MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseAnyRegister(OperandVector &Operands) { - DEBUG(dbgs() << "ParseAnyRegister\n"); +MipsAsmParser::parseAnyRegister(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + DEBUG(dbgs() << "parseAnyRegister\n"); auto Token = Parser.getTok(); @@ -2056,7 +2580,7 @@ MipsAsmParser::ParseAnyRegister(OperandVector &Operands) { } DEBUG(dbgs() << ".. $\n"); - OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S); + OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); if (ResTy == MatchOperand_Success) { Parser.Lex(); // $ Parser.Lex(); // identifier @@ -2065,7 +2589,8 @@ MipsAsmParser::ParseAnyRegister(OperandVector &Operands) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseImm(OperandVector &Operands) { +MipsAsmParser::parseImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; @@ -2089,18 +2614,19 @@ MipsAsmParser::ParseImm(OperandVector &Operands) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseJumpTarget(OperandVector &Operands) { - DEBUG(dbgs() << "ParseJumpTarget\n"); +MipsAsmParser::parseJumpTarget(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + DEBUG(dbgs() << "parseJumpTarget\n"); SMLoc S = getLexer().getLoc(); // Integers and expressions are acceptable - OperandMatchResultTy ResTy = ParseImm(Operands); + OperandMatchResultTy ResTy = parseImm(Operands); if (ResTy != MatchOperand_NoMatch) return ResTy; // Registers are a valid target and have priority over symbols. - ResTy = ParseAnyRegister(Operands); + ResTy = parseAnyRegister(Operands); if (ResTy != MatchOperand_NoMatch) return ResTy; @@ -2116,6 +2642,7 @@ MipsAsmParser::ParseJumpTarget(OperandVector &Operands) { MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseInvNum(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const MCExpr *IdVal; // If the first token is '$' we may have register operand. if (Parser.getTok().is(AsmToken::Dollar)) @@ -2133,7 +2660,8 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseLSAImm(OperandVector &Operands) { +MipsAsmParser::parseLSAImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; @@ -2171,6 +2699,98 @@ MipsAsmParser::ParseLSAImm(OperandVector &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseRegisterList(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SmallVector<unsigned, 10> Regs; + unsigned RegNo; + unsigned PrevReg = Mips::NoRegister; + bool RegRange = false; + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; + + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_ParseFail; + + SMLoc S = Parser.getTok().getLoc(); + while (parseAnyRegister(TmpOperands) == MatchOperand_Success) { + SMLoc E = getLexer().getLoc(); + MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back()); + RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg(); + if (RegRange) { + // Remove last register operand because registers from register range + // should be inserted first. + if (RegNo == Mips::RA) { + Regs.push_back(RegNo); + } else { + unsigned TmpReg = PrevReg + 1; + while (TmpReg <= RegNo) { + if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) { + Error(E, "invalid register operand"); + return MatchOperand_ParseFail; + } + + PrevReg = TmpReg; + Regs.push_back(TmpReg++); + } + } + + RegRange = false; + } else { + if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) && + (RegNo != Mips::RA)) { + Error(E, "$16 or $31 expected"); + return MatchOperand_ParseFail; + } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) && + (RegNo != Mips::FP) && (RegNo != Mips::RA)) { + Error(E, "invalid register operand"); + return MatchOperand_ParseFail; + } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) && + (RegNo != Mips::FP) && (RegNo != Mips::RA)) { + Error(E, "consecutive register numbers expected"); + return MatchOperand_ParseFail; + } + + Regs.push_back(RegNo); + } + + if (Parser.getTok().is(AsmToken::Minus)) + RegRange = true; + + if (!Parser.getTok().isNot(AsmToken::Minus) && + !Parser.getTok().isNot(AsmToken::Comma)) { + Error(E, "',' or '-' expected"); + return MatchOperand_ParseFail; + } + + Lex(); // Consume comma or minus + if (Parser.getTok().isNot(AsmToken::Dollar)) + break; + + PrevReg = RegNo; + } + + SMLoc E = Parser.getTok().getLoc(); + Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); + parseMemOperand(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; +} + MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind VK = @@ -2212,12 +2832,13 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { /// ::= '(', register, ')' /// handle it before we iterate so we don't get tripped up by the lack of /// a comma. -bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) { +bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) { + MCAsmParser &Parser = getParser(); if (getLexer().is(AsmToken::LParen)) { Operands.push_back( MipsOperand::CreateToken("(", getLexer().getLoc(), *this)); Parser.Lex(); - if (ParseOperand(Operands, Name)) { + if (parseOperand(Operands, Name)) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); @@ -2240,13 +2861,14 @@ bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) { /// ::= '[', integer, ']' /// handle it before we iterate so we don't get tripped up by the lack of /// a comma. -bool MipsAsmParser::ParseBracketSuffix(StringRef Name, +bool MipsAsmParser::parseBracketSuffix(StringRef Name, OperandVector &Operands) { + MCAsmParser &Parser = getParser(); if (getLexer().is(AsmToken::LBrac)) { Operands.push_back( MipsOperand::CreateToken("[", getLexer().getLoc(), *this)); Parser.Lex(); - if (ParseOperand(Operands, Name)) { + if (parseOperand(Operands, Name)) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); @@ -2265,14 +2887,16 @@ bool MipsAsmParser::ParseBracketSuffix(StringRef Name, bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { + MCAsmParser &Parser = getParser(); DEBUG(dbgs() << "ParseInstruction\n"); - // We have reached first instruction, module directive after - // this is forbidden. - getTargetStreamer().setCanHaveModuleDir(false); + + // We have reached first instruction, module directive are now forbidden. + getTargetStreamer().forbidModuleDirective(); + // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { Parser.eatToEndOfStatement(); - return Error(NameLoc, "Unknown instruction"); + return Error(NameLoc, "unknown instruction"); } // First operand in MCInst is instruction mnemonic. Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); @@ -2280,29 +2904,29 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. - if (ParseOperand(Operands, Name)) { + if (parseOperand(Operands, Name)) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } - if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands)) + if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands)) return true; // AFAIK, parenthesis suffixes are never on the first operand while (getLexer().is(AsmToken::Comma)) { Parser.Lex(); // Eat the comma. // Parse and remember the operand. - if (ParseOperand(Operands, Name)) { + if (parseOperand(Operands, Name)) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } // Parse bracket and parenthesis suffixes before we iterate if (getLexer().is(AsmToken::LBrac)) { - if (ParseBracketSuffix(Name, Operands)) + if (parseBracketSuffix(Name, Operands)) return true; } else if (getLexer().is(AsmToken::LParen) && - ParseParenSuffix(Name, Operands)) + parseParenSuffix(Name, Operands)) return true; } } @@ -2316,6 +2940,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } bool MipsAsmParser::reportParseError(Twine ErrorMsg) { + MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, ErrorMsg); @@ -2326,14 +2951,15 @@ bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { } bool MipsAsmParser::parseSetNoAtDirective() { + MCAsmParser &Parser = getParser(); // Line should look like: ".set noat". // set at reg to 0. - Options.setATReg(0); + AssemblerOptions.back()->setATReg(0); // eat noat Parser.Lex(); // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } Parser.Lex(); // Consume the EndOfStatement. @@ -2341,18 +2967,19 @@ bool MipsAsmParser::parseSetNoAtDirective() { } bool MipsAsmParser::parseSetAtDirective() { + MCAsmParser &Parser = getParser(); // Line can be .set at - defaults to $1 // or .set at=$reg int AtRegNo; getParser().Lex(); if (getLexer().is(AsmToken::EndOfStatement)) { - Options.setATReg(1); + AssemblerOptions.back()->setATReg(1); 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 in statement"); + reportParseError("unexpected token, expected dollar sign '$'"); return false; } Parser.Lex(); // Eat the '$'. @@ -2362,7 +2989,7 @@ bool MipsAsmParser::parseSetAtDirective() { } else if (Reg.is(AsmToken::Integer)) { AtRegNo = Reg.getIntVal(); } else { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected identifier or integer"); return false; } @@ -2371,14 +2998,14 @@ bool MipsAsmParser::parseSetAtDirective() { return false; } - if (!Options.setATReg(AtRegNo)) { - reportParseError("unexpected token in statement"); + if (!AssemblerOptions.back()->setATReg(AtRegNo)) { + reportParseError("invalid register"); return false; } getParser().Lex(); // Eat the register. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } Parser.Lex(); // Consume the EndOfStatement. @@ -2390,72 +3017,138 @@ bool MipsAsmParser::parseSetAtDirective() { } bool MipsAsmParser::parseSetReorderDirective() { + MCAsmParser &Parser = getParser(); Parser.Lex(); // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } - Options.setReorder(); + AssemblerOptions.back()->setReorder(); getTargetStreamer().emitDirectiveSetReorder(); Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetNoReorderDirective() { + MCAsmParser &Parser = getParser(); Parser.Lex(); // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } - Options.setNoreorder(); + AssemblerOptions.back()->setNoReorder(); getTargetStreamer().emitDirectiveSetNoReorder(); Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetMacroDirective() { + MCAsmParser &Parser = getParser(); Parser.Lex(); // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } - Options.setMacro(); + AssemblerOptions.back()->setMacro(); Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetNoMacroDirective() { + MCAsmParser &Parser = getParser(); Parser.Lex(); // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("`noreorder' must be set before `nomacro'"); + reportParseError("unexpected token, expected end of statement"); return false; } - if (Options.isReorder()) { + if (AssemblerOptions.back()->isReorder()) { reportParseError("`noreorder' must be set before `nomacro'"); return false; } - Options.setNomacro(); + AssemblerOptions.back()->setNoMacro(); Parser.Lex(); // Consume the EndOfStatement. return false; } -bool MipsAsmParser::parseSetNoMips16Directive() { +bool MipsAsmParser::parseSetMsaDirective() { + MCAsmParser &Parser = getParser(); Parser.Lex(); + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + setFeatureBits(Mips::FeatureMSA, "msa"); + getTargetStreamer().emitDirectiveSetMsa(); + return false; +} + +bool MipsAsmParser::parseSetNoMsaDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + clearFeatureBits(Mips::FeatureMSA, "msa"); + getTargetStreamer().emitDirectiveSetNoMsa(); + return false; +} + +bool MipsAsmParser::parseSetNoDspDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "nodsp". + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); + return false; + } + + clearFeatureBits(Mips::FeatureDSP, "dsp"); + getTargetStreamer().emitDirectiveSetNoDsp(); + return false; +} + +bool MipsAsmParser::parseSetMips16Directive() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "mips16". + + // 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; + } + + setFeatureBits(Mips::FeatureMips16, "mips16"); + getTargetStreamer().emitDirectiveSetMips16(); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + +bool MipsAsmParser::parseSetNoMips16Directive() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "nomips16". + + // 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; } - // For now do nothing. + + clearFeatureBits(Mips::FeatureMips16, "mips16"); + getTargetStreamer().emitDirectiveSetNoMips16(); Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetFpDirective() { + MCAsmParser &Parser = getParser(); MipsABIFlagsSection::FpABIKind FpAbiVal; // Line can be: .set fp=32 // .set fp=xx @@ -2463,7 +3156,7 @@ bool MipsAsmParser::parseSetFpDirective() { Parser.Lex(); // Eat fp token AsmToken Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Equal)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected equals sign '='"); return false; } Parser.Lex(); // Eat '=' token. @@ -2473,7 +3166,7 @@ bool MipsAsmParser::parseSetFpDirective() { return false; if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } getTargetStreamer().emitDirectiveSetFp(FpAbiVal); @@ -2481,15 +3174,50 @@ bool MipsAsmParser::parseSetFpDirective() { return false; } +bool MipsAsmParser::parseSetPopDirective() { + MCAsmParser &Parser = getParser(); + SMLoc Loc = getLexer().getLoc(); + + Parser.Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + // Always keep an element on the options "stack" to prevent the user + // from changing the initial options. This is how we remember them. + if (AssemblerOptions.size() == 2) + return reportParseError(Loc, ".set pop with no .set push"); + + AssemblerOptions.pop_back(); + setAvailableFeatures(AssemblerOptions.back()->getFeatures()); + + getTargetStreamer().emitDirectiveSetPop(); + return false; +} + +bool MipsAsmParser::parseSetPushDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + // Create a copy of the current assembler options environment and push it. + AssemblerOptions.push_back( + make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); + + getTargetStreamer().emitDirectiveSetPush(); + return false; +} + bool MipsAsmParser::parseSetAssignment() { StringRef Name; const MCExpr *Value; + MCAsmParser &Parser = getParser(); if (Parser.parseIdentifier(Name)) reportParseError("expected identifier after .set"); if (getLexer().isNot(AsmToken::Comma)) - return reportParseError("unexpected token in .set directive"); + return reportParseError("unexpected token, expected comma"); Lex(); // Eat comma if (Parser.parseExpression(Value)) @@ -2505,10 +3233,61 @@ bool MipsAsmParser::parseSetAssignment() { return false; } +bool MipsAsmParser::parseSetMips0Directive() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + // Reset assembler options to their initial values. + setAvailableFeatures(AssemblerOptions.front()->getFeatures()); + AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures()); + + getTargetStreamer().emitDirectiveSetMips0(); + return false; +} + +bool MipsAsmParser::parseSetArchDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); + if (getLexer().isNot(AsmToken::Equal)) + return reportParseError("unexpected token, expected equals sign"); + + Parser.Lex(); + StringRef Arch; + if (Parser.parseIdentifier(Arch)) + return reportParseError("expected arch identifier"); + + StringRef ArchFeatureName = + StringSwitch<StringRef>(Arch) + .Case("mips1", "mips1") + .Case("mips2", "mips2") + .Case("mips3", "mips3") + .Case("mips4", "mips4") + .Case("mips5", "mips5") + .Case("mips32", "mips32") + .Case("mips32r2", "mips32r2") + .Case("mips32r6", "mips32r6") + .Case("mips64", "mips64") + .Case("mips64r2", "mips64r2") + .Case("mips64r6", "mips64r6") + .Case("cnmips", "cnmips") + .Case("r4000", "mips3") // This is an implementation of Mips3. + .Default(""); + + if (ArchFeatureName.empty()) + return reportParseError("unsupported architecture"); + + selectArch(ArchFeatureName); + getTargetStreamer().emitDirectiveSetArch(Arch); + return false; +} + bool MipsAsmParser::parseSetFeature(uint64_t Feature) { + MCAsmParser &Parser = getParser(); Parser.Lex(); if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token in .set directive"); + return reportParseError("unexpected token, expected end of statement"); switch (Feature) { default: @@ -2520,26 +3299,56 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { case Mips::FeatureMicroMips: getTargetStreamer().emitDirectiveSetMicroMips(); break; - case Mips::FeatureMips16: - getTargetStreamer().emitDirectiveSetMips16(); + case Mips::FeatureMips1: + selectArch("mips1"); + getTargetStreamer().emitDirectiveSetMips1(); + break; + case Mips::FeatureMips2: + selectArch("mips2"); + getTargetStreamer().emitDirectiveSetMips2(); + break; + case Mips::FeatureMips3: + selectArch("mips3"); + getTargetStreamer().emitDirectiveSetMips3(); + break; + case Mips::FeatureMips4: + selectArch("mips4"); + getTargetStreamer().emitDirectiveSetMips4(); + break; + case Mips::FeatureMips5: + selectArch("mips5"); + getTargetStreamer().emitDirectiveSetMips5(); + break; + case Mips::FeatureMips32: + selectArch("mips32"); + getTargetStreamer().emitDirectiveSetMips32(); break; case Mips::FeatureMips32r2: - setFeatureBits(Mips::FeatureMips32r2, "mips32r2"); + selectArch("mips32r2"); getTargetStreamer().emitDirectiveSetMips32R2(); break; + case Mips::FeatureMips32r6: + selectArch("mips32r6"); + getTargetStreamer().emitDirectiveSetMips32R6(); + break; case Mips::FeatureMips64: - setFeatureBits(Mips::FeatureMips64, "mips64"); + selectArch("mips64"); getTargetStreamer().emitDirectiveSetMips64(); break; case Mips::FeatureMips64r2: - setFeatureBits(Mips::FeatureMips64r2, "mips64r2"); + selectArch("mips64r2"); getTargetStreamer().emitDirectiveSetMips64R2(); break; + case Mips::FeatureMips64r6: + selectArch("mips64r6"); + getTargetStreamer().emitDirectiveSetMips64R6(); + break; } return false; } bool MipsAsmParser::eatComma(StringRef ErrorStr) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::Comma)) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); @@ -2550,14 +3359,17 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) { return true; } -bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) { - if (Options.isReorder()) - Warning(Loc, ".cpload in reorder section"); +bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { + if (AssemblerOptions.back()->isReorder()) + Warning(Loc, ".cpload should be inside a noreorder section"); - // FIXME: Warn if cpload is used in Mips16 mode. + if (inMips16Mode()) { + reportParseError(".cpload is not supported in Mips16 mode"); + return false; + } SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; - OperandMatchResultTy ResTy = ParseAnyRegister(Reg); + OperandMatchResultTy ResTy = parseAnyRegister(Reg); if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { reportParseError("expected register containing function address"); return false; @@ -2569,17 +3381,24 @@ bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) { return false; } - getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg()); + // 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().emitDirectiveCpLoad(RegOpnd.getGPR32Reg()); return false; } bool MipsAsmParser::parseDirectiveCPSetup() { + MCAsmParser &Parser = getParser(); unsigned FuncReg; unsigned Save; bool SaveIsReg = true; SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; - OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg); + OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); if (ResTy == MatchOperand_NoMatch) { reportParseError("expected register containing function address"); Parser.eatToEndOfStatement(); @@ -2596,10 +3415,10 @@ bool MipsAsmParser::parseDirectiveCPSetup() { FuncReg = FuncRegOpnd.getGPR32Reg(); TmpReg.clear(); - if (!eatComma("expected comma parsing directive")) + if (!eatComma("unexpected token, expected comma")) return true; - ResTy = ParseAnyRegister(TmpReg); + ResTy = parseAnyRegister(TmpReg); if (ResTy == MatchOperand_NoMatch) { const AsmToken &Tok = Parser.getTok(); if (Tok.is(AsmToken::Integer)) { @@ -2621,7 +3440,7 @@ bool MipsAsmParser::parseDirectiveCPSetup() { Save = SaveOpnd.getGPR32Reg(); } - if (!eatComma("expected comma parsing directive")) + if (!eatComma("unexpected token, expected comma")) return true; StringRef Name; @@ -2634,6 +3453,7 @@ bool MipsAsmParser::parseDirectiveCPSetup() { } bool MipsAsmParser::parseDirectiveNaN() { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { const AsmToken &Tok = Parser.getTok(); @@ -2654,7 +3474,7 @@ bool MipsAsmParser::parseDirectiveNaN() { } bool MipsAsmParser::parseDirectiveSet() { - + MCAsmParser &Parser = getParser(); // Get the next token. const AsmToken &Tok = Parser.getTok(); @@ -2662,8 +3482,14 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetNoAtDirective(); } else if (Tok.getString() == "at") { return parseSetAtDirective(); + } else if (Tok.getString() == "arch") { + return parseSetArchDirective(); } else if (Tok.getString() == "fp") { return parseSetFpDirective(); + } else if (Tok.getString() == "pop") { + return parseSetPopDirective(); + } else if (Tok.getString() == "push") { + return parseSetPushDirective(); } else if (Tok.getString() == "reorder") { return parseSetReorderDirective(); } else if (Tok.getString() == "noreorder") { @@ -2673,7 +3499,7 @@ bool MipsAsmParser::parseDirectiveSet() { } else if (Tok.getString() == "nomacro") { return parseSetNoMacroDirective(); } else if (Tok.getString() == "mips16") { - return parseSetFeature(Mips::FeatureMips16); + return parseSetMips16Directive(); } else if (Tok.getString() == "nomips16") { return parseSetNoMips16Directive(); } else if (Tok.getString() == "nomicromips") { @@ -2682,14 +3508,38 @@ bool MipsAsmParser::parseDirectiveSet() { return false; } else if (Tok.getString() == "micromips") { return parseSetFeature(Mips::FeatureMicroMips); + } else if (Tok.getString() == "mips0") { + return parseSetMips0Directive(); + } else if (Tok.getString() == "mips1") { + return parseSetFeature(Mips::FeatureMips1); + } else if (Tok.getString() == "mips2") { + return parseSetFeature(Mips::FeatureMips2); + } else if (Tok.getString() == "mips3") { + return parseSetFeature(Mips::FeatureMips3); + } else if (Tok.getString() == "mips4") { + return parseSetFeature(Mips::FeatureMips4); + } else if (Tok.getString() == "mips5") { + return parseSetFeature(Mips::FeatureMips5); + } else if (Tok.getString() == "mips32") { + return parseSetFeature(Mips::FeatureMips32); } else if (Tok.getString() == "mips32r2") { return parseSetFeature(Mips::FeatureMips32r2); + } 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() == "mips64r6") { + return parseSetFeature(Mips::FeatureMips64r6); } else if (Tok.getString() == "dsp") { return parseSetFeature(Mips::FeatureDSP); + } else if (Tok.getString() == "nodsp") { + return parseSetNoDspDirective(); + } else if (Tok.getString() == "msa") { + return parseSetMsaDirective(); + } else if (Tok.getString() == "nomsa") { + return parseSetNoMsaDirective(); } else { // It is just an identifier, look for an assignment. parseSetAssignment(); @@ -2702,6 +3552,7 @@ bool MipsAsmParser::parseDirectiveSet() { /// parseDataDirective /// ::= .word [ expression (, expression)* ] bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { const MCExpr *Value; @@ -2713,9 +3564,8 @@ bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { if (getLexer().is(AsmToken::EndOfStatement)) break; - // FIXME: Improve diagnostic. if (getLexer().isNot(AsmToken::Comma)) - return Error(L, "unexpected token in directive"); + return Error(L, "unexpected token, expected comma"); Parser.Lex(); } } @@ -2727,6 +3577,7 @@ bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { /// parseDirectiveGpWord /// ::= .gpword local_sym bool MipsAsmParser::parseDirectiveGpWord() { + MCAsmParser &Parser = getParser(); const MCExpr *Value; // EmitGPRel32Value requires an expression, so we are using base class // method to evaluate the expression. @@ -2735,7 +3586,8 @@ bool MipsAsmParser::parseDirectiveGpWord() { getParser().getStreamer().EmitGPRel32Value(Value); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), "unexpected token in directive"); + return Error(getLexer().getLoc(), + "unexpected token, expected end of statement"); Parser.Lex(); // Eat EndOfStatement token. return false; } @@ -2743,6 +3595,7 @@ bool MipsAsmParser::parseDirectiveGpWord() { /// parseDirectiveGpDWord /// ::= .gpdword local_sym bool MipsAsmParser::parseDirectiveGpDWord() { + MCAsmParser &Parser = getParser(); const MCExpr *Value; // EmitGPRel64Value requires an expression, so we are using base class // method to evaluate the expression. @@ -2751,17 +3604,19 @@ bool MipsAsmParser::parseDirectiveGpDWord() { getParser().getStreamer().EmitGPRel64Value(Value); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), "unexpected token in directive"); + return Error(getLexer().getLoc(), + "unexpected token, expected end of statement"); Parser.Lex(); // Eat EndOfStatement token. return false; } bool MipsAsmParser::parseDirectiveOption() { + MCAsmParser &Parser = getParser(); // Get the option token. AsmToken Tok = Parser.getTok(); // At the moment only identifiers are supported. if (Tok.isNot(AsmToken::Identifier)) { - Error(Parser.getTok().getLoc(), "unexpected token in .option directive"); + Error(Parser.getTok().getLoc(), "unexpected token, expected identifier"); Parser.eatToEndOfStatement(); return false; } @@ -2773,7 +3628,7 @@ bool MipsAsmParser::parseDirectiveOption() { Parser.Lex(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { Error(Parser.getTok().getLoc(), - "unexpected token in .option pic0 directive"); + "unexpected token, expected end of statement"); Parser.eatToEndOfStatement(); } return false; @@ -2784,14 +3639,15 @@ bool MipsAsmParser::parseDirectiveOption() { Parser.Lex(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { Error(Parser.getTok().getLoc(), - "unexpected token in .option pic2 directive"); + "unexpected token, expected end of statement"); Parser.eatToEndOfStatement(); } return false; } // Unknown option. - Warning(Parser.getTok().getLoc(), "unknown option in .option directive"); + Warning(Parser.getTok().getLoc(), + "unknown option, expected 'pic0' or 'pic2'"); Parser.eatToEndOfStatement(); return false; } @@ -2801,10 +3657,11 @@ bool MipsAsmParser::parseDirectiveOption() { /// ::= .module nooddspreg /// ::= .module fp=value bool MipsAsmParser::parseDirectiveModule() { + MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); SMLoc L = Lexer.getLoc(); - if (!getTargetStreamer().getCanHaveModuleDir()) { + if (!getTargetStreamer().isModuleDirectiveAllowed()) { // TODO : get a better message. reportParseError(".module directive must appear before any code"); return false; @@ -2819,7 +3676,7 @@ bool MipsAsmParser::parseDirectiveModule() { clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("Expected end of statement"); + reportParseError("unexpected token, expected end of statement"); return false; } @@ -2834,7 +3691,7 @@ bool MipsAsmParser::parseDirectiveModule() { setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("Expected end of statement"); + reportParseError("unexpected token, expected end of statement"); return false; } @@ -2854,10 +3711,11 @@ bool MipsAsmParser::parseDirectiveModule() { /// ::= =xx /// ::= =64 bool MipsAsmParser::parseDirectiveModuleFP() { + MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); if (Lexer.isNot(AsmToken::Equal)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected equals sign '='"); return false; } Parser.Lex(); // Eat '=' token. @@ -2867,7 +3725,7 @@ bool MipsAsmParser::parseDirectiveModuleFP() { return false; if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected end of statement"); return false; } @@ -2879,6 +3737,7 @@ bool MipsAsmParser::parseDirectiveModuleFP() { bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, StringRef Directive) { + MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); if (Lexer.is(AsmToken::Identifier)) { @@ -2925,30 +3784,160 @@ bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, } bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { + MCAsmParser &Parser = getParser(); StringRef IDVal = DirectiveID.getString(); if (IDVal == ".cpload") - return parseDirectiveCPLoad(DirectiveID.getLoc()); + return parseDirectiveCpLoad(DirectiveID.getLoc()); if (IDVal == ".dword") { parseDataDirective(8, DirectiveID.getLoc()); return false; } - if (IDVal == ".ent") { - // Ignore this directive for now. - Parser.Lex(); + StringRef SymbolName; + + if (Parser.parseIdentifier(SymbolName)) { + reportParseError("expected identifier after .ent"); + return false; + } + + // There's an undocumented extension that allows an integer to + // follow the name of the procedure which AFAICS is ignored by GAS. + // Example: .ent foo,2 + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) { + // Even though we accept this undocumented extension for compatibility + // reasons, the additional integer argument does not actually change + // the behaviour of the '.ent' directive, so we would like to discourage + // its use. We do this by not referring to the extended version in + // error messages which are not directly related to its use. + reportParseError("unexpected token, expected end of statement"); + return false; + } + Parser.Lex(); // Eat the comma. + const MCExpr *DummyNumber; + int64_t DummyNumberVal; + // If the user was explicitly trying to use the extended version, + // we still give helpful extension-related error messages. + if (Parser.parseExpression(DummyNumber)) { + reportParseError("expected number after comma"); + return false; + } + if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) { + reportParseError("expected an absolute expression after comma"); + return false; + } + } + + // 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; + } + + MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); + + getTargetStreamer().emitDirectiveEnt(*Sym); + CurrentFn = Sym; return false; } if (IDVal == ".end") { - // Ignore this directive for now. - Parser.Lex(); + StringRef SymbolName; + + if (Parser.parseIdentifier(SymbolName)) { + reportParseError("expected identifier after .end"); + return false; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + if (CurrentFn == nullptr) { + reportParseError(".end used without .ent"); + return false; + } + + if ((SymbolName != CurrentFn->getName())) { + reportParseError(".end symbol does not match .ent symbol"); + return false; + } + + getTargetStreamer().emitDirectiveEnd(SymbolName); + CurrentFn = nullptr; return false; } if (IDVal == ".frame") { - // Ignore this directive for now. - Parser.eatToEndOfStatement(); + // .frame $stack_reg, frame_size_in_bytes, $return_reg + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; + OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); + if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { + reportParseError("expected stack register"); + return false; + } + + MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); + if (!StackRegOpnd.isGPRAsmReg()) { + reportParseError(StackRegOpnd.getStartLoc(), + "expected general purpose register"); + return false; + } + unsigned StackReg = StackRegOpnd.getGPR32Reg(); + + if (Parser.getTok().is(AsmToken::Comma)) + Parser.Lex(); + else { + reportParseError("unexpected token, expected comma"); + return false; + } + + // Parse the frame size. + const MCExpr *FrameSize; + int64_t FrameSizeVal; + + if (Parser.parseExpression(FrameSize)) { + reportParseError("expected frame size value"); + return false; + } + + if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) { + reportParseError("frame size not an absolute expression"); + return false; + } + + if (Parser.getTok().is(AsmToken::Comma)) + Parser.Lex(); + else { + reportParseError("unexpected token, expected comma"); + return false; + } + + // Parse the return register. + TmpReg.clear(); + ResTy = parseAnyRegister(TmpReg); + if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { + reportParseError("expected return register"); + return false; + } + + MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); + if (!ReturnRegOpnd.isGPRAsmReg()) { + reportParseError(ReturnRegOpnd.getStartLoc(), + "expected general purpose register"); + return false; + } + + // 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().emitFrame(StackReg, FrameSizeVal, + ReturnRegOpnd.getGPR32Reg()); return false; } @@ -2956,15 +3945,61 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return parseDirectiveSet(); } - if (IDVal == ".fmask") { - // Ignore this directive for now. - Parser.eatToEndOfStatement(); - return false; - } + if (IDVal == ".mask" || IDVal == ".fmask") { + // .mask bitmask, frame_offset + // bitmask: One bit for each register used. + // frame_offset: Offset from Canonical Frame Address ($sp on entry) where + // first register is expected to be saved. + // Examples: + // .mask 0x80000000, -4 + // .fmask 0x80000000, -4 + // - if (IDVal == ".mask") { - // Ignore this directive for now. - Parser.eatToEndOfStatement(); + // Parse the bitmask + const MCExpr *BitMask; + int64_t BitMaskVal; + + if (Parser.parseExpression(BitMask)) { + reportParseError("expected bitmask value"); + return false; + } + + if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) { + reportParseError("bitmask not an absolute expression"); + return false; + } + + if (Parser.getTok().is(AsmToken::Comma)) + Parser.Lex(); + else { + reportParseError("unexpected token, expected comma"); + return false; + } + + // Parse the frame_offset + const MCExpr *FrameOffset; + int64_t FrameOffsetVal; + + if (Parser.parseExpression(FrameOffset)) { + reportParseError("expected frame offset value"); + return false; + } + + if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) { + reportParseError("frame offset not an absolute expression"); + return false; + } + + // 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; + } + + if (IDVal == ".mask") + getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal); + else + getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal); return false; } @@ -2992,7 +4027,8 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { if (IDVal == ".abicalls") { getTargetStreamer().emitDirectiveAbiCalls(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), "unexpected token in directive"); + Error(Parser.getTok().getLoc(), + "unexpected token, expected end of statement"); // Clear line Parser.eatToEndOfStatement(); } diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 04f05236ccda..36ba8e559e0b 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -3,8 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Mips.td) tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info) tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info) tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler) -tablegen(LLVM MipsGenCodeEmitter.inc -gen-emitter) -tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter -mc-emitter) +tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM MipsGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM MipsGenDAGISel.inc -gen-dag-isel) tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel) @@ -22,15 +21,12 @@ add_llvm_target(MipsCodeGen Mips16ISelDAGToDAG.cpp Mips16ISelLowering.cpp Mips16RegisterInfo.cpp - MipsABIInfo.cpp MipsAnalyzeImmediate.cpp MipsAsmPrinter.cpp MipsCCState.cpp - MipsCodeEmitter.cpp MipsConstantIslandPass.cpp MipsDelaySlotFiller.cpp MipsFastISel.cpp - MipsJITInfo.cpp MipsInstrInfo.cpp MipsISelDAGToDAG.cpp MipsISelLowering.cpp diff --git a/lib/Target/Mips/Disassembler/LLVMBuild.txt b/lib/Target/Mips/Disassembler/LLVMBuild.txt index bb70fd3378bc..414b4f78480f 100644 --- a/lib/Target/Mips/Disassembler/LLVMBuild.txt +++ b/lib/Target/Mips/Disassembler/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = MipsDisassembler parent = Mips -required_libraries = MC MipsInfo Support +required_libraries = MCDisassembler MipsInfo Support add_to_library_groups = Mips diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 53fb7a10ad0d..da33f3b913cd 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -20,7 +20,6 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -31,32 +30,29 @@ typedef MCDisassembler::DecodeStatus DecodeStatus; namespace { -/// MipsDisassemblerBase - a disasembler class for Mips. +/// A disasembler class for Mips. class MipsDisassemblerBase : public MCDisassembler { public: - /// Constructor - Initializes the disassembler. - /// MipsDisassemblerBase(const MCSubtargetInfo &STI, MCContext &Ctx, - bool bigEndian) : - MCDisassembler(STI, Ctx), - IsN64(STI.getFeatureBits() & Mips::FeatureN64), isBigEndian(bigEndian) {} + bool IsBigEndian) + : MCDisassembler(STI, Ctx), + IsGP64Bit(STI.getFeatureBits() & Mips::FeatureGP64Bit), + IsBigEndian(IsBigEndian) {} virtual ~MipsDisassemblerBase() {} - bool isN64() const { return IsN64; } + bool isGP64Bit() const { return IsGP64Bit; } private: - bool IsN64; + bool IsGP64Bit; protected: - bool isBigEndian; + bool IsBigEndian; }; -/// MipsDisassembler - a disasembler class for Mips32. +/// A disasembler class for Mips32. class MipsDisassembler : public MipsDisassemblerBase { bool IsMicroMips; public: - /// Constructor - Initializes the disassembler. - /// MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool bigEndian) : MipsDisassemblerBase(STI, Ctx, bigEndian) { IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips; @@ -75,32 +71,23 @@ public: return !hasMips32() && !hasMips3(); } - /// getInstruction - See MCDisassembler. - DecodeStatus getInstruction(MCInst &instr, - uint64_t &size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const override; + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const override; }; - -/// Mips64Disassembler - a disasembler class for Mips64. +/// A disasembler class for Mips64. class Mips64Disassembler : public MipsDisassemblerBase { public: - /// Constructor - Initializes the disassembler. - /// Mips64Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool bigEndian) : MipsDisassemblerBase(STI, Ctx, bigEndian) {} - /// getInstruction - See MCDisassembler. - DecodeStatus getInstruction(MCInst &instr, - uint64_t &size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const override; + 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 @@ -117,6 +104,16 @@ static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -231,6 +228,13 @@ 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); + // DecodeBranchTargetMM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, @@ -255,9 +259,29 @@ static DecodeStatus DecodeCacheOp(MCInst &Inst, 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 DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -285,6 +309,26 @@ static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, 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, @@ -313,6 +357,15 @@ 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); + /// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't /// handle. template <typename InsnType> @@ -349,6 +402,14 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); +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); + namespace llvm { extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, TheMips64elTarget; @@ -704,43 +765,55 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, return MCDisassembler::Success; } - /// readInstruction - read four bytes from the MemoryObject - /// and return 32 bit word sorted according to the given endianess -static DecodeStatus readInstruction32(const MemoryObject ®ion, - uint64_t address, - uint64_t &size, - uint32_t &insn, - bool isBigEndian, - bool IsMicroMips) { - uint8_t Bytes[4]; +/// 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, + uint64_t &Size, uint32_t &Insn, + bool IsBigEndian, bool IsMicroMips) { // We want to read exactly 4 Bytes of data. - if (region.readBytes(address, 4, Bytes) == -1) { - size = 0; + if (Bytes.size() < 4) { + Size = 0; return MCDisassembler::Fail; } - if (isBigEndian) { + // 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 + Insn = + (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); + } else { if (IsMicroMips) { - insn = (Bytes[2] << 0) | - (Bytes[3] << 8) | - (Bytes[0] << 16) | + Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) | (Bytes[1] << 24); } else { - insn = (Bytes[0] << 0) | - (Bytes[1] << 8) | - (Bytes[2] << 16) | + Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | (Bytes[3] << 24); } } @@ -748,24 +821,33 @@ static DecodeStatus readInstruction32(const MemoryObject ®ion, return MCDisassembler::Success; } -DecodeStatus -MipsDisassembler::getInstruction(MCInst &instr, - uint64_t &Size, - const MemoryObject &Region, - uint64_t Address, - raw_ostream &vStream, - raw_ostream &cStream) const { +DecodeStatus MipsDisassembler::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(Region, 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, + Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; @@ -774,10 +856,14 @@ MipsDisassembler::getInstruction(MCInst &instr, 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 = - decodeInstruction(DecoderTableCOP3_32, instr, Insn, Address, this, STI); + decodeInstruction(DecoderTableCOP3_32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -786,7 +872,7 @@ MipsDisassembler::getInstruction(MCInst &instr, if (hasMips32r6() && isGP64()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, instr, Insn, + Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; @@ -796,7 +882,7 @@ MipsDisassembler::getInstruction(MCInst &instr, if (hasMips32r6()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips32r6_64r632, instr, Insn, + Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; @@ -806,8 +892,8 @@ MipsDisassembler::getInstruction(MCInst &instr, DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address, - this, STI); + Result = + decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -816,30 +902,28 @@ MipsDisassembler::getInstruction(MCInst &instr, return MCDisassembler::Fail; } -DecodeStatus -Mips64Disassembler::getInstruction(MCInst &instr, - uint64_t &Size, - const MemoryObject &Region, - uint64_t Address, - raw_ostream &vStream, - raw_ostream &cStream) const { +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(Region, Address, Size, - Insn, isBigEndian, false); + DecodeStatus Result = + readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); if (Result == MCDisassembler::Fail) return MCDisassembler::Fail; // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMips6432, instr, Insn, Address, - this, STI); + 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); + Result = + decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -870,6 +954,28 @@ static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + 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 DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -885,7 +991,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)->isGP64Bit()) return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); @@ -966,7 +1072,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)); } @@ -994,6 +1101,38 @@ 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 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)); @@ -1040,6 +1179,74 @@ 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 DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1051,12 +1258,26 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst, Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - if (Inst.getOpcode() == Mips::SC_MM) + switch (Inst.getOpcode()) { + case Mips::SWM32_MM: + case Mips::LWM32_MM: + if (DecodeRegListOperand(Inst, Insn, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + break; + case Mips::SC_MM: + Inst.addOperand(MCOperand::CreateReg(Reg)); + // 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(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + } return MCDisassembler::Success; } @@ -1326,6 +1547,15 @@ 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 DecodeBranchTargetMM(MCInst &Inst, unsigned Offset, uint64_t Address, @@ -1344,6 +1574,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, @@ -1392,3 +1662,76 @@ static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, Inst.addOperand(MCOperand::CreateImm(SignExtend32<18>(Insn) * 8)); 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, + const void *Decoder) { + unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, + Mips::S6, Mips::FP}; + unsigned RegNum; + + unsigned RegLst = fieldFromInstruction(Insn, 21, 5); + // Empty register lists are not allowed. + if (RegLst == 0) + return MCDisassembler::Fail; + + RegNum = RegLst & 0xf; + for (unsigned i = 0; i < RegNum; i++) + Inst.addOperand(MCOperand::CreateReg(Regs[i])); + + if (RegLst & 0x10) + Inst.addOperand(MCOperand::CreateReg(Mips::RA)); + + 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 RegNum; + + unsigned RegLst = fieldFromInstruction(Insn, 4, 2); + // Empty register lists are not allowed. + if (RegLst == 0) + return MCDisassembler::Fail; + + RegNum = RegLst & 0x3; + for (unsigned i = 0; i < RegNum - 1; i++) + Inst.addOperand(MCOperand::CreateReg(Regs[i])); + + Inst.addOperand(MCOperand::CreateReg(Mips::RA)); + + return MCDisassembler::Success; +} diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 8c797517e316..61743ff76205 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(); @@ -225,6 +225,20 @@ printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern lw $25,%call16($28) + + // 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::SWM32_MM: + case Mips::LWM32_MM: + case Mips::SWM16_MM: + case Mips::LWM16_MM: + opNum = MI->getNumOperands() - 2; + break; + } + printOperand(MI, opNum+1, O); O << "("; printOperand(MI, opNum, O); @@ -248,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"); } @@ -324,3 +343,13 @@ void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) { } } +void MipsInstPrinter:: +printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) { + // - 2 because register List is always first operand of instruction and it is + // always followed by memory operand (base + offset). + for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) { + if (i != opNum) + O << ", "; + printRegName(O, MI->getOperand(i).getReg()); + } +} diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 550a0f10d1ba..468dc07818e7 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSINSTPRINTER_H -#define MIPSINSTPRINTER_H +#ifndef LLVM_LIB_TARGET_MIPS_INSTPRINTER_MIPSINSTPRINTER_H +#define LLVM_LIB_TARGET_MIPS_INSTPRINTER_MIPSINSTPRINTER_H #include "llvm/MC/MCInstPrinter.h" namespace llvm { @@ -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, @@ -107,6 +108,7 @@ private: unsigned OpNo1, raw_ostream &OS); bool printAlias(const MCInst &MI, raw_ostream &OS); void printSaveRestore(const MCInst *MI, raw_ostream &O); + void printRegisterList(const MCInst *MI, int opNum, raw_ostream &O); }; } // end namespace llvm diff --git a/lib/Target/Mips/LLVMBuild.txt b/lib/Target/Mips/LLVMBuild.txt index e6d3a426b2ea..0e8d902c56d2 100644 --- a/lib/Target/Mips/LLVMBuild.txt +++ b/lib/Target/Mips/LLVMBuild.txt @@ -31,5 +31,5 @@ has_jit = 1 type = Library name = MipsCodeGen parent = Mips -required_libraries = Analysis AsmPrinter CodeGen Core MC MipsAsmPrinter MipsDesc MipsInfo Scalar SelectionDAG Support Target +required_libraries = Analysis AsmPrinter CodeGen Core MC MipsAsmPrinter MipsDesc MipsInfo SelectionDAG Support Target add_to_library_groups = Mips diff --git a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt index 6b3788ca515c..c63af7c710cc 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 ea5bc12b0740..8bcfb0fab9ee 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSABIFLAGSSECTION_H -#define MIPSABIFLAGSSECTION_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H #include "llvm/MC/MCStreamer.h" diff --git a/lib/Target/Mips/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index f885369845e7..f885369845e7 100644 --- a/lib/Target/Mips/MipsABIInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp diff --git a/lib/Target/Mips/MipsABIInfo.h b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index bea585e41bd4..eccb50d86240 100644 --- a/lib/Target/Mips/MipsABIInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -11,8 +11,8 @@ #define MIPSABIINFO_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCRegisterInfo.h" #include "llvm/IR/CallingConv.h" +#include "llvm/MC/MCRegisterInfo.h" namespace llvm { diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index d8e6128cd54d..6670dc208552 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -103,6 +103,14 @@ 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_PC16_S1: Value -= 4; // Forcing a signed division because Value can be negative. @@ -271,6 +279,7 @@ 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_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 0, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 }, @@ -334,6 +343,7 @@ 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_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 16, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 }, @@ -367,7 +377,12 @@ bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { // Check for a less than instruction size number of bytes // FIXME: 16 bit instructions are not handled yet here. // We shouldn't be using a hard coded number for instruction size. - if (Count % 4) return false; + + // If the count is not 4-byte aligned, we must be writing data into the text + // section (otherwise we have unaligned instructions, and thus have far + // bigger problems), so just write zeros instead. + for (uint64_t i = 0, e = Count % 4; i != e; ++i) + OW->Write8(0); uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index d5c3dbc47880..dd0e54c79cf1 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -12,12 +12,12 @@ //===----------------------------------------------------------------------===// // -#ifndef MIPSASMBACKEND_H -#define MIPSASMBACKEND_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSASMBACKEND_H +#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/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index d2323dc1b47b..ff7779ec1e78 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -11,8 +11,8 @@ // the Mips target useful for the compiler back-end and the MC libraries. // //===----------------------------------------------------------------------===// -#ifndef MIPSBASEINFO_H -#define MIPSBASEINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSBASEINFO_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSBASEINFO_H #include "MipsFixupKinds.h" #include "MipsMCTargetDesc.h" diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 4ea7846f83f6..56aac4eaea49 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,9 @@ 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_PC16_S1: Type = ELF::R_MICROMIPS_PC16_S1; break; @@ -219,7 +223,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 +248,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.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index 803ab85657dc..18c4a206059d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -8,7 +8,12 @@ //===----------------------------------------------------------------------===// #include "MipsELFStreamer.h" +#include "MipsTargetStreamer.h" +#include "llvm/MC/MCELF.h" #include "llvm/MC/MCInst.h" +#include "llvm/Support/ELF.h" + +using namespace llvm; void MipsELFStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { @@ -16,6 +21,8 @@ void MipsELFStreamer::EmitInstruction(const MCInst &Inst, MCContext &Context = getContext(); const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo(); + MipsTargetELFStreamer *ELFTargetStreamer = + static_cast<MipsTargetELFStreamer *>(getTargetStreamer()); for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) { const MCOperand &Op = Inst.getOperand(OpIndex); @@ -26,6 +33,35 @@ void MipsELFStreamer::EmitInstruction(const MCInst &Inst, unsigned Reg = Op.getReg(); RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo); } + + if (ELFTargetStreamer->isMicroMipsEnabled()) { + for (auto Label : Labels) { + MCSymbolData &Data = getOrCreateSymbolData(Label); + // The "other" values are stored in the last 6 bits of the second byte. + // The traditional defines for STO values assume the full byte and thus + // the shift to pack it. + MCELF::setOther(Data, ELF::STO_MIPS_MICROMIPS >> 2); + } + } + + Labels.clear(); +} + +void MipsELFStreamer::EmitLabel(MCSymbol *Symbol) { + MCELFStreamer::EmitLabel(Symbol); + Labels.push_back(Symbol); +} + +void MipsELFStreamer::SwitchSection(const MCSection * Section, + const MCExpr *Subsection) { + MCELFStreamer::SwitchSection(Section, Subsection); + Labels.clear(); +} + +void MipsELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { + MCELFStreamer::EmitValueImpl(Value, Size, Loc); + Labels.clear(); } void MipsELFStreamer::EmitMipsOptionRecords() { @@ -36,8 +72,8 @@ void MipsELFStreamer::EmitMipsOptionRecords() { namespace llvm { MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, bool RelaxAll, - bool NoExecStack) { + const MCSubtargetInfo &STI, + bool RelaxAll) { return new MipsELFStreamer(Context, MAB, OS, Emitter, STI); } } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index 58863be9cc23..136146b9474c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSELFSTREAMER_H -#define MIPSELFSTREAMER_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H #include "MipsOptionRecord.h" #include "llvm/ADT/SmallVector.h" @@ -29,6 +29,8 @@ class MCSubtargetInfo; class MipsELFStreamer : public MCELFStreamer { SmallVector<std::unique_ptr<MipsOptionRecord>, 8> MipsOptionRecords; MipsRegInfoRecord *RegInfoRecord; + SmallVector<MCSymbol*, 4> Labels; + public: MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, @@ -46,13 +48,27 @@ public: /// usage for the translation unit. void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + /// Overriding this function allows us to record all labels that should be + /// marked as microMIPS. Based on this data marking is done in + /// EmitInstruction. + void EmitLabel(MCSymbol *Symbol) override; + + /// Overriding this function allows us to dismiss all labels that are + /// candidates for marking as microMIPS when .section directive is processed. + void SwitchSection(const MCSection *Section, + const MCExpr *Subsection = nullptr) override; + + /// Overriding this function allows us to dismiss all labels that are + /// candidates for marking as microMIPS when .word directive is emitted. + void EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) override; + /// Emits all the option records stored up until the point it's called. void EmitMipsOptionRecords(); }; MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, bool RelaxAll, - bool NoExecStack); + const MCSubtargetInfo &STI, bool RelaxAll); } // namespace llvm. #endif diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 05080f046f89..71c11d76b316 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MIPS_MIPSFIXUPKINDS_H -#define LLVM_MIPS_MIPSFIXUPKINDS_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSFIXUPKINDS_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSFIXUPKINDS_H #include "llvm/MC/MCFixup.h" @@ -158,6 +158,9 @@ namespace Mips { // resulting in - R_MICROMIPS_GOT16 fixup_MICROMIPS_GOT16, + // resulting in - R_MICROMIPS_PC7_S1 + fixup_MICROMIPS_PC7_S1, + // resulting in - R_MICROMIPS_PC16_S1 fixup_MICROMIPS_PC16_S1, @@ -199,4 +202,4 @@ namespace Mips { } // namespace llvm -#endif // LLVM_MIPS_MIPSFIXUPKINDS_H +#endif diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index e415412ab6cb..e2bd5a815ab1 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"; @@ -41,6 +42,5 @@ MipsMCAsmInfo::MipsMCAsmInfo(StringRef TT) { UseAssignmentForEHBegin = true; SupportsDebugInformation = true; ExceptionsType = ExceptionHandling::DwarfCFI; - HasLEB128 = true; DwarfRegNumForCFI = true; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index 37ba0c4aaa7b..59ff1c41ed6e 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSTARGETASMINFO_H -#define MIPSTARGETASMINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H #include "llvm/MC/MCAsmInfoELF.h" diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 43fc52136ddc..a54a2eb6b452 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,28 @@ 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; +} + /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. @@ -345,6 +368,67 @@ getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, } unsigned MipsMCCodeEmitter:: +getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) { + // The immediate is encoded as 'immediate << 2'. + unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); + assert((Res & 3) == 0); + return Res >> 2; + } + + assert(MO.isExpr() && + "getUImm5Lsl2Encoding expects only expressions or an immediate"); + + return 0; +} + +unsigned MipsMCCodeEmitter:: +getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) { + int Value = MO.getImm(); + return Value >> 2; + } + + return 0; +} + +unsigned MipsMCCodeEmitter:: +getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) { + unsigned Value = MO.getImm(); + return Value >> 2; + } + + return 0; +} + +unsigned MipsMCCodeEmitter:: +getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) { + unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; + return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff)); + } + + return 0; +} + +unsigned MipsMCCodeEmitter:: getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { int64_t Res; @@ -574,9 +658,76 @@ 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:: getMemEncodingMMImm12(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::SWM32_MM: + case Mips::LWM32_MM: + OpNo = MI.getNumOperands() - 2; + break; + } + // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; @@ -585,6 +736,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, @@ -659,4 +834,75 @@ MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, return 0; } +unsigned +MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + assert(MI.getOperand(OpNo).isImm()); + const MCOperand &MO = MI.getOperand(OpNo); + return MO.getImm() % 8; +} + +unsigned +MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + assert(MI.getOperand(OpNo).isImm()); + const MCOperand &MO = MI.getOperand(OpNo); + unsigned Value = MO.getImm(); + switch (Value) { + case 128: return 0x0; + case 1: return 0x1; + case 2: return 0x2; + case 3: return 0x3; + case 4: return 0x4; + case 7: return 0x5; + case 8: return 0x6; + case 15: return 0x7; + case 16: return 0x8; + case 31: return 0x9; + case 32: return 0xa; + case 63: return 0xb; + case 64: return 0xc; + case 255: return 0xd; + case 32768: return 0xe; + case 65535: return 0xf; + } + llvm_unreachable("Unexpected value"); +} + +unsigned +MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + unsigned res = 0; + + // Register list operand is always first operand of instruction and it is + // placed before memory operand (register + imm). + + for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { + unsigned Reg = MI.getOperand(I).getReg(); + unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); + if (RegNo != 31) + res++; + else + res |= 0x10; + } + 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); +} + #include "MipsGenMCCodeEmitter.inc" diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 304167fd03db..0f0f49ddb978 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// // -#ifndef MIPS_MC_CODE_EMITTER_H -#define MIPS_MC_CODE_EMITTER_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H #include "llvm/MC/MCCodeEmitter.h" #include "llvm/Support/DataTypes.h" @@ -60,7 +60,7 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; - // getBranchJumpOpValue - Return binary encoding of the jump + // getJumpTargetOpValue - Return binary encoding of the jump // target operand. If the machine operand requires relocation, // record the relocation and return zero. unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, @@ -74,6 +74,26 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + // getUImm5Lsl2Encoding - Return binary encoding of the microMIPS jump + // target operand. + unsigned getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + // getSImm9AddiuspValue - Return binary encoding of the microMIPS addiusp + // instruction immediate operand. + unsigned getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + // getBranchTargetOpValue - Return binary encoding of the branch // target operand. If the machine operand requires relocation, // record the relocation and return zero. @@ -81,6 +101,13 @@ 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; + // getBranchTargetOpValue - Return binary encoding of the microMIPS branch // target operand. If the machine operand requires relocation, // record the relocation and return zero. @@ -122,9 +149,24 @@ 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 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; @@ -145,9 +187,27 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getUImm4AndValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getRegisterPairOpValue(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/MipsMCExpr.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 5bba3e5b7ae2..74490f334b37 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -80,8 +80,9 @@ void MipsMCExpr::PrintImpl(raw_ostream &OS) const { bool MipsMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const { - return getSubExpr()->EvaluateAsRelocatable(Res, Layout); + const MCAsmLayout *Layout, + const MCFixup *Fixup) const { + return getSubExpr()->EvaluateAsRelocatable(Res, Layout, Fixup); } void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const { diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h index f193dc9b9d50..2b8f0c89a2e6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSMCEXPR_H -#define MIPSMCEXPR_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCExpr.h" @@ -48,7 +48,8 @@ public: void PrintImpl(raw_ostream &OS) const override; bool EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const override; + const MCAsmLayout *Layout, + const MCFixup *Fixup) const override; void visitUsedExpr(MCStreamer &Streamer) const override; const MCSection *FindAssociatedSection() const override { return getSubExpr()->FindAssociatedSection(); diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h index 01d5363812ed..e756b4703efa 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSMCNACL_H -#define MIPSMCNACL_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCNACL_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCNACL_H #include "llvm/MC/MCELFStreamer.h" @@ -26,8 +26,7 @@ MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, const MCSubtargetInfo &STI, - bool RelaxAll, bool NoExecStack); - + bool RelaxAll); } #endif diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index d2b929bea334..bab425469433 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -109,15 +109,12 @@ static MCInstPrinter *createMipsMCInstPrinter(const Target &T, static MCStreamer *createMCStreamer(const Target &T, StringRef TT, MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, - bool RelaxAll, bool NoExecStack) { + const MCSubtargetInfo &STI, bool RelaxAll) { MCStreamer *S; if (!Triple(TT).isOSNaCl()) - S = createMipsELFStreamer(Context, MAB, OS, Emitter, STI, RelaxAll, - NoExecStack); + S = createMipsELFStreamer(Context, MAB, OS, Emitter, STI, RelaxAll); else - S = createMipsNaClELFStreamer(Context, MAB, OS, Emitter, STI, RelaxAll, - NoExecStack); + S = createMipsNaClELFStreamer(Context, MAB, OS, Emitter, STI, RelaxAll); new MipsTargetELFStreamer(*S, STI); return S; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index 161d1eae82b9..f08a8f46fe9c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSMCTARGETDESC_H -#define MIPSMCTARGETDESC_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCTARGETDESC_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCTARGETDESC_H #include "llvm/Support/DataTypes.h" diff --git a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp index 6cde8f9ae3e4..92b84551a68f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -255,13 +255,11 @@ MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, const MCSubtargetInfo &STI, - bool RelaxAll, bool NoExecStack) { + bool RelaxAll) { MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter, STI); if (RelaxAll) S->getAssembler().setRelaxAll(true); - if (NoExecStack) - S->getAssembler().setNoExecStack(true); // Set bundle-alignment as required by the NaCl ABI for the target. S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN); diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 4a178e2df7a9..1e092f219be9 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -29,17 +29,21 @@ using namespace llvm; MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) - : MCTargetStreamer(S), canHaveModuleDirective(true) {} + : MCTargetStreamer(S), ModuleDirectiveAllowed(true) { + GPRInfoSet = FPRInfoSet = FrameInfoSet = false; +} void MipsTargetStreamer::emitDirectiveSetMicroMips() {} void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {} void MipsTargetStreamer::emitDirectiveSetMips16() {} -void MipsTargetStreamer::emitDirectiveSetNoMips16() {} -void MipsTargetStreamer::emitDirectiveSetReorder() {} +void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoReorder() {} -void MipsTargetStreamer::emitDirectiveSetMacro() {} -void MipsTargetStreamer::emitDirectiveSetNoMacro() {} -void MipsTargetStreamer::emitDirectiveSetAt() {} -void MipsTargetStreamer::emitDirectiveSetNoAt() {} +void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {} void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {} void MipsTargetStreamer::emitDirectiveAbiCalls() {} @@ -52,11 +56,26 @@ void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize, void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { } -void MipsTargetStreamer::emitDirectiveSetMips32R2() {} -void MipsTargetStreamer::emitDirectiveSetMips64() {} -void MipsTargetStreamer::emitDirectiveSetMips64R2() {} -void MipsTargetStreamer::emitDirectiveSetDsp() {} -void MipsTargetStreamer::emitDirectiveCpload(unsigned RegNo) {} +void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) { + forbidModuleDirective(); +} +void MipsTargetStreamer::emitDirectiveSetMips0() {} +void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetPop() {} +void MipsTargetStreamer::emitDirectiveSetPush() {} +void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) { } @@ -72,52 +91,62 @@ MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() { OS << "\t.set\tmicromips\n"; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() { OS << "\t.set\tnomicromips\n"; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetAsmStreamer::emitDirectiveSetMips16() { OS << "\t.set\tmips16\n"; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() { OS << "\t.set\tnomips16\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetNoMips16(); } void MipsTargetAsmStreamer::emitDirectiveSetReorder() { OS << "\t.set\treorder\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetReorder(); } void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() { OS << "\t.set\tnoreorder\n"; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetAsmStreamer::emitDirectiveSetMacro() { OS << "\t.set\tmacro\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetMacro(); } void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() { OS << "\t.set\tnomacro\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetNoMacro(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMsa() { + OS << "\t.set\tmsa\n"; + MipsTargetStreamer::emitDirectiveSetMsa(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() { + OS << "\t.set\tnomsa\n"; + MipsTargetStreamer::emitDirectiveSetNoMsa(); } void MipsTargetAsmStreamer::emitDirectiveSetAt() { OS << "\t.set\tat\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetAt(); } void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { OS << "\t.set\tnoat\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetNoAt(); } void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) { @@ -152,25 +181,82 @@ void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n'; } +void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) { + OS << "\t.set arch=" << Arch << "\n"; + MipsTargetStreamer::emitDirectiveSetArch(Arch); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips0() { OS << "\t.set\tmips0\n"; } + +void MipsTargetAsmStreamer::emitDirectiveSetMips1() { + OS << "\t.set\tmips1\n"; + MipsTargetStreamer::emitDirectiveSetMips1(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips2() { + OS << "\t.set\tmips2\n"; + MipsTargetStreamer::emitDirectiveSetMips2(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips3() { + OS << "\t.set\tmips3\n"; + MipsTargetStreamer::emitDirectiveSetMips3(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips4() { + OS << "\t.set\tmips4\n"; + MipsTargetStreamer::emitDirectiveSetMips4(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips5() { + OS << "\t.set\tmips5\n"; + MipsTargetStreamer::emitDirectiveSetMips5(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips32() { + OS << "\t.set\tmips32\n"; + MipsTargetStreamer::emitDirectiveSetMips32(); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { OS << "\t.set\tmips32r2\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetMips32R2(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() { + OS << "\t.set\tmips32r6\n"; + MipsTargetStreamer::emitDirectiveSetMips32R6(); } void MipsTargetAsmStreamer::emitDirectiveSetMips64() { OS << "\t.set\tmips64\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetMips64(); } void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { OS << "\t.set\tmips64r2\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetMips64R2(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() { + OS << "\t.set\tmips64r6\n"; + MipsTargetStreamer::emitDirectiveSetMips64R6(); } void MipsTargetAsmStreamer::emitDirectiveSetDsp() { OS << "\t.set\tdsp\n"; - setCanHaveModuleDir(false); + MipsTargetStreamer::emitDirectiveSetDsp(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() { + OS << "\t.set\tnodsp\n"; + MipsTargetStreamer::emitDirectiveSetNoDsp(); } + +void MipsTargetAsmStreamer::emitDirectiveSetPop() { OS << "\t.set\tpop\n"; } + +void MipsTargetAsmStreamer::emitDirectiveSetPush() { OS << "\t.set\tpush\n"; } + // Print a 32 bit hex number with all numbers. static void printHex32(unsigned Value, raw_ostream &OS) { OS << "0x"; @@ -192,10 +278,10 @@ void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask, OS << "," << FPUTopSavedRegOff << '\n'; } -void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) { +void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) { OS << "\t.cpload\t$" << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -214,7 +300,7 @@ void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, OS << ", "; OS << Sym.getName() << "\n"; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetAsmStreamer::emitDirectiveModuleFP( @@ -378,11 +464,12 @@ void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { unsigned Flags = MCA.getELFHeaderEFlags(); Flags |= ELF::EF_MIPS_MICROMIPS; MCA.setELFHeaderEFlags(Flags); + forbidModuleDirective(); } void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { MicroMipsEnabled = false; - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetELFStreamer::emitDirectiveSetMips16() { @@ -390,17 +477,7 @@ void MipsTargetELFStreamer::emitDirectiveSetMips16() { unsigned Flags = MCA.getELFHeaderEFlags(); Flags |= ELF::EF_MIPS_ARCH_ASE_M16; MCA.setELFHeaderEFlags(Flags); - setCanHaveModuleDir(false); -} - -void MipsTargetELFStreamer::emitDirectiveSetNoMips16() { - // FIXME: implement. - setCanHaveModuleDir(false); -} - -void MipsTargetELFStreamer::emitDirectiveSetReorder() { - // FIXME: implement. - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { @@ -408,35 +485,49 @@ void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { unsigned Flags = MCA.getELFHeaderEFlags(); Flags |= ELF::EF_MIPS_NOREORDER; MCA.setELFHeaderEFlags(Flags); - setCanHaveModuleDir(false); + forbidModuleDirective(); } -void MipsTargetELFStreamer::emitDirectiveSetMacro() { - // FIXME: implement. - setCanHaveModuleDir(false); -} +void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { + MCAssembler &MCA = getStreamer().getAssembler(); + MCContext &Context = MCA.getContext(); + MCStreamer &OS = getStreamer(); -void MipsTargetELFStreamer::emitDirectiveSetNoMacro() { - // FIXME: implement. - setCanHaveModuleDir(false); -} + const MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHT_REL, + SectionKind::getMetadata()); -void MipsTargetELFStreamer::emitDirectiveSetAt() { - // FIXME: implement. - setCanHaveModuleDir(false); -} + const MCSymbolRefExpr *ExprRef = + MCSymbolRefExpr::Create(Name, MCSymbolRefExpr::VK_None, Context); -void MipsTargetELFStreamer::emitDirectiveSetNoAt() { - // FIXME: implement. - setCanHaveModuleDir(false); -} + MCSectionData &SecData = MCA.getOrCreateSectionData(*Sec); + SecData.setAlignment(4); -void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { - // FIXME: implement. + OS.PushSection(); + + OS.SwitchSection(Sec); + + OS.EmitValueImpl(ExprRef, 4); + + OS.EmitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask + OS.EmitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset + + OS.EmitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask + OS.EmitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset + + OS.EmitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset + OS.EmitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg + OS.EmitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg + + // The .end directive marks the end of a procedure. Invalidate + // the information gathered up until this point. + GPRInfoSet = FPRInfoSet = FrameInfoSet = false; + + OS.PopSection(); } void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { - // FIXME: implement. + GPRInfoSet = FPRInfoSet = FrameInfoSet = false; } void MipsTargetELFStreamer::emitDirectiveAbiCalls() { @@ -482,37 +573,31 @@ void MipsTargetELFStreamer::emitDirectiveOptionPic2() { } void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg) { - // FIXME: implement. + unsigned ReturnReg_) { + MCContext &Context = getStreamer().getAssembler().getContext(); + const MCRegisterInfo *RegInfo = Context.getRegisterInfo(); + + FrameInfoSet = true; + FrameReg = RegInfo->getEncodingValue(StackReg); + FrameOffset = StackSize; + ReturnReg = RegInfo->getEncodingValue(ReturnReg_); } void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) { - // FIXME: implement. + GPRInfoSet = true; + GPRBitMask = CPUBitmask; + GPROffset = CPUTopSavedRegOff; } void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { - // FIXME: implement. -} - -void MipsTargetELFStreamer::emitDirectiveSetMips32R2() { - setCanHaveModuleDir(false); -} - -void MipsTargetELFStreamer::emitDirectiveSetMips64() { - setCanHaveModuleDir(false); -} - -void MipsTargetELFStreamer::emitDirectiveSetMips64R2() { - setCanHaveModuleDir(false); -} - -void MipsTargetELFStreamer::emitDirectiveSetDsp() { - setCanHaveModuleDir(false); + FPRInfoSet = true; + FPRBitMask = FPUBitmask; + FPROffset = FPUTopSavedRegOff; } -void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) { +void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { // .cpload $reg // This directive expands to: // lui $gp, %hi(_gp_disp) @@ -560,7 +645,7 @@ void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) { TmpInst.addOperand(MCOperand::CreateReg(RegNo)); getStreamer().EmitInstruction(TmpInst, STI); - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -617,7 +702,7 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, Inst.addOperand(MCOperand::CreateReg(RegNo)); getStreamer().EmitInstruction(Inst, STI); - setCanHaveModuleDir(false); + forbidModuleDirective(); } void MipsTargetELFStreamer::emitMipsAbiFlags() { diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index 41efa470e42a..56db450f6961 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -13,7 +13,7 @@ TARGET = Mips # Make sure that tblgen is run, first thing. BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ - MipsGenAsmWriter.inc MipsGenFastISel.inc MipsGenCodeEmitter.inc \ + MipsGenAsmWriter.inc MipsGenFastISel.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc \ MipsGenDisassemblerTables.inc \ diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td index b93017a7400a..fae70598fa33 100644 --- a/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/lib/Target/Mips/MicroMipsInstrFPU.td @@ -123,10 +123,10 @@ def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, bitconvert>, MFC1_FM_MM<0x80>; def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>; -def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, FGRH32Opnd, II_MFHC1>, - MFC1_FM_MM<3>, ISA_MIPS32R2; -def MTHC1_MM : MMRel, MTC1_FT<"mthc1", FGRH32Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM_MM<7>, ISA_MIPS32R2; +def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, + MFC1_FM_MM<0xc0>, ISA_MIPS32R2, AdditionalRequires<[NotFP64bit]>; +def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, + MFC1_FM_MM<0xe0>, ISA_MIPS32R2, AdditionalRequires<[NotFP64bit]>; def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, MADDS_FM_MM<0x1>; diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td index 15b951d98c52..51b5c0cd612b 100644 --- a/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -41,6 +41,118 @@ class MicroMipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern, // MicroMIPS 16-bit Instruction Formats //===----------------------------------------------------------------------===// +class ARITH_FM_MM16<bit funct> { + bits<3> rd; + bits<3> rt; + bits<3> rs; + + bits<16> Inst; + + let Inst{15-10} = 0x01; + let Inst{9-7} = rd; + let Inst{6-4} = rt; + let Inst{3-1} = rs; + let Inst{0} = funct; +} + +class ANDI_FM_MM16<bits<6> funct> { + bits<3> rd; + bits<3> rs; + bits<4> imm; + + bits<16> Inst; + + let Inst{15-10} = funct; + let Inst{9-7} = rd; + let Inst{6-4} = rs; + let Inst{3-0} = imm; +} + +class LOGIC_FM_MM16<bits<4> funct> { + bits<3> rt; + bits<3> rs; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-6} = funct; + let Inst{5-3} = rt; + let Inst{2-0} = rs; +} + +class SHIFT_FM_MM16<bits<1> funct> { + bits<3> rd; + bits<3> rt; + bits<3> shamt; + + bits<16> Inst; + + let Inst{15-10} = 0x09; + let Inst{9-7} = rd; + let Inst{6-4} = rt; + let Inst{3-1} = shamt; + let Inst{0} = funct; +} + +class ADDIUR2_FM_MM16 { + bits<3> rd; + bits<3> rs; + bits<3> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x1b; + let Inst{9-7} = rd; + let Inst{6-4} = rs; + let Inst{3-1} = imm; + 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 ADDIUS5_FM_MM16 { + bits<5> rd; + bits<4> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x13; + let Inst{9-5} = rd; + let Inst{4-1} = imm; + let Inst{0} = 0; +} + +class ADDIUSP_FM_MM16 { + bits<9> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x13; + let Inst{9-1} = imm; + let Inst{0} = 1; +} + class MOVE_FM_MM16<bits<6> funct> { bits<5> rs; bits<5> rd; @@ -52,6 +164,17 @@ class MOVE_FM_MM16<bits<6> funct> { let Inst{4-0} = rs; } +class LI_FM_MM16 { + bits<3> rd; + bits<7> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x3b; + let Inst{9-7} = rd; + let Inst{6-0} = imm; +} + class JALR_FM_MM16<bits<5> op> { bits<5> rs; @@ -72,6 +195,49 @@ class MFHILO_FM_MM16<bits<5> funct> { let Inst{4-0} = rd; } +class JRADDIUSP_FM_MM16<bits<5> op> { + bits<5> rs; + bits<5> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-5} = op; + let Inst{4-0} = imm; +} + +class ADDIUR1SP_FM_MM16 { + bits<3> rd; + bits<6> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x1b; + let Inst{9-7} = rd; + let Inst{6-1} = imm; + 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; +} + //===----------------------------------------------------------------------===// // MicroMIPS 32-bit Instruction Formats //===----------------------------------------------------------------------===// @@ -621,3 +787,114 @@ class MADDS_FM_MM<bits<6> funct>: MMArch { let Inst{10-6} = fr; let Inst{5-0} = funct; } + +class COMPACT_BRANCH_FM_MM<bits<5> funct> { + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = 0x10; + let Inst{25-21} = funct; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + +class COP0_TLB_FM_MM<bits<10> op> : MMArch { + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-16} = 0x0; + let Inst{15-6} = op; + let Inst{5-0} = 0x3c; +} + +class SDBBP_FM_MM : MMArch { + bits<10> code_; + + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-16} = code_; + let Inst{15-6} = 0x36d; + let Inst{5-0} = 0x3c; +} + +class RDHWR_FM_MM : MMArch { + bits<5> rt; + bits<5> rd; + + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = rt; + let Inst{20-16} = rd; + let Inst{15-6} = 0x1ac; + let Inst{5-0} = 0x3c; +} + +class LWXS_FM_MM<bits<10> funct> { + bits<5> rd; + bits<5> base; + bits<5> index; + + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = index; + let Inst{20-16} = base; + let Inst{15-11} = rd; + let Inst{10} = 0; + let Inst{9-0} = funct; +} + +class LWM_FM_MM<bits<4> funct> : MMArch { + bits<5> rt; + bits<21> addr; + + bits<32> Inst; + + let Inst{31-26} = 0x8; + let Inst{25-21} = rt; + let Inst{20-16} = addr{20-16}; + 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; +} diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index 87a3a3e29ca2..241f4528658c 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,9 +1,101 @@ def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>; +def simm4 : Operand<i32> { + let DecoderMethod = "DecodeSimm4"; +} +def li_simm7 : Operand<i32> { + let DecoderMethod = "DecodeLiSimm7"; +} + def simm12 : Operand<i32> { let DecoderMethod = "DecodeSimm12"; } +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> { + let EncoderMethod = "getUImm3Mod8Encoding"; +} + +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 || + ((Imm % 4 == 0) && + Imm < 28 && Imm > 0);}]>; + +def immSExtAddius5 : ImmLeaf<i32, [{return Imm >= -8 && Imm <= 7;}]>; + +def immZExtAndi16 : ImmLeaf<i32, + [{return (Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || + Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || + Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535 );}]>; + +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 ptr_rc, 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_12 : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -12,6 +104,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"; } @@ -20,12 +128,29 @@ 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 brtarget_mm : Operand<OtherVT> { let EncoderMethod = "getBranchTargetOpValueMM"; let OperandType = "OPERAND_PCREL"; let DecoderMethod = "DecodeBranchTargetMM"; } +class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op, + RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, opnd:$offset), + !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 0; + let Defs = [AT]; +} + let canFoldAsLoad = 1 in class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, Operand MemOpnd> : @@ -45,6 +170,36 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, let DecoderMethod = "DecodeMemMMImm12"; } +/// 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> { @@ -70,6 +225,96 @@ class LoadMM<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, let mayLoad = 1; } +class ArithRMM16<string opstr, RegisterOperand RO, bit isComm = 0, + InstrItinClass Itin = NoItinerary, + SDPatternOperator OpNode = null_frag> : + MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, RO:$rt), + !strconcat(opstr, "\t$rd, $rs, $rt"), + [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> { + let isCommutable = isComm; +} + +class AndImmMM16<string opstr, RegisterOperand RO, + InstrItinClass Itin = NoItinerary> : + MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, uimm4_andi:$imm), + !strconcat(opstr, "\t$rd, $rs, $imm"), [], Itin, FrmI>; + +class LogicRMM16<string opstr, RegisterOperand RO, + InstrItinClass Itin = NoItinerary, + SDPatternOperator OpNode = null_frag> : + MicroMipsInst16<(outs RO:$dst), (ins RO:$rs, RO:$rt), + !strconcat(opstr, "\t$rt, $rs"), + [(set RO:$dst, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> { + let isCommutable = 1; + let Constraints = "$rt = $dst"; +} + +class NotMM16<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs RO:$rt), (ins RO:$rs), + !strconcat(opstr, "\t$rt, $rs"), + [(set RO:$rt, (not RO:$rs))], NoItinerary, FrmR>; + +class ShiftIMM16<string opstr, Operand ImmOpnd, RegisterOperand RO, + InstrItinClass Itin = NoItinerary> : + 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 AddImmUR2<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm), + !strconcat(opstr, "\t$rd, $rs, $imm"), + [], NoItinerary, FrmR> { + let isCommutable = 1; +} + +class AddImmUS5<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs RO:$dst), (ins RO:$rd, simm4:$imm), + !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmR> { + let Constraints = "$rd = $dst"; +} + +class AddImmUR1SP<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs RO:$rd), (ins uimm6_lsl2:$imm), + !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmR>; + +class AddImmUSP<string opstr> : + MicroMipsInst16<(outs), (ins simm9_addiusp:$imm), + !strconcat(opstr, "\t$imm"), [], NoItinerary, FrmI>; + class MoveFromHILOMM<string opstr, RegisterOperand RO, Register UseReg> : MicroMipsInst16<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], II_MFHI_MFLO, FrmR> { @@ -85,6 +330,12 @@ class MoveMM16<string opstr, RegisterOperand RO, bit isComm = 0, let isReMaterializable = 1; } +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; +} + // 16-bit Jump and Link (Call) class JumpLinkRegMM16<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), @@ -94,16 +345,207 @@ class JumpLinkRegMM16<string opstr, RegisterOperand RO> : let Defs = [RA]; } +// 16-bit Jump Reg +class JumpRegMM16<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [], IIBranch, FrmR> { + let hasDelaySlot = 1; + let isBranch = 1; + let isIndirectBranch = 1; +} + +// Base class for JRADDIUSP instruction. +class JumpRAddiuStackMM16 : + MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jraddiusp\t$imm", + [], IIBranch, FrmR> { + let isTerminator = 1; + let isBarrier = 1; + let isBranch = 1; + let isIndirectBranch = 1; +} + +// 16-bit Jump and Link (Call) - Short Delay Slot +class JumpLinkRegSMM16<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [], IIBranch, FrmR> { + let isCall = 1; + let hasDelaySlot = 1; + let Defs = [RA]; +} + +// 16-bit Jump Register Compact - No delay slot +class JumpRegCMM16<string opstr, RegisterOperand RO> : + MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [], IIBranch, FrmR> { + let isTerminator = 1; + let isBarrier = 1; + let isBranch = 1; + 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> : + InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), + [], IIBranch, FrmJ, opstr> { + let DecoderMethod = "DecodeJumpTargetMM"; + } + + class JumpLinkRegMM<string opstr, RegisterOperand RO>: + InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), + [], IIBranch, FrmR>; + + class BranchCompareToZeroLinkMM<string opstr, DAGOperand opnd, + RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, opnd:$offset), + !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr>; +} + +class LoadWordIndexedScaledMM<string opstr, RegisterOperand RO, + InstrItinClass Itin = NoItinerary, + SDPatternOperator OpNode = null_frag> : + InstSE<(outs RO:$rd), (ins PtrRC:$base, PtrRC:$index), + !strconcat(opstr, "\t$rd, ${index}(${base})"), [], Itin, FrmFI>; + +/// A list of registers used by load/store multiple instructions. +def RegListAsmOperand : AsmOperandClass { + let Name = "RegList"; + let ParserMethod = "parseRegisterList"; +} + +def reglist : Operand<i32> { + let EncoderMethod = "getRegisterListOpValue"; + let ParserMatchClass = RegListAsmOperand; + let PrintMethod = "printRegisterList"; + 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), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayStore = 1; +} + +class LoadMultMM<string opstr, + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : + InstSE<(outs reglist:$rt), (ins mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + 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 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 mayLoad = 1; +} + +def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, + ARITH_FM_MM16<0>; +def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, + ARITH_FM_MM16<1>; +def ANDI16_MM : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, ANDI_FM_MM16<0x0b>; +def AND16_MM : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, + LOGIC_FM_MM16<0x2>; +def OR16_MM : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, + LOGIC_FM_MM16<0x3>; +def XOR16_MM : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, + LOGIC_FM_MM16<0x1>; +def NOT16_MM : NotMM16<"not16", GPRMM16Opnd>, LOGIC_FM_MM16<0x0>; +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 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; +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", 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 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_"), [], NoItinerary, FrmOther, opstr>; let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { + /// Compact Branch Instructions + def BEQZC_MM : CompactBranchMM<"beqzc", brtarget_mm, seteq, GPR32Opnd>, + COMPACT_BRANCH_FM_MM<0x7>; + def BNEZC_MM : CompactBranchMM<"bnezc", brtarget_mm, setne, GPR32Opnd>, + COMPACT_BRANCH_FM_MM<0x5>; + /// Arithmetic Instructions (ALU Immediate) def ADDiu_MM : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd>, ADDI_FM_MM<0xc>; @@ -179,6 +621,8 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SW_MM : Store<"sw", GPR32Opnd>, MMRel, LW_FM_MM<0x3e>; } + def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>; + def LWU_MM : LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU>, LL_FM_MM<0xe>; /// Load and Store Instructions - unaligned @@ -191,6 +635,16 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12>, LWL_FM_MM<0x9>; + /// 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>; + /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, NoItinerary>, ADD_FM_MM<0, 0x58>; @@ -247,6 +701,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>; def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>; + /// Jump Instructions - Short Delay Slot + def JALS_MM : JumpLinkMM<"jals", calltarget_mm>, J_FM_MM<0x1d>; + def JALRS_MM : JumpLinkRegMM<"jalrs", GPR32Opnd>, JALR_FM_MM<0x13c>; + /// Branch Instructions def BEQ_MM : MMRel, CBranch<"beq", brtarget_mm, seteq, GPR32Opnd>, BEQ_FM_MM<0x25>; @@ -265,6 +723,12 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def BLTZAL_MM : MMRel, BGEZAL_FT<"bltzal", brtarget_mm, GPR32Opnd>, BGEZAL_FM_MM<0x01>; + /// Branch Instructions - Short Delay Slot + def BGEZALS_MM : BranchCompareToZeroLinkMM<"bgezals", brtarget_mm, + GPR32Opnd>, BGEZAL_FM_MM<0x13>; + def BLTZALS_MM : BranchCompareToZeroLinkMM<"bltzals", brtarget_mm, + GPR32Opnd>, BGEZAL_FM_MM<0x11>; + /// Control Instructions def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM; def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM; @@ -295,12 +759,66 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { /// Load-linked, Store-conditional 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>; + def TLBWR_MM : MMRel, TLB<"tlbwr">, COP0_TLB_FM_MM<0xcd>; + + def SDBBP_MM : MMRel, SYS_FT<"sdbbp">, SDBBP_FM_MM; + def RDHWR_MM : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM_MM; } +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), + (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>; +def : MipsPat<(add GPR32:$src, immSExt16:$imm), + (ADDiu_MM GPR32:$src, immSExt16:$imm)>; + +def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), + (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>; +def : MipsPat<(and GPR32:$src, immZExt16:$imm), + (ANDi_MM GPR32:$src, immZExt16:$imm)>; + +def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm), + (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>; +def : MipsPat<(shl GPR32:$src, immZExt5:$imm), + (SLL_MM GPR32:$src, immZExt5:$imm)>; + +def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), + (SRL16_MM GPRMM16:$src, immZExt2Shift:$imm)>; +def : MipsPat<(srl GPR32:$src, immZExt5:$imm), + (SRL_MM GPR32:$src, immZExt5:$imm)>; + //===----------------------------------------------------------------------===// // MicroMips instruction aliases //===----------------------------------------------------------------------===// -let Predicates = [InMicroMips] in { 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 d512d6589c40..87f1b0440132 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TARGET_MIPS_H -#define TARGET_MIPS_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS_H +#define LLVM_LIB_TARGET_MIPS_MIPS_H #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" @@ -26,8 +26,6 @@ namespace llvm { FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM); - FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM, - JITCodeEmitter &JCE); FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm); } // end namespace llvm; diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp index 93706c2c3fcc..6070276529e3 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.getTarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().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.getTarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().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.getTarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().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.getTarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); const MipsRegisterInfo &RI = TII.getRegisterInfo(); const BitVector Reserved = RI.getReservedRegs(MF); bool SaveS2 = Reserved[Mips::S2]; diff --git a/lib/Target/Mips/Mips16FrameLowering.h b/lib/Target/Mips/Mips16FrameLowering.h index 1fb7eda0e915..012d558d61a5 100644 --- a/lib/Target/Mips/Mips16FrameLowering.h +++ b/lib/Target/Mips/Mips16FrameLowering.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS16_FRAMEINFO_H -#define MIPS16_FRAMEINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16FRAMELOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPS16FRAMELOWERING_H #include "MipsFrameLowering.h" diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index 14055d608e11..32dc90af2ef4 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); @@ -403,7 +403,7 @@ static bool fixupFPReturnAndCall Attribute::ReadNone); A = A.addAttribute(C, AttributeSet::FunctionIndex, Attribute::NoInline); - Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, NULL)); + Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr)); CallInst::Create(F, Params, "", &Inst ); } else if (const CallInst *CI = dyn_cast<CallInst>(I)) { const Value* V = CI->getCalledValue(); @@ -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 826887ea5ebe..586cc252353b 100644 --- a/lib/Target/Mips/Mips16HardFloat.h +++ b/lib/Target/Mips/Mips16HardFloat.h @@ -12,40 +12,29 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOAT_H +#define LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOAT_H + #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsTargetMachine.h" #include "llvm/Pass.h" #include "llvm/Target/TargetMachine.h" - -#ifndef MIPS16HARDFLOAT_H -#define MIPS16HARDFLOAT_H - 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/Mips16HardFloatInfo.h b/lib/Target/Mips/Mips16HardFloatInfo.h index 02444d98c140..7295c287576d 100644 --- a/lib/Target/Mips/Mips16HardFloatInfo.h +++ b/lib/Target/Mips/Mips16HardFloatInfo.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS16HARDFLOATINFO_H -#define MIPS16HARDFLOATINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOATINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOATINFO_H namespace llvm { diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index 7b0584255542..36b3ac9c8043 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -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.getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().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.getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg(); @@ -135,8 +134,9 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { switch (SD->getMemoryVT().getSizeInBits()) { case 8: case 16: - AliasReg = TM.getFrameLowering()->hasFP(*MF)? - AliasFPReg: getMips16SPAliasReg(); + AliasReg = TM.getSubtargetImpl()->getFrameLowering()->hasFP(*MF) + ? AliasFPReg + : getMips16SPAliasReg(); return; } break; @@ -146,8 +146,9 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { switch (SD->getMemoryVT().getSizeInBits()) { case 8: case 16: - AliasReg = TM.getFrameLowering()->hasFP(*MF)? - AliasFPReg: getMips16SPAliasReg(); + AliasReg = TM.getSubtargetImpl()->getFrameLowering()->hasFP(*MF) + ? AliasFPReg + : getMips16SPAliasReg(); return; } break; diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h index e653b3910306..ae0e61e19d9d 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS16ISELDAGTODAG_H -#define MIPS16ISELDAGTODAG_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16ISELDAGTODAG_H +#define LLVM_LIB_TARGET_MIPS_MIPS16ISELDAGTODAG_H #include "MipsISelDAGToDAG.h" diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index 9576fd48a215..d4852c4ece40 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "Mips16ISelLowering.h" #include "MCTargetDesc/MipsBaseInfo.h" +#include "Mips16HardFloatInfo.h" +#include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsTargetMachine.h" #include "llvm/ADT/StringRef.h" @@ -27,7 +29,7 @@ using namespace llvm; static cl::opt<bool> DontExpandCondPseudos16( "mips16-dont-expand-cond-pseudo", cl::init(false), - cl::desc("Dont expand conditional move related " + cl::desc("Don't expand conditional move related " "pseudos for Mips 16"), cl::Hidden); @@ -118,7 +120,7 @@ static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = { {"truncf", "__mips16_call_stub_sf_1"}, }; -Mips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM, +Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) : MipsTargetLowering(TM, STI) { @@ -151,15 +153,16 @@ Mips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM, } const MipsTargetLowering * -llvm::createMips16TargetLowering(MipsTargetMachine &TM, +llvm::createMips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) { return new Mips16TargetLowering(TM, STI); } bool -Mips16TargetLowering::allowsUnalignedMemoryAccesses(EVT VT, - unsigned, - bool *Fast) const { +Mips16TargetLowering::allowsMisalignedMemoryAccesses(EVT VT, + unsigned, + unsigned, + bool *Fast) const { return false; } @@ -318,7 +321,7 @@ unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber } // -// prefixs are attached to stub numbers depending on the return type . +// Prefixes are attached to stub numbers depending on the return type. // return type: float sf_ // double df_ // single complex sc_ @@ -329,17 +332,16 @@ unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber // The full name of a helper function is__mips16_call_stub + // return type dependent prefix + stub number // -// -// This is something that probably should be in a different source file and -// perhaps done differently but my main purpose is to not waste runtime +// FIXME: This is something that probably should be in a different source file +// and perhaps done differently but my main purpose is to not waste runtime // on something that we can enumerate in the source. Another possibility is // to have a python script to generate these mapping tables. This will do // for now. There are a whole series of helper function mapping arrays, one // for each return type class as outlined above. There there are 11 possible -// entries. Ones with 0 are ones which should never be selected +// entries. Ones with 0 are ones which should never be selected. // // All the arrays are similar except for ones which return neither -// sf, df, sc, dc, in which only care about ones which have sf or df as a +// sf, df, sc, dc, in which we only care about ones which have sf or df as a // first parameter. // #define P_ "__mips16_call_stub_" @@ -421,7 +423,8 @@ void Mips16TargetLowering:: getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const { SelectionDAG &DAG = CLI.DAG; MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); @@ -511,14 +514,16 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, Ops.push_back(JumpTarget); MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, - InternalLinkage, CLI, Callee, Chain); + InternalLinkage, IsCallReloc, CLI, Callee, + Chain); } MachineBasicBlock *Mips16TargetLowering:: emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->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,7 +585,8 @@ MachineBasicBlock *Mips16TargetLowering::emitSelT16 MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->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 @@ -644,7 +650,8 @@ MachineBasicBlock *Mips16TargetLowering::emitSeliT16 MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->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 @@ -709,7 +716,8 @@ MachineBasicBlock MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); unsigned regX = MI->getOperand(0).getReg(); unsigned regY = MI->getOperand(1).getReg(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); @@ -725,7 +733,8 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); unsigned regX = MI->getOperand(0).getReg(); int64_t imm = MI->getOperand(1).getImm(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); @@ -759,7 +768,8 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins( MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); unsigned CC = MI->getOperand(0).getReg(); unsigned regX = MI->getOperand(1).getReg(); unsigned regY = MI->getOperand(2).getReg(); @@ -776,7 +786,8 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRXI16_ins( MachineInstr *MI, MachineBasicBlock *BB )const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->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/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h index 1649fe68b770..d3b9f750f347 100644 --- a/lib/Target/Mips/Mips16ISelLowering.h +++ b/lib/Target/Mips/Mips16ISelLowering.h @@ -11,19 +11,20 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS16ISELLOWERING_H -#define MIPS16ISELLOWERING_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16ISELLOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPS16ISELLOWERING_H #include "MipsISelLowering.h" namespace llvm { class Mips16TargetLowering : public MipsTargetLowering { public: - explicit Mips16TargetLowering(MipsTargetMachine &TM, + explicit Mips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI); - bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AddrSpace, - bool *Fast) const override; + bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, + unsigned Align, + bool *Fast) const override; MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, @@ -46,7 +47,7 @@ namespace llvm { getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const override; MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr *MI, @@ -78,4 +79,4 @@ namespace llvm { }; } -#endif // Mips16ISELLOWERING_H +#endif diff --git a/lib/Target/Mips/Mips16InstrFormats.td b/lib/Target/Mips/Mips16InstrFormats.td index da3a1f114af3..4ff68bef957e 100644 --- a/lib/Target/Mips/Mips16InstrFormats.td +++ b/lib/Target/Mips/Mips16InstrFormats.td @@ -591,7 +591,7 @@ class FEXT_I816<bits<3> _funct, dag outs, dag ins, string asmstr, bits<3> funct; let funct = _funct; - let I8 = 0b0110; + let I8 = 0b00110; let Inst{26-21} = imm16{10-5}; let Inst{20-16} = imm16{15-11}; diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index 4dd9af24968d..976beccfed9d 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.h b/lib/Target/Mips/Mips16InstrInfo.h index a004c567e6c9..e7d0c07f36c5 100644 --- a/lib/Target/Mips/Mips16InstrInfo.h +++ b/lib/Target/Mips/Mips16InstrInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS16INSTRUCTIONINFO_H -#define MIPS16INSTRUCTIONINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H #include "Mips16RegisterInfo.h" #include "MipsInstrInfo.h" diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index 5e4eebb62c12..10fff03b7240 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]; } @@ -1771,9 +1771,9 @@ def: Mips16Pat // // For constants, llvm transforms this to: -// x > (k -1) and then reverses the operands to use setlt. So this pattern +// x > (k - 1) and then reverses the operands to use setlt. So this pattern // is not used now by the compiler. (Presumably checking that k-1 does not -// overflow). The compiler never uses this at a the current time, due to +// overflow). The compiler never uses this at the current time, due to // other optimizations. // //def: Mips16Pat @@ -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 dbee774637dd..0bb452a3f7d5 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()->getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().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.getTarget().getFrameLowering(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); if (TFI->hasFP(MF)) { FrameReg = Mips::S0; } @@ -140,8 +140,8 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, DebugLoc DL = II->getDebugLoc(); unsigned NewImm; const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo*>( - MBB.getParent()->getTarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>( + MBB.getParent()->getSubtarget().getInstrInfo()); FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm); Offset = SignExtend64<16>(NewImm); IsKill = true; diff --git a/lib/Target/Mips/Mips16RegisterInfo.h b/lib/Target/Mips/Mips16RegisterInfo.h index f59f1a7c1098..3cdf836134a8 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.h +++ b/lib/Target/Mips/Mips16RegisterInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS16REGISTERINFO_H -#define MIPS16REGISTERINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPS16REGISTERINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPS16REGISTERINFO_H #include "MipsRegisterInfo.h" diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td index e4ec96a92f5b..e9a4289ec247 100644 --- a/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/lib/Target/Mips/Mips32r6InstrFormats.td @@ -403,7 +403,7 @@ class JMP_IDX_COMPACT_FM<bits<6> funct> : MipsR6Inst { bits<32> Inst; let Inst{31-26} = funct; - let Inst{25-21} = 0b000000; + let Inst{25-21} = 0b00000; let Inst{20-16} = rt; let Inst{15-0} = offset; } diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index f2072a6c06e3..bfe2ba011957 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -290,7 +290,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,7 +299,8 @@ 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"; } @@ -446,28 +448,22 @@ def : MipsInstAlias<"move $dst, $src", GPR_64; def : MipsInstAlias<"daddu $rs, $rt, $imm", (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), - 0>; + 0>, ISA_MIPS3; def : MipsInstAlias<"dadd $rs, $rt, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), 0>, ISA_MIPS3_NOT_32R6_64R6; def : MipsInstAlias<"daddu $rs, $imm", (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), - 0>; + 0>, ISA_MIPS3; def : MipsInstAlias<"dadd $rs, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), 0>, ISA_MIPS3_NOT_32R6_64R6; -def : MipsInstAlias<"add $rs, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), - 0>; -def : MipsInstAlias<"addu $rs, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), - 0>; def : MipsInstAlias<"dsll $rd, $rt, $rs", (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; def : MipsInstAlias<"dsubu $rt, $rs, $imm", (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs, - InvertedImOperand64:$imm), 0>; + InvertedImOperand64:$imm), 0>, ISA_MIPS3; def : MipsInstAlias<"dsubi $rs, $rt, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, InvertedImOperand64:$imm), @@ -487,7 +483,7 @@ def : MipsInstAlias<"dsub $rs, $imm", def : MipsInstAlias<"dsubu $rs, $imm", (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, InvertedImOperand64:$imm), - 0>; + 0>, ISA_MIPS3; def : MipsInstAlias<"dsra $rd, $rt, $rs", (DSRAV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; @@ -514,3 +510,9 @@ def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0 def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>; +let Predicates = [HasMips64, HasCnMips] in { +def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>; +def : MipsInstAlias<"syncs", (SYNC 0x6), 0>; +def : MipsInstAlias<"syncw", (SYNC 0x4), 0>; +def : MipsInstAlias<"syncws", (SYNC 0x5), 0>; +} diff --git a/lib/Target/Mips/MipsAnalyzeImmediate.cpp b/lib/Target/Mips/MipsAnalyzeImmediate.cpp index 31a9b7d63983..161345d2a845 100644 --- a/lib/Target/Mips/MipsAnalyzeImmediate.cpp +++ b/lib/Target/Mips/MipsAnalyzeImmediate.cpp @@ -72,7 +72,8 @@ void MipsAnalyzeImmediate::GetInstSeqLs(uint64_t Imm, unsigned RemSize, if (Imm & 0x8000) { InstSeqLs SeqLsORi; GetInstSeqLsORi(Imm, RemSize, SeqLsORi); - SeqLs.insert(SeqLs.end(), SeqLsORi.begin(), SeqLsORi.end()); + SeqLs.append(std::make_move_iterator(SeqLsORi.begin()), + std::make_move_iterator(SeqLsORi.end())); } } diff --git a/lib/Target/Mips/MipsAnalyzeImmediate.h b/lib/Target/Mips/MipsAnalyzeImmediate.h index cc09034a9c39..ae3c38ced80b 100644 --- a/lib/Target/Mips/MipsAnalyzeImmediate.h +++ b/lib/Target/Mips/MipsAnalyzeImmediate.h @@ -6,8 +6,8 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef MIPS_ANALYZE_IMMEDIATE_H -#define MIPS_ANALYZE_IMMEDIATE_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSANALYZEIMMEDIATE_H +#define LLVM_LIB_TARGET_MIPS_MIPSANALYZEIMMEDIATE_H #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 14463fce0dc3..50c0441e0dd4 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -53,7 +53,7 @@ using namespace llvm; #define DEBUG_TYPE "mips-asm-printer" -MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() { +MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { return static_cast<MipsTargetStreamer &>(*OutStreamer.getTargetStreamer()); } @@ -131,7 +131,7 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsTargetStreamer &TS = getTargetStreamer(); - TS.setCanHaveModuleDir(false); + TS.forbidModuleDirective(); if (MI->isDebugValue()) { SmallString<128> Str; @@ -266,7 +266,8 @@ void MipsAsmPrinter::printSavedRegsBitmask() { if (Mips::GPR32RegClass.contains(Reg)) break; - unsigned RegNum = TM.getRegisterInfo()->getEncodingValue(Reg); + unsigned RegNum = + TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg); if (Mips::AFGR64RegClass.contains(Reg)) { FPUBitmask |= (3 << RegNum); CSFPRegsSize += AFGR64RegSize; @@ -281,7 +282,8 @@ void MipsAsmPrinter::printSavedRegsBitmask() { // Set CPU Bitmask. for (; i != e; ++i) { unsigned Reg = CSI[i].getReg(); - unsigned RegNum = TM.getRegisterInfo()->getEncodingValue(Reg); + unsigned RegNum = + TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg); CPUBitmask |= (1 << RegNum); } @@ -306,7 +308,7 @@ void MipsAsmPrinter::printSavedRegsBitmask() { /// Frame Directive void MipsAsmPrinter::emitFrameDirective() { - const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + const TargetRegisterInfo &RI = *TM.getSubtargetImpl()->getRegisterInfo(); unsigned stackReg = RI.getFrameRegister(*MF); unsigned returnReg = RI.getRARegister(); @@ -558,7 +560,7 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); const MachineOperand &MO = MI->getOperand(opNum); bool closeP = false; @@ -643,6 +645,18 @@ printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern lw $25,%call16($28) + + // opNum can be invalid if instruction has reglist as operand. + // MemOperand is always last operand of instruction (base + offset). + switch (MI->getOpcode()) { + default: + break; + case Mips::SWM32_MM: + case Mips::LWM32_MM: + opNum = MI->getNumOperands() - 2; + break; + } + printOperand(MI, opNum+1, O); O << "("; printOperand(MI, opNum, O); @@ -666,6 +680,14 @@ printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } +void MipsAsmPrinter:: +printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { + for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) { + if (i != opNum) O << ", "; + printOperand(MI, i, O); + } +} + void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { bool IsABICalls = Subtarget->isABICalls(); if (IsABICalls) { @@ -721,6 +743,29 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { Subtarget->isABI_O32()); } +void MipsAsmPrinter::emitInlineAsmStart( + const MCSubtargetInfo &StartInfo) 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::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, + const MCSubtargetInfo *EndInfo) const { + OutStreamer.AddBlankLine(); + getTargetStreamer().emitDirectiveSetPop(); +} + void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) { MCInst I; I.setOpcode(Mips::JAL); @@ -929,7 +974,7 @@ void MipsAsmPrinter::EmitFPCallStub( // called otherwise. when the full stub generation is moved here // we need to deal with pic. // - if (Subtarget->getRelocationModel() == Reloc::PIC_) + if (TM.getRelocationModel() == Reloc::PIC_) llvm_unreachable("should not be here if we are compiling pic"); TS.emitDirectiveSetReorder(); // diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index abbd39b571a5..723155f5dd60 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSASMPRINTER_H -#define MIPSASMPRINTER_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSASMPRINTER_H +#define LLVM_LIB_TARGET_MIPS_MIPSASMPRINTER_H #include "Mips16HardFloatInfo.h" #include "MipsMCInstLower.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,6 +60,11 @@ private: std::map<const char *, const llvm::Mips16HardFloatInfo::FuncSignature *> StubsNeeded; + void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const override; + + void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, + const MCSubtargetInfo *EndInfo) const override; + void EmitJal(MCSymbol *Symbol); void EmitInstrReg(unsigned Opcode, unsigned Reg); @@ -134,6 +139,7 @@ public: void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = nullptr); + void printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O); void EmitStartOfAsmFile(Module &M) override; void EmitEndOfAsmFile(Module &M) override; void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); diff --git a/lib/Target/Mips/MipsCCState.h b/lib/Target/Mips/MipsCCState.h index 026b7b5e3275..9a08adef3823 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; @@ -65,10 +65,9 @@ private: public: MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs, - LLVMContext &C, + SmallVectorImpl<CCValAssign> &locs, LLVMContext &C, SpecialCallingConvType SpecialCC = NoSpecialCallingConv) - : CCState(CC, isVarArg, MF, TM, locs, C), SpecialCallingConv(SpecialCC) {} + : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 76297dcbbcf1..90bf9f3f5835 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -12,14 +12,37 @@ /// CCIfSubtarget - Match if the current subtarget has a feature F. class CCIfSubtarget<string F, CCAction A, string Invert = ""> : CCIf<!strconcat(Invert, - "State.getMachineFunction().getTarget()." - "getSubtarget<const MipsSubtarget>().", + "static_cast<const MipsSubtarget&>" + "(State.getMachineFunction().getSubtarget()).", F), A>; // 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]> @@ -51,6 +74,19 @@ def RetCC_F128 : CallingConv<[ // Mips O32 Calling Convention //===----------------------------------------------------------------------===// +def CC_MipsO32 : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i1, i8, i16], CCPromoteToType<i32>>, + + // Integer values get stored in stack slots that are 4 bytes in + // size and 4-byte aligned. + CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + + // Integer values get stored in stack slots that are 8 bytes in + // size and 8-byte aligned. + CCIfType<[f64], CCAssignToStack<8, 8>> +]>; + // Only the return rules are defined here for O32. The rules for argument // passing are defined in MipsISelLowering.cpp. def RetCC_MipsO32 : CallingConv<[ @@ -92,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>>>, @@ -149,9 +183,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 @@ -317,8 +349,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>>, @@ -335,8 +366,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>>, @@ -356,9 +386,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/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp deleted file mode 100644 index 794c71898fa3..000000000000 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ /dev/null @@ -1,481 +0,0 @@ -//===-- Mips/MipsCodeEmitter.cpp - Convert Mips Code to Machine Code ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===---------------------------------------------------------------------===// -// -// This file contains the pass that transforms the Mips machine instructions -// into relocatable machine code. -// -//===---------------------------------------------------------------------===// - -#include "Mips.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsInstrInfo.h" -#include "MipsRelocations.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/JITCodeEmitter.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/PassManager.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#ifndef NDEBUG -#include <iomanip> -#endif - -using namespace llvm; - -#define DEBUG_TYPE "jit" - -STATISTIC(NumEmitted, "Number of machine instructions emitted"); - -namespace { - -class MipsCodeEmitter : public MachineFunctionPass { - MipsJITInfo *JTI; - const MipsInstrInfo *II; - const DataLayout *TD; - const MipsSubtarget *Subtarget; - TargetMachine &TM; - JITCodeEmitter &MCE; - const std::vector<MachineConstantPoolEntry> *MCPEs; - const std::vector<MachineJumpTableEntry> *MJTEs; - bool IsPIC; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<MachineModuleInfo> (); - MachineFunctionPass::getAnalysisUsage(AU); - } - - static char ID; - -public: - MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) - : MachineFunctionPass(ID), JTI(nullptr), II(nullptr), TD(nullptr), - TM(tm), MCE(mce), MCPEs(nullptr), MJTEs(nullptr), - IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} - - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - return "Mips Machine Code Emitter"; - } - - /// getBinaryCodeForInstr - This function, generated by the - /// CodeEmitterGenerator using TableGen, produces the binary encoding for - /// machine instructions. - uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const; - - void emitInstruction(MachineBasicBlock::instr_iterator MI, - MachineBasicBlock &MBB); - -private: - - void emitWord(unsigned Word); - - /// Routines that handle operands which add machine relocations which are - /// fixed up by the relocation stage. - void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, - bool MayNeedFarStub) const; - void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; - void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; - void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const; - void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const; - - /// getMachineOpValue - Return binary encoding of operand. If the machine - /// operand requires relocation, record the relocation and return zero. - unsigned getMachineOpValue(const MachineInstr &MI, - const MachineOperand &MO) const; - - unsigned getRelocation(const MachineInstr &MI, - const MachineOperand &MO) const; - - unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; - unsigned getJumpTargetOpValueMM(const MachineInstr &MI, unsigned OpNo) const; - unsigned getBranchTargetOpValueMM(const MachineInstr &MI, - unsigned OpNo) const; - - unsigned getBranchTarget21OpValue(const MachineInstr &MI, - unsigned OpNo) const; - unsigned getBranchTarget26OpValue(const MachineInstr &MI, - unsigned OpNo) const; - unsigned getJumpOffset16OpValue(const MachineInstr &MI, unsigned OpNo) const; - - unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; - unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; - unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const; - unsigned getMSAMemEncoding(const MachineInstr &MI, unsigned OpNo) const; - unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; - unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const; - unsigned getLSAImmEncoding(const MachineInstr &MI, unsigned OpNo) const; - unsigned getSimm19Lsl2Encoding(const MachineInstr &MI, unsigned OpNo) const; - unsigned getSimm18Lsl3Encoding(const MachineInstr &MI, unsigned OpNo) const; - - /// Expand pseudo instructions with accumulator register operands. - void expandACCInstr(MachineBasicBlock::instr_iterator MI, - MachineBasicBlock &MBB, unsigned Opc) const; - - void expandPseudoIndirectBranch(MachineBasicBlock::instr_iterator MI, - MachineBasicBlock &MBB) const; - - /// \brief Expand pseudo instruction. Return true if MI was expanded. - bool expandPseudos(MachineBasicBlock::instr_iterator &MI, - MachineBasicBlock &MBB) const; -}; -} - -char MipsCodeEmitter::ID = 0; - -bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { - MipsTargetMachine &Target = static_cast<MipsTargetMachine &>( - const_cast<TargetMachine &>(MF.getTarget())); - - JTI = Target.getJITInfo(); - II = Target.getInstrInfo(); - TD = Target.getDataLayout(); - Subtarget = &TM.getSubtarget<MipsSubtarget> (); - MCPEs = &MF.getConstantPool()->getConstants(); - MJTEs = nullptr; - if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); - JTI->Initialize(MF, IsPIC, Subtarget->isLittle()); - MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ()); - - do { - DEBUG(errs() << "JITTing function '" - << MF.getName() << "'\n"); - MCE.startFunction(MF); - - for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); - MBB != E; ++MBB){ - MCE.StartMachineBasicBlock(MBB); - for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), - E = MBB->instr_end(); I != E;) - emitInstruction(*I++, *MBB); - } - } while (MCE.finishFunction(MF)); - - return false; -} - -unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, - const MachineOperand &MO) const { - // NOTE: This relocations are for static. - uint64_t TSFlags = MI.getDesc().TSFlags; - uint64_t Form = TSFlags & MipsII::FormMask; - if (Form == MipsII::FrmJ) - return Mips::reloc_mips_26; - if ((Form == MipsII::FrmI || Form == MipsII::FrmFI) - && MI.isBranch()) - return Mips::reloc_mips_pc16; - if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi) - return Mips::reloc_mips_hi; - return Mips::reloc_mips_lo; -} - -unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI, - unsigned OpNo) const { - MachineOperand MO = MI.getOperand(OpNo); - if (MO.isGlobal()) - emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); - else if (MO.isSymbol()) - emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); - else if (MO.isMBB()) - emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); - else - llvm_unreachable("Unexpected jump target operand kind."); - return 0; -} - -unsigned MipsCodeEmitter::getJumpTargetOpValueMM(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getBranchTargetOpValueMM(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getBranchTarget21OpValue(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getBranchTarget26OpValue(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getJumpOffset16OpValue(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, - unsigned OpNo) const { - MachineOperand MO = MI.getOperand(OpNo); - emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); - return 0; -} - -unsigned MipsCodeEmitter::getMemEncoding(const MachineInstr &MI, - unsigned OpNo) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo)) << 16; - return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; -} - -unsigned MipsCodeEmitter::getMemEncodingMMImm12(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getMSAMemEncoding(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI, - unsigned OpNo) const { - // size is encoded as size-1. - return getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; -} - -unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, - unsigned OpNo) const { - // size is encoded as pos+size-1. - return getMachineOpValue(MI, MI.getOperand(OpNo-1)) + - getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; -} - -unsigned MipsCodeEmitter::getLSAImmEncoding(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getSimm18Lsl3Encoding(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -unsigned MipsCodeEmitter::getSimm19Lsl2Encoding(const MachineInstr &MI, - unsigned OpNo) const { - llvm_unreachable("Unimplemented function."); - return 0; -} - -/// getMachineOpValue - Return binary encoding of operand. If the machine -/// operand requires relocation, record the relocation and return zero. -unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, - const MachineOperand &MO) const { - if (MO.isReg()) - return TM.getRegisterInfo()->getEncodingValue(MO.getReg()); - else if (MO.isImm()) - return static_cast<unsigned>(MO.getImm()); - else if (MO.isGlobal()) - emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); - else if (MO.isSymbol()) - emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); - else if (MO.isCPI()) - emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); - else if (MO.isJTI()) - emitJumpTableAddress(MO.getIndex(), getRelocation(MI, MO)); - else if (MO.isMBB()) - emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); - else - llvm_unreachable("Unable to encode MachineOperand!"); - return 0; -} - -void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, - bool MayNeedFarStub) const { - MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, - const_cast<GlobalValue *>(GV), 0, - MayNeedFarStub)); -} - -void MipsCodeEmitter:: -emitExternalSymbolAddress(const char *ES, unsigned Reloc) const { - MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), - Reloc, ES, 0, 0)); -} - -void MipsCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { - MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), - Reloc, CPI, 0, false)); -} - -void MipsCodeEmitter:: -emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { - MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), - Reloc, JTIndex, 0, false)); -} - -void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, - unsigned Reloc) const { - MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), - Reloc, BB)); -} - -void MipsCodeEmitter::emitInstruction(MachineBasicBlock::instr_iterator MI, - MachineBasicBlock &MBB) { - DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << *MI); - - // Expand pseudo instruction. Skip if MI was not expanded. - if (((MI->getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo) && - !expandPseudos(MI, MBB)) - return; - - MCE.processDebugLoc(MI->getDebugLoc(), true); - - emitWord(getBinaryCodeForInstr(*MI)); - ++NumEmitted; // Keep track of the # of mi's emitted - - MCE.processDebugLoc(MI->getDebugLoc(), false); -} - -void MipsCodeEmitter::emitWord(unsigned Word) { - DEBUG(errs() << " 0x"; - errs().write_hex(Word) << "\n"); - if (Subtarget->isLittle()) - MCE.emitWordLE(Word); - else - MCE.emitWordBE(Word); -} - -void MipsCodeEmitter::expandACCInstr(MachineBasicBlock::instr_iterator MI, - MachineBasicBlock &MBB, - unsigned Opc) const { - // Expand "pseudomult $ac0, $t0, $t1" to "mult $t0, $t1". - BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Opc)) - .addReg(MI->getOperand(1).getReg()).addReg(MI->getOperand(2).getReg()); -} - -void MipsCodeEmitter::expandPseudoIndirectBranch( - MachineBasicBlock::instr_iterator MI, MachineBasicBlock &MBB) const { - // This logic is duplicated from MipsAsmPrinter::emitPseudoIndirectBranch() - bool HasLinkReg = false; - unsigned Opcode = 0; - - if (Subtarget->hasMips64r6()) { - // MIPS64r6 should use (JALR64 ZERO_64, $rs) - Opcode = Mips::JALR64; - HasLinkReg = true; - } else if (Subtarget->hasMips32r6()) { - // MIPS32r6 should use (JALR ZERO, $rs) - Opcode = Mips::JALR; - HasLinkReg = true; - } else if (Subtarget->inMicroMipsMode()) - // microMIPS should use (JR_MM $rs) - Opcode = Mips::JR_MM; - else { - // Everything else should use (JR $rs) - Opcode = Mips::JR; - } - - auto MIB = BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Opcode)); - - if (HasLinkReg) { - unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; - MIB.addReg(ZeroReg); - } - - MIB.addReg(MI->getOperand(0).getReg()); -} - -bool MipsCodeEmitter::expandPseudos(MachineBasicBlock::instr_iterator &MI, - MachineBasicBlock &MBB) const { - switch (MI->getOpcode()) { - default: - llvm_unreachable("Unhandled pseudo"); - return false; - case Mips::NOP: - BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Mips::SLL), Mips::ZERO) - .addReg(Mips::ZERO).addImm(0); - break; - case Mips::B: - BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Mips::BEQ)).addReg(Mips::ZERO) - .addReg(Mips::ZERO).addOperand(MI->getOperand(0)); - break; - case Mips::TRAP: - BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Mips::BREAK)).addImm(0) - .addImm(0); - break; - case Mips::JALRPseudo: - BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Mips::JALR), Mips::RA) - .addReg(MI->getOperand(0).getReg()); - break; - case Mips::PseudoMULT: - expandACCInstr(MI, MBB, Mips::MULT); - break; - case Mips::PseudoMULTu: - expandACCInstr(MI, MBB, Mips::MULTu); - break; - case Mips::PseudoSDIV: - expandACCInstr(MI, MBB, Mips::SDIV); - break; - case Mips::PseudoUDIV: - expandACCInstr(MI, MBB, Mips::UDIV); - break; - case Mips::PseudoMADD: - expandACCInstr(MI, MBB, Mips::MADD); - break; - case Mips::PseudoMADDU: - expandACCInstr(MI, MBB, Mips::MADDU); - break; - case Mips::PseudoMSUB: - expandACCInstr(MI, MBB, Mips::MSUB); - break; - case Mips::PseudoMSUBU: - expandACCInstr(MI, MBB, Mips::MSUBU); - break; - case Mips::PseudoReturn: - case Mips::PseudoReturn64: - case Mips::PseudoIndirectBranch: - case Mips::PseudoIndirectBranch64: - expandPseudoIndirectBranch(MI, MBB); - break; - case TargetOpcode::CFI_INSTRUCTION: - case TargetOpcode::IMPLICIT_DEF: - case TargetOpcode::KILL: - // Do nothing - return false; - } - - (MI--)->eraseFromBundle(); - return true; -} - -/// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips -/// code to the specified MCE object. -FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM, - JITCodeEmitter &JCE) { - return new MipsCodeEmitter(TM, JCE); -} - -#include "MipsGenCodeEmitter.inc" diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index 690f62608504..af10cd4e576c 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 76313b1d1a9d..c4e5ac0745d3 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -28,6 +28,7 @@ #include "MipsTargetMachine.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -452,7 +453,9 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { if (!STI->inMips16Mode() || !MipsSubtarget::useConstantIslands()) { return false; } - TII = (const Mips16InstrInfo*)MF->getTarget().getInstrInfo(); + TII = (const Mips16InstrInfo *)MF->getTarget() + .getSubtargetImpl() + ->getInstrInfo(); MFI = MF->getInfo<MipsFunctionInfo>(); DEBUG(dbgs() << "constant island processing " << "\n"); // @@ -559,7 +562,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->getTarget().getDataLayout(); + const DataLayout &TD = *MF->getSubtarget().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"); @@ -585,9 +588,7 @@ MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { if (InsPoint[a] == InsAt) InsPoint[a] = CPEMI; // Add a new CPEntry, but no corresponding CPUser yet. - std::vector<CPEntry> CPEs; - CPEs.push_back(CPEntry(CPEMI, i)); - CPEntries.push_back(CPEs); + CPEntries.emplace_back(1, CPEntry(CPEMI, i)); ++NumCPEs; DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = " << Size << ", align = " << Align <<'\n'); diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index bcfbc12df01c..d5027b9c3ca3 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -196,6 +196,9 @@ namespace { private: bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + Iter replaceWithCompactBranch(MachineBasicBlock &MBB, + Iter Branch, 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 +210,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,7 +278,11 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { #ifndef NDEBUG const MachineFunction &MF = *MBB.getParent(); - assert(MF.getTarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && + assert(MF.getTarget() + .getSubtargetImpl() + ->getRegisterInfo() + ->getAllocatableSet(MF) + .test(R) && "Shouldn't move an instruction with unallocatable registers across " "basic block boundaries."); #endif @@ -286,8 +293,8 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { } RegDefsUses::RegDefsUses(TargetMachine &TM) - : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(), false), - Uses(TRI.getNumRegs(), false) {} + : TRI(*TM.getSubtargetImpl()->getRegisterInfo()), + Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} void RegDefsUses::init(const MachineInstr &MI) { // Add all register operands which are explicit and non-variadic. @@ -451,7 +458,8 @@ bool MemDefsUses::hasHazard_(const MachineInstr &MI) { bool MemDefsUses::updateDefsUses(ValueType V, bool MayStore) { if (MayStore) - return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad; + return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore || + SeenNoObjLoad; Uses.insert(V); return Defs.count(V) || SeenNoObjStore; @@ -489,10 +497,55 @@ 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= static_cast<const MipsInstrInfo *>( + TM.getSubtargetImpl()->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; +} + +// 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 MipsInstrInfo *TII = + static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); for (Iter I = MBB.begin(); I != MBB.end(); ++I) { if (!hasUnoccupiedSlot(&*I)) @@ -503,22 +556,48 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { // Delay slot filling is disabled at -O0. if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { - if (searchBackward(MBB, I)) - continue; - - if (I->isTerminator()) { - if (searchSuccBBs(MBB, I)) - continue; + 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; } } - // Bundle the NOP to the instruction with the delay slot. - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); - BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); - MIBundleBuilder(MBB, I, std::next(I, 2)); + // 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 && + (Opcode == Mips::BEQ || Opcode == Mips::BNE) && + ((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { + + I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); + + } else { + // Bundle the NOP to the instruction with the delay slot. + BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); + MIBundleBuilder(MBB, I, std::next(I, 2)); + } } return Changed; @@ -533,7 +612,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()) @@ -554,12 +633,22 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, // branches are not checked because non-NaCl targets never put them in // delay slots. unsigned AddrIdx; - if ((isBasePlusOffsetMemoryAccess(I->getOpcode(), &AddrIdx) - && baseRegNeedsLoadStoreMask(I->getOperand(AddrIdx).getReg())) - || I->modifiesRegister(Mips::SP, TM.getRegisterInfo())) + if ((isBasePlusOffsetMemoryAccess(I->getOpcode(), &AddrIdx) && + baseRegNeedsLoadStoreMask(I->getOperand(AddrIdx).getReg())) || + I->modifiesRegister(Mips::SP, + TM.getSubtargetImpl()->getRegisterInfo())) continue; } + bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); + const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( + TM.getSubtargetImpl()->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; } @@ -577,7 +666,8 @@ bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot) const { 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()); @@ -597,7 +687,7 @@ bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { 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); @@ -640,7 +730,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); @@ -667,7 +758,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.getInstrInfo()); + static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->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 617801ba8c67..4588f40b84d5 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -2,42 +2,63 @@ //---------------------===// #include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "MipsCCState.h" +#include "MipsISelLowering.h" +#include "MipsMachineFunction.h" +#include "MipsRegisterInfo.h" +#include "MipsSubtarget.h" +#include "MipsTargetMachine.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 "MipsRegisterInfo.h" -#include "MipsISelLowering.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" using namespace llvm; namespace { -// All possible address modes. -typedef struct Address { - enum { RegBase, FrameIndexBase } BaseType; +class MipsFastISel final : public FastISel { - union { - unsigned Reg; - int FI; - } Base; + // All possible address modes. + class Address { + public: + typedef enum { RegBase, FrameIndexBase } BaseKind; - int64_t Offset; + private: + BaseKind Kind; + union { + unsigned Reg; + int FI; + } Base; - // Innocuous defaults for our address. - Address() : BaseType(RegBase), Offset(0) { Base.Reg = 0; } -} Address; + int64_t Offset; -class MipsFastISel final : public FastISel { + const GlobalValue *GV; + + public: + // Innocuous defaults for our address. + Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; } + void setKind(BaseKind K) { Kind = K; } + BaseKind getKind() const { return Kind; } + bool isRegBase() const { return Kind == RegBase; } + void setReg(unsigned Reg) { + assert(isRegBase() && "Invalid base register access!"); + Base.Reg = Reg; + } + unsigned getReg() const { + assert(isRegBase() && "Invalid base register access!"); + return Base.Reg; + } + void setOffset(int64_t Offset_) { Offset = Offset_; } + int64_t getOffset() const { return Offset; } + void setGlobalValue(const GlobalValue *G) { GV = G; } + const GlobalValue *getGlobalValue() { return GV; } + }; /// 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 TargetInstrInfo &TII; const TargetLowering &TLI; @@ -47,74 +68,265 @@ class MipsFastISel final : public FastISel { // Convenience variables to avoid some queries. LLVMContext *Context; - bool TargetSupported; + bool fastLowerCall(CallLoweringInfo &CLI) override; -public: - explicit MipsFastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo) - : FastISel(funcInfo, libInfo), - M(const_cast<Module &>(*funcInfo.Fn->getParent())), - TM(funcInfo.MF->getTarget()), TII(*TM.getInstrInfo()), - TLI(*TM.getTargetLowering()), - Subtarget(&TM.getSubtarget<MipsSubtarget>()) { - MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); - Context = &funcInfo.Fn->getContext(); - TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) && - (Subtarget->hasMips32r2() && (Subtarget->isABI_O32()))); - } + bool TargetSupported; + bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle + // floating point but not reject doing fast-isel in other + // situations - bool TargetSelectInstruction(const Instruction *I) override; - unsigned TargetMaterializeConstant(const Constant *C) override; +private: + // Selection routines. + bool selectLoad(const Instruction *I); + bool selectStore(const Instruction *I); + bool selectBranch(const Instruction *I); + bool selectCmp(const Instruction *I); + bool selectFPExt(const Instruction *I); + bool selectFPTrunc(const Instruction *I); + bool selectFPToInt(const Instruction *I, bool IsSigned); + bool selectRet(const Instruction *I); + bool selectTrunc(const Instruction *I); + bool selectIntExt(const Instruction *I); - bool ComputeAddress(const Value *Obj, Address &Addr); + // Utility helper routines. + bool isTypeLegal(Type *Ty, MVT &VT); + bool isLoadTypeLegal(Type *Ty, MVT &VT); + bool computeAddress(const Value *Obj, Address &Addr); + bool computeCallAddress(const Value *V, Address &Addr); -private: - bool EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, + // Emit helper routines. + bool emitCmp(unsigned DestReg, const CmpInst *CI); + bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, unsigned Alignment = 0); - bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr, + bool emitStore(MVT VT, unsigned SrcReg, Address Addr, + MachineMemOperand *MMO = nullptr); + bool emitStore(MVT VT, unsigned SrcReg, Address &Addr, unsigned Alignment = 0); - bool SelectLoad(const Instruction *I); - bool SelectRet(const Instruction *I); - bool SelectStore(const Instruction *I); + unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt); + bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, - bool isTypeLegal(Type *Ty, MVT &VT); - bool isLoadTypeLegal(Type *Ty, MVT &VT); + bool IsZExt); + bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); + + bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); + bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg); + bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg); + + unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned); - unsigned MaterializeFP(const ConstantFP *CFP, MVT VT); - unsigned MaterializeGV(const GlobalValue *GV, MVT VT); - unsigned MaterializeInt(const Constant *C, MVT VT); - unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); + unsigned materializeFP(const ConstantFP *CFP, MVT VT); + unsigned materializeGV(const GlobalValue *GV, MVT VT); + unsigned materializeInt(const Constant *C, MVT VT); + unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); + MachineInstrBuilder emitInst(unsigned Opc) { + return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); + } + MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) { + return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), + DstReg); + } + MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg, + unsigned MemReg, int64_t MemOffset) { + return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset); + } + MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg, + unsigned MemReg, int64_t MemOffset) { + return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); + } // for some reason, this default is not generated by tablegen // so we explicitly generate it here. // - unsigned FastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC, + unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t imm1, uint64_t imm2, unsigned Op3, bool Op3IsKill) { return 0; } - MachineInstrBuilder EmitInst(unsigned Opc) { - return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); + // Call handling routines. +private: + CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const; + bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs, + unsigned &NumBytes); + bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes); + +public: + // Backend specific FastISel code. + explicit MipsFastISel(FunctionLoweringInfo &funcInfo, + const TargetLibraryInfo *libInfo) + : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()), + TII(*TM.getSubtargetImpl()->getInstrInfo()), + TLI(*TM.getSubtargetImpl()->getTargetLowering()), + Subtarget(&TM.getSubtarget<MipsSubtarget>()) { + MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); + Context = &funcInfo.Fn->getContext(); + TargetSupported = ((TM.getRelocationModel() == Reloc::PIC_) && + ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) && + (Subtarget->isABI_O32()))); + UnsupportedFPMode = Subtarget->isFP64bit(); } - MachineInstrBuilder EmitInst(unsigned Opc, unsigned DstReg) { - return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), - DstReg); + unsigned fastMaterializeConstant(const Constant *C) override; + bool fastSelectInstruction(const Instruction *I) override; + +#include "MipsGenFastISel.inc" +}; +} // end anonymous namespace. + +static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State) LLVM_ATTRIBUTE_UNUSED; + +static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + llvm_unreachable("should not be called"); +} + +bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State) { + llvm_unreachable("should not be called"); +} + +#include "MipsGenCallingConv.inc" + +CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { + return CC_MipsO32; +} + +unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) { + if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) + return 0; + const TargetRegisterClass *RC = &Mips::GPR32RegClass; + const ConstantInt *CI = cast<ConstantInt>(C); + int64_t Imm; + if ((VT != MVT::i1) && CI->isNegative()) + Imm = CI->getSExtValue(); + else + Imm = CI->getZExtValue(); + return materialize32BitInt(Imm, RC); +} + +unsigned MipsFastISel::materialize32BitInt(int64_t Imm, + const TargetRegisterClass *RC) { + unsigned ResultReg = createResultReg(RC); + + if (isInt<16>(Imm)) { + unsigned Opc = Mips::ADDiu; + emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm); + return ResultReg; + } else if (isUInt<16>(Imm)) { + emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm); + return ResultReg; } + unsigned Lo = Imm & 0xFFFF; + unsigned Hi = (Imm >> 16) & 0xFFFF; + if (Lo) { + // Both Lo and Hi have nonzero bits. + unsigned TmpReg = createResultReg(RC); + emitInst(Mips::LUi, TmpReg).addImm(Hi); + emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo); + } else { + emitInst(Mips::LUi, ResultReg).addImm(Hi); + } + return ResultReg; +} - MachineInstrBuilder EmitInstStore(unsigned Opc, unsigned SrcReg, - unsigned MemReg, int64_t MemOffset) { - return EmitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset); +unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) { + if (UnsupportedFPMode) + return 0; + int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + if (VT == MVT::f32) { + const TargetRegisterClass *RC = &Mips::FGR32RegClass; + unsigned DestReg = createResultReg(RC); + unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass); + emitInst(Mips::MTC1, DestReg).addReg(TempReg); + return DestReg; + } else if (VT == MVT::f64) { + const TargetRegisterClass *RC = &Mips::AFGR64RegClass; + unsigned DestReg = createResultReg(RC); + unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass); + unsigned TempReg2 = + materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass); + emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1); + return DestReg; } + return 0; +} - MachineInstrBuilder EmitInstLoad(unsigned Opc, unsigned DstReg, - unsigned MemReg, int64_t MemOffset) { - return EmitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); +unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) { + // For now 32-bit only. + if (VT != MVT::i32) + return 0; + const TargetRegisterClass *RC = &Mips::GPR32RegClass; + unsigned DestReg = createResultReg(RC); + const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); + bool IsThreadLocal = GVar && GVar->isThreadLocal(); + // TLS not supported at this time. + if (IsThreadLocal) + return 0; + emitInst(Mips::LW, DestReg) + .addReg(MFI->getGlobalBaseReg()) + .addGlobalAddress(GV, 0, MipsII::MO_GOT); + if ((GV->hasInternalLinkage() || + (GV->hasLocalLinkage() && !isa<Function>(GV)))) { + unsigned TempReg = createResultReg(RC); + emitInst(Mips::ADDiu, TempReg) + .addReg(DestReg) + .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO); + DestReg = TempReg; } + return DestReg; +} -#include "MipsGenFastISel.inc" -}; +// Materialize a constant into a register, and return the register +// number (or zero if we failed to handle it). +unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { + EVT CEVT = TLI.getValueType(C->getType(), true); + + // Only handle simple types. + if (!CEVT.isSimple()) + return 0; + MVT VT = CEVT.getSimpleVT(); + + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) + return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT); + else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) + return materializeGV(GV, VT); + else if (isa<ConstantInt>(C)) + return materializeInt(C, VT); + + return 0; +} + +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)) + return false; + Addr.setReg(getRegForValue(Obj)); + return Addr.getReg() != 0; +} + +bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) { + const GlobalValue *GV = dyn_cast<GlobalValue>(V); + if (GV && isa<Function>(GV) && dyn_cast<Function>(GV)->isIntrinsic()) + return false; + if (!GV) + return false; + if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { + Addr.setGlobalValue(GV); + return true; + } + return false; +} bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { EVT evt = TLI.getValueType(Ty, true); @@ -138,21 +350,134 @@ bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { return true; return false; } - -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)) +// Because of how EmitCmp is called with fast-isel, you can +// end up with redundant "andi" instructions after the sequences emitted below. +// We should try and solve this issue in the future. +// +bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { + const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1); + bool IsUnsigned = CI->isUnsigned(); + unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned); + if (LeftReg == 0) return false; - else if (isa<ConstantExpr>(Obj)) + unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned); + if (RightReg == 0) return false; - Addr.Base.Reg = getRegForValue(Obj); - return Addr.Base.Reg != 0; -} + CmpInst::Predicate P = CI->getPredicate(); -bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, + switch (P) { + default: + return false; + case CmpInst::ICMP_EQ: { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); + emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1); + break; + } + case CmpInst::ICMP_NE: { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); + emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg); + break; + } + case CmpInst::ICMP_UGT: { + emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg); + break; + } + case CmpInst::ICMP_ULT: { + emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg); + break; + } + case CmpInst::ICMP_UGE: { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg); + emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); + break; + } + case CmpInst::ICMP_ULE: { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg); + emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); + break; + } + case CmpInst::ICMP_SGT: { + emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg); + break; + } + case CmpInst::ICMP_SLT: { + emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg); + break; + } + case CmpInst::ICMP_SGE: { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg); + emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); + break; + } + case CmpInst::ICMP_SLE: { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg); + emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); + break; + } + case CmpInst::FCMP_OEQ: + case CmpInst::FCMP_UNE: + case CmpInst::FCMP_OLT: + case CmpInst::FCMP_OLE: + case CmpInst::FCMP_OGT: + case CmpInst::FCMP_OGE: { + if (UnsupportedFPMode) + return false; + bool IsFloat = Left->getType()->isFloatTy(); + bool IsDouble = Left->getType()->isDoubleTy(); + if (!IsFloat && !IsDouble) + return false; + unsigned Opc, CondMovOpc; + switch (P) { + case CmpInst::FCMP_OEQ: + Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; + CondMovOpc = Mips::MOVT_I; + break; + case CmpInst::FCMP_UNE: + Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; + CondMovOpc = Mips::MOVF_I; + break; + case CmpInst::FCMP_OLT: + Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32; + CondMovOpc = Mips::MOVT_I; + break; + case CmpInst::FCMP_OLE: + Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32; + CondMovOpc = Mips::MOVT_I; + break; + case CmpInst::FCMP_OGT: + Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32; + CondMovOpc = Mips::MOVF_I; + break; + case CmpInst::FCMP_OGE: + Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32; + CondMovOpc = Mips::MOVF_I; + break; + default: + llvm_unreachable("Only switching of a subset of CCs."); + } + unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass); + unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0); + emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1); + emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg( + Mips::FCC0, RegState::ImplicitDefine); + MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg) + .addReg(RegWithOne) + .addReg(Mips::FCC0) + .addReg(RegWithZero, RegState::Implicit); + MI->tieOperands(0, 3); + break; + } + } + return true; +} +bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, unsigned Alignment) { // // more cases will be handled here in following patches. @@ -175,11 +500,15 @@ bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, break; } case MVT::f32: { + if (UnsupportedFPMode) + return false; ResultReg = createResultReg(&Mips::FGR32RegClass); Opc = Mips::LWC1; break; } case MVT::f64: { + if (UnsupportedFPMode) + return false; ResultReg = createResultReg(&Mips::AFGR64RegClass); Opc = Mips::LDC1; break; @@ -187,31 +516,11 @@ bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, default: return false; } - EmitInstLoad(Opc, ResultReg, Addr.Base.Reg, Addr.Offset); + emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); return true; } -// Materialize a constant into a register, and return the register -// number (or zero if we failed to handle it). -unsigned MipsFastISel::TargetMaterializeConstant(const Constant *C) { - EVT CEVT = TLI.getValueType(C->getType(), true); - - // Only handle simple types. - if (!CEVT.isSimple()) - return 0; - MVT VT = CEVT.getSimpleVT(); - - if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) - return MaterializeFP(CFP, VT); - else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) - return MaterializeGV(GV, VT); - else if (isa<ConstantInt>(C)) - return MaterializeInt(C, VT); - - return 0; -} - -bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr, +bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, unsigned Alignment) { // // more cases will be handled here in following patches. @@ -228,19 +537,23 @@ bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr, Opc = Mips::SW; break; case MVT::f32: + if (UnsupportedFPMode) + return false; Opc = Mips::SWC1; break; case MVT::f64: + if (UnsupportedFPMode) + return false; Opc = Mips::SDC1; break; default: return false; } - EmitInstStore(Opc, SrcReg, Addr.Base.Reg, Addr.Offset); + emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); return true; } -bool MipsFastISel::SelectLoad(const Instruction *I) { +bool MipsFastISel::selectLoad(const Instruction *I) { // Atomic loads need special handling. if (cast<LoadInst>(I)->isAtomic()) return false; @@ -252,17 +565,17 @@ bool MipsFastISel::SelectLoad(const Instruction *I) { // See if we can handle this address. Address Addr; - if (!ComputeAddress(I->getOperand(0), Addr)) + if (!computeAddress(I->getOperand(0), Addr)) return false; unsigned ResultReg; - if (!EmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment())) + if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment())) return false; - UpdateValueMap(I, ResultReg); + updateValueMap(I, ResultReg); return true; } -bool MipsFastISel::SelectStore(const Instruction *I) { +bool MipsFastISel::selectStore(const Instruction *I) { Value *Op0 = I->getOperand(0); unsigned SrcReg = 0; @@ -282,15 +595,394 @@ bool MipsFastISel::SelectStore(const Instruction *I) { // See if we can handle this address. Address Addr; - if (!ComputeAddress(I->getOperand(1), Addr)) + if (!computeAddress(I->getOperand(1), Addr)) return false; - if (!EmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment())) + if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment())) return false; return true; } -bool MipsFastISel::SelectRet(const Instruction *I) { +// +// This can cause a redundant sltiu to be generated. +// FIXME: try and eliminate this in a future patch. +// +bool MipsFastISel::selectBranch(const Instruction *I) { + const BranchInst *BI = cast<BranchInst>(I); + MachineBasicBlock *BrBB = FuncInfo.MBB; + // + // TBB is the basic block for the case where the comparison is true. + // FBB is the basic block for the case where the comparison is false. + // if (cond) goto TBB + // goto FBB + // TBB: + // + MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; + MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; + BI->getCondition(); + // For now, just try the simplest case where it's fed by a compare. + if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { + unsigned CondReg = createResultReg(&Mips::GPR32RegClass); + if (!emitCmp(CondReg, CI)) + return false; + BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) + .addReg(CondReg) + .addMBB(TBB); + fastEmitBranch(FBB, DbgLoc); + FuncInfo.MBB->addSuccessor(TBB); + return true; + } + return false; +} + +bool MipsFastISel::selectCmp(const Instruction *I) { + const CmpInst *CI = cast<CmpInst>(I); + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!emitCmp(ResultReg, CI)) + return false; + updateValueMap(I, ResultReg); + return true; +} + +// Attempt to fast-select a floating-point extend instruction. +bool MipsFastISel::selectFPExt(const Instruction *I) { + if (UnsupportedFPMode) + return false; + Value *Src = I->getOperand(0); + EVT SrcVT = TLI.getValueType(Src->getType(), true); + EVT DestVT = TLI.getValueType(I->getType(), true); + + if (SrcVT != MVT::f32 || DestVT != MVT::f64) + return false; + + unsigned SrcReg = + getRegForValue(Src); // his must be a 32 bit floating point register class + // maybe we should handle this differently + if (!SrcReg) + return false; + + unsigned DestReg = createResultReg(&Mips::AFGR64RegClass); + emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg); + updateValueMap(I, DestReg); + return true; +} + +// Attempt to fast-select a floating-point truncate instruction. +bool MipsFastISel::selectFPTrunc(const Instruction *I) { + if (UnsupportedFPMode) + return false; + Value *Src = I->getOperand(0); + EVT SrcVT = TLI.getValueType(Src->getType(), true); + EVT DestVT = TLI.getValueType(I->getType(), true); + + if (SrcVT != MVT::f64 || DestVT != MVT::f32) + return false; + + unsigned SrcReg = getRegForValue(Src); + if (!SrcReg) + return false; + + unsigned DestReg = createResultReg(&Mips::FGR32RegClass); + if (!DestReg) + return false; + + emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg); + updateValueMap(I, DestReg); + return true; +} + +// Attempt to fast-select a floating-point-to-integer conversion. +bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) { + if (UnsupportedFPMode) + return false; + MVT DstVT, SrcVT; + if (!IsSigned) + return false; // We don't handle this case yet. There is no native + // instruction for this but it can be synthesized. + Type *DstTy = I->getType(); + if (!isTypeLegal(DstTy, DstVT)) + return false; + + if (DstVT != MVT::i32) + return false; + + Value *Src = I->getOperand(0); + Type *SrcTy = Src->getType(); + if (!isTypeLegal(SrcTy, SrcVT)) + return false; + + if (SrcVT != MVT::f32 && SrcVT != MVT::f64) + return false; + + unsigned SrcReg = getRegForValue(Src); + if (SrcReg == 0) + return false; + + // Determine the opcode for the conversion, which takes place + // entirely within FPRs. + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + unsigned TempReg = createResultReg(&Mips::FGR32RegClass); + unsigned Opc; + + if (SrcVT == MVT::f32) + Opc = Mips::TRUNC_W_S; + else + Opc = Mips::TRUNC_W_D32; + + // Generate the convert. + emitInst(Opc, TempReg).addReg(SrcReg); + + emitInst(Mips::MFC1, DestReg).addReg(TempReg); + + updateValueMap(I, DestReg); + return true; +} +// +bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, + SmallVectorImpl<MVT> &OutVTs, + unsigned &NumBytes) { + CallingConv::ID CC = CLI.CallConv; + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context); + CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC)); + // Get a count of how many bytes are to be pushed on the stack. + NumBytes = CCInfo.getNextStackOffset(); + // This is the minimum argument area used for A0-A3. + if (NumBytes < 16) + NumBytes = 16; + + emitInst(Mips::ADJCALLSTACKDOWN).addImm(16); + // Process the args. + MVT firstMVT; + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + const Value *ArgVal = CLI.OutVals[VA.getValNo()]; + MVT ArgVT = OutVTs[VA.getValNo()]; + + if (i == 0) { + firstMVT = ArgVT; + if (ArgVT == MVT::f32) { + VA.convertToReg(Mips::F12); + } else if (ArgVT == MVT::f64) { + VA.convertToReg(Mips::D6); + } + } else if (i == 1) { + if ((firstMVT == MVT::f32) || (firstMVT == MVT::f64)) { + if (ArgVT == MVT::f32) { + VA.convertToReg(Mips::F14); + } else if (ArgVT == MVT::f64) { + VA.convertToReg(Mips::D7); + } + } + } + if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32)) && VA.isMemLoc()) { + switch (VA.getLocMemOffset()) { + case 0: + VA.convertToReg(Mips::A0); + break; + case 4: + VA.convertToReg(Mips::A1); + break; + case 8: + VA.convertToReg(Mips::A2); + break; + case 12: + VA.convertToReg(Mips::A3); + break; + default: + break; + } + } + unsigned ArgReg = getRegForValue(ArgVal); + if (!ArgReg) + return false; + + // Handle arg promotion: SExt, ZExt, AExt. + switch (VA.getLocInfo()) { + case CCValAssign::Full: + break; + case CCValAssign::AExt: + case CCValAssign::SExt: { + MVT DestVT = VA.getLocVT(); + MVT SrcVT = ArgVT; + ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false); + if (!ArgReg) + return false; + break; + } + case CCValAssign::ZExt: { + MVT DestVT = VA.getLocVT(); + MVT SrcVT = ArgVT; + ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true); + if (!ArgReg) + return false; + break; + } + default: + llvm_unreachable("Unknown arg promotion!"); + } + + // Now copy/store arg to correct locations. + if (VA.isRegLoc() && !VA.needsCustom()) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg); + CLI.OutRegs.push_back(VA.getLocReg()); + } else if (VA.needsCustom()) { + llvm_unreachable("Mips does not use custom args."); + return false; + } else { + // + // FIXME: This path will currently return false. It was copied + // from the AArch64 port and should be essentially fine for Mips too. + // The work to finish up this path will be done in a follow-on patch. + // + assert(VA.isMemLoc() && "Assuming store on stack."); + // Don't emit stores for undef values. + if (isa<UndefValue>(ArgVal)) + continue; + + // Need to store on the stack. + // FIXME: This alignment is incorrect but this path is disabled + // for now (will return false). We need to determine the right alignment + // based on the normal alignment for the underlying machine type. + // + unsigned ArgSize = RoundUpToAlignment(ArgVT.getSizeInBits(), 4); + + unsigned BEAlign = 0; + if (ArgSize < 8 && !Subtarget->isLittle()) + BEAlign = 8 - ArgSize; + + Address Addr; + Addr.setKind(Address::RegBase); + Addr.setReg(Mips::SP); + Addr.setOffset(VA.getLocMemOffset() + BEAlign); + + unsigned Alignment = DL.getABITypeAlignment(ArgVal->getType()); + MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand( + MachinePointerInfo::getStack(Addr.getOffset()), + MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment); + (void)(MMO); + // if (!emitStore(ArgVT, ArgReg, Addr, MMO)) + return false; // can't store on the stack yet. + } + } + + return true; +} + +bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, + unsigned NumBytes) { + CallingConv::ID CC = CLI.CallConv; + emitInst(Mips::ADJCALLSTACKUP).addImm(16); + if (RetVT != MVT::isVoid) { + SmallVector<CCValAssign, 16> RVLocs; + CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context); + CCInfo.AnalyzeCallResult(RetVT, RetCC_Mips); + + // Only handle a single return value. + if (RVLocs.size() != 1) + return false; + // Copy all of the result registers out of their specified physreg. + MVT CopyVT = RVLocs[0].getValVT(); + // Special handling for extended integers. + if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16) + CopyVT = MVT::i32; + + unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT)); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), + ResultReg).addReg(RVLocs[0].getLocReg()); + CLI.InRegs.push_back(RVLocs[0].getLocReg()); + + CLI.ResultReg = ResultReg; + CLI.NumResultRegs = 1; + } + return true; +} + +bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { + CallingConv::ID CC = CLI.CallConv; + bool IsTailCall = CLI.IsTailCall; + bool IsVarArg = CLI.IsVarArg; + const Value *Callee = CLI.Callee; + // const char *SymName = CLI.SymName; + + // Allow SelectionDAG isel to handle tail calls. + if (IsTailCall) + return false; + + // Let SDISel handle vararg functions. + if (IsVarArg) + return false; + + // FIXME: Only handle *simple* calls for now. + MVT RetVT; + if (CLI.RetTy->isVoidTy()) + RetVT = MVT::isVoid; + else if (!isTypeLegal(CLI.RetTy, RetVT)) + return false; + + for (auto Flag : CLI.OutFlags) + if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal()) + return false; + + // Set up the argument vectors. + SmallVector<MVT, 16> OutVTs; + OutVTs.reserve(CLI.OutVals.size()); + + for (auto *Val : CLI.OutVals) { + MVT VT; + if (!isTypeLegal(Val->getType(), VT) && + !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)) + return false; + + // We don't handle vector parameters yet. + if (VT.isVector() || VT.getSizeInBits() > 64) + return false; + + OutVTs.push_back(VT); + } + + Address Addr; + if (!computeCallAddress(Callee, Addr)) + return false; + + // Handle the arguments now that we've gotten them. + unsigned NumBytes; + if (!processCallArgs(CLI, OutVTs, NumBytes)) + return false; + + // Issue the call. + unsigned DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); + emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress); + MachineInstrBuilder MIB = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR), + Mips::RA).addReg(Mips::T9); + + // 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; + + // 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 ReturnInst *Ret = cast<ReturnInst>(I); if (!FuncInfo.CanLowerReturn) @@ -298,98 +990,181 @@ bool MipsFastISel::SelectRet(const Instruction *I) { if (Ret->getNumOperands() > 0) { return false; } - EmitInst(Mips::RetRA); + emitInst(Mips::RetRA); return true; } -bool MipsFastISel::TargetSelectInstruction(const Instruction *I) { - if (!TargetSupported) +bool MipsFastISel::selectTrunc(const Instruction *I) { + // The high bits for a type smaller than the register size are assumed to be + // undefined. + Value *Op = I->getOperand(0); + + EVT SrcVT, DestVT; + SrcVT = TLI.getValueType(Op->getType(), true); + DestVT = TLI.getValueType(I->getType(), true); + + if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8) return false; - switch (I->getOpcode()) { + if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1) + return false; + + unsigned SrcReg = getRegForValue(Op); + if (!SrcReg) + return false; + + // Because the high bits are undefined, a truncate doesn't generate + // any code. + updateValueMap(I, SrcReg); + return true; +} +bool MipsFastISel::selectIntExt(const Instruction *I) { + Type *DestTy = I->getType(); + Value *Src = I->getOperand(0); + Type *SrcTy = Src->getType(); + + bool isZExt = isa<ZExtInst>(I); + unsigned SrcReg = getRegForValue(Src); + if (!SrcReg) + return false; + + EVT SrcEVT, DestEVT; + SrcEVT = TLI.getValueType(SrcTy, true); + DestEVT = TLI.getValueType(DestTy, true); + if (!SrcEVT.isSimple()) + return false; + if (!DestEVT.isSimple()) + return false; + + MVT SrcVT = SrcEVT.getSimpleVT(); + MVT DestVT = DestEVT.getSimpleVT(); + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + + if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt)) + return false; + updateValueMap(I, ResultReg); + return true; +} +bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg) { + unsigned ShiftAmt; + switch (SrcVT.SimpleTy) { default: + return false; + case MVT::i8: + ShiftAmt = 24; + break; + case MVT::i16: + ShiftAmt = 16; break; - case Instruction::Load: - return SelectLoad(I); - case Instruction::Store: - return SelectStore(I); - case Instruction::Ret: - return SelectRet(I); } - return false; -} + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt); + emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt); + return true; } -unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) { - int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - if (VT == MVT::f32) { - const TargetRegisterClass *RC = &Mips::FGR32RegClass; - unsigned DestReg = createResultReg(RC); - unsigned TempReg = Materialize32BitInt(Imm, &Mips::GPR32RegClass); - EmitInst(Mips::MTC1, DestReg).addReg(TempReg); - return DestReg; - } else if (VT == MVT::f64) { - const TargetRegisterClass *RC = &Mips::AFGR64RegClass; - unsigned DestReg = createResultReg(RC); - unsigned TempReg1 = Materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass); - unsigned TempReg2 = - Materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass); - EmitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1); - return DestReg; +bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg) { + switch (SrcVT.SimpleTy) { + default: + return false; + case MVT::i8: + emitInst(Mips::SEB, DestReg).addReg(SrcReg); + break; + case MVT::i16: + emitInst(Mips::SEH, DestReg).addReg(SrcReg); + break; } - return 0; + return true; } -unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) { - // For now 32-bit only. - if (VT != MVT::i32) - return 0; - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - unsigned DestReg = createResultReg(RC); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); - bool IsThreadLocal = GVar && GVar->isThreadLocal(); - // TLS not supported at this time. - if (IsThreadLocal) - return 0; - EmitInst(Mips::LW, DestReg).addReg(MFI->getGlobalBaseReg()).addGlobalAddress( - GV, 0, MipsII::MO_GOT); - return DestReg; +bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg) { + if ((DestVT != MVT::i32) && (DestVT != MVT::i16)) + return false; + if (Subtarget->hasMips32r2()) + return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg); + return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg); } -unsigned MipsFastISel::MaterializeInt(const Constant *C, MVT VT) { - if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) - return 0; - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - const ConstantInt *CI = cast<ConstantInt>(C); - int64_t Imm; - if (CI->isNegative()) - Imm = CI->getSExtValue(); - else - Imm = CI->getZExtValue(); - return Materialize32BitInt(Imm, RC); + +bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg) { + switch (SrcVT.SimpleTy) { + default: + return false; + case MVT::i1: + emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1); + break; + case MVT::i8: + emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff); + break; + case MVT::i16: + emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff); + break; + } + return true; } -unsigned MipsFastISel::Materialize32BitInt(int64_t Imm, - const TargetRegisterClass *RC) { - unsigned ResultReg = createResultReg(RC); +bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, + unsigned DestReg, bool IsZExt) { + if (IsZExt) + return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg); + return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg); +} - if (isInt<16>(Imm)) { - unsigned Opc = Mips::ADDiu; - EmitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm); - return ResultReg; - } else if (isUInt<16>(Imm)) { - EmitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm); - return ResultReg; +unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, + bool isZExt) { + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + return emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); +} + +bool MipsFastISel::fastSelectInstruction(const Instruction *I) { + if (!TargetSupported) + return false; + switch (I->getOpcode()) { + default: + break; + case Instruction::Load: + return selectLoad(I); + case Instruction::Store: + return selectStore(I); + case Instruction::Br: + return selectBranch(I); + case Instruction::Ret: + return selectRet(I); + case Instruction::Trunc: + return selectTrunc(I); + case Instruction::ZExt: + case Instruction::SExt: + return selectIntExt(I); + case Instruction::FPTrunc: + return selectFPTrunc(I); + case Instruction::FPExt: + return selectFPExt(I); + case Instruction::FPToSI: + return selectFPToInt(I, /*isSigned*/ true); + case Instruction::FPToUI: + return selectFPToInt(I, /*isSigned*/ false); + case Instruction::ICmp: + case Instruction::FCmp: + return selectCmp(I); } - unsigned Lo = Imm & 0xFFFF; - unsigned Hi = (Imm >> 16) & 0xFFFF; - if (Lo) { - // Both Lo and Hi have nonzero bits. - unsigned TmpReg = createResultReg(RC); - EmitInst(Mips::LUi, TmpReg).addImm(Hi); - EmitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo); - } else { - EmitInst(Mips::LUi, ResultReg).addImm(Hi); + return false; +} + +unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, + bool IsUnsigned) { + unsigned VReg = getRegForValue(V); + if (VReg == 0) + return 0; + MVT VMVT = TLI.getValueType(V->getType(), true).getSimpleVT(); + if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned)) + return 0; + VReg = TempReg; } - return ResultReg; + return VReg; } namespace llvm { diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index 61afe179df57..3014a0d95342 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.getTarget().getRegisterInfo(); + const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); int64_t Offset = 0; diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h index 9d593091e018..90a8d2af63b2 100644 --- a/lib/Target/Mips/MipsFrameLowering.h +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS_FRAMEINFO_H -#define MIPS_FRAMEINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSFRAMELOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPSFRAMELOWERING_H #include "Mips.h" #include "llvm/Target/TargetFrameLowering.h" diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h index 52f4c0d3b9ea..ff8760da3fa6 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/lib/Target/Mips/MipsISelDAGToDAG.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSISELDAGTODAG_H -#define MIPSISELDAGTODAG_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSISELDAGTODAG_H +#define LLVM_LIB_TARGET_MIPS_MIPSISELDAGTODAG_H #include "Mips.h" #include "MipsSubtarget.h" diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 8e40668b2fa7..99fd739c3ed0 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -25,6 +25,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" @@ -200,9 +201,9 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { } } -MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM, +MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) - : TargetLowering(TM, new MipsTargetObjectFile()), Subtarget(STI) { + : TargetLowering(TM), Subtarget(STI) { // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); @@ -214,12 +215,15 @@ MipsTargetLowering::MipsTargetLowering(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. @@ -367,9 +371,9 @@ MipsTargetLowering::MipsTargetLowering(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); } @@ -400,7 +404,7 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM, isMicroMips = Subtarget.inMicroMipsMode(); } -const MipsTargetLowering *MipsTargetLowering::create(MipsTargetMachine &TM, +const MipsTargetLowering *MipsTargetLowering::create(const MipsTargetMachine &TM, const MipsSubtarget &STI) { if (STI.inMips16Mode()) return llvm::createMips16TargetLowering(TM, STI); @@ -932,18 +936,37 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case Mips::DIVU: case Mips::MOD: case Mips::MODU: - return insertDivByZeroTrap(MI, *BB, *getTargetMachine().getInstrInfo(), - false); + return insertDivByZeroTrap( + MI, *BB, *getTargetMachine().getSubtargetImpl()->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().getInstrInfo(), - true); + return insertDivByZeroTrap( + MI, *BB, *getTargetMachine().getSubtargetImpl()->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); } } @@ -958,7 +981,8 @@ 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().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, AND, NOR, ZERO, BEQ; @@ -1041,7 +1065,8 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, unsigned SrcReg) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); if (Subtarget.hasMips32r2() && Size == 1) { @@ -1077,7 +1102,8 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1174,7 +1200,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 @@ -1197,7 +1224,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); @@ -1227,7 +1255,8 @@ 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().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, ZERO, BNE, BEQ; @@ -1309,7 +1338,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1406,7 +1436,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)) @@ -1422,7 +1453,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); @@ -1444,8 +1476,10 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const { MachineFunction *MF = BB->getParent(); - const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetRegisterInfo *TRI = + getTargetMachine().getSubtargetImpl()->getRegisterInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); MachineBasicBlock::iterator II(MI); @@ -1486,7 +1520,7 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); Addr = DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr, MachinePointerInfo::getJumpTable(), MemVT, false, false, - 0); + false, 0); Chain = Addr.getValue(1); if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || @@ -1568,8 +1602,6 @@ SDValue MipsTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { - // FIXME there isn't actually debug info here - SDLoc DL(Op); EVT Ty = Op.getValueType(); GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = N->getGlobal(); @@ -1579,15 +1611,9 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, const MipsTargetObjectFile &TLOF = (const MipsTargetObjectFile&)getObjFileLowering(); - // %gp_rel relocation - if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { - SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0, - MipsII::MO_GPREL); - SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, DL, - DAG.getVTList(MVT::i32), GA); - SDValue GPReg = DAG.getRegister(Mips::GP, MVT::i32); - return DAG.getNode(ISD::ADD, DL, MVT::i32, GPReg, GPRelNode); - } + if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) + // %gp_rel relocation + return getAddrGPRel(N, Ty, DAG); // %hi/%lo relocation return getAddrNonPIC(N, Ty, DAG); @@ -1718,21 +1744,20 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const SDValue MipsTargetLowering:: lowerConstantPool(SDValue Op, SelectionDAG &DAG) const { - // gp_rel relocation - // FIXME: we should reference the constant pool using small data sections, - // but the asm printer currently doesn't support this feature without - // hacking it. This feature should come soon so we can uncomment the - // stuff below. - //if (IsInSmallSection(C->getType())) { - // SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, MVT::i32, CP); - // SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); - // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); EVT Ty = Op.getValueType(); if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) + !Subtarget.isABI_N64()) { + const MipsTargetObjectFile &TLOF = + (const MipsTargetObjectFile&)getObjFileLowering(); + + if (TLOF.IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) + // %gp_rel relocation + return getAddrGPRel(N, Ty, DAG); + return getAddrNonPIC(N, Ty, DAG); + } return getAddrLocal(N, Ty, DAG, Subtarget.isABI_N32() || Subtarget.isABI_N64()); @@ -2259,7 +2284,7 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, // an argument. Otherwise, passed in A1, A2, A3 and stack. // f64 - Only passed in two aliased f32 registers if no int reg has been used // yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is -// not used, it must be shadowed. If only A3 is avaiable, shadow it and +// not used, it must be shadowed. If only A3 is available, shadow it and // go to stack. // // For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack. @@ -2373,6 +2398,10 @@ static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); } +static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State) LLVM_ATTRIBUTE_UNUSED; + #include "MipsGenCallingConv.inc" //===----------------------------------------------------------------------===// @@ -2407,13 +2436,19 @@ void MipsTargetLowering:: getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const { // Insert node "GP copy globalreg" before call to function. // // R_MIPS_CALL* operators (emitted when non-internal functions are called // in PIC mode) allow symbols to be resolved via lazy binding. // The lazy binding stub requires GP to point to the GOT. - if (IsPICCall && !InternalLinkage) { + // Note that we don't need GP to point to the GOT for indirect calls + // (when R_MIPS_CALL* is not used for the call) because Mips linker generates + // lazy binding stub for a function only when R_MIPS_CALL* are the only relocs + // 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; RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); @@ -2438,7 +2473,8 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); + const TargetRegisterInfo *TRI = + getTargetMachine().getSubtargetImpl()->getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); assert(Mask && "Missing call preserved mask for calling convention"); if (Subtarget.inMips16HardFloat()) { @@ -2474,15 +2510,14 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetFrameLowering *TFL = MF.getTarget().getFrameLowering(); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; MipsCCState CCInfo( - CallConv, IsVarArg, DAG.getMachineFunction(), - getTargetMachine(), ArgLocs, *DAG.getContext(), + CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), MipsCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); // Allocate the reserved argument area. It seems strange to do this from the @@ -2636,7 +2671,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, bool IsPICCall = (Subtarget.isABI_N64() || IsPIC); // true if calls are translated to // jalr $25 - bool GlobalOrExternal = false, InternalLinkage = false; + bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false; SDValue CalleeLo; EVT Ty = Callee.getValueType(); @@ -2648,13 +2683,16 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, if (InternalLinkage) Callee = getAddrLocal(G, Ty, DAG, Subtarget.isABI_N32() || Subtarget.isABI_N64()); - else if (LargeGOT) + else if (LargeGOT) { Callee = getAddrGlobalLargeGOT(G, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Val)); - else + IsCallReloc = true; + } else { Callee = getAddrGlobal(G, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Val)); + IsCallReloc = true; + } } else Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, MipsII::MO_NO_FLAG); @@ -2666,13 +2704,16 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, if (!Subtarget.isABI_N64() && !IsPIC) // !N64 && static Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), MipsII::MO_NO_FLAG); - else if (LargeGOT) + else if (LargeGOT) { Callee = getAddrGlobalLargeGOT(S, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Sym)); - else // N64 || PIC + IsCallReloc = true; + } else { // N64 || PIC Callee = getAddrGlobal(S, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Sym)); + IsCallReloc = true; + } GlobalOrExternal = true; } @@ -2681,7 +2722,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, - CLI, Callee, Chain); + IsCallReloc, CLI, Callee, Chain); if (IsTailCall) return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops); @@ -2709,8 +2750,8 @@ SDValue MipsTargetLowering::LowerCallResult( TargetLowering::CallLoweringInfo &CLI) const { // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; - MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI); // Copy all of the result registers out of their specified physreg. @@ -2843,8 +2884,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; - MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), - getTargetMachine(), ArgLocs, *DAG.getContext()); + 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 = @@ -2982,8 +3023,7 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { SmallVector<CCValAssign, 16> RVLocs; - MipsCCState CCInfo(CallConv, IsVarArg, MF, getTargetMachine(), - RVLocs, Context); + MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); return CCInfo.CheckReturn(Outs, RetCC_Mips); } @@ -2999,8 +3039,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, MachineFunction &MF = DAG.getMachineFunction(); // CCState - Info about the registers and stack slot. - MipsCCState CCInfo(CallConv, IsVarArg, MF, getTargetMachine(), RVLocs, - *DAG.getContext()); + MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); // Analyze return values. CCInfo.AnalyzeReturn(Outs, RetCC_Mips); @@ -3181,7 +3220,7 @@ MipsTargetLowering::getSingleConstraintMatchWeight( /// that is returned indicates whether parsing was successful. The second flag /// is true if the numeric part exists. static std::pair<bool, bool> -parsePhysicalReg(const StringRef &C, std::string &Prefix, +parsePhysicalReg(StringRef C, std::string &Prefix, unsigned long long &Reg) { if (C.front() != '{' || C.back() != '}') return std::make_pair(false, false); @@ -3202,8 +3241,9 @@ parsePhysicalReg(const StringRef &C, std::string &Prefix, } std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering:: -parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const { - const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); +parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { + const TargetRegisterInfo *TRI = + getTargetMachine().getSubtargetImpl()->getRegisterInfo(); const TargetRegisterClass *RC; std::string Prefix; unsigned long long Reg; @@ -3585,7 +3625,8 @@ void MipsTargetLowering::passByValArg( DAG.getConstant(OffsetInBytes, PtrTy)); SDValue LoadVal = DAG.getExtLoad( ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), - MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, Alignment); + MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false, + Alignment); MemOpChains.push_back(LoadVal.getValue(1)); // Shift the loaded value. @@ -3679,7 +3720,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.getTarget().getFrameLowering(); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); assert(Size && "Byval argument's size shouldn't be 0."); @@ -3721,3 +3762,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 = + getTargetMachine().getSubtargetImpl()->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 23163b73e0a4..71f140b7a656 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MipsISELLOWERING_H -#define MipsISELLOWERING_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H #include "MCTargetDesc/MipsBaseInfo.h" #include "Mips.h" @@ -215,10 +215,10 @@ namespace llvm { class MipsTargetLowering : public TargetLowering { bool isMicroMips; public: - explicit MipsTargetLowering(MipsTargetMachine &TM, + explicit MipsTargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI); - static const MipsTargetLowering *create(MipsTargetMachine &TM, + static const MipsTargetLowering *create(const MipsTargetMachine &TM, const MipsSubtarget &STI); /// createFastISel - This method returns a target specific FastISel object, @@ -262,6 +262,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; @@ -332,6 +334,21 @@ namespace llvm { DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); } + // This method creates the following nodes, which are necessary for + // 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); + assert(Ty == MVT::i32); + SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); + return DAG.getNode(ISD::ADD, DL, Ty, + DAG.getRegister(Mips::GP, Ty), + DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), + GPRel)); + } + /// This function fills Ops, which is the list of operands that will later /// be used when a function call node is created. It also generates /// copyToReg nodes to set up argument registers. @@ -339,7 +356,8 @@ namespace llvm { getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const; + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const; protected: SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; @@ -470,7 +488,7 @@ namespace llvm { /// This function parses registers that appear in inline-asm constraints. /// It returns pair (0, 0) on failure. std::pair<unsigned, const TargetRegisterClass *> - parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const; + parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, @@ -518,13 +536,18 @@ 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. const MipsTargetLowering * - createMips16TargetLowering(MipsTargetMachine &TM, const MipsSubtarget &STI); + createMips16TargetLowering(const MipsTargetMachine &TM, + const MipsSubtarget &STI); const MipsTargetLowering * - createMipsSETargetLowering(MipsTargetMachine &TM, const MipsSubtarget &STI); + createMipsSETargetLowering(const MipsTargetMachine &TM, + const MipsSubtarget &STI); namespace Mips { FastISel *createFastISel(FunctionLoweringInfo &funcInfo, @@ -532,4 +555,4 @@ namespace llvm { } } -#endif // MipsISELLOWERING_H +#endif diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 1100e1e0323a..2aa83289a106 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -178,38 +178,6 @@ class SW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, let mayStore = 1; } -class SW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem2"; - let mayStore = 1; -} - -class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem2"; - let mayLoad = 1; -} - -class SW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem3"; - let mayStore = 1; -} - -class LW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem3"; - let mayLoad = 1; -} - class MADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), @@ -243,14 +211,14 @@ class SWXC1_FT<string opstr, RegisterOperand DRC, } class BC1F_FT<string opstr, DAGOperand opnd, InstrItinClass Itin, - SDPatternOperator Op = null_frag> : + SDPatternOperator Op = null_frag, bit DelaySlot = 1> : InstSE<(outs), (ins FCCRegsOpnd:$fcc, opnd:$offset), !strconcat(opstr, "\t$fcc, $offset"), [(MipsFPBrcond Op, FCCRegsOpnd:$fcc, bb:$offset)], Itin, FrmFI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; } @@ -436,30 +404,6 @@ def LDC1 : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM<0x35>, def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, LW_FM<0x3d>, ISA_MIPS2, FGR_32; -// Cop2 Memory Instructions -// FIXME: These aren't really FPU instructions and as such don't belong in this -// file -def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, - ISA_MIPS1_NOT_32R6_64R6; -def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>, - ISA_MIPS1_NOT_32R6_64R6; -def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>, - ISA_MIPS2_NOT_32R6_64R6; -def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>, - ISA_MIPS2_NOT_32R6_64R6; - -// Cop3 Memory Instructions -// FIXME: These aren't really FPU instructions and as such don't belong in this -// file -let DecoderNamespace = "COP3_" in { - def LWC3 : LW_FT3<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>; - def SWC3 : SW_FT3<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>; - def LDC3 : LW_FT3<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, - ISA_MIPS2; - def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, - ISA_MIPS2; -} - // Indexed loads and stores. // Base register + offset register addressing mode (indicated by "x" in the // instruction mnemonic) is disallowed under NaCl. @@ -562,8 +506,12 @@ def MIPS_BRANCH_T : PatLeaf<(i32 1)>; def BC1F : MMRel, BC1F_FT<"bc1f", brtarget, IIBranch, MIPS_BRANCH_F>, BC1F_FM<0, 0>, ISA_MIPS1_NOT_32R6_64R6; +def BC1FL : MMRel, BC1F_FT<"bc1fl", brtarget, IIBranch, MIPS_BRANCH_F, 0>, + BC1F_FM<1, 0>, ISA_MIPS2_NOT_32R6_64R6; def BC1T : MMRel, BC1F_FT<"bc1t", brtarget, IIBranch, MIPS_BRANCH_T>, BC1F_FM<0, 1>, ISA_MIPS1_NOT_32R6_64R6; +def BC1TL : MMRel, BC1F_FT<"bc1tl", brtarget, IIBranch, MIPS_BRANCH_T, 0>, + BC1F_FM<1, 1>, ISA_MIPS2_NOT_32R6_64R6; //===----------------------------------------------------------------------===// // Floating Point Flag Conditions @@ -629,8 +577,12 @@ def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>, //===----------------------------------------------------------------------===// def : MipsInstAlias<"bc1t $offset", (BC1T FCC0, brtarget:$offset)>, ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"bc1tl $offset", (BC1TL FCC0, brtarget:$offset)>, + ISA_MIPS2_NOT_32R6_64R6; def : MipsInstAlias<"bc1f $offset", (BC1F FCC0, brtarget:$offset)>, ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"bc1fl $offset", (BC1FL FCC0, brtarget:$offset)>, + ISA_MIPS2_NOT_32R6_64R6; //===----------------------------------------------------------------------===// // Floating Point Patterns diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 6a01ae560f3a..d8dae25aca9f 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -411,6 +411,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; @@ -440,7 +454,7 @@ class EXT_FM<bits<6> funct> : StdArch { let Inst{5-0} = funct; } -class RDHWR_FM { +class RDHWR_FM : StdArch { bits<5> rt; bits<5> rd; diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index dcc0e24e080b..0839147984b5 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.h b/lib/Target/Mips/MipsInstrInfo.h index bdf2fd37ed8c..db149d4dc9d0 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -15,8 +15,8 @@ // size in bytes; MipsLongBranch only expects it to be the correct upper bound. //===----------------------------------------------------------------------===// -#ifndef MIPSINSTRUCTIONINFO_H -#define MIPSINSTRUCTIONINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H #include "Mips.h" #include "MipsAnalyzeImmediate.h" diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 26ecfbf6f4e6..aef103956978 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; } //===----------------------------------------------------------------------===// @@ -331,7 +334,7 @@ include "MipsInstrFormats.td" def MipsJumpTargetAsmOperand : AsmOperandClass { let Name = "JumpTarget"; - let ParserMethod = "ParseJumpTarget"; + let ParserMethod = "parseJumpTarget"; let PredicateMethod = "isImm"; let RenderMethod = "addImmOperands"; } @@ -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; } @@ -672,28 +688,62 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, let DecoderMethod = "DecodeMem"; } +// COP2 Load/Store +class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, + SDPatternOperator OpNode= null_frag> : + InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem2"; + let mayLoad = 1; +} + +class SW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, + SDPatternOperator OpNode= null_frag> : + InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem2"; + let mayStore = 1; +} + +// COP3 Load/Store +class LW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, + SDPatternOperator OpNode= null_frag> : + InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem3"; + let mayLoad = 1; +} + +class SW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, + SDPatternOperator OpNode= null_frag> : + InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { + let DecoderMethod = "DecodeFMem3"; + let mayStore = 1; +} + // Conditional Branch class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op, - RegisterOperand RO> : + RegisterOperand RO, bit DelaySlot = 1> : InstSE<(outs), (ins RO:$rs, RO:$rt, opnd:$offset), !strconcat(opstr, "\t$rs, $rt, $offset"), [(brcond (i32 (cond_op RO:$rs, RO:$rt)), bb:$offset)], IIBranch, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; } class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op, - RegisterOperand RO> : + RegisterOperand RO, bit DelaySlot = 1> : InstSE<(outs), (ins RO:$rs, opnd:$offset), !strconcat(opstr, "\t$rs, $offset"), [(brcond (i32 (cond_op RO:$rs, 0)), bb:$offset)], IIBranch, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; } @@ -765,9 +815,12 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in { InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), [], IIBranch, FrmR>; - class BGEZAL_FT<string opstr, DAGOperand opnd, RegisterOperand RO> : + class BGEZAL_FT<string opstr, DAGOperand opnd, + RegisterOperand RO, bit DelaySlot = 1> : InstSE<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr>; + !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr> { + let hasDelaySlot = DelaySlot; + } } @@ -823,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_), @@ -839,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 @@ -885,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> @@ -897,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> : @@ -927,13 +987,13 @@ 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 class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> : InstSE<(outs CPURegOperand:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [], - II_RDHWR, FrmR>; + II_RDHWR, FrmR, "rdhwr">; // Ext and Ins class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, @@ -1059,18 +1119,20 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) +let AdditionalPredicates = [NotInMicroMips] in { def ADDiu : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, - add>, - ADDI_FM<0x9>, IsAsCheapAsAMove; + add>, ADDI_FM<0x9>, IsAsCheapAsAMove; +} def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6; def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xa>; def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xb>; +let AdditionalPredicates = [NotInMicroMips] in { def ANDi : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, - and>, - ADDI_FM<0xc>; + and>, ADDI_FM<0xc>; +} def ORi : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, ADDI_FM<0xd>; @@ -1100,10 +1162,12 @@ def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, def NOR : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; /// Shift Instructions +let AdditionalPredicates = [NotInMicroMips] in { def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl, immZExt5>, SRA_FM<0, 0>; def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl, immZExt5>, SRA_FM<2, 0>; +} def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra, immZExt5>, SRA_FM<3, 0>; def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>, @@ -1147,13 +1211,35 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, ISA_MIPS1_NOT_32R6_64R6; } +// COP2 Memory Instructions +def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, + ISA_MIPS1_NOT_32R6_64R6; +def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>, + ISA_MIPS1_NOT_32R6_64R6; +def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>, + ISA_MIPS2_NOT_32R6_64R6; +def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>, + ISA_MIPS2_NOT_32R6_64R6; + +// COP3 Memory Instructions +let DecoderNamespace = "COP3_" in { + def LWC3 : LW_FT3<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>; + def SWC3 : SW_FT3<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>; + def LDC3 : LW_FT3<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, + ISA_MIPS2; + def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, + ISA_MIPS2; +} + def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; -def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>; -def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>; -def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>; -def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>; -def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>; -def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>; +def 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; +def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>, ISA_MIPS2; +def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>, ISA_MIPS2; +def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>, ISA_MIPS2; +def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>, ISA_MIPS2; def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>, ISA_MIPS2_NOT_32R6_64R6; @@ -1171,7 +1257,7 @@ def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>, def BREAK : MMRel, BRK_FT<"break">, BRK_FM<0xd>; def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>; def TRAP : TrapBase<BREAK>; -def SDBBP : SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; +def SDBBP : MMRel, SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18>, INSN_MIPS3_32; def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f>, ISA_MIPS32; @@ -1193,15 +1279,27 @@ def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>, AdditionalRequires<[RelocStatic]>, IsBranch; def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>; def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>; +def BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>, + BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6; def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>; +def BNEL : MMRel, CBranch<"bnel", brtarget, setne, GPR32Opnd, 0>, + BEQ_FM<21>, ISA_MIPS2_NOT_32R6_64R6; def BGEZ : MMRel, CBranchZero<"bgez", brtarget, setge, GPR32Opnd>, BGEZ_FM<1, 1>; +def BGEZL : MMRel, CBranchZero<"bgezl", brtarget, setge, GPR32Opnd, 0>, + BGEZ_FM<1, 3>, ISA_MIPS2_NOT_32R6_64R6; def BGTZ : MMRel, CBranchZero<"bgtz", brtarget, setgt, GPR32Opnd>, BGEZ_FM<7, 0>; +def BGTZL : MMRel, CBranchZero<"bgtzl", brtarget, setgt, GPR32Opnd, 0>, + BGEZ_FM<23, 0>, ISA_MIPS2_NOT_32R6_64R6; def BLEZ : MMRel, CBranchZero<"blez", brtarget, setle, GPR32Opnd>, BGEZ_FM<6, 0>; +def BLEZL : MMRel, CBranchZero<"blezl", brtarget, setle, GPR32Opnd, 0>, + BGEZ_FM<22, 0>, ISA_MIPS2_NOT_32R6_64R6; def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>, BGEZ_FM<1, 0>; +def BLTZL : MMRel, CBranchZero<"bltzl", brtarget, setlt, GPR32Opnd, 0>, + BGEZ_FM<1, 2>, ISA_MIPS2_NOT_32R6_64R6; def B : UncondBranch<BEQ>; def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>; @@ -1214,8 +1312,12 @@ let AdditionalPredicates = [NotInMicroMips] in { def JALX : 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>, + BGEZAL_FM<0x13>, ISA_MIPS2_NOT_32R6_64R6; def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>, ISA_MIPS1_NOT_32R6_64R6; +def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd, 0>, + BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6; def BAL_BR : BAL_BR_Pseudo<BGEZAL>; def TAILCALL : TailCall<J>; def TAILCALL_R : TailCallReg<GPR32Opnd, JR>; @@ -1350,7 +1452,7 @@ def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV, def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; -def RDHWR : ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM; +def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM; def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>, EXT_FM<0>; def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>; @@ -1362,10 +1464,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 @@ -1408,21 +1510,22 @@ def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32; class TLB<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary, - FrmOther>; -def TLBP : TLB<"tlbp">, COP0_TLB_FM<0x08>; -def TLBR : TLB<"tlbr">, COP0_TLB_FM<0x01>; -def TLBWI : TLB<"tlbwi">, COP0_TLB_FM<0x02>; -def TLBWR : TLB<"tlbwr">, COP0_TLB_FM<0x06>; + FrmOther, asmstr>; +def TLBP : MMRel, TLB<"tlbp">, COP0_TLB_FM<0x08>; +def TLBR : MMRel, TLB<"tlbr">, COP0_TLB_FM<0x01>; +def TLBWI : MMRel, TLB<"tlbwi">, COP0_TLB_FM<0x02>; +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; //===----------------------------------------------------------------------===// @@ -1437,8 +1540,14 @@ def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>, ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"addu $rs, $rt, $imm", (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; +def : MipsInstAlias<"addu $rs, $imm", + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; def : MipsInstAlias<"add $rs, $rt, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"add $rs, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"and $rs, $rt, $imm", (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; def : MipsInstAlias<"and $rs, $imm", @@ -1482,25 +1591,30 @@ def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; def : MipsInstAlias<"break", (BREAK 0, 0), 1>; def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; -def : MipsInstAlias<"ei", (EI ZERO), 1>; -def : MipsInstAlias<"di", (DI ZERO), 1>; - -def : MipsInstAlias<"teq $rs, $rt", (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tge $rs, $rt", (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tgeu $rs, $rt", (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), - 1>; -def : MipsInstAlias<"tlt $rs, $rt", (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tltu $rs, $rt", (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), - 1>; -def : MipsInstAlias<"tne $rs, $rt", (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; +def : MipsInstAlias<"ei", (EI ZERO), 1>, ISA_MIPS32R2; +def : MipsInstAlias<"di", (DI ZERO), 1>, ISA_MIPS32R2; + +def : MipsInstAlias<"teq $rs, $rt", + (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tge $rs, $rt", + (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tgeu $rs, $rt", + (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tlt $rs, $rt", + (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tltu $rs, $rt", + (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; +def : MipsInstAlias<"tne $rs, $rt", + (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; + def : MipsInstAlias<"sll $rd, $rt, $rs", (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"sub, $rd, $rs, $imm", (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, - InvertedImOperand:$imm), 0>; + InvertedImOperand:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"sub $rs, $imm", (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm), - 0>; + 0>, ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"subu, $rd, $rs, $imm", (ADDiu GPR32Opnd:$rd, GPR32Opnd:$rs, InvertedImOperand:$imm), 0>; @@ -1544,10 +1658,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))>; @@ -1565,6 +1681,12 @@ let AdditionalPredicates = [NotDSP] in { (ADDiu GPR32:$src, imm:$imm)>; } +// Support multiplication for pre-Mips32 targets that don't have +// the MUL instruction. +def : MipsPat<(mul GPR32:$lhs, GPR32:$rhs), + (PseudoMFLO (PseudoMULT GPR32:$lhs, GPR32:$rhs))>, + ISA_MIPS1_NOT_32R6_64R6; + // SYNC def : MipsPat<(MipsSync (i32 immz)), (SYNC 0)>, ISA_MIPS2; diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp deleted file mode 100644 index 2072488206aa..000000000000 --- a/lib/Target/Mips/MipsJITInfo.cpp +++ /dev/null @@ -1,286 +0,0 @@ -//===-- MipsJITInfo.cpp - Implement the Mips JIT Interface ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the JIT interfaces for the Mips target. -// -//===----------------------------------------------------------------------===// - -#include "MipsJITInfo.h" -#include "MipsInstrInfo.h" -#include "MipsRelocations.h" -#include "MipsSubtarget.h" -#include "llvm/CodeGen/JITCodeEmitter.h" -#include "llvm/IR/Function.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Memory.h" -#include "llvm/Support/raw_ostream.h" -#include <cstdlib> -using namespace llvm; - -#define DEBUG_TYPE "jit" - - -void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { - unsigned NewAddr = (intptr_t)New; - unsigned OldAddr = (intptr_t)Old; - const unsigned NopInstr = 0x0; - - // If the functions are in the same memory segment, insert PC-region branch. - if ((NewAddr & 0xF0000000) == ((OldAddr + 4) & 0xF0000000)) { - unsigned *OldInstruction = (unsigned *)Old; - *OldInstruction = 0x08000000; - unsigned JTargetAddr = NewAddr & 0x0FFFFFFC; - - JTargetAddr >>= 2; - *OldInstruction |= JTargetAddr; - - // Insert a NOP. - OldInstruction++; - *OldInstruction = NopInstr; - - sys::Memory::InvalidateInstructionCache(Old, 2 * 4); - } else { - // We need to clear hint bits from the instruction, in case it is 'jr ra'. - const unsigned HintMask = 0xFFFFF83F, ReturnSequence = 0x03e00008; - unsigned* CurrentInstr = (unsigned*)Old; - unsigned CurrInstrHintClear = (*CurrentInstr) & HintMask; - unsigned* NextInstr = CurrentInstr + 1; - unsigned NextInstrHintClear = (*NextInstr) & HintMask; - - // Do absolute jump if there are 2 or more instructions before return from - // the old function. - if ((CurrInstrHintClear != ReturnSequence) && - (NextInstrHintClear != ReturnSequence)) { - const unsigned LuiT0Instr = 0x3c080000, AddiuT0Instr = 0x25080000; - const unsigned JrT0Instr = 0x01000008; - // lui t0, high 16 bit of the NewAddr - (*(CurrentInstr++)) = LuiT0Instr | ((NewAddr & 0xffff0000) >> 16); - // addiu t0, t0, low 16 bit of the NewAddr - (*(CurrentInstr++)) = AddiuT0Instr | (NewAddr & 0x0000ffff); - // jr t0 - (*(CurrentInstr++)) = JrT0Instr; - (*CurrentInstr) = NopInstr; - - sys::Memory::InvalidateInstructionCache(Old, 4 * 4); - } else { - // Unsupported case - report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction"); - } - } -} - -/// JITCompilerFunction - This contains the address of the JIT function used to -/// compile a function lazily. -static TargetJITInfo::JITCompilerFn JITCompilerFunction; - -// Get the ASMPREFIX for the current host. This is often '_'. -#ifndef __USER_LABEL_PREFIX__ -#define __USER_LABEL_PREFIX__ -#endif -#define GETASMPREFIX2(X) #X -#define GETASMPREFIX(X) GETASMPREFIX2(X) -#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__) - -// CompilationCallback stub - We can't use a C function with inline assembly in -// it, because the prolog/epilog inserted by GCC won't work for us. Instead, -// write our own wrapper, which does things our way, so we have complete control -// over register saving and restoring. This code saves registers, calls -// MipsCompilationCallbackC and restores registers. -extern "C" { -#if defined (__mips__) -void MipsCompilationCallback(); - - asm( - ".text\n" - ".align 2\n" - ".globl " ASMPREFIX "MipsCompilationCallback\n" - ASMPREFIX "MipsCompilationCallback:\n" - ".ent " ASMPREFIX "MipsCompilationCallback\n" - ".frame $sp, 32, $ra\n" - ".set noreorder\n" - ".cpload $t9\n" - - "addiu $sp, $sp, -64\n" - ".cprestore 16\n" - - // Save argument registers a0, a1, a2, a3, f12, f14 since they may contain - // stuff for the real target function right now. We have to act as if this - // whole compilation callback doesn't exist as far as the caller is - // concerned. We also need to save the ra register since it contains the - // original return address, and t8 register since it contains the address - // of the end of function stub. - "sw $a0, 20($sp)\n" - "sw $a1, 24($sp)\n" - "sw $a2, 28($sp)\n" - "sw $a3, 32($sp)\n" - "sw $ra, 36($sp)\n" - "sw $t8, 40($sp)\n" - "sdc1 $f12, 48($sp)\n" - "sdc1 $f14, 56($sp)\n" - - // t8 points at the end of function stub. Pass the beginning of the stub - // to the MipsCompilationCallbackC. - "addiu $a0, $t8, -16\n" - "jal " ASMPREFIX "MipsCompilationCallbackC\n" - "nop\n" - - // Restore registers. - "lw $a0, 20($sp)\n" - "lw $a1, 24($sp)\n" - "lw $a2, 28($sp)\n" - "lw $a3, 32($sp)\n" - "lw $ra, 36($sp)\n" - "lw $t8, 40($sp)\n" - "ldc1 $f12, 48($sp)\n" - "ldc1 $f14, 56($sp)\n" - "addiu $sp, $sp, 64\n" - - // Jump to the (newly modified) stub to invoke the real function. - "addiu $t8, $t8, -16\n" - "jr $t8\n" - "nop\n" - - ".set reorder\n" - ".end " ASMPREFIX "MipsCompilationCallback\n" - ); -#else // host != Mips - void MipsCompilationCallback() { - llvm_unreachable( - "Cannot call MipsCompilationCallback() on a non-Mips arch!"); - } -#endif -} - -/// MipsCompilationCallbackC - This is the target-specific function invoked -/// by the function stub when we did not know the real target of a call. -/// This function must locate the start of the stub or call site and pass -/// it into the JIT compiler function. -extern "C" void MipsCompilationCallbackC(intptr_t StubAddr) { - // Get the address of the compiled code for this function. - intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr); - - // Rewrite the function stub so that we don't end up here every time we - // execute the call. We're replacing the first four instructions of the - // stub with code that jumps to the compiled function: - // lui $t9, %hi(NewVal) - // addiu $t9, $t9, %lo(NewVal) - // jr $t9 - // nop - - int Hi = ((unsigned)NewVal & 0xffff0000) >> 16; - if ((NewVal & 0x8000) != 0) - Hi++; - int Lo = (int)(NewVal & 0xffff); - - *(intptr_t *)(StubAddr) = 0xf << 26 | 25 << 16 | Hi; - *(intptr_t *)(StubAddr + 4) = 9 << 26 | 25 << 21 | 25 << 16 | Lo; - *(intptr_t *)(StubAddr + 8) = 25 << 21 | 8; - *(intptr_t *)(StubAddr + 12) = 0; - - sys::Memory::InvalidateInstructionCache((void*) StubAddr, 16); -} - -TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction( - JITCompilerFn F) { - JITCompilerFunction = F; - return MipsCompilationCallback; -} - -TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() { - // The stub contains 4 4-byte instructions, aligned at 4 bytes. See - // emitFunctionStub for details. - StubLayout Result = { 4*4, 4 }; - return Result; -} - -void *MipsJITInfo::emitFunctionStub(const Function *F, void *Fn, - JITCodeEmitter &JCE) { - JCE.emitAlignment(4); - void *Addr = (void*) (JCE.getCurrentPCValue()); - if (!sys::Memory::setRangeWritable(Addr, 16)) - llvm_unreachable("ERROR: Unable to mark stub writable."); - - intptr_t EmittedAddr; - if (Fn != (void*)(intptr_t)MipsCompilationCallback) - EmittedAddr = (intptr_t)Fn; - else - EmittedAddr = (intptr_t)MipsCompilationCallback; - - - int Hi = ((unsigned)EmittedAddr & 0xffff0000) >> 16; - if ((EmittedAddr & 0x8000) != 0) - Hi++; - int Lo = (int)(EmittedAddr & 0xffff); - - // lui $t9, %hi(EmittedAddr) - // addiu $t9, $t9, %lo(EmittedAddr) - // jalr $t8, $t9 - // nop - if (IsLittleEndian) { - JCE.emitWordLE(0xf << 26 | 25 << 16 | Hi); - JCE.emitWordLE(9 << 26 | 25 << 21 | 25 << 16 | Lo); - JCE.emitWordLE(25 << 21 | 24 << 11 | 9); - JCE.emitWordLE(0); - } else { - JCE.emitWordBE(0xf << 26 | 25 << 16 | Hi); - JCE.emitWordBE(9 << 26 | 25 << 21 | 25 << 16 | Lo); - JCE.emitWordBE(25 << 21 | 24 << 11 | 9); - JCE.emitWordBE(0); - } - - sys::Memory::InvalidateInstructionCache(Addr, 16); - if (!sys::Memory::setRangeExecutable(Addr, 16)) - llvm_unreachable("ERROR: Unable to mark stub executable."); - - return Addr; -} - -/// relocate - Before the JIT can run a block of code that has been emitted, -/// it must rewrite the code to contain the actual addresses of any -/// referenced global symbols. -void MipsJITInfo::relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char *GOTBase) { - for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { - - void *RelocPos = (char*) Function + MR->getMachineCodeOffset(); - intptr_t ResultPtr = (intptr_t) MR->getResultPointer(); - - switch ((Mips::RelocationType) MR->getRelocationType()) { - case Mips::reloc_mips_pc16: - ResultPtr = (((ResultPtr - (intptr_t) RelocPos) - 4) >> 2) & 0xffff; - *((unsigned*) RelocPos) |= (unsigned) ResultPtr; - break; - - case Mips::reloc_mips_26: - ResultPtr = (ResultPtr & 0x0fffffff) >> 2; - *((unsigned*) RelocPos) |= (unsigned) ResultPtr; - break; - - case Mips::reloc_mips_hi: - ResultPtr = ResultPtr >> 16; - if ((((intptr_t) (MR->getResultPointer()) & 0xffff) >> 15) == 1) { - ResultPtr += 1; - } - *((unsigned*) RelocPos) |= (unsigned) ResultPtr; - break; - - case Mips::reloc_mips_lo: { - // Addend is needed for unaligned load/store instructions, where offset - // for the second load/store in the expanded instruction sequence must - // be modified by +1 or +3. Otherwise, Addend is 0. - int Addend = *((unsigned*) RelocPos) & 0xffff; - ResultPtr = (ResultPtr + Addend) & 0xffff; - *((unsigned*) RelocPos) &= 0xffff0000; - *((unsigned*) RelocPos) |= (unsigned) ResultPtr; - break; - } - } - } -} diff --git a/lib/Target/Mips/MipsJITInfo.h b/lib/Target/Mips/MipsJITInfo.h deleted file mode 100644 index c9dfd831d2df..000000000000 --- a/lib/Target/Mips/MipsJITInfo.h +++ /dev/null @@ -1,71 +0,0 @@ -//===- MipsJITInfo.h - Mips Implementation of the JIT Interface -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MipsJITInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef MIPSJITINFO_H -#define MIPSJITINFO_H - -#include "MipsMachineFunction.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/Target/TargetJITInfo.h" - -namespace llvm { -class MipsTargetMachine; - -class MipsJITInfo : public TargetJITInfo { - - bool IsPIC; - bool IsLittleEndian; - - public: - explicit MipsJITInfo() : - IsPIC(false), IsLittleEndian(true) {} - - /// replaceMachineCodeForFunction - Make it so that calling the function - /// whose machine code is at OLD turns into a call to NEW, perhaps by - /// overwriting OLD with a branch to NEW. This is used for self-modifying - /// code. - /// - void replaceMachineCodeForFunction(void *Old, void *New) override; - - // getStubLayout - Returns the size and alignment of the largest call stub - // on Mips. - StubLayout getStubLayout() override; - - /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a - /// small native function that simply calls the function at the specified - /// address. - void *emitFunctionStub(const Function *F, void *Fn, - JITCodeEmitter &JCE) override; - - /// getLazyResolverFunction - Expose the lazy resolver to the JIT. - LazyResolverFn getLazyResolverFunction(JITCompilerFn) override; - - /// relocate - Before the JIT can run a block of code that has been emitted, - /// it must rewrite the code to contain the actual addresses of any - /// referenced global symbols. - void relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char *GOTBase) override; - - /// Initialize - Initialize internal stage for the function being JITted. - void Initialize(const MachineFunction &MF, bool isPIC, - bool isLittleEndian) { - IsPIC = isPIC; - IsLittleEndian = isLittleEndian; - } - -}; -} - -#endif diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index 5790ed6053c8..aae0922e79eb 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -16,6 +16,7 @@ #include "Mips.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsMCNaCl.h" +#include "MipsMachineFunction.h" #include "MipsTargetMachine.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -109,8 +110,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 @@ -170,7 +170,7 @@ void MipsLongBranch::initMBBInfo() { MBBInfos.resize(MF->size()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); + static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { MachineBasicBlock *MBB = MF->getBlockNumbered(I); @@ -217,7 +217,7 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, MachineBasicBlock *MBBOpnd) { const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); + static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); const MCInstrDesc &NewDesc = TII->get(NewOpc); @@ -236,15 +236,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); @@ -254,7 +260,7 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); + static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->removeSuccessor(TgtMBB); @@ -447,7 +453,7 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); + static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); const MipsSubtarget &STI = TM.getSubtarget<MipsSubtarget>(); if (STI.inMips16Mode() || !STI.enableLongBranchPass()) diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index 269190ffc065..1ce27e401850 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSMCINSTLOWER_H -#define MIPSMCINSTLOWER_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H +#define LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H #include "MCTargetDesc/MipsMCExpr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineOperand.h" diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index 285bb146cdb6..68230e6957a8 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -69,7 +69,7 @@ def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT", // as the encoded value should be subtracted by one. def uimm2LSAAsmOperand : AsmOperandClass { let Name = "LSAImm"; - let ParserMethod = "ParseLSAImm"; + let ParserMethod = "parseLSAImm"; let RenderMethod = "addImmOperands"; } diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index bc896be4e1de..19babc720ce0 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -24,7 +24,7 @@ FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true), cl::desc("Always use $gp as the global base register.")); // class MipsCallEntry. -MipsCallEntry::MipsCallEntry(const StringRef &N) { +MipsCallEntry::MipsCallEntry(StringRef N) { #ifndef NDEBUG Name = N; Val = nullptr; @@ -80,13 +80,10 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { 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 = + ST.inMips16Mode() ? &Mips::CPU16RegsRegClass + : ST.isABI_N64() ? &Mips::GPR64RegClass + : &Mips::GPR32RegClass; return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); } @@ -98,8 +95,7 @@ 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); } @@ -119,7 +115,7 @@ bool MipsFunctionInfo::isEhDataRegFI(int FI) const { || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]); } -MachinePointerInfo MipsFunctionInfo::callPtrInfo(const StringRef &Name) { +MachinePointerInfo MipsFunctionInfo::callPtrInfo(StringRef Name) { const MipsCallEntry *&E = ExternalCallEntries[Name]; if (!E) diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index 61260e578159..217f30734b29 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPS_MACHINE_FUNCTION_INFO_H -#define MIPS_MACHINE_FUNCTION_INFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H +#define LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H #include "Mips16HardFloatInfo.h" #include "llvm/ADT/StringMap.h" @@ -34,7 +34,7 @@ namespace llvm { /// resolved by lazy-binding. class MipsCallEntry : public PseudoSourceValue { public: - explicit MipsCallEntry(const StringRef &N); + explicit MipsCallEntry(StringRef N); explicit MipsCallEntry(const GlobalValue *V); bool isConstant(const MachineFrameInfo *) const override; bool isAliased(const MachineFrameInfo *) const override; @@ -88,7 +88,7 @@ public: /// \brief Create a MachinePointerInfo that has a MipsCallEntr object /// representing a GOT entry for an external function. - MachinePointerInfo callPtrInfo(const StringRef &Name); + MachinePointerInfo callPtrInfo(StringRef Name); /// \brief Create a MachinePointerInfo that has a MipsCallEntr object /// representing a GOT entry for a global function. @@ -150,4 +150,4 @@ private: } // end of namespace llvm -#endif // MIPS_MACHINE_FUNCTION_INFO_H +#endif diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/lib/Target/Mips/MipsModuleISelDAGToDAG.h index f7a03104880b..85bae47aa08e 100644 --- a/lib/Target/Mips/MipsModuleISelDAGToDAG.h +++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSMODULEISELDAGTODAG_H -#define MIPSMODULEISELDAGTODAG_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSMODULEISELDAGTODAG_H +#define LLVM_LIB_TARGET_MIPS_MIPSMODULEISELDAGTODAG_H #include "Mips.h" #include "MipsSubtarget.h" diff --git a/lib/Target/Mips/MipsOptimizePICCall.cpp b/lib/Target/Mips/MipsOptimizePICCall.cpp index c234049ed125..22c524ea4370 100644 --- a/lib/Target/Mips/MipsOptimizePICCall.cpp +++ b/lib/Target/Mips/MipsOptimizePICCall.cpp @@ -130,7 +130,7 @@ static MVT::SimpleValueType getRegTy(unsigned Reg, MachineFunction &MF) { static void setCallTargetReg(MachineBasicBlock *MBB, MachineBasicBlock::iterator I) { MachineFunction &MF = *MBB->getParent(); - const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); unsigned SrcReg = I->getOperand(0).getReg(); unsigned DstReg = getRegTy(SrcReg, MF) == MVT::i32 ? Mips::T9 : Mips::T9_64; BuildMI(*MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg) diff --git a/lib/Target/Mips/MipsOptionRecord.h b/lib/Target/Mips/MipsOptionRecord.h index c0abce3eaddb..f82544ae43ae 100644 --- a/lib/Target/Mips/MipsOptionRecord.h +++ b/lib/Target/Mips/MipsOptionRecord.h @@ -17,19 +17,16 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSOPTIONRECORD_H -#define MIPSOPTIONRECORD_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H +#define LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H -#include "MipsMCTargetDesc.h" +#include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCRegisterInfo.h" -using namespace llvm; - namespace llvm { class MipsELFStreamer; class MCSubtargetInfo; -} class MipsOptionRecord { public: @@ -58,7 +55,7 @@ public: } ~MipsRegInfoRecord() {} - void EmitMipsOptionRecord(); + void EmitMipsOptionRecord() override; void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo); private: @@ -77,4 +74,5 @@ private: uint32_t ri_cprmask[4]; int64_t ri_gp_value; }; +} // namespace llvm #endif diff --git a/lib/Target/Mips/MipsOs16.h b/lib/Target/Mips/MipsOs16.h index 55e5a81daf99..77183ece7b9f 100644 --- a/lib/Target/Mips/MipsOs16.h +++ b/lib/Target/Mips/MipsOs16.h @@ -11,16 +11,14 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_TARGET_MIPS_MIPSOS16_H +#define LLVM_LIB_TARGET_MIPS_MIPSOS16_H + #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsTargetMachine.h" #include "llvm/Pass.h" #include "llvm/Target/TargetMachine.h" - - -#ifndef MIPSOS16_H -#define MIPSOS16_H - using namespace llvm; namespace llvm { diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index a6169705fe01..20ef3f387dcc 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -62,7 +62,7 @@ MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, case Mips::GPR32RegClassID: case Mips::GPR64RegClassID: case Mips::DSPRRegClassID: { - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); return 28 - TFI->hasFP(MF); } case Mips::FGR32RegClassID: @@ -167,7 +167,7 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(*Reg); } // Reserve FP if this function should have a dedicated frame pointer register. - if (MF.getTarget().getFrameLowering()->hasFP(MF)) { + if (MF.getSubtarget().getFrameLowering()->hasFP(MF)) { if (Subtarget.inMips16Mode()) Reserved.set(Mips::S0); else { @@ -256,7 +256,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); bool IsN64 = Subtarget.isABI_N64(); if (Subtarget.inMips16Mode()) diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index b34496fd8e12..9ec4a38862dd 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSREGISTERINFO_H -#define MIPSREGISTERINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPSREGISTERINFO_H #include "Mips.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 74dfa4fe7d9c..2b3b6c1e5242 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -212,8 +212,13 @@ let Namespace = "Mips" in { // PC register def PC : Register<"pc">; - // Hardware register $29 - foreach I = 0-31 in + // Hardware registers + def HWR0 : MipsReg<0, "hwr_cpunum">; + def HWR1 : MipsReg<1, "hwr_synci_step">; + def HWR2 : MipsReg<2, "hwr_cc">; + def HWR3 : MipsReg<3, "hwr_ccres">; + + foreach I = 4-31 in def HWR#I : MipsReg<#I, ""#I>; // Accum registers @@ -283,6 +288,20 @@ class GPR32Class<list<ValueType> regTypes> : 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)>; + +def GPRMM16Zero : RegisterClass<"Mips", [i32], 32, (add + // Reserved + ZERO, + // Callee save + S1, + // Return Values and Arguments + V0, V1, A0, A1, A2, A3)>; + def GPR64 : RegisterClass<"Mips", [i64], 64, (add // Reserved ZERO_64, AT_64, @@ -417,7 +436,7 @@ def OCTEON_P : RegisterClass<"Mips", [i64], 64, (add P0, P1, P2)>, // Register Operands. class MipsAsmRegOperand : AsmOperandClass { - let ParserMethod = "ParseAnyRegister"; + let ParserMethod = "parseAnyRegister"; } def GPR64AsmOperand : MipsAsmRegOperand { @@ -430,6 +449,16 @@ def GPR32AsmOperand : MipsAsmRegOperand { let PredicateMethod = "isGPRAsmReg"; } +def GPRMM16AsmOperand : MipsAsmRegOperand { + let Name = "GPRMM16AsmReg"; + let PredicateMethod = "isMM16AsmReg"; +} + +def GPRMM16AsmOperandZero : MipsAsmRegOperand { + let Name = "GPRMM16AsmRegZero"; + let PredicateMethod = "isMM16AsmRegZero"; +} + def ACC64DSPAsmOperand : MipsAsmRegOperand { let Name = "ACC64DSPAsmReg"; let PredicateMethod = "isACCAsmReg"; @@ -485,6 +514,14 @@ def GPR32Opnd : RegisterOperand<GPR32> { let ParserMatchClass = GPR32AsmOperand; } +def GPRMM16Opnd : RegisterOperand<GPRMM16> { + let ParserMatchClass = GPRMM16AsmOperand; +} + +def GPRMM16OpndZero : RegisterOperand<GPRMM16Zero> { + let ParserMatchClass = GPRMM16AsmOperandZero; +} + def GPR64Opnd : RegisterOperand<GPR64> { let ParserMatchClass = GPR64AsmOperand; } @@ -578,4 +615,3 @@ def MSA128DOpnd : RegisterOperand<MSA128D> { def MSA128CROpnd : RegisterOperand<MSACtrl> { let ParserMatchClass = MSACtrlAsmOperand; } - diff --git a/lib/Target/Mips/MipsRelocations.h b/lib/Target/Mips/MipsRelocations.h deleted file mode 100644 index 0787ed399d5f..000000000000 --- a/lib/Target/Mips/MipsRelocations.h +++ /dev/null @@ -1,41 +0,0 @@ -//===-- MipsRelocations.h - Mips Code Relocations ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the Mips target-specific relocation types -// (for relocation-model=static). -// -//===----------------------------------------------------------------------===// - -#ifndef MIPSRELOCATIONS_H_ -#define MIPSRELOCATIONS_H_ - -#include "llvm/CodeGen/MachineRelocation.h" - -namespace llvm { - namespace Mips{ - enum RelocationType { - // reloc_mips_pc16 - pc relative relocation for branches. The lower 18 - // bits of the difference between the branch target and the branch - // instruction, shifted right by 2. - reloc_mips_pc16 = 1, - - // reloc_mips_hi - upper 16 bits of the address (modified by +1 if the - // lower 16 bits of the address is negative). - reloc_mips_hi = 2, - - // reloc_mips_lo - lower 16 bits of the address. - reloc_mips_lo = 3, - - // reloc_mips_26 - lower 28 bits of the address, shifted right by 2. - reloc_mips_26 = 4 - }; - } -} - -#endif /* MIPSRELOCATIONS_H_ */ diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index 4825e1e569ee..97d9edfe6a5c 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -147,9 +147,9 @@ void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *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); @@ -167,9 +167,9 @@ void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *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); @@ -190,9 +190,9 @@ void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *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); @@ -220,9 +220,9 @@ void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *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); @@ -255,9 +255,9 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, // copy dst_hi, $vr1 const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *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; @@ -303,10 +303,10 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || (FP64 && !Subtarget.useOddSPReg())) { - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(TM.getInstrInfo()); - const MipsRegisterInfo &TRI = - *static_cast<const MipsRegisterInfo*>(TM.getRegisterInfo()); + 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(); @@ -363,10 +363,10 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || (FP64 && !Subtarget.useOddSPReg())) { - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(TM.getInstrInfo()); - const MipsRegisterInfo &TRI = - *static_cast<const MipsRegisterInfo *>(TM.getRegisterInfo()); + 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(); @@ -415,9 +415,9 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( + MF.getSubtarget().getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); @@ -550,9 +550,9 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( + MF.getSubtarget().getRegisterInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; @@ -605,7 +605,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); MachineBasicBlock *EntryBlock = MF->begin(); - const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF->getSubtarget().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 +646,7 @@ void MipsSEFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); + *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); if (!hasReservedCallFrame(MF)) { int64_t Amount = I->getOperand(0).getImm(); diff --git a/lib/Target/Mips/MipsSEFrameLowering.h b/lib/Target/Mips/MipsSEFrameLowering.h index e832848754dc..0eca1df12b0f 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.h +++ b/lib/Target/Mips/MipsSEFrameLowering.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSE_FRAMEINFO_H -#define MIPSSE_FRAMEINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H #include "MipsFrameLowering.h" diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 47e193191c3e..70963821690c 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -130,15 +130,12 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().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; + RC = (Subtarget->isABI_N64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index 57328d2f9270..2e11fa7282a7 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSEISELDAGTODAG_H -#define MIPSSEISELDAGTODAG_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEISELDAGTODAG_H +#define LLVM_LIB_TARGET_MIPS_MIPSSEISELDAGTODAG_H #include "MipsISelDAGToDAG.h" diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index d7452e281e36..29aac2e276b0 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "MipsSEISelLowering.h" +#include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -34,7 +35,7 @@ static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(false), "stores to their single precision " "counterparts")); -MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM, +MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) : MipsTargetLowering(TM, STI) { // Set up the register classes @@ -45,17 +46,13 @@ MipsSETargetLowering::MipsSETargetLowering(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); + } } } @@ -127,6 +124,8 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM, if (Subtarget.isGP64bit()) { setOperationAction(ISD::MULHS, MVT::i64, Custom); setOperationAction(ISD::MULHU, MVT::i64, Custom); + setOperationAction(ISD::SDIVREM, MVT::i64, Custom); + setOperationAction(ISD::UDIVREM, MVT::i64, Custom); } setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); @@ -134,8 +133,6 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM, setOperationAction(ISD::SDIVREM, MVT::i32, Custom); setOperationAction(ISD::UDIVREM, MVT::i32, Custom); - setOperationAction(ISD::SDIVREM, MVT::i64, Custom); - setOperationAction(ISD::UDIVREM, MVT::i64, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); setOperationAction(ISD::LOAD, MVT::i32, Custom); setOperationAction(ISD::STORE, MVT::i32, Custom); @@ -227,7 +224,7 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM, } const MipsTargetLowering * -llvm::createMipsSETargetLowering(MipsTargetMachine &TM, +llvm::createMipsSETargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) { return new MipsSETargetLowering(TM, STI); } @@ -329,9 +326,10 @@ addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) { } bool -MipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT, - unsigned, - bool *Fast) const { +MipsSETargetLowering::allowsMisalignedMemoryAccesses(EVT VT, + unsigned, + unsigned, + bool *Fast) const { MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; if (Subtarget.systemSupportsUnalignedAccess()) { @@ -577,10 +575,9 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, if ((Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT && Log2 >= ExtendTySize) || Log2 == ExtendTySize) { SDValue Ops[] = { Op0->getOperand(0), Op0->getOperand(1), Op0Op2 }; - DAG.MorphNodeTo(Op0.getNode(), MipsISD::VEXTRACT_ZEXT_ELT, - Op0->getVTList(), - makeArrayRef(Ops, Op0->getNumOperands())); - return Op0; + return DAG.getNode(MipsISD::VEXTRACT_ZEXT_ELT, SDLoc(Op0), + Op0->getVTList(), + makeArrayRef(Ops, Op0->getNumOperands())); } } @@ -922,10 +919,9 @@ static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, TotalBits <= 32)) { SDValue Ops[] = { Op0Op0->getOperand(0), Op0Op0->getOperand(1), Op0Op0->getOperand(2) }; - DAG.MorphNodeTo(Op0Op0.getNode(), MipsISD::VEXTRACT_SEXT_ELT, - Op0Op0->getVTList(), - makeArrayRef(Ops, Op0Op0->getNumOperands())); - return Op0Op0; + return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0), + Op0Op0->getVTList(), + makeArrayRef(Ops, Op0Op0->getNumOperands())); } } } @@ -1186,10 +1182,12 @@ void MipsSETargetLowering:: getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const { Ops.push_back(Callee); MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, - InternalLinkage, CLI, Callee, Chain); + InternalLinkage, IsCallReloc, CLI, Callee, + Chain); } SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { @@ -1245,13 +1243,13 @@ SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { // i32 store to lower address. Chain = DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.isVolatile(), Nd.isNonTemporal(), Nd.getAlignment(), - Nd.getTBAAInfo()); + Nd.getAAInfo()); // i32 store to higher address. Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, PtrVT)); return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(), Nd.isVolatile(), Nd.isNonTemporal(), - std::min(Nd.getAlignment(), 4U), Nd.getTBAAInfo()); + std::min(Nd.getAlignment(), 4U), Nd.getAAInfo()); } SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, @@ -2745,7 +2743,8 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ // $vr0 = phi($vr2, $fbb, $vr1, $tbb) MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; DebugLoc DL = MI->getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -2810,7 +2809,8 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // $rd = phi($rd1, $fbb, $rd2, $tbb) MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; DebugLoc DL = MI->getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -2871,7 +2871,8 @@ 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().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Fd = MI->getOperand(0).getReg(); @@ -2905,7 +2906,8 @@ MachineBasicBlock * MipsSETargetLowering:: emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); unsigned Fd = MI->getOperand(0).getReg(); unsigned Ws = MI->getOperand(1).getReg(); @@ -2934,7 +2936,8 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ MachineBasicBlock * MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -2968,7 +2971,8 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3016,7 +3020,8 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, bool IsFP) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3126,7 +3131,8 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFILL_FW(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3157,7 +3163,8 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3185,7 +3192,8 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128WRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); @@ -3214,7 +3222,8 @@ MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFEXP2_D_1(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrInfo *TII = + getTargetMachine().getSubtargetImpl()->getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128DRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index 2121b3bcaa51..d44f8d82ec3e 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSEISELLOWERING_H -#define MIPSSEISELLOWERING_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEISELLOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPSSEISELLOWERING_H #include "MipsISelLowering.h" #include "MipsRegisterInfo.h" @@ -20,7 +20,7 @@ namespace llvm { class MipsSETargetLowering : public MipsTargetLowering { public: - explicit MipsSETargetLowering(MipsTargetMachine &TM, + explicit MipsSETargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI); /// \brief Enable MSA support for the given integer type and Register @@ -31,8 +31,9 @@ namespace llvm { void addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); - bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AS = 0, - bool *Fast = nullptr) const override; + bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AS = 0, + unsigned Align = 1, + bool *Fast = nullptr) const override; SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; @@ -58,7 +59,7 @@ namespace llvm { getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const override; SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; @@ -113,4 +114,4 @@ namespace llvm { }; } -#endif // MipsSEISELLOWERING_H +#endif diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index 69cb74cb1e49..74f291f609fd 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,15 +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.getInstrInfo()->get(ADDU), T9) + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9) .addReg(TargetReg) .addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(ADDU), RA) + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA) .addReg(TargetReg) .addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), TM.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 9576fef1bd92..d16fab2e92fa 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.h +++ b/lib/Target/Mips/MipsSEInstrInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSEINSTRUCTIONINFO_H -#define MIPSSEINSTRUCTIONINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEINSTRINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPSSEINSTRINFO_H #include "MipsInstrInfo.h" #include "MipsSERegisterInfo.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/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp index 0af1a6b9e5c3..55c6638b45da 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -172,7 +172,7 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned Reg = RegInfo.createVirtualRegister(RC); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( - MBB.getParent()->getTarget().getInstrInfo()); + MBB.getParent()->getSubtarget().getInstrInfo()); BuildMI(MBB, II, DL, TII.get(ADDiu), Reg).addReg(FrameReg).addImm(Offset); FrameReg = Reg; @@ -187,7 +187,7 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned NewImm = 0; const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( - MBB.getParent()->getTarget().getInstrInfo()); + MBB.getParent()->getSubtarget().getInstrInfo()); unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, OffsetBitSize == 16 ? &NewImm : nullptr); BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg) diff --git a/lib/Target/Mips/MipsSERegisterInfo.h b/lib/Target/Mips/MipsSERegisterInfo.h index f2f3a7e75fd8..6b70d07b20dc 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.h +++ b/lib/Target/Mips/MipsSERegisterInfo.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSEREGISTERINFO_H -#define MIPSSEREGISTERINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEREGISTERINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPSSEREGISTERINFO_H #include "MipsRegisterInfo.h" diff --git a/lib/Target/Mips/MipsSelectionDAGInfo.h b/lib/Target/Mips/MipsSelectionDAGInfo.h index 2b3d527fe6ff..061423fbeb86 100644 --- a/lib/Target/Mips/MipsSelectionDAGInfo.h +++ b/lib/Target/Mips/MipsSelectionDAGInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSELECTIONDAGINFO_H -#define MIPSSELECTIONDAGINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSSELECTIONDAGINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPSSELECTIONDAGINFO_H #include "llvm/Target/TargetSelectionDAGInfo.h" diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 9a1c40902e8a..d035ebec4a54 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -58,6 +58,10 @@ Mips16ConstantIslands( cl::desc("MIPS: mips16 constant islands enable."), 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) { @@ -104,34 +108,30 @@ static std::string computeDataLayout(const MipsSubtarget &ST) { MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little, - MipsTargetMachine *_TM) - : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips32), + 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), + 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), JITInfo(), InstrInfo(MipsInstrInfo::create(*this)), + TSInfo(DL), InstrInfo(MipsInstrInfo::create(*this)), FrameLowering(MipsFrameLowering::create(*this)), - TLInfo(MipsTargetLowering::create(*TM, *this)) { + TLInfo(MipsTargetLowering::create(TM, *this)) { PreviousInMips16Mode = InMips16Mode; - // Don't even attempt to generate code for MIPS-I, MIPS-II, MIPS-III, and - // MIPS-V. They have not been tested and currently exist for the integrated - // assembler only. + if (MipsArchVersion == MipsDefault) + MipsArchVersion = Mips32; + + // 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 == Mips2) - report_fatal_error("Code generation for MIPS-II 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); @@ -167,14 +167,16 @@ 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_) + report_fatal_error("position-independent code requires '-mabicalls'"); // Set UseSmallSection. - // TODO: Investigate the IsLinux check. I suspect it's really checking for - // bare-metal. - UseSmallSection = !IsLinux && (TM->getRelocationModel() == Reloc::Static); + UseSmallSection = GPOpt; + if (!NoABICalls && GPOpt) { + errs() << "warning: cannot use small-data accesses for '-mabicalls'" + << "\n"; + UseSmallSection = false; + } } /// This overrides the PostRAScheduler bit in the SchedModel for any CPU. @@ -192,7 +194,7 @@ CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const { MipsSubtarget & MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine *TM) { + const TargetMachine &TM) { std::string CPUName = selectMipsCPU(TargetTriple, CPU); // Parse features string. @@ -200,14 +202,14 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef 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() { @@ -216,5 +218,5 @@ bool MipsSubtarget::useConstantIslands() { } Reloc::Model MipsSubtarget::getRelocationModel() const { - return TM->getRelocationModel(); + return TM.getRelocationModel(); } diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index c5b9a3e754d6..aca69a6839b3 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -11,19 +11,18 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSSUBTARGET_H -#define MIPSSUBTARGET_H +#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" -#include "MipsJITInfo.h" #include "MipsSelectionDAGInfo.h" #include "llvm/IR/DataLayout.h" #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,6 +37,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo { virtual void anchor(); enum MipsArchEnum { + MipsDefault, Mips1, Mips2, Mips32, Mips32r2, Mips32r6, Mips3, Mips4, Mips5, Mips64, Mips64r2, Mips64r6 }; @@ -136,13 +136,12 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // as from the command line enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode; - MipsTargetMachine *TM; + const MipsTargetMachine &TM; Triple TargetTriple; const DataLayout DL; // Calculates type size & alignment const MipsSelectionDAGInfo TSInfo; - MipsJITInfo JITInfo; std::unique_ptr<const MipsInstrInfo> InstrInfo; std::unique_ptr<const MipsFrameLowering> FrameLowering; std::unique_ptr<const MipsTargetLowering> TLInfo; @@ -164,7 +163,8 @@ public: /// 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, MipsTargetMachine *TM); + const std::string &FS, bool little, + const MipsTargetMachine &TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. @@ -223,7 +223,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(); } @@ -238,7 +237,6 @@ public: bool hasExtractInsert() const { return !inMips16Mode() && hasMips32r2(); } bool hasMTHC1() const { return hasMips32r2(); } - const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } bool allowMixed16_32() const { return inMips16ModeDefault() | AllowMixed16_32;} @@ -256,7 +254,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. /// @@ -269,17 +267,23 @@ public: void setHelperClassesMips16(); void setHelperClassesMipsSE(); - MipsJITInfo *getJITInfo() { return &JITInfo; } - const MipsSelectionDAGInfo *getSelectionDAGInfo() const { return &TSInfo; } - const DataLayout *getDataLayout() const { return &DL; } - const MipsInstrInfo *getInstrInfo() const { return InstrInfo.get(); } - const TargetFrameLowering *getFrameLowering() const { + 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(); } - const MipsRegisterInfo *getRegisterInfo() const { + const MipsRegisterInfo *getRegisterInfo() const override { return &InstrInfo->getRegisterInfo(); } - const MipsTargetLowering *getTargetLowering() const { return TLInfo.get(); } + const MipsTargetLowering *getTargetLowering() const override { + return TLInfo.get(); + } + const InstrItineraryData *getInstrItineraryData() const override { + return &InstrItins; + } }; } // End llvm namespace diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index bb1870ebe605..426b71ddeafd 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -26,6 +26,7 @@ #include "MipsSEISelDAGToDAG.h" #include "MipsSEISelLowering.h" #include "MipsSEInstrInfo.h" +#include "MipsTargetObjectFile.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/PassManager.h" @@ -56,15 +57,20 @@ 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), - Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, this), + isLittle(isLittle), + TLOF(make_unique<MipsTargetObjectFile>()), + 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(); } +MipsTargetMachine::~MipsTargetMachine() {} + void MipsebTargetMachine::anchor() { } MipsebTargetMachine:: @@ -83,20 +89,60 @@ MipselTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} +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"); + + std::string CPU = !CPUAttr.hasAttribute(Attribute::None) + ? CPUAttr.getValueAsString().str() + : TargetCPU; + std::string FS = !FSAttr.hasAttribute(Attribute::None) + ? FSAttr.getValueAsString().str() + : TargetFS; + bool hasMips16Attr = + !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "mips16") + .hasAttribute(Attribute::None); + bool hasNoMips16Attr = + !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "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"); + bool softFloat = !SFAttr.hasAttribute(Attribute::None) + ? SFAttr.getValueAsString() == "true" + : Options.UseSoftFloat; + + if (hasMips16Attr) + FS += FS.empty() ? "+mips16" : ",+mips16"; + else if (hasNoMips16Attr) + FS += FS.empty() ? "-mips16" : ",-mips16"; + + auto &I = SubtargetMap[CPU + FS + (softFloat ? "use-soft-float=true" + : "use-soft-float=false")]; + if (!I) { + // This needs to be done before we create a new subtarget since any + // 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); + } + return I.get(); +} + void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { DEBUG(dbgs() << "resetSubtarget\n"); - AttributeSet FnAttrs = MF->getFunction()->getAttributes(); - bool Mips16Attr = FnAttrs.hasAttribute(AttributeSet::FunctionIndex, "mips16"); - bool NoMips16Attr = - FnAttrs.hasAttribute(AttributeSet::FunctionIndex, "nomips16"); - assert(!(Mips16Attr && NoMips16Attr) && - "mips16 and nomips16 specified on the same function"); - if (Mips16Attr) - Subtarget = &Mips16Subtarget; - else if (NoMips16Attr) - Subtarget = &NoMips16Subtarget; - else - Subtarget = &DefaultSubtarget; + + Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction())); + MF->setSubtarget(Subtarget); return; } @@ -124,9 +170,9 @@ public: void addIRPasses() override; bool addInstSelector() override; void addMachineSSAOptimization() override; - bool addPreEmitPass() override; + void addPreEmitPass() override; - bool addPreRegAlloc() override; + void addPreRegAlloc() override; }; } // namespace @@ -137,11 +183,11 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { void MipsPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); + addPass(createAtomicExpandPass(&getMipsTargetMachine())); if (getMipsSubtarget().os16()) addPass(createMipsOs16(getMipsTargetMachine())); if (getMipsSubtarget().inMips16HardFloat()) addPass(createMips16HardFloat(getMipsTargetMachine())); - addPass(createPartiallyInlineLibCallsPass()); } // Install an instruction selector pass using // the ISelDag to gen Mips code. @@ -157,13 +203,9 @@ 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) { @@ -182,17 +224,9 @@ void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) { // 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; -} - -bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM, - JITCodeEmitter &JCE) { - // Machine code emitter pass for Mips. - PM.add(createMipsJITCodeEmitterPass(*this, JCE)); - return false; } diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index bcf411f9cd6f..4b097a2cf02a 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSTARGETMACHINE_H -#define MIPSTARGETMACHINE_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H +#define LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H #include "MipsSubtarget.h" #include "llvm/CodeGen/Passes.h" @@ -25,57 +25,42 @@ class formatted_raw_ostream; class MipsRegisterInfo; class MipsTargetMachine : public LLVMTargetMachine { + bool isLittle; + std::unique_ptr<TargetLoweringObjectFile> TLOF; MipsSubtarget *Subtarget; MipsSubtarget DefaultSubtarget; MipsSubtarget NoMips16Subtarget; MipsSubtarget Mips16Subtarget; + mutable StringMap<std::unique_ptr<MipsSubtarget>> SubtargetMap; + public: MipsTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle); - - virtual ~MipsTargetMachine() {} + ~MipsTargetMachine() override; void addAnalysisPasses(PassManagerBase &PM) override; - const MipsInstrInfo *getInstrInfo() const override { - return getSubtargetImpl()->getInstrInfo(); - } - const TargetFrameLowering *getFrameLowering() const override { - return getSubtargetImpl()->getFrameLowering(); - } const MipsSubtarget *getSubtargetImpl() const override { if (Subtarget) return Subtarget; return &DefaultSubtarget; } - const InstrItineraryData *getInstrItineraryData() const override { - return Subtarget->inMips16Mode() - ? nullptr - : &getSubtargetImpl()->getInstrItineraryData(); - } - MipsJITInfo *getJITInfo() override { - return Subtarget->getJITInfo(); - } - const MipsRegisterInfo *getRegisterInfo() const override { - return getSubtargetImpl()->getRegisterInfo(); - } - const MipsTargetLowering *getTargetLowering() const override { - return getSubtargetImpl()->getTargetLowering(); - } - const DataLayout *getDataLayout() const override { - return getSubtargetImpl()->getDataLayout(); - } - const MipsSelectionDAGInfo* getSelectionDAGInfo() const override { - return getSubtargetImpl()->getSelectionDAGInfo(); - } + + const MipsSubtarget *getSubtargetImpl(const Function &F) const override; + /// \brief Reset the subtarget for the Mips target. void resetSubtarget(MachineFunction *MF); // Pass Pipeline Configuration TargetPassConfig *createPassConfig(PassManagerBase &PM) override; - bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE) override; + + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } + + bool isLittleEndian() const { return isLittle; } }; /// MipsebTargetMachine - Mips32/64 big endian target machine. diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index 13f9408f4e6e..b56c39bf496c 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -24,6 +24,17 @@ SSThreshold("mips-ssection-threshold", cl::Hidden, cl::desc("Small data and bss section threshold size (default=8)"), cl::init(8)); +static cl::opt<bool> +LocalSData("mlocal-sdata", cl::Hidden, + cl::desc("MIPS: Use gp_rel for object-local data."), + cl::init(true)); + +static cl::opt<bool> +ExternSData("mextern-sdata", cl::Hidden, + cl::desc("MIPS: Use gp_rel for data that is not defined by the " + "current object."), + cl::init(true)); + void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); InitializeELF(TM.Options.UseInitArray); @@ -37,29 +48,46 @@ void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ getContext().getELFSection(".sbss", ELF::SHT_NOBITS, ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getBSS()); + this->TM = &TM; } // A address must be loaded from a small section if its size is less than the // small section size threshold. Data in this section must be addressed using // gp_rel operator. static bool IsInSmallSection(uint64_t Size) { + // gcc has traditionally not treated zero-sized objects as small data, so this + // is effectively part of the ABI. return Size > 0 && Size <= SSThreshold; } -bool MipsTargetObjectFile::IsGlobalInSmallSection(const GlobalValue *GV, - const TargetMachine &TM) const { +/// Return true if this global address should be placed into small data/bss +/// section. +bool MipsTargetObjectFile:: +IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const { + // We first check the case where global is a declaration, because finding + // section kind using getKindForGlobal() is only allowed for global + // definitions. if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) - return false; + return IsGlobalInSmallSectionImpl(GV, TM); return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); } -/// IsGlobalInSmallSection - Return true if this global address should be -/// placed into small data/bss section. +/// Return true if this global address should be placed into small data/bss +/// section. bool MipsTargetObjectFile:: IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, SectionKind Kind) const { + return (IsGlobalInSmallSectionImpl(GV, TM) && + (Kind.isDataRel() || Kind.isBSS() || Kind.isCommon())); +} +/// Return true if this global address should be placed into small data/bss +/// section. This method does all the work, except for checking the section +/// kind. +bool MipsTargetObjectFile:: +IsGlobalInSmallSectionImpl(const GlobalValue *GV, + const TargetMachine &TM) const { const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); // Return if small section is not available. @@ -71,21 +99,20 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, if (!GVA) return false; - // We can only do this for datarel or BSS objects for now. - if (!Kind.isBSS() && !Kind.isDataRel()) + // Enforce -mlocal-sdata. + if (!LocalSData && GV->hasLocalLinkage()) return false; - // If this is a internal constant string, there is a special - // section for it, but not in small data/bss. - if (Kind.isMergeable1ByteCString()) + // Enforce -mextern-sdata. + if (!ExternSData && ((GV->hasExternalLinkage() && GV->isDeclaration()) || + GV->hasCommonLinkage())) return false; Type *Ty = GV->getType()->getElementType(); - return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty)); + return IsInSmallSection( + TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(Ty)); } - - const MCSection *MipsTargetObjectFile:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { @@ -95,9 +122,27 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, // Handle Small Section classification here. if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) return SmallBSSSection; - if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind)) + if (Kind.isDataRel() && IsGlobalInSmallSection(GV, TM, Kind)) return SmallDataSection; // Otherwise, we work the same as ELF. return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); } + +/// 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()))); +} + +const MCSection *MipsTargetObjectFile:: +getSectionForConstant(SectionKind Kind, const Constant *C) const { + if (IsConstantInSmallSection(C, *TM)) + return SmallDataSection; + + // Otherwise, we work the same as ELF. + return TargetLoweringObjectFileELF::getSectionForConstant(Kind, C); +} diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h index 2bf5a75be90c..3a2b298db329 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.h +++ b/lib/Target/Mips/MipsTargetObjectFile.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_MIPS_TARGETOBJECTFILE_H -#define LLVM_TARGET_MIPS_TARGETOBJECTFILE_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETOBJECTFILE_H +#define LLVM_LIB_TARGET_MIPS_MIPSTARGETOBJECTFILE_H #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" @@ -17,21 +17,30 @@ namespace llvm { class MipsTargetObjectFile : public TargetLoweringObjectFileELF { const MCSection *SmallDataSection; const MCSection *SmallBSSSection; + const TargetMachine *TM; public: void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - - /// IsGlobalInSmallSection - Return true if this global address should be - /// placed into small data/bss section. - bool IsGlobalInSmallSection(const GlobalValue *GV, - const TargetMachine &TM, SectionKind Kind)const; + /// Return true if this global address should be placed into small data/bss + /// section. + bool IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, + SectionKind Kind) const; bool IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const; + bool IsGlobalInSmallSectionImpl(const GlobalValue *GV, + const TargetMachine &TM) const; const MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const override; + + /// Return true if this constant should be placed into small data section. + bool IsConstantInSmallSection(const Constant *CN, + const TargetMachine &TM) const; + + const MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; }; } // end namespace llvm diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index 99f7d4c92cfb..6dcd15acef05 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSTARGETSTREAMER_H -#define MIPSTARGETSTREAMER_H +#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H +#define LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H +#include "MCTargetDesc/MipsABIFlagsSection.h" #include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" -#include "MCTargetDesc/MipsABIFlagsSection.h" namespace llvm { @@ -30,6 +31,8 @@ public: virtual void emitDirectiveSetNoReorder(); virtual void emitDirectiveSetMacro(); virtual void emitDirectiveSetNoMacro(); + virtual void emitDirectiveSetMsa(); + virtual void emitDirectiveSetNoMsa(); virtual void emitDirectiveSetAt(); virtual void emitDirectiveSetNoAt(); virtual void emitDirectiveEnd(StringRef Name); @@ -45,13 +48,26 @@ public: virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff); virtual void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff); + virtual void emitDirectiveSetArch(StringRef Arch); + virtual void emitDirectiveSetMips0(); + virtual void emitDirectiveSetMips1(); + virtual void emitDirectiveSetMips2(); + virtual void emitDirectiveSetMips3(); + virtual void emitDirectiveSetMips4(); + virtual void emitDirectiveSetMips5(); + virtual void emitDirectiveSetMips32(); virtual void emitDirectiveSetMips32R2(); + virtual void emitDirectiveSetMips32R6(); virtual void emitDirectiveSetMips64(); virtual void emitDirectiveSetMips64R2(); + virtual void emitDirectiveSetMips64R6(); virtual void emitDirectiveSetDsp(); + virtual void emitDirectiveSetNoDsp(); + virtual void emitDirectiveSetPop(); + virtual void emitDirectiveSetPush(); // PIC support - virtual void emitDirectiveCpload(unsigned RegNo); + virtual void emitDirectiveCpLoad(unsigned RegNo); virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); @@ -72,8 +88,8 @@ public: virtual void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI); virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value){}; virtual void emitMipsAbiFlags(){}; - void setCanHaveModuleDir(bool Can) { canHaveModuleDirective = Can; } - bool getCanHaveModuleDir() { return canHaveModuleDirective; } + void forbidModuleDirective() { ModuleDirectiveAllowed = false; } + bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } // This method enables template classes to set internal abi flags // structure values. @@ -87,8 +103,21 @@ public: protected: MipsABIFlagsSection ABIFlagsSection; + bool GPRInfoSet; + unsigned GPRBitMask; + int GPROffset; + + bool FPRInfoSet; + unsigned FPRBitMask; + int FPROffset; + + bool FrameInfoSet; + int FrameOffset; + unsigned FrameReg; + unsigned ReturnReg; + private: - bool canHaveModuleDirective; + bool ModuleDirectiveAllowed; }; // This part is for ascii assembly output @@ -106,6 +135,8 @@ public: void emitDirectiveSetNoReorder() override; void emitDirectiveSetMacro() override; void emitDirectiveSetNoMacro() override; + void emitDirectiveSetMsa() override; + void emitDirectiveSetNoMsa() override; void emitDirectiveSetAt() override; void emitDirectiveSetNoAt() override; void emitDirectiveEnd(StringRef Name) override; @@ -121,13 +152,26 @@ public: void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override; + void emitDirectiveSetArch(StringRef Arch) override; + void emitDirectiveSetMips0() override; + void emitDirectiveSetMips1() override; + void emitDirectiveSetMips2() override; + void emitDirectiveSetMips3() override; + void emitDirectiveSetMips4() override; + void emitDirectiveSetMips5() override; + void emitDirectiveSetMips32() override; void emitDirectiveSetMips32R2() override; + void emitDirectiveSetMips32R6() override; void emitDirectiveSetMips64() override; void emitDirectiveSetMips64R2() override; + void emitDirectiveSetMips64R6() override; void emitDirectiveSetDsp() override; + void emitDirectiveSetNoDsp() override; + void emitDirectiveSetPop() override; + void emitDirectiveSetPush() override; // PIC support - virtual void emitDirectiveCpload(unsigned RegNo); + void emitDirectiveCpLoad(unsigned RegNo) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; @@ -157,14 +201,8 @@ public: void emitDirectiveSetMicroMips() override; void emitDirectiveSetNoMicroMips() override; void emitDirectiveSetMips16() override; - void emitDirectiveSetNoMips16() override; - void emitDirectiveSetReorder() override; void emitDirectiveSetNoReorder() override; - void emitDirectiveSetMacro() override; - void emitDirectiveSetNoMacro() override; - void emitDirectiveSetAt() override; - void emitDirectiveSetNoAt() override; void emitDirectiveEnd(StringRef Name) override; void emitDirectiveEnt(const MCSymbol &Symbol) override; @@ -178,13 +216,8 @@ public: void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override; - void emitDirectiveSetMips32R2() override; - void emitDirectiveSetMips64() override; - void emitDirectiveSetMips64R2() override; - void emitDirectiveSetDsp() override; - // PIC support - virtual void emitDirectiveCpload(unsigned RegNo); + void emitDirectiveCpLoad(unsigned RegNo) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; |