diff options
author | Pascal Stumpf <pascal@cvs.openbsd.org> | 2016-09-03 22:47:02 +0000 |
---|---|---|
committer | Pascal Stumpf <pascal@cvs.openbsd.org> | 2016-09-03 22:47:02 +0000 |
commit | 6e362578e8020fa6de5da1e0d11e30e360318a5a (patch) | |
tree | 86dd63849af9145bf5727ea9c67ca5a97f9498ce /gnu/llvm/lib | |
parent | 9f18fb39bd48df66a878b9f7092f8707cce051aa (diff) |
Use the space freed up by sparc and zaurus to import LLVM.
ok hackroom@
Diffstat (limited to 'gnu/llvm/lib')
-rw-r--r-- | gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 4865 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp | 528 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td | 1078 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/Mips/MipsInstrInfo.td | 2407 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h | 112 |
5 files changed, 2501 insertions, 6489 deletions
diff --git a/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index f10d100bfe1..d4e061f00d3 100644 --- a/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -7,71 +7,45 @@ // //===----------------------------------------------------------------------===// -#include "MCTargetDesc/MipsABIFlagsSection.h" #include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" +#include "MipsRegisterInfo.h" +#include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/MCValue.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> #include <memory> -#include <string> -#include <utility> using namespace llvm; #define DEBUG_TYPE "mips-asm-parser" namespace llvm { - class MCInstrInfo; - -} // end namespace llvm - -extern cl::opt<bool> EmitJalrReloc; +} namespace { - class MipsAssemblerOptions { public: - MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {} + MipsAssemblerOptions(const FeatureBitset &Features_) : + ATReg(1), Reorder(true), Macro(true), Features(Features_) {} MipsAssemblerOptions(const MipsAssemblerOptions *Opts) { ATReg = Opts->getATRegIndex(); @@ -108,13 +82,12 @@ public: static const FeatureBitset AllArchRelatedMask; private: - unsigned ATReg = 1; - bool Reorder = true; - bool Macro = true; + unsigned ATReg; + bool Reorder; + bool Macro; FeatureBitset Features; }; - -} // end anonymous namespace +} const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3, @@ -128,7 +101,6 @@ const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { }; namespace { - class MipsAsmParser : public MCTargetAsmParser { MipsTargetStreamer &getTargetStreamer() { MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); @@ -149,21 +121,13 @@ class MipsAsmParser : public MCTargetAsmParser { /// If true, then CpSaveLocation is a register, otherwise it's an offset. bool CpSaveLocationIsRegister; - // Map of register aliases created via the .set directive. - StringMap<AsmToken> RegisterSets; - // 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); - void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands); - #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" - unsigned - checkEarlyTargetMatchPredicate(MCInst &Inst, - const OperandVector &Operands) override; unsigned checkTargetMatchPredicate(MCInst &Inst) override; bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, @@ -178,8 +142,6 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseBracketSuffix(StringRef Name, OperandVector &Operands); - bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID); - bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -190,14 +152,14 @@ class MipsAsmParser : public MCTargetAsmParser { matchAnyRegisterNameWithoutDollar(OperandVector &Operands, StringRef Identifier, SMLoc S); OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, - const AsmToken &Token, - SMLoc S); - OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S); OperandMatchResultTy parseAnyRegister(OperandVector &Operands); OperandMatchResultTy parseImm(OperandVector &Operands); OperandMatchResultTy parseJumpTarget(OperandVector &Operands); OperandMatchResultTy parseInvNum(OperandVector &Operands); + OperandMatchResultTy parseLSAImm(OperandVector &Operands); + OperandMatchResultTy parseRegisterPair(OperandVector &Operands); + OperandMatchResultTy parseMovePRegPair(OperandVector &Operands); OperandMatchResultTy parseRegisterList(OperandVector &Operands); bool searchSymbolAlias(OperandVector &Operands); @@ -211,109 +173,82 @@ class MipsAsmParser : public MCTargetAsmParser { }; // Expands assembly pseudo instructions. - MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI); + MacroExpanderResultTy + tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, bool Is32BitImm, bool IsAddress, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); + SmallVectorImpl<MCInst> &Instructions); bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); - - bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym); + SmallVectorImpl<MCInst> &Instructions); bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); - - bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU, - SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + SmallVectorImpl<MCInst> &Instructions); bool expandLoadAddress(unsigned DstReg, unsigned BaseReg, const MCOperand &Offset, bool Is32BitAddress, - SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad); + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); - bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + void expandMemInst(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions, bool isLoad, + bool isImmOpnd); - bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, const bool IsMips64, - const bool Signed); + bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandDiv(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions, const bool IsMips64, + const bool Signed); - bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool expandUlw(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); bool expandRotation(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); - bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + SmallVectorImpl<MCInst> &Instructions); + bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + bool expandDRotation(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad); + void createNop(bool hasShortDelaySlot, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, + bool Is64Bit, SmallVectorImpl<MCInst> &Instructions); - bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); + bool parseRelocOperand(const MCExpr *&Res); + + const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); bool isEvaluated(const MCExpr *Expr); bool parseSetMips0Directive(); @@ -328,8 +263,6 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseDirectiveSet(); bool parseDirectiveOption(); bool parseInsnDirective(); - bool parseRSectionDirective(StringRef Section); - bool parseSSectionDirective(StringRef Section, unsigned Type); bool parseSetAtDirective(); bool parseSetNoAtDirective(); @@ -349,20 +282,12 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetPushDirective(); bool parseSetSoftFloatDirective(); bool parseSetHardFloatDirective(); - bool parseSetMtDirective(); - bool parseSetNoMtDirective(); - bool parseSetNoCRCDirective(); - bool parseSetNoVirtDirective(); - bool parseSetNoGINVDirective(); bool parseSetAssignment(); + bool parseDataDirective(unsigned Size, SMLoc L); bool parseDirectiveGpWord(); bool parseDirectiveGpDWord(); - bool parseDirectiveDtpRelWord(); - bool parseDirectiveDtpRelDWord(); - bool parseDirectiveTpRelWord(); - bool parseDirectiveTpRelDWord(); bool parseDirectiveModule(); bool parseDirectiveModuleFP(); bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, @@ -370,12 +295,16 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseInternalDirectiveReallowModule(); + MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); + bool eatComma(StringRef ErrorStr); int matchCPURegisterName(StringRef Symbol); int matchHWRegsRegisterName(StringRef Symbol); + int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); + int matchFPURegisterName(StringRef Name); int matchFCCRegisterName(StringRef Name); @@ -388,15 +317,15 @@ class MipsAsmParser : public MCTargetAsmParser { unsigned getReg(int RC, int RegNo); + unsigned getGPR(int RegNo); + /// Returns the internal register number for the current AT. Also checks if /// the current AT is unavailable (set to $0) and gives an error if it is. /// This should be used in pseudo-instruction expansions which need AT. unsigned getATReg(SMLoc Loc); - bool canUseATReg(); - - bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); + bool processInstruction(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); // Helper function that checks if the value of a vector index is within the // boundaries of accepted values for each RegisterKind @@ -466,15 +395,6 @@ class MipsAsmParser : public MCTargetAsmParser { public: enum MipsMatchResultTy { Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY, - Match_RequiresDifferentOperands, - Match_RequiresNoZeroRegister, - Match_RequiresSameSrcAndDst, - Match_NoFCCRegisterForCurrentISA, - Match_NonZeroOperandForSync, - Match_NonZeroOperandForMTCX, - Match_RequiresPosSizeRange0_32, - Match_RequiresPosSizeRange33_64, - Match_RequiresPosSizeUImm6, #define GET_OPERAND_DIAGNOSTIC_TYPES #include "MipsGenAsmMatcher.inc" #undef GET_OPERAND_DIAGNOSTIC_TYPES @@ -482,15 +402,12 @@ public: MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII, const MCTargetOptions &Options) - : MCTargetAsmParser(Options, sti, MII), + : MCTargetAsmParser(Options, sti), ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()), sti.getCPU(), Options)) { MCAsmParserExtension::Initialize(parser); parser.addAliasForDirective(".asciiz", ".asciz"); - parser.addAliasForDirective(".hword", ".2byte"); - parser.addAliasForDirective(".word", ".4byte"); - parser.addAliasForDirective(".dword", ".8byte"); // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); @@ -510,19 +427,18 @@ public: CurrentFn = nullptr; - IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent(); + IsPicEnabled = + (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_); IsCpRestoreSet = false; CpRestoreOffset = -1; - const Triple &TheTriple = sti.getTargetTriple(); - IsLittleEndian = TheTriple.isLittleEndian(); - - if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode()) - report_fatal_error("microMIPS64R6 is not supported", false); - - if (!isABI_O32() && inMicroMipsMode()) - report_fatal_error("microMIPS64 is not supported", false); + Triple TheTriple(sti.getTargetTriple()); + if ((TheTriple.getArch() == Triple::mips) || + (TheTriple.getArch() == Triple::mips64)) + IsLittleEndian = false; + else + IsLittleEndian = true; } /// True if all of $fcc0 - $fcc7 exist for the current ISA. @@ -531,11 +447,9 @@ public: bool isGP64bit() const { return getSTI().getFeatureBits()[Mips::FeatureGP64Bit]; } - bool isFP64bit() const { return getSTI().getFeatureBits()[Mips::FeatureFP64Bit]; } - const MipsABIInfo &getABI() const { return ABI; } bool isABI_N32() const { return ABI.IsN32(); } bool isABI_N64() const { return ABI.IsN64(); } @@ -551,63 +465,48 @@ public: bool inMicroMipsMode() const { return getSTI().getFeatureBits()[Mips::FeatureMicroMips]; } - bool hasMips1() const { return getSTI().getFeatureBits()[Mips::FeatureMips1]; } - bool hasMips2() const { return getSTI().getFeatureBits()[Mips::FeatureMips2]; } - bool hasMips3() const { return getSTI().getFeatureBits()[Mips::FeatureMips3]; } - bool hasMips4() const { return getSTI().getFeatureBits()[Mips::FeatureMips4]; } - bool hasMips5() const { return getSTI().getFeatureBits()[Mips::FeatureMips5]; } - bool hasMips32() const { return getSTI().getFeatureBits()[Mips::FeatureMips32]; } - bool hasMips64() const { return getSTI().getFeatureBits()[Mips::FeatureMips64]; } - bool hasMips32r2() const { return getSTI().getFeatureBits()[Mips::FeatureMips32r2]; } - bool hasMips64r2() const { return getSTI().getFeatureBits()[Mips::FeatureMips64r2]; } - bool hasMips32r3() const { return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]); } - bool hasMips64r3() const { return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]); } - bool hasMips32r5() const { return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]); } - bool hasMips64r5() const { return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]); } - bool hasMips32r6() const { return getSTI().getFeatureBits()[Mips::FeatureMips32r6]; } - bool hasMips64r6() const { return getSTI().getFeatureBits()[Mips::FeatureMips64r6]; } @@ -615,19 +514,15 @@ public: bool hasDSP() const { return getSTI().getFeatureBits()[Mips::FeatureDSP]; } - bool hasDSPR2() const { return getSTI().getFeatureBits()[Mips::FeatureDSPR2]; } - bool hasDSPR3() const { return getSTI().getFeatureBits()[Mips::FeatureDSPR3]; } - bool hasMSA() const { return getSTI().getFeatureBits()[Mips::FeatureMSA]; } - bool hasCnMips() const { return (getSTI().getFeatureBits()[Mips::FeatureCnMips]); } @@ -647,21 +542,6 @@ public: bool useSoftFloat() const { return getSTI().getFeatureBits()[Mips::FeatureSoftFloat]; } - bool hasMT() const { - return getSTI().getFeatureBits()[Mips::FeatureMT]; - } - - bool hasCRC() const { - return getSTI().getFeatureBits()[Mips::FeatureCRC]; - } - - bool hasVirt() const { - return getSTI().getFeatureBits()[Mips::FeatureVirt]; - } - - bool hasGINV() const { - return getSTI().getFeatureBits()[Mips::FeatureGINV]; - } /// Warn if RegIndex is the same as the current AT. void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc); @@ -669,65 +549,10 @@ public: void warnIfNoMacro(SMLoc Loc); bool isLittle() const { return IsLittleEndian; } - - const MCExpr *createTargetUnaryExpr(const MCExpr *E, - AsmToken::TokenKind OperatorToken, - MCContext &Ctx) override { - switch(OperatorToken) { - default: - llvm_unreachable("Unknown token"); - return nullptr; - case AsmToken::PercentCall16: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx); - case AsmToken::PercentCall_Hi: - return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx); - case AsmToken::PercentCall_Lo: - return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx); - case AsmToken::PercentDtprel_Hi: - return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx); - case AsmToken::PercentDtprel_Lo: - return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx); - case AsmToken::PercentGot: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx); - case AsmToken::PercentGot_Disp: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx); - case AsmToken::PercentGot_Hi: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx); - case AsmToken::PercentGot_Lo: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx); - case AsmToken::PercentGot_Ofst: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx); - case AsmToken::PercentGot_Page: - return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx); - case AsmToken::PercentGottprel: - return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx); - case AsmToken::PercentGp_Rel: - return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx); - case AsmToken::PercentHi: - return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx); - case AsmToken::PercentHigher: - return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx); - case AsmToken::PercentHighest: - return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx); - case AsmToken::PercentLo: - return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx); - case AsmToken::PercentNeg: - return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx); - case AsmToken::PercentPcrel_Hi: - return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx); - case AsmToken::PercentPcrel_Lo: - return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx); - case AsmToken::PercentTlsgd: - return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx); - case AsmToken::PercentTlsldm: - return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx); - case AsmToken::PercentTprel_Hi: - return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx); - case AsmToken::PercentTprel_Lo: - return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx); - } - } }; +} + +namespace { /// MipsOperand - Instances of this class represent a parsed Mips machine /// instruction. @@ -759,30 +584,17 @@ private: enum KindTy { k_Immediate, /// An immediate (possibly involving symbol references) 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_RegList, /// A physical register list + k_RegPair /// A pair of physical register } Kind; public: MipsOperand(KindTy K, MipsAsmParser &Parser) : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} - ~MipsOperand() override { - switch (Kind) { - case k_Memory: - delete Mem.Base; - break; - case k_RegList: - delete RegList.List; - break; - case k_Immediate: - case k_RegisterIndex: - case k_Token: - break; - } - } - private: /// For diagnostics, and checking the assembler temporary MipsAsmParser &AsmParser; @@ -792,10 +604,13 @@ private: unsigned Length; }; + struct PhysRegOp { + unsigned Num; /// Register Number + }; + struct RegIdxOp { unsigned Index; /// Index into the register class RegKind Kind; /// Bitfield of the kinds it could possibly be - struct Token Tok; /// The input token this operand originated from. const MCRegisterInfo *RegInfo; }; @@ -814,6 +629,7 @@ private: union { struct Token Tok; + struct PhysRegOp PhysReg; struct RegIdxOp RegIdx; struct ImmOp Imm; struct MemOp Mem; @@ -823,17 +639,14 @@ private: SMLoc StartLoc, EndLoc; /// Internal constructor for register kinds - static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str, - RegKind RegKind, + static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser); + auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser); Op->RegIdx.Index = Index; Op->RegIdx.RegInfo = RegInfo; Op->RegIdx.Kind = RegKind; - Op->RegIdx.Tok.Data = Str.data(); - Op->RegIdx.Tok.Length = Str.size(); Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -1008,16 +821,6 @@ public: /// Render the operand to an MCInst as a GPR32 /// Asserts if the wrong number of operands are requested, or the operand /// is not a k_RegisterIndex compatible with RegKind_GPR - void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getGPR32Reg())); - } - - void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getGPR32Reg())); - } - void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getGPR32Reg())); @@ -1038,17 +841,6 @@ public: Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); } - void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); - } - - void addGPRMM16AsmRegMovePPairSecondOperands(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 @@ -1062,16 +854,6 @@ public: Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); } - void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); - } - - void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getFGR64Reg())); - } - void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getFGR64Reg())); @@ -1081,17 +863,6 @@ public: assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getFGR32Reg())); // FIXME: We ought to do this for -integrated-as without -via-file-asm too. - // FIXME: This should propagate failure up to parseStatement. - if (!AsmParser.useOddSPReg() && RegIdx.Index & 1) - AsmParser.getParser().printError( - StartLoc, "-mno-odd-spreg prohibits the use of odd FPU " - "registers"); - } - - void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getFGR32Reg())); - // FIXME: We ought to do this for -integrated-as without -via-file-asm too. if (!AsmParser.useOddSPReg() && RegIdx.Index & 1) AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU " "registers"); @@ -1161,35 +932,7 @@ public: void addConstantUImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); uint64_t Imm = getConstantImm() - Offset; - Imm &= (1ULL << Bits) - 1; - Imm += Offset; - Imm += AdjustOffset; - Inst.addOperand(MCOperand::createImm(Imm)); - } - - template <unsigned Bits> - void addSImmOperands(MCInst &Inst, unsigned N) const { - if (isImm() && !isConstantImm()) { - addExpr(Inst, getImm()); - return; - } - addConstantSImmOperands<Bits, 0, 0>(Inst, N); - } - - template <unsigned Bits> - void addUImmOperands(MCInst &Inst, unsigned N) const { - if (isImm() && !isConstantImm()) { - addExpr(Inst, getImm()); - return; - } - addConstantUImmOperands<Bits, 0, 0>(Inst, N); - } - - template <unsigned Bits, int Offset = 0, int AdjustOffset = 0> - void addConstantSImmOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - int64_t Imm = getConstantImm() - Offset; - Imm = SignExtend64<Bits>(Imm); + Imm &= (1 << Bits) - 1; Imm += Offset; Imm += AdjustOffset; Inst.addOperand(MCOperand::createImm(Imm)); @@ -1228,136 +971,75 @@ public: Inst.addOperand(MCOperand::createReg(RegNo)); } - bool isReg() const override { - // As a special case until we sort out the definition of div/divu, accept - // $0/$zero here so that MCK_ZERO works correctly. - return isGPRAsmReg() && RegIdx.Index == 0; + void addRegPairOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + unsigned RegNo = getRegPair(); + Inst.addOperand(MCOperand::createReg(RegNo++)); + Inst.addOperand(MCOperand::createReg(RegNo)); } + void addMovePRegPairOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + for (auto RegNo : getRegList()) + Inst.addOperand(MCOperand::createReg(RegNo)); + } + + bool isReg() const override { + // As a special case until we sort out the definition of div/divu, pretend + // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. + if (isGPRAsmReg() && RegIdx.Index == 0) + return true; + + return Kind == k_PhysRegister; + } bool isRegIdx() const { return Kind == k_RegisterIndex; } bool isImm() const override { return Kind == k_Immediate; } - bool isConstantImm() const { - int64_t Res; - return isImm() && getImm()->evaluateAsAbsolute(Res); + return isImm() && isa<MCConstantExpr>(getImm()); } - bool isConstantImmz() const { return isConstantImm() && getConstantImm() == 0; } - template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); } - - template <unsigned Bits> bool isSImm() const { - return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm(); - } - - template <unsigned Bits> bool isUImm() const { - return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm(); - } - - template <unsigned Bits> bool isAnyImm() const { - return isConstantImm() ? (isInt<Bits>(getConstantImm()) || - isUInt<Bits>(getConstantImm())) - : isImm(); - } - - template <unsigned Bits, int Offset = 0> bool isConstantSImm() const { - return isConstantImm() && isInt<Bits>(getConstantImm() - Offset); + template <unsigned Bits> bool isConstantSImm() const { + return isConstantImm() && isInt<Bits>(getConstantImm()); } - - template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const { - return isConstantImm() && getConstantImm() >= Bottom && - getConstantImm() <= Top; - } - bool isToken() const override { // Note: It's not possible to pretend that other operand kinds are tokens. // The matcher emitter checks tokens first. return Kind == k_Token; } - bool isMem() const override { return Kind == k_Memory; } - bool isConstantMemOff() const { return isMem() && isa<MCConstantExpr>(getMemOff()); } - - // Allow relocation operators. - // FIXME: This predicate and others need to look through binary expressions - // and determine whether a Value is a constant or not. - template <unsigned Bits, unsigned ShiftAmount = 0> - bool isMemWithSimmOffset() const { - if (!isMem()) - return false; - if (!getMemBase()->isGPRAsmReg()) - return false; - if (isa<MCTargetExpr>(getMemOff()) || - (isConstantMemOff() && - isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()))) - return true; - MCValue Res; - bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); - return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant()); + template <unsigned Bits> bool isMemWithSimmOffset() const { + return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) + && getMemBase()->isGPRAsmReg(); } - - bool isMemWithPtrSizeOffset() const { - if (!isMem()) - return false; - if (!getMemBase()->isGPRAsmReg()) - return false; - const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32; - if (isa<MCTargetExpr>(getMemOff()) || - (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff()))) - return true; - MCValue Res; - bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); - return IsReloc && isIntN(PtrBits, Res.getConstant()); + template <unsigned Bits> bool isMemWithSimmOffsetGPR() const { + return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) && + getMemBase()->isGPRAsmReg(); } - 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); } - - template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const { - return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) - && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() - && (getMemBase()->getGPR32Reg() == Mips::GP); - } - template <unsigned Bits, unsigned ShiftLeftAmount> bool isScaledUImm() const { return isConstantImm() && isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm()); } - - template <unsigned Bits, unsigned ShiftLeftAmount> - bool isScaledSImm() const { - if (isConstantImm() && - isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm())) - return true; - // Operand can also be a symbol or symbol plus - // offset in case of relocations. - if (Kind != k_Immediate) - return false; - MCValue Res; - bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr); - return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant()); - } - bool isRegList16() const { if (!isRegList()) return false; @@ -1382,32 +1064,49 @@ public: return true; } - bool isInvNum() const { return Kind == k_Immediate; } - bool isLSAImm() const { if (!isConstantImm()) return false; int64_t Val = getConstantImm(); return 1 <= Val && Val <= 4; } - bool isRegList() const { return Kind == k_RegList; } + bool isMovePRegPair() const { + if (Kind != k_RegList || RegList.List->size() != 2) + return false; + + unsigned R0 = RegList.List->front(); + unsigned R1 = RegList.List->back(); + + if ((R0 == Mips::A1 && R1 == Mips::A2) || + (R0 == Mips::A1 && R1 == Mips::A3) || + (R0 == Mips::A2 && R1 == Mips::A3) || + (R0 == Mips::A0 && R1 == Mips::S5) || + (R0 == Mips::A0 && R1 == Mips::S6) || + (R0 == Mips::A0 && R1 == Mips::A1) || + (R0 == Mips::A0 && R1 == Mips::A2) || + (R0 == Mips::A0 && R1 == Mips::A3)) + return true; + + return false; + } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } + bool isRegPair() const { return Kind == k_RegPair; } unsigned getReg() const override { - // As a special case until we sort out the definition of div/divu, accept - // $0/$zero here so that MCK_ZERO works correctly. + // 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. if (Kind == k_RegisterIndex && RegIdx.Index == 0 && RegIdx.Kind & RegKind_GPR) return getGPR32Reg(); // FIXME: GPR64 too - llvm_unreachable("Invalid access!"); - return 0; + assert(Kind == k_PhysRegister && "Invalid access!"); + return PhysReg.Num; } const MCExpr *getImm() const { @@ -1417,9 +1116,7 @@ public: int64_t getConstantImm() const { const MCExpr *Val = getImm(); - int64_t Value = 0; - (void)Val->evaluateAsAbsolute(Value); - return Value; + return static_cast<const MCConstantExpr *>(Val)->getValue(); } MipsOperand *getMemBase() const { @@ -1441,9 +1138,14 @@ public: return *(RegList.List); } + unsigned getRegPair() const { + assert((Kind == k_RegPair) && "Invalid access!"); + return RegIdx.Index; + } + static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, MipsAsmParser &Parser) { - auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser); + auto Op = make_unique<MipsOperand>(k_Token, Parser); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -1454,71 +1156,71 @@ 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); - return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser); + createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, + SMLoc E, MipsAsmParser &Parser) { + 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser); + createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + MipsAsmParser &Parser) { + return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser); } /// 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser); + 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, StringRef Str, const MCRegisterInfo *RegInfo, + createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser); + createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + MipsAsmParser &Parser) { + return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser); } /// 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser); + createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, + MipsAsmParser &Parser) { + return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser); } /// 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser); + createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, + SMLoc E, MipsAsmParser &Parser) { + return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser); } /// 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, StringRef Str, const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser); + createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, + SMLoc E, MipsAsmParser &Parser) { + return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser); } static std::unique_ptr<MipsOperand> CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser); + auto Op = make_unique<MipsOperand>(k_Immediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; @@ -1528,7 +1230,7 @@ public: static std::unique_ptr<MipsOperand> CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser); + auto Op = make_unique<MipsOperand>(k_Memory, Parser); Op->Mem.Base = Base.release(); Op->Mem.Off = Off; Op->StartLoc = S; @@ -1539,34 +1241,32 @@ public: static std::unique_ptr<MipsOperand> CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc, MipsAsmParser &Parser) { - assert(Regs.size() > 0 && "Empty list not allowed"); + assert (Regs.size() > 0 && "Empty list not allowed"); - auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser); + auto Op = make_unique<MipsOperand>(k_RegList, Parser); Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end()); Op->StartLoc = StartLoc; Op->EndLoc = EndLoc; return Op; } - bool isGPRZeroAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0; - } - - bool isGPRNonZeroAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 && - RegIdx.Index <= 31; + 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)) @@ -1575,71 +1275,44 @@ public: (RegIdx.Index >= 2 && RegIdx.Index <= 7) || RegIdx.Index == 17); } - bool isMM16AsmRegMoveP() const { if (!(isRegIdx() && RegIdx.Kind)) return false; return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || (RegIdx.Index >= 16 && RegIdx.Index <= 20)); } - - bool isMM16AsmRegMovePPairFirst() const { - if (!(isRegIdx() && RegIdx.Kind)) - return false; - return RegIdx.Index >= 4 && RegIdx.Index <= 6; - } - - bool isMM16AsmRegMovePPairSecond() const { - if (!(isRegIdx() && RegIdx.Kind)) - return false; - return (RegIdx.Index == 21 || RegIdx.Index == 22 || - (RegIdx.Index >= 5 && RegIdx.Index <= 7)); - } - bool isFGRAsmReg() const { // AFGR64 is $0-$15 but we handle this in getAFGR64() return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; } - - bool isStrictlyFGRAsmReg() const { - // AFGR64 is $0-$15 but we handle this in getAFGR64() - return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31; - } - bool isHWRegsAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; } - bool isCCRAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31; } - bool isFCCAsmReg() const { if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC)) return false; + if (!AsmParser.hasEightFccRegisters()) + return RegIdx.Index == 0; return RegIdx.Index <= 7; } - bool isACCAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3; } - bool isCOP0AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31; } - bool isCOP2AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31; } - bool isCOP3AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31; } - bool isMSA128AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31; } - bool isMSACtrlAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7; } @@ -1649,6 +1322,23 @@ public: /// getEndLoc - Get the location of the last token of this operand. SMLoc getEndLoc() const override { return EndLoc; } + virtual ~MipsOperand() { + switch (Kind) { + case k_Immediate: + break; + 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; + } + } + void print(raw_ostream &OS) const override { switch (Kind) { case k_Immediate: @@ -1663,12 +1353,14 @@ public: OS << *Mem.Off; OS << ">"; break; + case k_PhysRegister: + OS << "PhysReg<" << PhysReg.Num << ">"; + break; case k_RegisterIndex: - OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", " - << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">"; + OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">"; break; case k_Token: - OS << getToken(); + OS << Tok.Data; break; case k_RegList: OS << "RegList< "; @@ -1676,55 +1368,29 @@ public: OS << Reg << " "; OS << ">"; break; - } - } - - bool isValidForTie(const MipsOperand &Other) const { - if (Kind != Other.Kind) - return false; - - switch (Kind) { - default: - llvm_unreachable("Unexpected kind"); - return false; - case k_RegisterIndex: { - StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length); - StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length); - return Token == OtherToken; - } + case k_RegPair: + OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; + break; } } }; // class MipsOperand - -} // end anonymous namespace +} // namespace namespace llvm { - extern const MCInstrDesc MipsInsts[]; - -} // end namespace llvm - +} static const MCInstrDesc &getInstDesc(unsigned Opcode) { return MipsInsts[Opcode]; } -static bool hasShortDelaySlot(MCInst &Inst) { - switch (Inst.getOpcode()) { - case Mips::BEQ_MM: - case Mips::BNE_MM: - case Mips::BLTZ_MM: - case Mips::BGEZ_MM: - case Mips::BLEZ_MM: - case Mips::BGTZ_MM: - case Mips::JRC16_MM: +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; - case Mips::J_MM: - return !Inst.getOperand(0).isReg(); default: return false; } @@ -1768,10 +1434,83 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { return 0; } +namespace { +void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + MCInst tmpInst; + tmpInst.setOpcode(Opcode); + tmpInst.addOperand(MCOperand::createReg(Reg0)); + tmpInst.addOperand(Op1); + tmpInst.setLoc(IDLoc); + Instructions.push_back(tmpInst); +} + +void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions); +} + +void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions); +} + +void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + MCInst tmpInst; + tmpInst.setOpcode(Opcode); + tmpInst.addOperand(MCOperand::createImm(Imm1)); + tmpInst.addOperand(MCOperand::createImm(Imm2)); + tmpInst.setLoc(IDLoc); + Instructions.push_back(tmpInst); +} + +void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + MCInst tmpInst; + tmpInst.setOpcode(Opcode); + tmpInst.addOperand(MCOperand::createReg(Reg0)); + tmpInst.setLoc(IDLoc); + Instructions.push_back(tmpInst); +} + +void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + MCInst tmpInst; + tmpInst.setOpcode(Opcode); + tmpInst.addOperand(MCOperand::createReg(Reg0)); + tmpInst.addOperand(MCOperand::createReg(Reg1)); + tmpInst.addOperand(Op2); + tmpInst.setLoc(IDLoc); + Instructions.push_back(tmpInst); +} + +void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, + Instructions); +} + +void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, + Instructions); +} + +void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + if (ShiftAmount >= 32) { + emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, + Instructions); + return; + } + + emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions); +} +} // end anonymous namespace. + bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); + SmallVectorImpl<MCInst> &Instructions) { const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); bool ExpandedJalSym = false; @@ -1789,7 +1528,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case Mips::BBIT1: case Mips::BBIT132: assert(hasCnMips() && "instruction only valid for octeon cpus"); - LLVM_FALLTHROUGH; + // Fall through case Mips::BEQ: case Mips::BNE: @@ -1821,10 +1560,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case Mips::BLTZAL_MM: case Mips::BC1F_MM: case Mips::BC1T_MM: - case Mips::BC1EQZC_MMR6: - case Mips::BC1NEZC_MMR6: - case Mips::BC2EQZC_MMR6: - case Mips::BC2NEZC_MMR6: assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); Offset = Inst.getOperand(1); if (!Offset.isImm()) @@ -1835,45 +1570,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 1LL << (inMicroMipsMode() ? 1 : 2))) return Error(IDLoc, "branch to misaligned address"); break; - case Mips::BGEC: case Mips::BGEC_MMR6: - case Mips::BLTC: case Mips::BLTC_MMR6: - case Mips::BGEUC: case Mips::BGEUC_MMR6: - case Mips::BLTUC: case Mips::BLTUC_MMR6: - case Mips::BEQC: case Mips::BEQC_MMR6: - case Mips::BNEC: case Mips::BNEC_MMR6: - assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); - Offset = Inst.getOperand(2); - if (!Offset.isImm()) - break; // We'll deal with this situation later on when applying fixups. - if (!isIntN(18, Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 1LL << 2)) - return Error(IDLoc, "branch to misaligned address"); - break; - case Mips::BLEZC: case Mips::BLEZC_MMR6: - case Mips::BGEZC: case Mips::BGEZC_MMR6: - case Mips::BGTZC: case Mips::BGTZC_MMR6: - case Mips::BLTZC: case Mips::BLTZC_MMR6: - 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(18, Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 1LL << 2)) - return Error(IDLoc, "branch to misaligned address"); - break; - case Mips::BEQZC: case Mips::BEQZC_MMR6: - case Mips::BNEZC: case Mips::BNEZC_MMR6: - 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(23, Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 1LL << 2)) - return Error(IDLoc, "branch to misaligned address"); - break; case Mips::BEQZ16_MM: case Mips::BEQZC16_MMR6: case Mips::BNEZ16_MM: @@ -1940,71 +1636,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } } - // Warn on division by zero. We're checking here as all instructions get - // processed here, not just the macros that need expansion. - // - // The MIPS backend models most of the divison instructions and macros as - // three operand instructions. The pre-R6 divide instructions however have - // two operands and explicitly define HI/LO as part of the instruction, - // not in the operands. - unsigned FirstOp = 1; - unsigned SecondOp = 2; - switch (Inst.getOpcode()) { - default: - break; - case Mips::SDivIMacro: - case Mips::UDivIMacro: - case Mips::DSDivIMacro: - case Mips::DUDivIMacro: - if (Inst.getOperand(2).getImm() == 0) { - if (Inst.getOperand(1).getReg() == Mips::ZERO || - Inst.getOperand(1).getReg() == Mips::ZERO_64) - Warning(IDLoc, "dividing zero by zero"); - else - Warning(IDLoc, "division by zero"); - } - break; - case Mips::DSDIV: - case Mips::SDIV: - case Mips::UDIV: - case Mips::DUDIV: - case Mips::UDIV_MM: - case Mips::SDIV_MM: - FirstOp = 0; - SecondOp = 1; - LLVM_FALLTHROUGH; - case Mips::SDivMacro: - case Mips::DSDivMacro: - case Mips::UDivMacro: - case Mips::DUDivMacro: - case Mips::DIV: - case Mips::DIVU: - case Mips::DDIV: - case Mips::DDIVU: - case Mips::DIVU_MMR6: - case Mips::DIV_MMR6: - if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO || - Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) { - if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO || - Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64) - Warning(IDLoc, "dividing zero by zero"); - else - Warning(IDLoc, "division by zero"); - } - break; - } - - // For PIC code convert unconditional jump to unconditional branch. - if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) && - inPicMode()) { - MCInst BInst; - BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ); - BInst.addOperand(MCOperand::createReg(Mips::ZERO)); - BInst.addOperand(MCOperand::createReg(Mips::ZERO)); - BInst.addOperand(Inst.getOperand(0)); - Inst = BInst; - } - // This expansion is not in a function called by tryExpandInstruction() // because the pseudo-instruction doesn't have a distinct opcode. if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) && @@ -2019,15 +1650,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode"); // FIXME: This is checking the expression can be handled by the later stages - // of the assembler. We ought to leave it to those later stages. + // of the assembler. We ought to leave it to those later stages but + // we can't do that until we stop evaluateRelocExpr() rewriting the + // expressions into non-equivalent forms. const MCSymbol *JalSym = getSingleMCSymbol(JalExpr); // FIXME: Add support for label+offset operands (currently causes an error). // FIXME: Add support for forward-declared local symbols. // FIXME: Add expansion for when the LargeGOT option is enabled. - if (JalSym->isInSection() || JalSym->isTemporary() || - (JalSym->isELF() && - cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) { + if (JalSym->isInSection() || JalSym->isTemporary()) { if (isABI_O32()) { // If it's a local symbol and the O32 ABI is being used, we expand to: // lw $25, 0($gp) @@ -2035,38 +1666,33 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // addiu $25, $25, 0 // R_(MICRO)MIPS_LO16 label // jalr $25 - const MCExpr *Got16RelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext()); - const MCExpr *Lo16RelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext()); - - TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP, - MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); - TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, - MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); + const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got"); + const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo"); + + emitRRX(Mips::LW, Mips::T9, Mips::GP, + MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions); + emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, + MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions); } else if (isABI_N32() || isABI_N64()) { // If it's a local symbol and the N32/N64 ABIs are being used, // we expand to: // lw/ld $25, 0($gp) // R_(MICRO)MIPS_GOT_DISP label // jalr $25 - const MCExpr *GotDispRelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext()); + const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp"); - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, - Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc, - STI); + emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, + MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions); } } else { // If it's an external/weak symbol, we expand to: // lw/ld $25, 0($gp) // R_(MICRO)MIPS_CALL16 label // jalr $25 - const MCExpr *Call16RelocExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext()); + const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16"); - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, - MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); + emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, + MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions); } MCInst JalrInst; @@ -2077,28 +1703,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, JalrInst.addOperand(MCOperand::createReg(Mips::RA)); JalrInst.addOperand(MCOperand::createReg(Mips::T9)); - if (EmitJalrReloc) { - // As an optimization hint for the linker, before the JALR we add: - // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol - // tmplabel: - MCSymbol *TmpLabel = getContext().createTempSymbol(); - const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext()); - const MCExpr *RelocJalrExpr = - MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None, - getContext(), IDLoc); - - TOut.getStreamer().EmitRelocDirective(*TmpExpr, - inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", - RelocJalrExpr, IDLoc, *STI); - TOut.getStreamer().EmitLabel(TmpLabel); - } + // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR. + // This relocation is supposed to be an optimization hint for the linker + // and is not necessary for correctness. Inst = JalrInst; ExpandedJalSym = true; } - bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0; - if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { + if (MCID.mayLoad() || MCID.mayStore()) { // Check the offset of memory operand, if it is a symbol // reference or immediate we may have to expand instructions. for (unsigned i = 0; i < MCID.getNumOperands(); i++) { @@ -2107,11 +1720,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { MCOperand &Op = Inst.getOperand(i); if (Op.isImm()) { - int64_t MemOffset = Op.getImm(); + int MemOffset = Op.getImm(); if (MemOffset < -32768 || MemOffset > 32767) { // Offset can't exceed 16bit value. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); + expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true); + return false; } } else if (Op.isExpr()) { const MCExpr *Expr = Op.getExpr(); @@ -2120,12 +1733,12 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, static_cast<const MCSymbolRefExpr *>(Expr); if (SR->getKind() == MCSymbolRefExpr::VK_None) { // Expand symbol. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); + expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); + return false; } } else if (!isEvaluated(Expr)) { - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); + expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); + return false; } } } @@ -2133,7 +1746,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } // if load/store if (inMicroMipsMode()) { - if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) { + if (MCID.mayLoad()) { // Try to create 16-bit GP relative load instruction. for (unsigned i = 0; i < MCID.getNumOperands(); i++) { const MCOperandInfo &OpInfo = MCID.OpInfo[i]; @@ -2150,8 +1763,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, (BaseReg.getReg() == Mips::GP || BaseReg.getReg() == Mips::GP_64)) { - TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, - IDLoc, STI); + emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, + IDLoc, Instructions); return false; } } @@ -2167,6 +1780,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 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()) @@ -2202,6 +1823,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, ((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()) @@ -2220,6 +1851,12 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, if (Imm < -1 || Imm > 14) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::TEQ_MM: + case Mips::TGE_MM: + case Mips::TGEU_MM: + case Mips::TLT_MM: + case Mips::TLTU_MM: + case Mips::TNE_MM: case Mips::SB16_MM: case Mips::SB16_MMR6: Opnd = Inst.getOperand(2); @@ -2250,47 +1887,21 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, return Error(IDLoc, "immediate operand value out of range"); break; case Mips::ADDIUPC_MM: - Opnd = Inst.getOperand(1); + MCOperand Opnd = Inst.getOperand(1); if (!Opnd.isImm()) return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); + int Imm = Opnd.getImm(); if ((Imm % 4 != 0) || !isInt<25>(Imm)) return Error(IDLoc, "immediate operand value out of range"); break; - case Mips::LWP_MM: - case Mips::SWP_MM: - if (Inst.getOperand(0).getReg() == Mips::RA) - return Error(IDLoc, "invalid operand for instruction"); - break; - case Mips::MOVEP_MM: - case Mips::MOVEP_MMR6: { - unsigned R0 = Inst.getOperand(0).getReg(); - unsigned R1 = Inst.getOperand(1).getReg(); - bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) || - (R0 == Mips::A1 && R1 == Mips::A3) || - (R0 == Mips::A2 && R1 == Mips::A3) || - (R0 == Mips::A0 && R1 == Mips::S5) || - (R0 == Mips::A0 && R1 == Mips::S6) || - (R0 == Mips::A0 && R1 == Mips::A1) || - (R0 == Mips::A0 && R1 == Mips::A2) || - (R0 == Mips::A0 && R1 == Mips::A3)); - if (!RegPair) - return Error(IDLoc, "invalid operand for instruction"); - break; - } } } - bool FillDelaySlot = - MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder(); - if (FillDelaySlot) - TOut.emitDirectiveSetNoReorder(); - MacroExpanderResultTy ExpandResult = - tryExpandInstruction(Inst, IDLoc, Out, STI); + tryExpandInstruction(Inst, IDLoc, Instructions); switch (ExpandResult) { case MER_NotAMacro: - Out.EmitInstruction(Inst, *STI); + Instructions.push_back(Inst); break; case MER_Success: break; @@ -2298,19 +1909,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, return true; } - // We know we emitted an instruction on the MER_NotAMacro or MER_Success path. - // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS. - if (inMicroMipsMode()) { - TOut.setUsesMicroMips(); - TOut.updateABIInfo(*this); - } - // If this instruction has a delay slot and .set reorder is active, // emit a NOP after it. - if (FillDelaySlot) { - TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI); - TOut.emitDirectiveSetReorder(); - } + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) + createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); if ((Inst.getOpcode() == Mips::JalOneReg || Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && @@ -2320,11 +1922,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // If .set reorder has been used, we've already emitted a NOP. // If .set noreorder has been used, we need to emit a NOP at this point. if (!AssemblerOptions.back()->isReorder()) - TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, - STI); + createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); // Load the $gp from the stack. - TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI); + SmallVector<MCInst, 3> LoadInsts; + createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/, + IDLoc, LoadInsts); + + for (const MCInst &Inst : LoadInsts) + Instructions.push_back(Inst); + } else Warning(IDLoc, "no .cprestore used in PIC mode"); } @@ -2333,15 +1940,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } MipsAsmParser::MacroExpanderResultTy -MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { +MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { switch (Inst.getOpcode()) { default: return MER_NotAMacro; case Mips::LoadImm32: - return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::LoadImm64: - return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::LoadAddrImm32: case Mips::LoadAddrImm64: assert(Inst.getOperand(0).isReg() && "expected register operand kind"); @@ -2351,7 +1960,7 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1), Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, - Out, STI) + Instructions) ? MER_Fail : MER_Success; case Mips::LoadAddrReg32: @@ -2364,25 +1973,24 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return expandLoadAddress(Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2), Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, - Out, STI) + Instructions) ? MER_Fail : MER_Success; case Mips::B_MM_Pseudo: case Mips::B_MMR6_Pseudo: - return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail - : MER_Success; + return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::SWM_MM: case Mips::LWM_MM: - return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail - : MER_Success; + return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::JalOneReg: case Mips::JalTwoReg: - return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::BneImm: case Mips::BeqImm: - case Mips::BEQLImmMacro: - case Mips::BNELImmMacro: - return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success; case Mips::BLT: case Mips::BLE: case Mips::BGE: @@ -2415,163 +2023,75 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::BLEULImmMacro: case Mips::BGEULImmMacro: case Mips::BGTULImmMacro: - return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::SDivMacro: - case Mips::SDivIMacro: - case Mips::SRemMacro: - case Mips::SRemIMacro: - return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail + : MER_Success; case Mips::DSDivMacro: - case Mips::DSDivIMacro: - case Mips::DSRemMacro: - case Mips::DSRemIMacro: - return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail + : MER_Success; case Mips::UDivMacro: - case Mips::UDivIMacro: - case Mips::URemMacro: - case Mips::URemIMacro: - return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail + : MER_Success; case Mips::DUDivMacro: - case Mips::DUDivIMacro: - case Mips::DURemMacro: - case Mips::DURemIMacro: - return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail - : MER_Success; - case Mips::PseudoTRUNC_W_S: - return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail - : MER_Success; - case Mips::PseudoTRUNC_W_D32: - return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail - : MER_Success; - case Mips::PseudoTRUNC_W_D: - return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail - : MER_Success; - - case Mips::LoadImmSingleGPR: - return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI) - ? MER_Fail - : MER_Success; - case Mips::LoadImmSingleFGR: - return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI) - ? MER_Fail - : MER_Success; - case Mips::LoadImmDoubleGPR: - return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI) - ? MER_Fail - : MER_Success; - case Mips::LoadImmDoubleFGR: - return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI) - ? MER_Fail - : MER_Success; - case Mips::LoadImmDoubleFGR_32: - return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI) - ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail + : MER_Success; case Mips::Ulh: - return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success; case Mips::Ulhu: - return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::Ush: - return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success; case Mips::Ulw: - case Mips::Usw: - return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success; case Mips::NORImm: - case Mips::NORImm64: - return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::SLTImm64: - if (isInt<16>(Inst.getOperand(2).getImm())) { - Inst.setOpcode(Mips::SLTi64); - return MER_NotAMacro; - } - return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::SLTUImm64: - if (isInt<16>(Inst.getOperand(2).getImm())) { - Inst.setOpcode(Mips::SLTiu64); - return MER_NotAMacro; - } - return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::ADDi: case Mips::ADDi_MM: - case Mips::ADDiu: case Mips::ADDiu_MM: - case Mips::SLTi: case Mips::SLTi_MM: - case Mips::SLTiu: case Mips::SLTiu_MM: + return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; + case Mips::ADDi: + case Mips::ADDiu: + case Mips::SLTi: + case Mips::SLTiu: if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) { int64_t ImmValue = Inst.getOperand(2).getImm(); if (isInt<16>(ImmValue)) return MER_NotAMacro; - return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail - : MER_Success; + return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; } return MER_NotAMacro; - case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64: - case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64: - case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64: + case Mips::ANDi: + case Mips::ORi: + case Mips::XORi: if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) { int64_t ImmValue = Inst.getOperand(2).getImm(); if (isUInt<16>(ImmValue)) return MER_NotAMacro; - return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail - : MER_Success; + return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; } return MER_NotAMacro; case Mips::ROL: case Mips::ROR: - return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::ROLImm: case Mips::RORImm: - return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::DROL: case Mips::DROR: - return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; case Mips::DROLImm: case Mips::DRORImm: - return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::ABSMacro: - return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::MULImmMacro: - case Mips::DMULImmMacro: - return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::MULOMacro: - case Mips::DMULOMacro: - return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::MULOUMacro: - case Mips::DMULOUMacro: - return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::DMULMacro: - return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::LDMacro: - case Mips::SDMacro: - return expandLoadStoreDMacro(Inst, IDLoc, Out, STI, - Inst.getOpcode() == Mips::LDMacro) - ? MER_Fail - : MER_Success; - case Mips::SEQMacro: - return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::SEQIMacro: - return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::MFTC0: case Mips::MTTC0: - case Mips::MFTGPR: case Mips::MTTGPR: - case Mips::MFTLO: case Mips::MTTLO: - case Mips::MFTHI: case Mips::MTTHI: - case Mips::MFTACX: case Mips::MTTACX: - case Mips::MFTDSP: case Mips::MTTDSP: - case Mips::MFTC1: case Mips::MTTC1: - case Mips::MFTHC1: case Mips::MTTHC1: - case Mips::CFTC1: case Mips::CTTC1: - return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail + : MER_Success; } } bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - + SmallVectorImpl<MCInst> &Instructions) { // Create a JALR instruction which is going to replace the pseudo-JAL. MCInst JalrInst; JalrInst.setLoc(IDLoc); @@ -2601,14 +2121,14 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, const MCOperand SecondRegOp = Inst.getOperand(1); JalrInst.addOperand(SecondRegOp); } - Out.EmitInstruction(JalrInst, *STI); + Instructions.push_back(JalrInst); // If .set reorder is active and branch instruction has a delay slot, // emit a NOP after it. const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode()); - if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) - TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc, - STI); + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { + createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions); + } return false; } @@ -2630,12 +2150,11 @@ template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) { /// @param IsAddress True if the immediate represents an address. False if it /// is an integer. /// @param IDLoc Location of the immediate in the source file. +/// @param Instructions The instructions emitted by this expansion. bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, bool Is32BitImm, - bool IsAddress, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - + bool IsAddress, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { if (!Is32BitImm && !isGP64bit()) { Error(IDLoc, "instruction requires a 64-bit architecture"); return true; @@ -2661,8 +2180,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, UseSrcReg = true; unsigned TmpReg = DstReg; - if (UseSrcReg && - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { + if (UseSrcReg && (DstReg == SrcReg)) { // At this point we need AT to perform the expansions and we exit if it is // not available. unsigned ATReg = getATReg(IDLoc); @@ -2679,11 +2197,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // traditional assembler behaviour. N32 would normally use addiu for both // integers and addresses. if (IsAddress && !Is32BitImm) { - TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI); + emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions); return false; } - TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI); + emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions); return false; } @@ -2695,9 +2213,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, return true; } - TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI); + emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions); if (UseSrcReg) - TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions); return false; } @@ -2706,33 +2224,34 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff; uint16_t Bits15To0 = ImmValue & 0xffff; + if (!Is32BitImm && !isInt<32>(ImmValue)) { // Traditional behaviour seems to special case this particular value. It's // not clear why other masks are handled differently. if (ImmValue == 0xffffffff) { - TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI); - TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI); + emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions); + emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions); if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); return false; } // Expand to an ORi instead of a LUi to avoid sign-extending into the // upper 32 bits. - TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI); - TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI); + emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions); + emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions); if (Bits15To0) - TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); + emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions); if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); return false; } - TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI); + emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions); if (Bits15To0) - TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); + emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions); if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); return false; } @@ -2748,11 +2267,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned LastSet = findLastSet((uint64_t)ImmValue); unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet)); uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff; - TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI); - TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI); + emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions); + emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions); if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); return false; } @@ -2765,7 +2284,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register. if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false, - IDLoc, Out, STI)) + IDLoc, Instructions)) return false; // Shift and accumulate into the register. If a 16-bit chunk is zero, then @@ -2775,8 +2294,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff; if (ImmChunk != 0) { - TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI); - TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI); + emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, + Instructions); + emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions); ShiftCarriedForwards = 0; } @@ -2786,23 +2306,24 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // Finish any remaining shifts left by trailing zeros. if (ShiftCarriedForwards) - TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI); + emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, + Instructions); if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); return false; } bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI) { + SmallVectorImpl<MCInst> &Instructions) { const MCOperand &ImmOp = Inst.getOperand(1); assert(ImmOp.isImm() && "expected immediate operand kind"); const MCOperand &DstRegOp = Inst.getOperand(0); assert(DstRegOp.isReg() && "expected register operand kind"); if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister, - Is32BitImm, false, IDLoc, Out, STI)) + Is32BitImm, false, IDLoc, Instructions)) return true; return false; @@ -2811,8 +2332,7 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, const MCOperand &Offset, bool Is32BitAddress, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { + SmallVectorImpl<MCInst> &Instructions) { // la can't produce a usable address when addresses are 64-bit. if (Is32BitAddress && ABI.ArePtrs64bit()) { // FIXME: Demote this to a warning and continue as if we had 'dla' instead. @@ -2821,218 +2341,49 @@ bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, Error(IDLoc, "la used to load 64-bit address"); // Continue as if we had 'dla' instead. Is32BitAddress = false; - return true; } // dla requires 64-bit addresses. - if (!Is32BitAddress && !hasMips3()) { + if (!Is32BitAddress && !ABI.ArePtrs64bit()) { Error(IDLoc, "instruction requires a 64-bit architecture"); return true; } if (!Offset.isImm()) return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg, - Is32BitAddress, IDLoc, Out, STI); - - if (!ABI.ArePtrs64bit()) { - // Continue as if we had 'la' whether we had 'la' or 'dla'. - Is32BitAddress = true; - } + Is32BitAddress, IDLoc, Instructions); return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true, - IDLoc, Out, STI); + IDLoc, Instructions); } -bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, - unsigned DstReg, unsigned SrcReg, - bool Is32BitSym, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - // FIXME: These expansions do not respect -mxgot. - MipsTargetStreamer &TOut = getTargetStreamer(); - bool UseSrcReg = SrcReg != Mips::NoRegister; +bool MipsAsmParser::loadAndAddSymbolAddress( + const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym, + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { warnIfNoMacro(IDLoc); - if (inPicMode() && ABI.IsO32()) { - MCValue Res; - if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { - Error(IDLoc, "expected relocatable expression"); - return true; - } - if (Res.getSymB() != nullptr) { - Error(IDLoc, "expected relocatable expression with only one symbol"); - return true; - } - - // The case where the result register is $25 is somewhat special. If the - // symbol in the final relocation is external and not modified with a - // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16. - if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg && - Res.getConstant() == 0 && - !(Res.getSymA()->getSymbol().isInSection() || - Res.getSymA()->getSymbol().isTemporary() || - (Res.getSymA()->getSymbol().isELF() && - cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() == - ELF::STB_LOCAL))) { - const MCExpr *CallExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); - TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(CallExpr), IDLoc, STI); - return false; - } - - // The remaining cases are: - // External GOT: lw $tmp, %got(symbol+offset)($gp) - // >addiu $tmp, $tmp, %lo(offset) - // >addiu $rd, $tmp, $rs - // Local GOT: lw $tmp, %got(symbol+offset)($gp) - // addiu $tmp, $tmp, %lo(symbol+offset)($gp) - // >addiu $rd, $tmp, $rs - // The addiu's marked with a '>' may be omitted if they are redundant. If - // this happens then the last instruction must use $rd as the result - // register. - const MipsMCExpr *GotExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext()); - const MCExpr *LoExpr = nullptr; - if (Res.getSymA()->getSymbol().isInSection() || - Res.getSymA()->getSymbol().isTemporary()) - LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); - else if (Res.getConstant() != 0) { - // External symbols fully resolve the symbol with just the %got(symbol) - // but we must still account for any offset to the symbol for expressions - // like symbol+8. - LoExpr = MCConstantExpr::create(Res.getConstant(), getContext()); - } - - unsigned TmpReg = DstReg; - if (UseSrcReg && - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, - SrcReg)) { - // If $rs is the same as $rd, we need to use AT. - // If it is not available we exit. - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - TmpReg = ATReg; - } - - TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(GotExpr), IDLoc, STI); - - if (LoExpr) - TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); - - if (UseSrcReg) - TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); - - return false; - } - - if (inPicMode() && ABI.ArePtrs64bit()) { - MCValue Res; - if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { - Error(IDLoc, "expected relocatable expression"); - return true; - } - if (Res.getSymB() != nullptr) { - Error(IDLoc, "expected relocatable expression with only one symbol"); - return true; - } - - // The case where the result register is $25 is somewhat special. If the - // symbol in the final relocation is external and not modified with a - // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP. - if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg && - Res.getConstant() == 0 && - !(Res.getSymA()->getSymbol().isInSection() || - Res.getSymA()->getSymbol().isTemporary() || - (Res.getSymA()->getSymbol().isELF() && - cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() == - ELF::STB_LOCAL))) { - const MCExpr *CallExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); - TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(CallExpr), IDLoc, STI); - return false; - } - - // The remaining cases are: - // Small offset: ld $tmp, %got_disp(symbol)($gp) - // >daddiu $tmp, $tmp, offset - // >daddu $rd, $tmp, $rs - // The daddiu's marked with a '>' may be omitted if they are redundant. If - // this happens then the last instruction must use $rd as the result - // register. - const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, - Res.getSymA(), - getContext()); - const MCExpr *LoExpr = nullptr; - if (Res.getConstant() != 0) { - // Symbols fully resolve with just the %got_disp(symbol) but we - // must still account for any offset to the symbol for - // expressions like symbol+8. - LoExpr = MCConstantExpr::create(Res.getConstant(), getContext()); - - // FIXME: Offsets greater than 16 bits are not yet implemented. - // FIXME: The correct range is a 32-bit sign-extended number. - if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) { - Error(IDLoc, "macro instruction uses large offset, which is not " - "currently supported"); - return true; - } - } - - unsigned TmpReg = DstReg; - if (UseSrcReg && - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, - SrcReg)) { - // If $rs is the same as $rd, we need to use AT. - // If it is not available we exit. - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - TmpReg = ATReg; - } - - TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(GotExpr), IDLoc, STI); - - if (LoExpr) - TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); - - if (UseSrcReg) - TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); + const MCExpr *Symbol = cast<MCExpr>(SymExpr); + const MipsMCExpr *HiExpr = MipsMCExpr::create( + MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext()); + const MipsMCExpr *LoExpr = MipsMCExpr::create( + MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext()); - return false; - } - - const MipsMCExpr *HiExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext()); - const MipsMCExpr *LoExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); + bool UseSrcReg = SrcReg != Mips::NoRegister; // This is the 64-bit symbol address expansion. if (ABI.ArePtrs64bit() && isGP64bit()) { - // We need AT for the 64-bit expansion in the cases where the optional - // source register is the destination register and for the superscalar - // scheduled form. - // - // If it is not available we exit if the destination is the same as the - // source register. - - const MipsMCExpr *HighestExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext()); - const MipsMCExpr *HigherExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext()); - - bool RdRegIsRsReg = - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg); + // We always need AT for the 64-bit expansion. + // If it is not available we exit. + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; - if (canUseATReg() && UseSrcReg && RdRegIsRsReg) { - unsigned ATReg = getATReg(IDLoc); + const MipsMCExpr *HighestExpr = MipsMCExpr::create( + MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext()); + const MipsMCExpr *HigherExpr = MipsMCExpr::create( + MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext()); + if (UseSrcReg && (DstReg == SrcReg)) { // If $rs is the same as $rd: // (d)la $rd, sym($rd) => lui $at, %highest(sym) // daddiu $at, $at, %higher(sym) @@ -3041,78 +2392,43 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, // dsll $at, $at, 16 // daddiu $at, $at, %lo(sym) // daddu $rd, $at, $rd - TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, - STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, - MCOperand::createExpr(HigherExpr), IDLoc, STI); - TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), - IDLoc, STI); - TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); - TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI); + emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, + Instructions); + emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr), + IDLoc, Instructions); + emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions); + emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc, + Instructions); + emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions); + emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc, + Instructions); + emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions); return false; - } else if (canUseATReg() && !RdRegIsRsReg) { - unsigned ATReg = getATReg(IDLoc); - - // If the $rs is different from $rd or if $rs isn't specified and we - // have $at available: - // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) - // lui $at, %hi(sym) - // daddiu $rd, $rd, %higher(sym) - // daddiu $at, $at, %lo(sym) - // dsll32 $rd, $rd, 0 - // daddu $rd, $rd, $at - // (daddu $rd, $rd, $rs) - // - // Which is preferred for superscalar issue. - TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, - STI); - TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, - MCOperand::createExpr(HigherExpr), IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); - TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI); - TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI); - if (UseSrcReg) - TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); + } - return false; - } else if (!canUseATReg() && !RdRegIsRsReg) { - // Otherwise, synthesize the address in the destination register - // serially: - // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) - // daddiu $rd, $rd, %higher(sym) - // dsll $rd, $rd, 16 - // daddiu $rd, $rd, %hi(sym) - // dsll $rd, $rd, 16 - // daddiu $rd, $rd, %lo(sym) - TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, - STI); - TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, - MCOperand::createExpr(HigherExpr), IDLoc, STI); - TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, - MCOperand::createExpr(HiExpr), IDLoc, STI); - TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, - MCOperand::createExpr(LoExpr), IDLoc, STI); - if (UseSrcReg) - TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); + // Otherwise, if the $rs is different from $rd or if $rs isn't specified: + // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) + // lui $at, %hi(sym) + // daddiu $rd, $rd, %higher(sym) + // daddiu $at, $at, %lo(sym) + // dsll32 $rd, $rd, 0 + // daddu $rd, $rd, $at + // (daddu $rd, $rd, $rs) + emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, + Instructions); + emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, + Instructions); + emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr), + IDLoc, Instructions); + emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc, + Instructions); + emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions); + emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions); + if (UseSrcReg) + emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions); - return false; - } else { - // We have a case where SrcReg == DstReg and we don't have $at - // available. We can't expand this case, so error out appropriately. - assert(SrcReg == DstReg && !canUseATReg() && - "Could have expanded dla but didn't?"); - reportParseError(IDLoc, - "pseudo-instruction requires $at, which is not available"); - return true; - } + return false; } // And now, the 32-bit symbol address expansion: @@ -3125,8 +2441,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, // ori $rd, $rd, %lo(sym) // (addu $rd, $rd, $rs) unsigned TmpReg = DstReg; - if (UseSrcReg && - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { + if (UseSrcReg && (DstReg == SrcReg)) { // If $rs is the same as $rd, we need to use AT. // If it is not available we exit. unsigned ATReg = getATReg(IDLoc); @@ -3135,320 +2450,20 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TmpReg = ATReg; } - TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI); - TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); + emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions); + emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc, + Instructions); if (UseSrcReg) - TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); + emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions); else - assert( - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg)); - - return false; -} - -// Each double-precision register DO-D15 overlaps with two of the single -// precision registers F0-F31. As an example, all of the following hold true: -// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context. -static unsigned nextReg(unsigned Reg) { - if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg)) - return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1; - switch (Reg) { - default: llvm_unreachable("Unknown register in assembly macro expansion!"); - case Mips::ZERO: return Mips::AT; - case Mips::AT: return Mips::V0; - case Mips::V0: return Mips::V1; - case Mips::V1: return Mips::A0; - case Mips::A0: return Mips::A1; - case Mips::A1: return Mips::A2; - case Mips::A2: return Mips::A3; - case Mips::A3: return Mips::T0; - case Mips::T0: return Mips::T1; - case Mips::T1: return Mips::T2; - case Mips::T2: return Mips::T3; - case Mips::T3: return Mips::T4; - case Mips::T4: return Mips::T5; - case Mips::T5: return Mips::T6; - case Mips::T6: return Mips::T7; - case Mips::T7: return Mips::S0; - case Mips::S0: return Mips::S1; - case Mips::S1: return Mips::S2; - case Mips::S2: return Mips::S3; - case Mips::S3: return Mips::S4; - case Mips::S4: return Mips::S5; - case Mips::S5: return Mips::S6; - case Mips::S6: return Mips::S7; - case Mips::S7: return Mips::T8; - case Mips::T8: return Mips::T9; - case Mips::T9: return Mips::K0; - case Mips::K0: return Mips::K1; - case Mips::K1: return Mips::GP; - case Mips::GP: return Mips::SP; - case Mips::SP: return Mips::FP; - case Mips::FP: return Mips::RA; - case Mips::RA: return Mips::ZERO; - case Mips::D0: return Mips::F1; - case Mips::D1: return Mips::F3; - case Mips::D2: return Mips::F5; - case Mips::D3: return Mips::F7; - case Mips::D4: return Mips::F9; - case Mips::D5: return Mips::F11; - case Mips::D6: return Mips::F13; - case Mips::D7: return Mips::F15; - case Mips::D8: return Mips::F17; - case Mips::D9: return Mips::F19; - case Mips::D10: return Mips::F21; - case Mips::D11: return Mips::F23; - case Mips::D12: return Mips::F25; - case Mips::D13: return Mips::F27; - case Mips::D14: return Mips::F29; - case Mips::D15: return Mips::F31; - } -} - -// FIXME: This method is too general. In principle we should compute the number -// of instructions required to synthesize the immediate inline compared to -// synthesizing the address inline and relying on non .text sections. -// For static O32 and N32 this may yield a small benefit, for static N64 this is -// likely to yield a much larger benefit as we have to synthesize a 64bit -// address to load a 64 bit value. -bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, - MCSymbol *Sym) { - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - if(IsPicEnabled) { - const MCExpr *GotSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *GotExpr = - MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext()); - - if(isABI_O32() || isABI_N32()) { - TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), - IDLoc, STI); - } else { //isABI_N64() - TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), - IDLoc, STI); - } - } else { //!IsPicEnabled - const MCExpr *HiSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *HiExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext()); - - // FIXME: This is technically correct but gives a different result to gas, - // but gas is incomplete there (it has a fixme noting it doesn't work with - // 64-bit addresses). - // FIXME: With -msym32 option, the address expansion for N64 should probably - // use the O32 / N32 case. It's safe to use the 64 address expansion as the - // symbol's value is considered sign extended. - if(isABI_O32() || isABI_N32()) { - TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI); - } else { //isABI_N64() - const MCExpr *HighestSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *HighestExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext()); - const MCExpr *HigherSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *HigherExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext()); - - TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, - STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, - MCOperand::createExpr(HigherExpr), IDLoc, STI); - TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), - IDLoc, STI); - TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); - } - } - return false; -} - -bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, - bool Is64FPU, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - assert(Inst.getNumOperands() == 2 && "Invalid operand count"); - assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && - "Invalid instruction operand."); - - unsigned FirstReg = Inst.getOperand(0).getReg(); - uint64_t ImmOp64 = Inst.getOperand(1).getImm(); - - uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32; - // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the - // exponent field), convert it to double (e.g. 1 to 1.0) - if ((HiImmOp64 & 0x7ff00000) == 0) { - APFloat RealVal(APFloat::IEEEdouble(), ImmOp64); - ImmOp64 = RealVal.bitcastToAPInt().getZExtValue(); - } - - uint32_t LoImmOp64 = ImmOp64 & 0xffffffff; - HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32; - - if (IsSingle) { - // Conversion of a double in an uint64_t to a float in a uint32_t, - // retaining the bit pattern of a float. - uint32_t ImmOp32; - double doubleImm = BitsToDouble(ImmOp64); - float tmp_float = static_cast<float>(doubleImm); - ImmOp32 = FloatToBits(tmp_float); - - if (IsGPR) { - if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc, - Out, STI)) - return true; - return false; - } else { - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - if (LoImmOp64 == 0) { - if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc, - Out, STI)) - return true; - TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI); - return false; - } - - MCSection *CS = getStreamer().getCurrentSectionOnly(); - // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections - // where appropriate. - MCSection *ReadOnlySection = getContext().getELFSection( - ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - - MCSymbol *Sym = getContext().createTempSymbol(); - const MCExpr *LoSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *LoExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext()); - - getStreamer().SwitchSection(ReadOnlySection); - getStreamer().EmitLabel(Sym, IDLoc); - getStreamer().EmitIntValue(ImmOp32, 4); - getStreamer().SwitchSection(CS); - - if(emitPartialAddress(TOut, IDLoc, Sym)) - return true; - TOut.emitRRX(Mips::LWC1, FirstReg, ATReg, - MCOperand::createExpr(LoExpr), IDLoc, STI); - } - return false; - } - - // if(!IsSingle) - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - if (IsGPR) { - if (LoImmOp64 == 0) { - if(isABI_N32() || isABI_N64()) { - if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true, - IDLoc, Out, STI)) - return true; - return false; - } else { - if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true, - IDLoc, Out, STI)) - return true; - - if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true, - IDLoc, Out, STI)) - return true; - return false; - } - } - - MCSection *CS = getStreamer().getCurrentSectionOnly(); - MCSection *ReadOnlySection = getContext().getELFSection( - ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - - MCSymbol *Sym = getContext().createTempSymbol(); - const MCExpr *LoSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *LoExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext()); - - getStreamer().SwitchSection(ReadOnlySection); - getStreamer().EmitLabel(Sym, IDLoc); - getStreamer().EmitIntValue(HiImmOp64, 4); - getStreamer().EmitIntValue(LoImmOp64, 4); - getStreamer().SwitchSection(CS); - - if(emitPartialAddress(TOut, IDLoc, Sym)) - return true; - if(isABI_N64()) - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, - MCOperand::createExpr(LoExpr), IDLoc, STI); - else - TOut.emitRRX(Mips::ADDiu, ATReg, ATReg, - MCOperand::createExpr(LoExpr), IDLoc, STI); - - if(isABI_N32() || isABI_N64()) - TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI); - else { - TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI); - TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI); - } - return false; - } else { // if(!IsGPR && !IsSingle) - if ((LoImmOp64 == 0) && - !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) { - // FIXME: In the case where the constant is zero, we can load the - // register directly from the zero register. - if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc, - Out, STI)) - return true; - if (isABI_N32() || isABI_N64()) - TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI); - else if (hasMips32r2()) { - TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI); - TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI); - } else { - TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI); - TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI); - } - return false; - } - - MCSection *CS = getStreamer().getCurrentSectionOnly(); - // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections - // where appropriate. - MCSection *ReadOnlySection = getContext().getELFSection( - ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - - MCSymbol *Sym = getContext().createTempSymbol(); - const MCExpr *LoSym = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - const MipsMCExpr *LoExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext()); - - getStreamer().SwitchSection(ReadOnlySection); - getStreamer().EmitLabel(Sym, IDLoc); - getStreamer().EmitIntValue(HiImmOp64, 4); - getStreamer().EmitIntValue(LoImmOp64, 4); - getStreamer().SwitchSection(CS); + assert(DstReg == TmpReg); - if(emitPartialAddress(TOut, IDLoc, Sym)) - return true; - TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg, - MCOperand::createExpr(LoExpr), IDLoc, STI); - } return false; } -bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - +bool MipsAsmParser::expandUncondBranchMMPseudo( + MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && "unexpected number of operands"); @@ -3468,9 +2483,9 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM); } else { if (!isInt<17>(Offset.getImm())) - return Error(IDLoc, "branch target out of range"); + Error(IDLoc, "branch target out of range"); if (OffsetToAlignment(Offset.getImm(), 1LL << 1)) - return Error(IDLoc, "branch to misaligned address"); + Error(IDLoc, "branch to misaligned address"); Inst.clear(); Inst.setOpcode(Mips::BEQ_MM); Inst.addOperand(MCOperand::createReg(Mips::ZERO)); @@ -3478,20 +2493,19 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, Inst.addOperand(MCOperand::createImm(Offset.getImm())); } } - Out.EmitInstruction(Inst, *STI); + Instructions.push_back(Inst); // If .set reorder is active and branch instruction has a delay slot, // emit a NOP after it. const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) - TOut.emitEmptyDelaySlot(true, IDLoc, STI); + createNop(true, IDLoc, Instructions); return false; } -bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); +bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { const MCOperand &DstRegOp = Inst.getOperand(0); assert(DstRegOp.isReg() && "expected register operand kind"); @@ -3499,10 +2513,7 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, assert(ImmOp.isImm() && "expected immediate operand kind"); const MCOperand &MemOffsetOp = Inst.getOperand(2); - assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) && - "expected immediate or expression operand"); - - bool IsLikely = false; + assert(MemOffsetOp.isImm() && "expected immediate operand kind"); unsigned OpCode = 0; switch(Inst.getOpcode()) { @@ -3512,29 +2523,16 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::BeqImm: OpCode = Mips::BEQ; break; - case Mips::BEQLImmMacro: - OpCode = Mips::BEQL; - IsLikely = true; - break; - case Mips::BNELImmMacro: - OpCode = Mips::BNEL; - IsLikely = true; - break; default: llvm_unreachable("Unknown immediate branch pseudo-instruction."); break; } int64_t ImmValue = ImmOp.getImm(); - if (ImmValue == 0) { - if (IsLikely) { - TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, - MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI); - TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); - } else - TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, - STI); - } else { + if (ImmValue == 0) + emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, + Instructions); + else { warnIfNoMacro(IDLoc); unsigned ATReg = getATReg(IDLoc); @@ -3542,96 +2540,101 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return true; if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true, - IDLoc, Out, STI)) + IDLoc, Instructions)) return true; - if (IsLikely) { - TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, - MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI); - TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); - } else - TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI); + emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions); } return false; } -void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad) { - const MCOperand &DstRegOp = Inst.getOperand(0); - assert(DstRegOp.isReg() && "expected register operand kind"); - const MCOperand &BaseRegOp = Inst.getOperand(1); - assert(BaseRegOp.isReg() && "expected register operand kind"); - const MCOperand &OffsetOp = Inst.getOperand(2); - - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned DstReg = DstRegOp.getReg(); - unsigned BaseReg = BaseRegOp.getReg(); - unsigned TmpReg = DstReg; - +void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions, + bool isLoad, bool isImmOpnd) { + unsigned ImmOffset, HiOffset, LoOffset; + const MCExpr *ExprOffset; + unsigned TmpRegNum; + // 1st operand is either the source or destination register. + assert(Inst.getOperand(0).isReg() && "expected register operand kind"); + unsigned RegOpNum = Inst.getOperand(0).getReg(); + // 2nd operand is the base register. + assert(Inst.getOperand(1).isReg() && "expected register operand kind"); + unsigned BaseRegNum = Inst.getOperand(1).getReg(); + // 3rd operand is either an immediate or expression. + if (isImmOpnd) { + assert(Inst.getOperand(2).isImm() && "expected immediate operand kind"); + ImmOffset = Inst.getOperand(2).getImm(); + LoOffset = ImmOffset & 0x0000ffff; + HiOffset = (ImmOffset & 0xffff0000) >> 16; + // If msb of LoOffset is 1(negative number) we must increment HiOffset. + if (LoOffset & 0x8000) + HiOffset++; + } else + ExprOffset = Inst.getOperand(2).getExpr(); + // These are some of the types of expansions we perform here: + // 1) lw $8, sym => lui $8, %hi(sym) + // lw $8, %lo(sym)($8) + // 2) lw $8, offset($9) => lui $8, %hi(offset) + // add $8, $8, $9 + // lw $8, %lo(offset)($9) + // 3) lw $8, offset($8) => lui $at, %hi(offset) + // add $at, $at, $8 + // lw $8, %lo(offset)($at) + // 4) sw $8, sym => lui $at, %hi(sym) + // sw $8, %lo(sym)($at) + // 5) sw $8, offset($8) => lui $at, %hi(offset) + // add $at, $at, $8 + // sw $8, %lo(offset)($at) + // 6) ldc1 $f0, sym => lui $at, %hi(sym) + // ldc1 $f0, %lo(sym)($at) + // + // For load instructions we can use the destination register as a temporary + // if base and dst are different (examples 1 and 2) and if the base register + // is general purpose otherwise we must use $at (example 6) and error if it's + // not available. For stores we must use $at (examples 4 and 5) because we + // must not clobber the source register setting up the offset. const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode()); - int16_t DstRegClass = Desc.OpInfo[0].RegClass; - unsigned DstRegClassID = - getContext().getRegisterInfo()->getRegClass(DstRegClass).getID(); - bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) || - (DstRegClassID == Mips::GPR64RegClassID); - - if (!IsLoad || !IsGPR || (BaseReg == DstReg)) { - // At this point we need AT to perform the expansions - // and we exit if it is not available. - TmpReg = getATReg(IDLoc); - if (!TmpReg) + int16_t RegClassOp0 = Desc.OpInfo[0].RegClass; + unsigned RegClassIDOp0 = + getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID(); + bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) || + (RegClassIDOp0 == Mips::GPR64RegClassID); + if (isLoad && IsGPR && (BaseRegNum != RegOpNum)) + TmpRegNum = RegOpNum; + else { + // At this point we need AT to perform the expansions and we exit if it is + // not available. + TmpRegNum = getATReg(IDLoc); + if (!TmpRegNum) return; } - if (OffsetOp.isImm()) { - int64_t LoOffset = OffsetOp.getImm() & 0xffff; - int64_t HiOffset = OffsetOp.getImm() & ~0xffff; - - // If msb of LoOffset is 1(negative number) we must increment - // HiOffset to account for the sign-extension of the low part. - if (LoOffset & 0x8000) - HiOffset += 0x10000; - - bool IsLargeOffset = HiOffset != 0; - - if (IsLargeOffset) { - bool Is32BitImm = (HiOffset >> 32) == 0; - if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true, - IDLoc, Out, STI)) - return; - } - - if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64) - TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, - BaseReg, IDLoc, STI); - TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI); - } else { - assert(OffsetOp.isExpr() && "expected expression operand kind"); - const MCExpr *ExprOffset = OffsetOp.getExpr(); - MCOperand LoOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); - MCOperand HiOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); - - if (IsLoad) - TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, TmpReg, IDLoc, STI); - else - TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, TmpReg, IDLoc, STI); - } -} - -bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { + emitRX(Mips::LUi, TmpRegNum, + isImmOpnd ? MCOperand::createImm(HiOffset) + : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")), + IDLoc, Instructions); + // Add temp register to base. + if (BaseRegNum != Mips::ZERO) + emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions); + // And finally, create original instruction with low part + // of offset and new base. + emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, + isImmOpnd + ? MCOperand::createImm(LoOffset) + : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")), + IDLoc, Instructions); +} + +bool +MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { unsigned OpNum = Inst.getNumOperands(); unsigned Opcode = Inst.getOpcode(); unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; - assert(Inst.getOperand(OpNum - 1).isImm() && - Inst.getOperand(OpNum - 2).isReg() && - Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); + assert (Inst.getOperand(OpNum - 1).isImm() && + Inst.getOperand(OpNum - 2).isReg() && + Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && Inst.getOperand(OpNum - 1).getImm() >= 0 && @@ -3647,14 +2650,12 @@ bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, } Inst.setOpcode(NewOpcode); - Out.EmitInstruction(Inst, *STI); + Instructions.push_back(Inst); return false; } bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); + SmallVectorImpl<MCInst> &Instructions) { bool EmittedNoMacroWarning = false; unsigned PseudoOpcode = Inst.getOpcode(); unsigned SrcReg = Inst.getOperand(0).getReg(); @@ -3729,7 +2730,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, } if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(), - false, IDLoc, Out, STI)) + false, IDLoc, Instructions)) return true; } @@ -3740,8 +2741,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BLTUL: AcceptsEquality = false; ReverseOrderSLT = false; - IsUnsigned = - ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); + IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL)); ZeroSrcOpcode = Mips::BGTZ; ZeroTrgOpcode = Mips::BLTZ; @@ -3752,8 +2752,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BLEUL: AcceptsEquality = true; ReverseOrderSLT = true; - IsUnsigned = - ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); + IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL)); ZeroSrcOpcode = Mips::BGEZ; ZeroTrgOpcode = Mips::BLEZ; @@ -3764,8 +2763,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BGEUL: AcceptsEquality = true; ReverseOrderSLT = false; - IsUnsigned = - ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); + IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL)); ZeroSrcOpcode = Mips::BLEZ; ZeroTrgOpcode = Mips::BGEZ; @@ -3776,8 +2774,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BGTUL: AcceptsEquality = false; ReverseOrderSLT = true; - IsUnsigned = - ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); + IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL)); ZeroSrcOpcode = Mips::BLTZ; ZeroTrgOpcode = Mips::BGTZ; @@ -3793,37 +2790,37 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // with GAS' behaviour. However, they may not generate the most efficient // code in some circumstances. if (PseudoOpcode == Mips::BLT) { - TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); + emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, + Instructions); return false; } if (PseudoOpcode == Mips::BLE) { - TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); + emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, + Instructions); Warning(IDLoc, "branch is always taken"); return false; } if (PseudoOpcode == Mips::BGE) { - TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); + emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, + Instructions); Warning(IDLoc, "branch is always taken"); return false; } if (PseudoOpcode == Mips::BGT) { - TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); + emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, + Instructions); return false; } if (PseudoOpcode == Mips::BGTU) { - TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, STI); + emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); return false; } if (AcceptsEquality) { // If both registers are $0 and the pseudo-branch accepts equality, it // will always be taken, so we emit an unconditional branch. - TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, STI); + emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); Warning(IDLoc, "branch is always taken"); return false; } @@ -3847,8 +2844,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // the pseudo-branch will always be taken, so we emit an unconditional // branch. // This only applies to unsigned pseudo-branches. - TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, STI); + emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); Warning(IDLoc, "branch is always taken"); return false; } @@ -3865,17 +2862,17 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // // Because only BLEU and BGEU branch on equality, we can use the // AcceptsEquality variable to decide when to emit the BEQZ. - TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE, - IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, STI); + emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE, + IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); return false; } // If we have a signed pseudo-branch and one of the registers is $0, // we can use an appropriate compare-to-zero branch. We select which one // to use in the switch statement above. - TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode, - IsSrcRegZero ? TrgReg : SrcReg, - MCOperand::createExpr(OffsetExpr), IDLoc, STI); + emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode, + IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr), + IDLoc, Instructions); return false; } @@ -3895,7 +2892,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // This is accomplished by using a BNEZ with the result of the SLT. // // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT - // and BLE with BGT), so we change the BNEZ into a BEQZ. + // and BLE with BGT), so we change the BNEZ into a a BEQZ. // Because only BGE and BLE branch on equality, we can use the // AcceptsEquality variable to decide when to emit the BEQZ. // Note that the order of the SLT arguments doesn't change between @@ -3903,155 +2900,102 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // // The same applies to the unsigned variants, except that SLTu is used // instead of SLT. - TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum, - ReverseOrderSLT ? TrgReg : SrcReg, - ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI); - - TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL) - : (AcceptsEquality ? Mips::BEQ : Mips::BNE), - ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, - STI); + emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum, + ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg, + IDLoc, Instructions); + + emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL) + : (AcceptsEquality ? Mips::BEQ : Mips::BNE), + ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, + Instructions); return false; } -// Expand a integer division macro. -// -// Notably we don't have to emit a warning when encountering $rt as the $zero -// register, or 0 as an immediate. processInstruction() has already done that. -// -// The destination register can only be $zero when expanding (S)DivIMacro or -// D(S)DivMacro. - -bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, const bool IsMips64, - const bool Signed) { - MipsTargetStreamer &TOut = getTargetStreamer(); +bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions, + const bool IsMips64, const bool Signed) { + if (hasMips32r6()) { + Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); + return false; + } warnIfNoMacro(IDLoc); - const MCOperand &RdRegOp = Inst.getOperand(0); - assert(RdRegOp.isReg() && "expected register operand kind"); - unsigned RdReg = RdRegOp.getReg(); - - const MCOperand &RsRegOp = Inst.getOperand(1); + const MCOperand &RsRegOp = Inst.getOperand(0); assert(RsRegOp.isReg() && "expected register operand kind"); unsigned RsReg = RsRegOp.getReg(); - unsigned RtReg; - int64_t ImmValue; - - const MCOperand &RtOp = Inst.getOperand(2); - assert((RtOp.isReg() || RtOp.isImm()) && - "expected register or immediate operand kind"); - if (RtOp.isReg()) - RtReg = RtOp.getReg(); - else - ImmValue = RtOp.getImm(); - + const MCOperand &RtRegOp = Inst.getOperand(1); + assert(RtRegOp.isReg() && "expected register operand kind"); + unsigned RtReg = RtRegOp.getReg(); unsigned DivOp; unsigned ZeroReg; - unsigned SubOp; if (IsMips64) { DivOp = Signed ? Mips::DSDIV : Mips::DUDIV; ZeroReg = Mips::ZERO_64; - SubOp = Mips::DSUB; } else { DivOp = Signed ? Mips::SDIV : Mips::UDIV; ZeroReg = Mips::ZERO; - SubOp = Mips::SUB; } bool UseTraps = useTraps(); - unsigned Opcode = Inst.getOpcode(); - bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro || - Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro || - Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro || - Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro; - - bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro || - Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro || - Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro || - Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro; - - if (RtOp.isImm()) { - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - if (ImmValue == 0) { - if (UseTraps) - TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI); - else - TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); - return false; - } + if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) { + if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) + Warning(IDLoc, "dividing zero by zero"); + if (IsMips64) { + if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) { + if (UseTraps) { + emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); + return false; + } - if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) { - TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI); - return false; - } else if (isDiv && ImmValue == 1) { - TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI); - return false; - } else if (isDiv && Signed && ImmValue == -1) { - TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI); - return false; + emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); + return false; + } } else { - if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue), - false, Inst.getLoc(), Out, STI)) - return true; - TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI); - TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); + emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions); return false; } - return true; } - // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or - // break, insert the trap/break and exit. This gives a different result to - // GAS. GAS has an inconsistency/missed optimization in that not all cases - // are handled equivalently. As the observed behaviour is the same, we're ok. if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) { - if (UseTraps) { - TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI); + Warning(IDLoc, "division by zero"); + if (Signed) { + if (UseTraps) { + emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); + return false; + } + + emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); return false; } - TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); - return false; } - // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does - // not expand to macro sequence. - if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) { - TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); - return false; - } - - // Temporary label for first branch traget - MCContext &Context = TOut.getStreamer().getContext(); - MCSymbol *BrTarget; - MCOperand LabelOp; + // FIXME: The values for these two BranchTarget variables may be different in + // micromips. These magic numbers need to be removed. + unsigned BranchTargetNoTraps; + unsigned BranchTarget; if (UseTraps) { - TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); + BranchTarget = IsMips64 ? 12 : 8; + emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); } else { + BranchTarget = IsMips64 ? 20 : 16; + BranchTargetNoTraps = 8; // Branch to the li instruction. - BrTarget = Context.createTempSymbol(); - LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); - TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI); + emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, + Instructions); } - TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); + emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions); if (!UseTraps) - TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); + emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); if (!Signed) { - if (!UseTraps) - TOut.getStreamer().EmitLabel(BrTarget); - - TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); + emitR(Mips::MFLO, RsReg, IDLoc, Instructions); return false; } @@ -4059,246 +3003,179 @@ bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (!ATReg) return true; - if (!UseTraps) - TOut.getStreamer().EmitLabel(BrTarget); - - TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI); - - // Temporary label for the second branch target. - MCSymbol *BrTargetEnd = Context.createTempSymbol(); - MCOperand LabelOpEnd = - MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context)); - - // Branch to the mflo instruction. - TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI); - + emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions); if (IsMips64) { - TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI); - TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI); + // Branch to the mflo instruction. + emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions); + emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions); + emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions); } else { - TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI); + // Branch to the mflo instruction. + emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions); + emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions); } if (UseTraps) - TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI); + emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions); else { // Branch to the mflo instruction. - TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI); - TOut.emitNop(IDLoc, STI); - TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI); + emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions); + emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions); + emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions); } - - TOut.getStreamer().EmitLabel(BrTargetEnd); - TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); - return false; -} - -bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, - SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - - assert(Inst.getNumOperands() == 3 && "Invalid operand count"); - assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && - Inst.getOperand(2).isReg() && "Invalid instruction operand."); - - unsigned FirstReg = Inst.getOperand(0).getReg(); - unsigned SecondReg = Inst.getOperand(1).getReg(); - unsigned ThirdReg = Inst.getOperand(2).getReg(); - - if (hasMips1() && !hasMips2()) { - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI); - TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI); - TOut.emitNop(IDLoc, STI); - TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI); - TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI); - TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI); - TOut.emitNop(IDLoc, STI); - TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32) - : Mips::CVT_W_S, - FirstReg, SecondReg, IDLoc, STI); - TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI); - TOut.emitNop(IDLoc, STI); - return false; - } - - TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32) - : Mips::TRUNC_W_S, - FirstReg, SecondReg, IDLoc, STI); - + emitR(Mips::MFLO, RsReg, IDLoc, Instructions); return false; } bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI) { + SmallVectorImpl<MCInst> &Instructions) { if (hasMips32r6() || hasMips64r6()) { - return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); + Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); + return false; } + warnIfNoMacro(IDLoc); + const MCOperand &DstRegOp = Inst.getOperand(0); assert(DstRegOp.isReg() && "expected register operand kind"); + const MCOperand &SrcRegOp = Inst.getOperand(1); assert(SrcRegOp.isReg() && "expected register operand kind"); + const MCOperand &OffsetImmOp = Inst.getOperand(2); assert(OffsetImmOp.isImm() && "expected immediate operand kind"); - MipsTargetStreamer &TOut = getTargetStreamer(); unsigned DstReg = DstRegOp.getReg(); unsigned SrcReg = SrcRegOp.getReg(); int64_t OffsetValue = OffsetImmOp.getImm(); // NOTE: We always need AT for ULHU, as it is always used as the source // register for one of the LBu's. - warnIfNoMacro(IDLoc); unsigned ATReg = getATReg(IDLoc); if (!ATReg) return true; - bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue)); - if (IsLargeOffset) { - if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true, - IDLoc, Out, STI)) - return true; - } - - int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue; - int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1); - if (isLittle()) - std::swap(FirstOffset, SecondOffset); + // When the value of offset+1 does not fit in 16 bits, we have to load the + // offset in AT, (D)ADDu the original source register (if there was one), and + // then use AT as the source register for the 2 generated LBu's. + bool LoadedOffsetInAT = false; + if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) { + LoadedOffsetInAT = true; - unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg; - unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg; + if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(), + true, IDLoc, Instructions)) + return true; - unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg; - unsigned SllReg = IsLargeOffset ? DstReg : ATReg; + // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate() + // because it will make our output more similar to GAS'. For example, + // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9", + // instead of just an "ori $1, $9, 32768". + // NOTE: If there is no source register specified in the ULHU, the parser + // will interpret it as $0. + if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64) + createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions); + } - TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg, - FirstOffset, IDLoc, STI); - TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI); - TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI); - TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI); + unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg; + unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg; + unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg; - return false; -} - -bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - if (hasMips32r6() || hasMips64r6()) { - return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); + int64_t FirstLbuOffset = 0, SecondLbuOffset = 0; + if (isLittle()) { + FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1); + SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue; + } else { + FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue; + SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1); } - const MCOperand &DstRegOp = Inst.getOperand(0); - assert(DstRegOp.isReg() && "expected register operand kind"); - const MCOperand &SrcRegOp = Inst.getOperand(1); - assert(SrcRegOp.isReg() && "expected register operand kind"); - const MCOperand &OffsetImmOp = Inst.getOperand(2); - assert(OffsetImmOp.isImm() && "expected immediate operand kind"); + unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg; - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned DstReg = DstRegOp.getReg(); - unsigned SrcReg = SrcRegOp.getReg(); - int64_t OffsetValue = OffsetImmOp.getImm(); - - warnIfNoMacro(IDLoc); - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; + emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg, + FirstLbuOffset, IDLoc, Instructions); - bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue)); - if (IsLargeOffset) { - if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true, - IDLoc, Out, STI)) - return true; - } + emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc, + Instructions); - int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1); - int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue; - if (isLittle()) - std::swap(FirstOffset, SecondOffset); + emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions); - if (IsLargeOffset) { - TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI); - TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI); - TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI); - TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI); - TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI); - TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI); - } else { - TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI); - TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI); - TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI); - } + emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions); return false; } -bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { +bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { if (hasMips32r6() || hasMips64r6()) { - return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); + Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); + return false; } const MCOperand &DstRegOp = Inst.getOperand(0); assert(DstRegOp.isReg() && "expected register operand kind"); + const MCOperand &SrcRegOp = Inst.getOperand(1); assert(SrcRegOp.isReg() && "expected register operand kind"); + const MCOperand &OffsetImmOp = Inst.getOperand(2); assert(OffsetImmOp.isImm() && "expected immediate operand kind"); - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned DstReg = DstRegOp.getReg(); unsigned SrcReg = SrcRegOp.getReg(); int64_t OffsetValue = OffsetImmOp.getImm(); + unsigned ATReg = 0; + + // When the value of offset+3 does not fit in 16 bits, we have to load the + // offset in AT, (D)ADDu the original source register (if there was one), and + // then use AT as the source register for the generated LWL and LWR. + bool LoadedOffsetInAT = false; + if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) { + ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + LoadedOffsetInAT = true; - // Compute left/right load/store offsets. - bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue)); - int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue; - int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3); - if (isLittle()) - std::swap(LxlOffset, LxrOffset); - - bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw); - bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset; - unsigned TmpReg = SrcReg; - if (IsLargeOffset || DoMove) { warnIfNoMacro(IDLoc); - TmpReg = getATReg(IDLoc); - if (!TmpReg) - return true; - } - if (IsLargeOffset) { - if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true, - IDLoc, Out, STI)) + if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(), + true, IDLoc, Instructions)) return true; - } - if (DoMove) - std::swap(DstReg, TmpReg); + // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate() + // because it will make our output more similar to GAS'. For example, + // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9", + // instead of just an "ori $1, $9, 32768". + // NOTE: If there is no source register specified in the ULW, the parser + // will interpret it as $0. + if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64) + createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions); + } + + unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg; + int64_t LeftLoadOffset = 0, RightLoadOffset = 0; + if (isLittle()) { + LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3); + RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue; + } else { + LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue; + RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3); + } - unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL; - unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR; - TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI); - TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI); + emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc, + Instructions); - if (DoMove) - TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI); + emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc, + Instructions); return false; } bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); + SmallVectorImpl<MCInst> &Instructions) { - assert(Inst.getNumOperands() == 3 && "Invalid operand count"); - assert(Inst.getOperand(0).isReg() && - Inst.getOperand(1).isReg() && - Inst.getOperand(2).isImm() && "Invalid instruction operand."); + assert (Inst.getNumOperands() == 3 && "Invalid operand count"); + assert (Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); unsigned ATReg = Mips::NoRegister; unsigned FinalDstReg = Mips::NoRegister; @@ -4306,7 +3183,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, unsigned SrcReg = Inst.getOperand(1).getReg(); int64_t ImmValue = Inst.getOperand(2).getImm(); - bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue)); + bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue); unsigned FinalOpcode = Inst.getOpcode(); @@ -4318,88 +3195,48 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, DstReg = ATReg; } - if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, - Inst.getLoc(), Out, STI)) { + if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) { switch (FinalOpcode) { default: llvm_unreachable("unimplemented expansion"); - case Mips::ADDi: + case (Mips::ADDi): FinalOpcode = Mips::ADD; break; - case Mips::ADDiu: + case (Mips::ADDiu): FinalOpcode = Mips::ADDu; break; - case Mips::ANDi: + case (Mips::ANDi): FinalOpcode = Mips::AND; break; - case Mips::NORImm: + case (Mips::NORImm): FinalOpcode = Mips::NOR; break; - case Mips::ORi: + case (Mips::ORi): FinalOpcode = Mips::OR; break; - case Mips::SLTi: + case (Mips::SLTi): FinalOpcode = Mips::SLT; break; - case Mips::SLTiu: + case (Mips::SLTiu): FinalOpcode = Mips::SLTu; break; - case Mips::XORi: + case (Mips::XORi): FinalOpcode = Mips::XOR; break; - case Mips::ADDi_MM: - FinalOpcode = Mips::ADD_MM; - break; - case Mips::ADDiu_MM: - FinalOpcode = Mips::ADDu_MM; - break; - case Mips::ANDi_MM: - FinalOpcode = Mips::AND_MM; - break; - case Mips::ORi_MM: - FinalOpcode = Mips::OR_MM; - break; - case Mips::SLTi_MM: - FinalOpcode = Mips::SLT_MM; - break; - case Mips::SLTiu_MM: - FinalOpcode = Mips::SLTu_MM; - break; - case Mips::XORi_MM: - FinalOpcode = Mips::XOR_MM; - break; - case Mips::ANDi64: - FinalOpcode = Mips::AND64; - break; - case Mips::NORImm64: - FinalOpcode = Mips::NOR64; - break; - case Mips::ORi64: - FinalOpcode = Mips::OR64; - break; - case Mips::SLTImm64: - FinalOpcode = Mips::SLT64; - break; - case Mips::SLTUImm64: - FinalOpcode = Mips::SLTu64; - break; - case Mips::XORi64: - FinalOpcode = Mips::XOR64; - break; } if (FinalDstReg == Mips::NoRegister) - TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI); + emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions); else - TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI); + emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, + Instructions); return false; } return true; } -bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); +bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -4410,6 +3247,7 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, unsigned SecondShift = Mips::NOP; if (hasMips32r2()) { + if (DReg == SReg) { TmpReg = getATReg(Inst.getLoc()); if (!TmpReg) @@ -4417,13 +3255,13 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } if (Inst.getOpcode() == Mips::ROL) { - TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI); - TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI); + emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); + emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions); return false; } if (Inst.getOpcode() == Mips::ROR) { - TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); + emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions); return false; } @@ -4431,6 +3269,7 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } if (hasMips32()) { + switch (Inst.getOpcode()) { default: llvm_unreachable("unexpected instruction opcode"); @@ -4448,10 +3287,10 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (!ATReg) return true; - TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI); - TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI); - TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI); - TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); + emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); + emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions); + emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions); + emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); return false; } @@ -4460,9 +3299,8 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); + SmallVectorImpl<MCInst> &Instructions) { + unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -4472,17 +3310,18 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, unsigned SecondShift = Mips::NOP; if (hasMips32r2()) { + if (Inst.getOpcode() == Mips::ROLImm) { uint64_t MaxShift = 32; uint64_t ShiftValue = ImmValue; if (ImmValue != 0) ShiftValue = MaxShift - ImmValue; - TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI); + emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions); return false; } if (Inst.getOpcode() == Mips::RORImm) { - TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI); + emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions); return false; } @@ -4490,8 +3329,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, } if (hasMips32()) { + if (ImmValue == 0) { - TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI); + emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions); return false; } @@ -4512,9 +3352,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI); - TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI); - TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); + emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions); + emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions); + emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); return false; } @@ -4522,9 +3362,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, return true; } -bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); +bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -4535,6 +3375,7 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, unsigned SecondShift = Mips::NOP; if (hasMips64r2()) { + if (TmpReg == SReg) { TmpReg = getATReg(Inst.getLoc()); if (!TmpReg) @@ -4542,13 +3383,13 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } if (Inst.getOpcode() == Mips::DROL) { - TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI); - TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI); + emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); + emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions); return false; } if (Inst.getOpcode() == Mips::DROR) { - TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); + emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions); return false; } @@ -4556,6 +3397,7 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } if (hasMips64()) { + switch (Inst.getOpcode()) { default: llvm_unreachable("unexpected instruction opcode"); @@ -4573,10 +3415,10 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (!ATReg) return true; - TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI); - TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI); - TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI); - TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); + emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); + emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions); + emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions); + emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); return false; } @@ -4585,9 +3427,8 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); + SmallVectorImpl<MCInst> &Instructions) { + unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -4599,6 +3440,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCInst TmpInst; if (hasMips64r2()) { + unsigned FinalOpcode = Mips::NOP; if (ImmValue == 0) FinalOpcode = Mips::DROTR; @@ -4620,14 +3462,15 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, if (Inst.getOpcode() == Mips::DROLImm) ShiftValue = (32 - ImmValue % 32) % 32; - TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI); + emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions); return false; } if (hasMips64()) { + if (ImmValue == 0) { - TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI); + emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions); return false; } @@ -4668,10 +3511,9 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI); - TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, - Inst.getLoc(), STI); - TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); + emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions); + emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions); + emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); return false; } @@ -4679,620 +3521,49 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, return true; } -bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned FirstRegOp = Inst.getOperand(0).getReg(); - unsigned SecondRegOp = Inst.getOperand(1).getReg(); - - TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI); - if (FirstRegOp != SecondRegOp) - TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI); +void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + if (hasShortDelaySlot) + emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions); else - TOut.emitEmptyDelaySlot(false, IDLoc, STI); - TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI); - - return false; + emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions); } -bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - int32_t ImmValue = Inst.getOperand(2).getImm(); - - ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, - STI); - - TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT, - SrcReg, ATReg, IDLoc, STI); - - TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); - - return false; -} - -bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - unsigned TmpReg = Inst.getOperand(2).getReg(); - - ATReg = getATReg(Inst.getLoc()); - if (!ATReg) - return true; - - TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT, - SrcReg, TmpReg, IDLoc, STI); - - TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); - - TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32, - DstReg, DstReg, 0x1F, IDLoc, STI); - - TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI); - - if (useTraps()) { - TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI); - } else { - MCContext & Context = TOut.getStreamer().getContext(); - MCSymbol * BrTarget = Context.createTempSymbol(); - MCOperand LabelOp = - MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); - - TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI); - if (AssemblerOptions.back()->isReorder()) - TOut.emitNop(IDLoc, STI); - TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI); - - TOut.getStreamer().EmitLabel(BrTarget); - } - TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); - - return false; +void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg, + unsigned TrgReg, bool Is64Bit, + SmallVectorImpl<MCInst> &Instructions) { + emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(), + Instructions); } -bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - unsigned TmpReg = Inst.getOperand(2).getReg(); - - ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu, - SrcReg, TmpReg, IDLoc, STI); - - TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI); - TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); - if (useTraps()) { - TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI); - } else { - MCContext & Context = TOut.getStreamer().getContext(); - MCSymbol * BrTarget = Context.createTempSymbol(); - MCOperand LabelOp = - MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); - - TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI); - if (AssemblerOptions.back()->isReorder()) - TOut.emitNop(IDLoc, STI); - TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI); - - TOut.getStreamer().EmitLabel(BrTarget); +void MipsAsmParser::createCpRestoreMemOp( + bool IsLoad, int StackOffset, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + // If the offset can not fit into 16 bits, we need to expand. + if (!isInt<16>(StackOffset)) { + MCInst MemInst; + MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW); + MemInst.addOperand(MCOperand::createReg(Mips::GP)); + MemInst.addOperand(MCOperand::createReg(Mips::SP)); + MemInst.addOperand(MCOperand::createImm(StackOffset)); + expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/); + return; } - return false; -} - -bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - unsigned TmpReg = Inst.getOperand(2).getReg(); - - TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI); - TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); - - return false; -} - -// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2); -// lw $<reg+1>>, offset+4($reg2)' -// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2); -// sw $<reg+1>>, offset+4($reg2)' -// for O32. -bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI, - bool IsLoad) { - if (!isABI_O32()) - return true; - - warnIfNoMacro(IDLoc); - - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned Opcode = IsLoad ? Mips::LW : Mips::SW; - unsigned FirstReg = Inst.getOperand(0).getReg(); - unsigned SecondReg = nextReg(FirstReg); - unsigned BaseReg = Inst.getOperand(1).getReg(); - if (!SecondReg) - return true; - - warnIfRegIndexIsAT(FirstReg, IDLoc); - - assert(Inst.getOperand(2).isImm() && - "Offset for load macro is not immediate!"); - - MCOperand &FirstOffset = Inst.getOperand(2); - signed NextOffset = FirstOffset.getImm() + 4; - MCOperand SecondOffset = MCOperand::createImm(NextOffset); - - if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset)) - return true; - - // For loads, clobber the base register with the second load instead of the - // first if the BaseReg == FirstReg. - if (FirstReg != BaseReg || !IsLoad) { - TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); - TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); - } else { - TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); - TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); - } - - return false; -} - -bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - - warnIfNoMacro(IDLoc); - MipsTargetStreamer &TOut = getTargetStreamer(); - - if (Inst.getOperand(1).getReg() != Mips::ZERO && - Inst.getOperand(2).getReg() != Mips::ZERO) { - TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(), - IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); - return false; - } - - unsigned Reg = 0; - if (Inst.getOperand(1).getReg() == Mips::ZERO) { - Reg = Inst.getOperand(2).getReg(); - } else { - Reg = Inst.getOperand(1).getReg(); - } - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI); - return false; -} - -bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - warnIfNoMacro(IDLoc); - MipsTargetStreamer &TOut = getTargetStreamer(); - - unsigned Opc; - int64_t Imm = Inst.getOperand(2).getImm(); - unsigned Reg = Inst.getOperand(1).getReg(); - - if (Imm == 0) { - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), 1, IDLoc, STI); - return false; - } else { - - if (Reg == Mips::ZERO) { - Warning(IDLoc, "comparison is always false"); - TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, - Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI); - return false; - } - - if (Imm > -0x8000 && Imm < 0) { - Imm = -Imm; - Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu; - } else { - Opc = Mips::XORi; - } - } - if (!isUInt<16>(Imm)) { - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc, - Out, STI)) - return true; - - TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), ATReg, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); - return false; - } - - TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), - Imm, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); - return false; -} - -// Map the DSP accumulator and control register to the corresponding gpr -// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions -// do not map the DSP registers contigously to gpr registers. -static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) { - switch (Inst.getOpcode()) { - case Mips::MFTLO: - case Mips::MTTLO: - switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) { - case Mips::AC0: - return Mips::ZERO; - case Mips::AC1: - return Mips::A0; - case Mips::AC2: - return Mips::T0; - case Mips::AC3: - return Mips::T4; - default: - llvm_unreachable("Unknown register for 'mttr' alias!"); - } - case Mips::MFTHI: - case Mips::MTTHI: - switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) { - case Mips::AC0: - return Mips::AT; - case Mips::AC1: - return Mips::A1; - case Mips::AC2: - return Mips::T1; - case Mips::AC3: - return Mips::T5; - default: - llvm_unreachable("Unknown register for 'mttr' alias!"); - } - case Mips::MFTACX: - case Mips::MTTACX: - switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) { - case Mips::AC0: - return Mips::V0; - case Mips::AC1: - return Mips::A2; - case Mips::AC2: - return Mips::T2; - case Mips::AC3: - return Mips::T6; - default: - llvm_unreachable("Unknown register for 'mttr' alias!"); - } - case Mips::MFTDSP: - case Mips::MTTDSP: - return Mips::S0; - default: - llvm_unreachable("Unknown instruction for 'mttr' dsp alias!"); - } -} - -// Map the floating point register operand to the corresponding register -// operand. -static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) { - switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) { - case Mips::F0: return Mips::ZERO; - case Mips::F1: return Mips::AT; - case Mips::F2: return Mips::V0; - case Mips::F3: return Mips::V1; - case Mips::F4: return Mips::A0; - case Mips::F5: return Mips::A1; - case Mips::F6: return Mips::A2; - case Mips::F7: return Mips::A3; - case Mips::F8: return Mips::T0; - case Mips::F9: return Mips::T1; - case Mips::F10: return Mips::T2; - case Mips::F11: return Mips::T3; - case Mips::F12: return Mips::T4; - case Mips::F13: return Mips::T5; - case Mips::F14: return Mips::T6; - case Mips::F15: return Mips::T7; - case Mips::F16: return Mips::S0; - case Mips::F17: return Mips::S1; - case Mips::F18: return Mips::S2; - case Mips::F19: return Mips::S3; - case Mips::F20: return Mips::S4; - case Mips::F21: return Mips::S5; - case Mips::F22: return Mips::S6; - case Mips::F23: return Mips::S7; - case Mips::F24: return Mips::T8; - case Mips::F25: return Mips::T9; - case Mips::F26: return Mips::K0; - case Mips::F27: return Mips::K1; - case Mips::F28: return Mips::GP; - case Mips::F29: return Mips::SP; - case Mips::F30: return Mips::FP; - case Mips::F31: return Mips::RA; - default: llvm_unreachable("Unknown register for mttc1 alias!"); - } -} - -// Map the coprocessor operand the corresponding gpr register operand. -static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) { - switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) { - case Mips::COP00: return Mips::ZERO; - case Mips::COP01: return Mips::AT; - case Mips::COP02: return Mips::V0; - case Mips::COP03: return Mips::V1; - case Mips::COP04: return Mips::A0; - case Mips::COP05: return Mips::A1; - case Mips::COP06: return Mips::A2; - case Mips::COP07: return Mips::A3; - case Mips::COP08: return Mips::T0; - case Mips::COP09: return Mips::T1; - case Mips::COP010: return Mips::T2; - case Mips::COP011: return Mips::T3; - case Mips::COP012: return Mips::T4; - case Mips::COP013: return Mips::T5; - case Mips::COP014: return Mips::T6; - case Mips::COP015: return Mips::T7; - case Mips::COP016: return Mips::S0; - case Mips::COP017: return Mips::S1; - case Mips::COP018: return Mips::S2; - case Mips::COP019: return Mips::S3; - case Mips::COP020: return Mips::S4; - case Mips::COP021: return Mips::S5; - case Mips::COP022: return Mips::S6; - case Mips::COP023: return Mips::S7; - case Mips::COP024: return Mips::T8; - case Mips::COP025: return Mips::T9; - case Mips::COP026: return Mips::K0; - case Mips::COP027: return Mips::K1; - case Mips::COP028: return Mips::GP; - case Mips::COP029: return Mips::SP; - case Mips::COP030: return Mips::FP; - case Mips::COP031: return Mips::RA; - default: llvm_unreachable("Unknown register for mttc0 alias!"); - } -} - -/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing -/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits. -bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned rd = 0; - unsigned u = 1; - unsigned sel = 0; - unsigned h = 0; - bool IsMFTR = false; - switch (Inst.getOpcode()) { - case Mips::MFTC0: - IsMFTR = true; - LLVM_FALLTHROUGH; - case Mips::MTTC0: - u = 0; - rd = getRegisterForMxtrC0(Inst, IsMFTR); - sel = Inst.getOperand(2).getImm(); - break; - case Mips::MFTGPR: - IsMFTR = true; - LLVM_FALLTHROUGH; - case Mips::MTTGPR: - rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg(); - break; - case Mips::MFTLO: - case Mips::MFTHI: - case Mips::MFTACX: - case Mips::MFTDSP: - IsMFTR = true; - LLVM_FALLTHROUGH; - case Mips::MTTLO: - case Mips::MTTHI: - case Mips::MTTACX: - case Mips::MTTDSP: - rd = getRegisterForMxtrDSP(Inst, IsMFTR); - sel = 1; - break; - case Mips::MFTHC1: - h = 1; - LLVM_FALLTHROUGH; - case Mips::MFTC1: - IsMFTR = true; - rd = getRegisterForMxtrFP(Inst, IsMFTR); - sel = 2; - break; - case Mips::MTTHC1: - h = 1; - LLVM_FALLTHROUGH; - case Mips::MTTC1: - rd = getRegisterForMxtrFP(Inst, IsMFTR); - sel = 2; - break; - case Mips::CFTC1: - IsMFTR = true; - LLVM_FALLTHROUGH; - case Mips::CTTC1: - rd = getRegisterForMxtrFP(Inst, IsMFTR); - sel = 3; - break; - } - unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd; - unsigned Op1 = - IsMFTR ? rd - : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg() - : Inst.getOperand(0).getReg()); - - TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc, - STI); - return false; -} - -unsigned -MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst, - const OperandVector &Operands) { - switch (Inst.getOpcode()) { - default: - return Match_Success; - case Mips::DATI: - case Mips::DAHI: - if (static_cast<MipsOperand &>(*Operands[1]) - .isValidForTie(static_cast<MipsOperand &>(*Operands[2]))) - return Match_Success; - return Match_RequiresSameSrcAndDst; - } + emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc, + Instructions); } unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { - switch (Inst.getOpcode()) { - // As described by the MIPSR6 spec, daui must not use the zero operand for - // its source operand. - case Mips::DAUI: - if (Inst.getOperand(1).getReg() == Mips::ZERO || - Inst.getOperand(1).getReg() == Mips::ZERO_64) - return Match_RequiresNoZeroRegister; - return Match_Success; // As described by the Mips32r2 spec, the registers Rd and Rs for // jalr.hb must be different. - // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction - // and registers Rd and Base for microMIPS lwp instruction - case Mips::JALR_HB: - case Mips::JALR_HB64: - case Mips::JALRC_HB_MMR6: - case Mips::JALRC_MMR6: - if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) - return Match_RequiresDifferentSrcAndDst; - return Match_Success; - case Mips::LWP_MM: - if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) - return Match_RequiresDifferentSrcAndDst; - return Match_Success; - case Mips::SYNC: - if (Inst.getOperand(0).getImm() != 0 && !hasMips32()) - return Match_NonZeroOperandForSync; - return Match_Success; - case Mips::MFC0: - case Mips::MTC0: - case Mips::MTC2: - case Mips::MFC2: - if (Inst.getOperand(2).getImm() != 0 && !hasMips32()) - return Match_NonZeroOperandForMTCX; - return Match_Success; - // As described the MIPSR6 spec, the compact branches that compare registers - // must: - // a) Not use the zero register. - // b) Not use the same register twice. - // c) rs < rt for bnec, beqc. - // NB: For this case, the encoding will swap the operands as their - // ordering doesn't matter. GAS performs this transformation too. - // Hence, that constraint does not have to be enforced. - // - // The compact branches that branch iff the signed addition of two registers - // would overflow must have rs >= rt. That can be handled like beqc/bnec with - // operand swapping. They do not have restriction of using the zero register. - case Mips::BLEZC: case Mips::BLEZC_MMR6: - case Mips::BGEZC: case Mips::BGEZC_MMR6: - case Mips::BGTZC: case Mips::BGTZC_MMR6: - case Mips::BLTZC: case Mips::BLTZC_MMR6: - case Mips::BEQZC: case Mips::BEQZC_MMR6: - case Mips::BNEZC: case Mips::BNEZC_MMR6: - case Mips::BLEZC64: - case Mips::BGEZC64: - case Mips::BGTZC64: - case Mips::BLTZC64: - case Mips::BEQZC64: - case Mips::BNEZC64: - if (Inst.getOperand(0).getReg() == Mips::ZERO || - Inst.getOperand(0).getReg() == Mips::ZERO_64) - return Match_RequiresNoZeroRegister; - return Match_Success; - case Mips::BGEC: case Mips::BGEC_MMR6: - case Mips::BLTC: case Mips::BLTC_MMR6: - case Mips::BGEUC: case Mips::BGEUC_MMR6: - case Mips::BLTUC: case Mips::BLTUC_MMR6: - case Mips::BEQC: case Mips::BEQC_MMR6: - case Mips::BNEC: case Mips::BNEC_MMR6: - case Mips::BGEC64: - case Mips::BLTC64: - case Mips::BGEUC64: - case Mips::BLTUC64: - case Mips::BEQC64: - case Mips::BNEC64: - if (Inst.getOperand(0).getReg() == Mips::ZERO || - Inst.getOperand(0).getReg() == Mips::ZERO_64) - return Match_RequiresNoZeroRegister; - if (Inst.getOperand(1).getReg() == Mips::ZERO || - Inst.getOperand(1).getReg() == Mips::ZERO_64) - return Match_RequiresNoZeroRegister; - if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) - return Match_RequiresDifferentOperands; - return Match_Success; - case Mips::DINS: { - assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && - "Operands must be immediates for dins!"); - const signed Pos = Inst.getOperand(2).getImm(); - const signed Size = Inst.getOperand(3).getImm(); - if ((0 > (Pos + Size)) || ((Pos + Size) > 32)) - return Match_RequiresPosSizeRange0_32; - return Match_Success; - } - case Mips::DINSM: - case Mips::DINSU: { - assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && - "Operands must be immediates for dinsm/dinsu!"); - const signed Pos = Inst.getOperand(2).getImm(); - const signed Size = Inst.getOperand(3).getImm(); - if ((32 >= (Pos + Size)) || ((Pos + Size) > 64)) - return Match_RequiresPosSizeRange33_64; - return Match_Success; - } - case Mips::DEXT: { - assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && - "Operands must be immediates for DEXTM!"); - const signed Pos = Inst.getOperand(2).getImm(); - const signed Size = Inst.getOperand(3).getImm(); - if ((1 > (Pos + Size)) || ((Pos + Size) > 63)) - return Match_RequiresPosSizeUImm6; - return Match_Success; - } - case Mips::DEXTM: - case Mips::DEXTU: { - assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() && - "Operands must be immediates for dextm/dextu!"); - const signed Pos = Inst.getOperand(2).getImm(); - const signed Size = Inst.getOperand(3).getImm(); - if ((32 > (Pos + Size)) || ((Pos + Size) > 64)) - return Match_RequiresPosSizeRange33_64; - return Match_Success; - } - case Mips::CRC32B: case Mips::CRC32CB: - case Mips::CRC32H: case Mips::CRC32CH: - case Mips::CRC32W: case Mips::CRC32CW: - case Mips::CRC32D: case Mips::CRC32CD: - if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) - return Match_RequiresSameSrcAndDst; - return Match_Success; - } - - uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags; - if ((TSFlags & MipsII::HasFCCRegOperand) && - (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters()) - return Match_NoFCCRegisterForCurrentISA; + unsigned Opcode = Inst.getOpcode(); - return Match_Success; + if (Opcode == Mips::JALR_HB && + (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())) + return Match_RequiresDifferentSrcAndDst; + return Match_Success; } static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, @@ -5311,15 +3582,20 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) { + MCInst Inst; + SmallVector<MCInst, 8> Instructions; unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { - case Match_Success: - if (processInstruction(Inst, IDLoc, Out, STI)) + case Match_Success: { + if (processInstruction(Inst, IDLoc, Instructions)) return true; + for (unsigned i = 0; i < Instructions.size(); i++) + Out.EmitInstruction(Instructions[i], getSTI()); return false; + } case Match_MissingFeature: Error(IDLoc, "instruction requires a CPU feature not currently enabled"); return true; @@ -5336,24 +3612,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(ErrorLoc, "invalid operand for instruction"); } - case Match_NonZeroOperandForSync: - return Error(IDLoc, - "s-type must be zero or unspecified for pre-MIPS32 ISAs"); - case Match_NonZeroOperandForMTCX: - return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs"); case Match_MnemonicFail: return Error(IDLoc, "invalid instruction"); case Match_RequiresDifferentSrcAndDst: return Error(IDLoc, "source and destination must be different"); - case Match_RequiresDifferentOperands: - return Error(IDLoc, "registers must be different"); - case Match_RequiresNoZeroRegister: - return Error(IDLoc, "invalid operand ($zero) for instruction"); - case Match_RequiresSameSrcAndDst: - return Error(IDLoc, "source and destination must match"); - case Match_NoFCCRegisterForCurrentISA: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "non-zero fcc register doesn't exist in current ISA level"); case Match_Immz: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'"); case Match_UImm1_0: @@ -5371,15 +3633,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_UImm4_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 4-bit unsigned immediate"); - case Match_SImm4_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 4-bit signed immediate"); case Match_UImm5_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 5-bit unsigned immediate"); - case Match_SImm5_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 5-bit signed immediate"); case Match_UImm5_1: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected immediate in range 1 .. 32"); @@ -5397,109 +3653,21 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_UImm5_Lsl2: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected both 7-bit unsigned immediate and multiple of 4"); - case Match_UImmRange2_64: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected immediate in range 2 .. 64"); case Match_UImm6_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 6-bit unsigned immediate"); - case Match_UImm6_Lsl2: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected both 8-bit unsigned immediate and multiple of 4"); - case Match_SImm6_0: + case Match_SImm6: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 6-bit signed immediate"); case Match_UImm7_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 7-bit unsigned immediate"); - case Match_UImm7_N1: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected immediate in range -1 .. 126"); - case Match_SImm7_Lsl2: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected both 9-bit signed immediate and multiple of 4"); case Match_UImm8_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 8-bit unsigned immediate"); case Match_UImm10_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 10-bit unsigned immediate"); - case Match_SImm10_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 10-bit signed immediate"); - case Match_SImm11_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 11-bit signed immediate"); - case Match_UImm16: - case Match_UImm16_Relaxed: - case Match_UImm16_AltRelaxed: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 16-bit unsigned immediate"); - case Match_SImm16: - case Match_SImm16_Relaxed: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 16-bit signed immediate"); - case Match_SImm19_Lsl2: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected both 19-bit signed immediate and multiple of 4"); - case Match_UImm20_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 20-bit unsigned immediate"); - case Match_UImm26_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 26-bit unsigned immediate"); - case Match_SImm32: - case Match_SImm32_Relaxed: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 32-bit signed immediate"); - case Match_UImm32_Coerced: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 32-bit immediate"); - case Match_MemSImm9: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 9-bit signed offset"); - case Match_MemSImm10: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 10-bit signed offset"); - case Match_MemSImm10Lsl1: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 11-bit signed offset and multiple of 2"); - case Match_MemSImm10Lsl2: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 12-bit signed offset and multiple of 4"); - case Match_MemSImm10Lsl3: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 13-bit signed offset and multiple of 8"); - case Match_MemSImm11: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 11-bit signed offset"); - case Match_MemSImm12: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 12-bit signed offset"); - case Match_MemSImm16: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 16-bit signed offset"); - case Match_MemSImmPtr: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected memory with 32-bit signed offset"); - case Match_RequiresPosSizeRange0_32: { - SMLoc ErrorStart = Operands[3]->getStartLoc(); - SMLoc ErrorEnd = Operands[4]->getEndLoc(); - return Error(ErrorStart, "size plus position are not in the range 0 .. 32", - SMRange(ErrorStart, ErrorEnd)); - } - case Match_RequiresPosSizeUImm6: { - SMLoc ErrorStart = Operands[3]->getStartLoc(); - SMLoc ErrorEnd = Operands[4]->getEndLoc(); - return Error(ErrorStart, "size plus position are not in the range 1 .. 63", - SMRange(ErrorStart, ErrorEnd)); - } - case Match_RequiresPosSizeRange33_64: { - SMLoc ErrorStart = Operands[3]->getStartLoc(); - SMLoc ErrorEnd = Operands[4]->getEndLoc(); - return Error(ErrorStart, "size plus position are not in the range 33 .. 64", - SMRange(ErrorStart, ErrorEnd)); - } } llvm_unreachable("Implement any new match types added!"); @@ -5516,17 +3684,6 @@ void MipsAsmParser::warnIfNoMacro(SMLoc Loc) { Warning(Loc, "macro instruction expanded into multiple instructions"); } -void MipsAsmParser::ConvertXWPOperands(MCInst &Inst, - const OperandVector &Operands) { - assert( - (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) && - "Unexpected instruction!"); - ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1); - int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg()); - Inst.addOperand(MCOperand::createReg(NextReg)); - ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2); -} - void MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, SMRange Range, bool ShowColors) { @@ -5540,7 +3697,7 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { CC = StringSwitch<unsigned>(Name) .Case("zero", 0) - .Cases("at", "AT", 1) + .Case("at", 1) .Case("a0", 4) .Case("a1", 5) .Case("a2", 6) @@ -5628,6 +3785,7 @@ int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) { } int MipsAsmParser::matchFPURegisterName(StringRef Name) { + if (Name[0] == 'f') { StringRef NumString = Name.substr(1); unsigned IntVal; @@ -5641,6 +3799,7 @@ int MipsAsmParser::matchFPURegisterName(StringRef Name) { } int MipsAsmParser::matchFCCRegisterName(StringRef Name) { + if (Name.startswith("fcc")) { StringRef NumString = Name.substr(3); unsigned IntVal; @@ -5654,6 +3813,7 @@ int MipsAsmParser::matchFCCRegisterName(StringRef Name) { } int MipsAsmParser::matchACRegisterName(StringRef Name) { + if (Name.startswith("ac")) { StringRef NumString = Name.substr(2); unsigned IntVal; @@ -5695,10 +3855,6 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { return CC; } -bool MipsAsmParser::canUseATReg() { - return AssemblerOptions.back()->getATRegIndex() != 0; -} - unsigned MipsAsmParser::getATReg(SMLoc Loc) { unsigned ATIndex = AssemblerOptions.back()->getATRegIndex(); if (ATIndex == 0) { @@ -5715,9 +3871,22 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) { return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); } +unsigned MipsAsmParser::getGPR(int RegNo) { + return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, + RegNo); +} + +int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { + if (RegNum > + getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1) + return -1; + + return getReg(RegClass, RegNum); +} + bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseOperand\n"); + 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. @@ -5730,9 +3899,12 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (ResTy == MatchOperand_ParseFail) return true; - LLVM_DEBUG(dbgs() << ".. Generic Parser\n"); + DEBUG(dbgs() << ".. Generic Parser\n"); switch (getLexer().getKind()) { + default: + Error(Parser.getTok().getLoc(), "unexpected token in operand"); + return true; case AsmToken::Dollar: { // Parse the register. SMLoc S = Parser.getTok().getLoc(); @@ -5759,35 +3931,107 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); return false; } - default: { - LLVM_DEBUG(dbgs() << ".. generic integer expression\n"); - - const MCExpr *Expr; + // Else drop to expression parsing. + case AsmToken::LParen: + case AsmToken::Minus: + case AsmToken::Plus: + case AsmToken::Integer: + case AsmToken::Tilde: + case AsmToken::String: { + DEBUG(dbgs() << ".. generic integer\n"); + OperandMatchResultTy ResTy = parseImm(Operands); + return ResTy != MatchOperand_Success; + } + case AsmToken::Percent: { + // It is a symbol reference or constant expression. + const MCExpr *IdVal; SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. - if (getParser().parseExpression(Expr)) + if (parseRelocOperand(IdVal)) return true; SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this)); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); return false; - } + } // case AsmToken::Percent } // switch(getLexer().getKind()) return true; } +const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, + StringRef RelocStr) { + const MCExpr *Res; + // Check the type of the expression. + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) { + // It's a constant, evaluate reloc value. + int16_t Val; + switch (getVariantKind(RelocStr)) { + case MCSymbolRefExpr::VK_Mips_ABS_LO: + // Get the 1st 16-bits. + Val = MCE->getValue() & 0xffff; + break; + case MCSymbolRefExpr::VK_Mips_ABS_HI: + // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low + // 16 bits being negative. + Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff; + break; + case MCSymbolRefExpr::VK_Mips_HIGHER: + // Get the 3rd 16-bits. + Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff; + break; + case MCSymbolRefExpr::VK_Mips_HIGHEST: + // Get the 4th 16-bits. + Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff; + break; + default: + report_fatal_error("unsupported reloc value"); + } + return MCConstantExpr::create(Val, getContext()); + } + + if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) { + // It's a symbol, create a symbolic expression from the symbol. + const MCSymbol *Symbol = &MSRE->getSymbol(); + MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); + Res = MCSymbolRefExpr::create(Symbol, VK, getContext()); + return Res; + } + + if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { + MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); + + // Try to create target expression. + if (MipsMCExpr::isSupportedBinaryExpr(VK, BE)) + return MipsMCExpr::create(VK, Expr, getContext()); + + const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr); + const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr); + Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext()); + return Res; + } + + if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) { + const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr); + Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext()); + return Res; + } + // Just return the original expression. + return Expr; +} + bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { + switch (Expr->getKind()) { case MCExpr::Constant: return true; case MCExpr::SymbolRef: return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None); - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); - if (!isEvaluated(BE->getLHS())) - return false; - return isEvaluated(BE->getRHS()); - } + case MCExpr::Binary: + if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { + if (!isEvaluated(BE->getLHS())) + return false; + return isEvaluated(BE->getRHS()); + } case MCExpr::Unary: return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); case MCExpr::Target: @@ -5796,6 +4040,49 @@ bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { return false; } +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)) + return true; + + std::string Str = Tok.getIdentifier(); + + Parser.Lex(); // Eat the identifier. + // Now make an expression from the rest of the operand. + const MCExpr *IdVal; + SMLoc EndLoc; + + if (getLexer().getKind() == AsmToken::LParen) { + while (1) { + Parser.Lex(); // Eat the '(' token. + if (getLexer().getKind() == AsmToken::Percent) { + Parser.Lex(); // Eat the % token. + const AsmToken &nextTok = Parser.getTok(); + if (nextTok.isNot(AsmToken::Identifier)) + return true; + Str += "(%"; + Str += nextTok.getIdentifier(); + Parser.Lex(); // Eat the identifier. + if (getLexer().getKind() != AsmToken::LParen) + return true; + } else + break; + } + if (getParser().parseParenExpression(IdVal, EndLoc)) + return true; + + while (getLexer().getKind() == AsmToken::RParen) + Parser.Lex(); // Eat the ')' token. + + } else + return true; // Parenthesis must follow the relocation operand. + + Res = evaluateRelocExpr(IdVal, Str); + return false; +} + bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; @@ -5823,21 +4110,45 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, } bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { + MCAsmParser &Parser = getParser(); SMLoc S; + bool Result = true; + unsigned NumOfLParen = 0; - if (isParenExpr) - return getParser().parseParenExprOfDepth(0, Res, S); - return getParser().parseExpression(Res); + while (getLexer().getKind() == AsmToken::LParen) { + Parser.Lex(); + ++NumOfLParen; + } + + switch (getLexer().getKind()) { + default: + return true; + case AsmToken::Identifier: + case AsmToken::LParen: + case AsmToken::Integer: + case AsmToken::Minus: + case AsmToken::Plus: + if (isParenExpr) + Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S); + else + Result = (getParser().parseExpression(Res)); + while (getLexer().getKind() == AsmToken::RParen) + Parser.Lex(); + break; + case AsmToken::Percent: + Result = parseRelocOperand(Res); + } + return Result; } -OperandMatchResultTy +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseMemOperand\n"); + DEBUG(dbgs() << "parseMemOperand\n"); const MCExpr *IdVal = nullptr; SMLoc S; bool isParenExpr = false; - OperandMatchResultTy Res = MatchOperand_NoMatch; + MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch; // First operand is the offset. S = Parser.getTok().getLoc(); @@ -5865,66 +4176,14 @@ 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, "0", getContext().getRegisterInfo(), S, E, *this); + auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(), + S, E, *this); Operands.push_back( MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this)); return MatchOperand_Success; } - MCBinaryExpr::Opcode Opcode; - // GAS and LLVM treat comparison operators different. GAS will generate -1 - // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is - // highly unlikely to be found in a memory offset expression, we don't - // handle them. - switch (Tok.getKind()) { - case AsmToken::Plus: - Opcode = MCBinaryExpr::Add; - Parser.Lex(); - break; - case AsmToken::Minus: - Opcode = MCBinaryExpr::Sub; - Parser.Lex(); - break; - case AsmToken::Star: - Opcode = MCBinaryExpr::Mul; - Parser.Lex(); - break; - case AsmToken::Pipe: - Opcode = MCBinaryExpr::Or; - Parser.Lex(); - break; - case AsmToken::Amp: - Opcode = MCBinaryExpr::And; - Parser.Lex(); - break; - case AsmToken::LessLess: - Opcode = MCBinaryExpr::Shl; - Parser.Lex(); - break; - case AsmToken::GreaterGreater: - Opcode = MCBinaryExpr::LShr; - Parser.Lex(); - break; - case AsmToken::Caret: - Opcode = MCBinaryExpr::Xor; - Parser.Lex(); - break; - case AsmToken::Slash: - Opcode = MCBinaryExpr::Div; - Parser.Lex(); - break; - case AsmToken::Percent: - Opcode = MCBinaryExpr::Mod; - Parser.Lex(); - break; - default: - Error(Parser.getTok().getLoc(), "'(' or expression expected"); - return MatchOperand_ParseFail; - } - const MCExpr * NextExpr; - if (getParser().parseExpression(NextExpr)) - return MatchOperand_ParseFail; - IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext()); + Error(Parser.getTok().getLoc(), "'(' expected"); + return MatchOperand_ParseFail; } Parser.Lex(); // Eat the '(' token. @@ -5969,12 +4228,13 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { MCAsmParser &Parser = getParser(); MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier()); - if (!Sym) - return false; - - SMLoc S = Parser.getTok().getLoc(); - if (Sym->isVariable()) { - const MCExpr *Expr = Sym->getVariableValue(); + if (Sym) { + SMLoc S = Parser.getTok().getLoc(); + const MCExpr *Expr; + if (Sym->isVariable()) + Expr = Sym->getVariableValue(); + else + return false; if (Expr->getKind() == MCExpr::SymbolRef) { const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); StringRef DefSymbol = Ref->getSymbol().getName(); @@ -5984,146 +4244,120 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { if (ResTy == MatchOperand_Success) { Parser.Lex(); return true; - } - if (ResTy == MatchOperand_ParseFail) + } else if (ResTy == MatchOperand_ParseFail) llvm_unreachable("Should never ParseFail"); + return false; } - } - } else if (Sym->isUnset()) { - // If symbol is unset, it might be created in the `parseSetAssignment` - // routine as an alias for a numeric register name. - // Lookup in the aliases list. - auto Entry = RegisterSets.find(Sym->getName()); - if (Entry != RegisterSets.end()) { - OperandMatchResultTy ResTy = - matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S); - if (ResTy == MatchOperand_Success) { - Parser.Lex(); - return true; - } + } else if (Expr->getKind() == MCExpr::Constant) { + Parser.Lex(); + const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr); + Operands.push_back( + MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this)); + return true; } } - return false; } -OperandMatchResultTy +MipsAsmParser::OperandMatchResultTy MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands, StringRef Identifier, SMLoc S) { int Index = matchCPURegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createGPRReg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchHWRegsRegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createHWRegsReg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchFPURegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createFGRReg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchFCCRegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createFCCReg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchACRegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createACCReg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchMSA128RegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createMSA128Reg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } Index = matchMSA128CtrlRegisterName(Identifier); if (Index != -1) { Operands.push_back(MipsOperand::createMSACtrlReg( - Index, Identifier, getContext().getRegisterInfo(), S, - getLexer().getLoc(), *this)); + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); return MatchOperand_Success; } return MatchOperand_NoMatch; } -OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, - const AsmToken &Token, SMLoc S) { +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { + MCAsmParser &Parser = getParser(); + auto Token = Parser.getLexer().peekTok(false); + if (Token.is(AsmToken::Identifier)) { - LLVM_DEBUG(dbgs() << ".. identifier\n"); + DEBUG(dbgs() << ".. identifier\n"); StringRef Identifier = Token.getIdentifier(); OperandMatchResultTy ResTy = matchAnyRegisterNameWithoutDollar(Operands, Identifier, S); return ResTy; } else if (Token.is(AsmToken::Integer)) { - LLVM_DEBUG(dbgs() << ".. integer\n"); - int64_t RegNum = Token.getIntVal(); - if (RegNum < 0 || RegNum > 31) { - // Show the error, but treat invalid register - // number as a normal one to continue parsing - // and catch other possible errors. - Error(getLexer().getLoc(), "invalid register number"); - } + DEBUG(dbgs() << ".. integer\n"); Operands.push_back(MipsOperand::createNumericReg( - RegNum, Token.getString(), getContext().getRegisterInfo(), S, - Token.getLoc(), *this)); + Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(), + *this)); return MatchOperand_Success; } - LLVM_DEBUG(dbgs() << Token.getKind() << "\n"); + DEBUG(dbgs() << Parser.getTok().getKind() << "\n"); return MatchOperand_NoMatch; } -OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { - auto Token = getLexer().peekTok(false); - return matchAnyRegisterWithoutDollar(Operands, Token, S); -} - -OperandMatchResultTy +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAnyRegister(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseAnyRegister\n"); + DEBUG(dbgs() << "parseAnyRegister\n"); auto Token = Parser.getTok(); SMLoc S = Token.getLoc(); if (Token.isNot(AsmToken::Dollar)) { - LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); + DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); if (Token.is(AsmToken::Identifier)) { if (searchSymbolAlias(Operands)) return MatchOperand_Success; } - LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); + DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); return MatchOperand_NoMatch; } - LLVM_DEBUG(dbgs() << ".. $\n"); + DEBUG(dbgs() << ".. $\n"); OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); if (ResTy == MatchOperand_Success) { @@ -6133,19 +4367,48 @@ MipsAsmParser::parseAnyRegister(OperandVector &Operands) { return ResTy; } -OperandMatchResultTy +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + switch (getLexer().getKind()) { + default: + return MatchOperand_NoMatch; + case AsmToken::LParen: + case AsmToken::Minus: + case AsmToken::Plus: + case AsmToken::Integer: + case AsmToken::Tilde: + case AsmToken::String: + break; + } + + const MCExpr *IdVal; + SMLoc S = Parser.getTok().getLoc(); + if (getParser().parseExpression(IdVal)) + return MatchOperand_ParseFail; + + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseJumpTarget(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseJumpTarget\n"); + DEBUG(dbgs() << "parseJumpTarget\n"); SMLoc S = getLexer().getLoc(); + // Integers and expressions are acceptable + OperandMatchResultTy ResTy = parseImm(Operands); + if (ResTy != MatchOperand_NoMatch) + return ResTy; + // Registers are a valid target and have priority over symbols. - OperandMatchResultTy ResTy = parseAnyRegister(Operands); + ResTy = parseAnyRegister(Operands); if (ResTy != MatchOperand_NoMatch) return ResTy; - // Integers and expressions are acceptable const MCExpr *Expr = nullptr; if (Parser.parseExpression(Expr)) { // We have no way of knowing if a symbol was consumed so we must ParseFail @@ -6156,25 +4419,18 @@ MipsAsmParser::parseJumpTarget(OperandVector &Operands) { return MatchOperand_Success; } -OperandMatchResultTy +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseInvNum(OperandVector &Operands) { MCAsmParser &Parser = getParser(); const MCExpr *IdVal; - // If the first token is '$' we may have register operand. We have to reject - // cases where it is not a register. Complicating the matter is that - // register names are not reserved across all ABIs. - // Peek past the dollar to see if it's a register name for this ABI. + // If the first token is '$' we may have register operand. + if (Parser.getTok().is(AsmToken::Dollar)) + return MatchOperand_NoMatch; SMLoc S = Parser.getTok().getLoc(); - if (Parser.getTok().is(AsmToken::Dollar)) { - return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1 - ? MatchOperand_ParseFail - : MatchOperand_NoMatch; - } if (getParser().parseExpression(IdVal)) return MatchOperand_ParseFail; const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal); - if (!MCE) - return MatchOperand_NoMatch; + assert(MCE && "Unexpected MCExpr type."); int64_t Val = MCE->getValue(); SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(MipsOperand::CreateImm( @@ -6182,7 +4438,47 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) { return MatchOperand_Success; } -OperandMatchResultTy +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseLSAImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + switch (getLexer().getKind()) { + default: + return MatchOperand_NoMatch; + case AsmToken::LParen: + case AsmToken::Plus: + case AsmToken::Minus: + case AsmToken::Integer: + break; + } + + const MCExpr *Expr; + SMLoc S = Parser.getTok().getLoc(); + + if (getParser().parseExpression(Expr)) + return MatchOperand_ParseFail; + + int64_t Val; + if (!Expr->evaluateAsAbsolute(Val)) { + Error(S, "expected immediate value"); + return MatchOperand_ParseFail; + } + + // The LSA instruction allows a 2-bit unsigned immediate. For this reason + // and because the CPU always adds one to the immediate field, the allowed + // range becomes 1..4. We'll only check the range here and will deal + // with the addition/subtraction when actually decoding/encoding + // the instruction. + if (Val < 1 || Val > 4) { + Error(S, "immediate not in range (1..4)"); + return MatchOperand_ParseFail; + } + + Operands.push_back( + MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this)); + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseRegisterList(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SmallVector<unsigned, 10> Regs; @@ -6268,6 +4564,97 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseRegisterPair(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + + SMLoc S = Parser.getTok().getLoc(); + if (parseAnyRegister(Operands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + SMLoc E = Parser.getTok().getLoc(); + MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back()); + unsigned Reg = Op.getGPR32Reg(); + Operands.pop_back(); + Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; + SmallVector<unsigned, 10> Regs; + + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_ParseFail; + + SMLoc S = Parser.getTok().getLoc(); + + if (parseAnyRegister(TmpOperands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); + unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); + Regs.push_back(RegNo); + + SMLoc E = Parser.getTok().getLoc(); + if (Parser.getTok().isNot(AsmToken::Comma)) { + Error(E, "',' expected"); + return MatchOperand_ParseFail; + } + + // Remove comma. + Parser.Lex(); + + if (parseAnyRegister(TmpOperands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); + RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); + Regs.push_back(RegNo); + + Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); + + return MatchOperand_Success; +} + +MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { + + MCSymbolRefExpr::VariantKind VK = + StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol) + .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI) + .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO) + .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL) + .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL) + .Case("got", MCSymbolRefExpr::VK_Mips_GOT) + .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD) + .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM) + .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI) + .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO) + .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL) + .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI) + .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO) + .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP) + .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE) + .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST) + .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI) + .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO) + .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16) + .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16) + .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16) + .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16) + .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER) + .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST) + .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16) + .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16) + .Default(MCSymbolRefExpr::VK_None); + + assert(VK != MCSymbolRefExpr::VK_None); + + return VK; +} + /// Sometimes (i.e. load/stores) the operand may be followed immediately by /// either this. /// ::= '(', register, ')' @@ -6281,10 +4668,12 @@ bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) { Parser.Lex(); if (parseOperand(Operands, Name)) { SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } if (Parser.getTok().isNot(AsmToken::RParen)) { SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token, expected ')'"); } Operands.push_back( @@ -6309,10 +4698,12 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name, Parser.Lex(); if (parseOperand(Operands, Name)) { SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } if (Parser.getTok().isNot(AsmToken::RBrac)) { SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token, expected ']'"); } Operands.push_back( @@ -6322,22 +4713,18 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name, return false; } -static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS, - unsigned VariantID = 0); - bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "ParseInstruction\n"); + DEBUG(dbgs() << "ParseInstruction\n"); // We have reached first instruction, module directive are now forbidden. getTargetStreamer().forbidModuleDirective(); // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); - std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS); - return Error(NameLoc, "unknown instruction" + Suggestion); + Parser.eatToEndOfStatement(); + return Error(NameLoc, "unknown instruction"); } // First operand in MCInst is instruction mnemonic. Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); @@ -6347,6 +4734,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Read the first operand. 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)) @@ -6358,6 +4746,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Parse and remember the operand. 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 @@ -6371,16 +4760,17 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } if (getLexer().isNot(AsmToken::EndOfStatement)) { SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } Parser.Lex(); // Consume the EndOfStatement. return false; } -// FIXME: Given that these have the same name, these should both be -// consistent on affecting the Parser. bool MipsAsmParser::reportParseError(Twine ErrorMsg) { + MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, ErrorMsg); } @@ -6659,90 +5049,6 @@ bool MipsAsmParser::parseSetNoOddSPRegDirective() { return false; } -bool MipsAsmParser::parseSetMtDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "mt". - - // 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::FeatureMT, "mt"); - getTargetStreamer().emitDirectiveSetMt(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoMtDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "nomt". - - // 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; - } - - clearFeatureBits(Mips::FeatureMT, "mt"); - - getTargetStreamer().emitDirectiveSetNoMt(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoCRCDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "nocrc". - - // 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; - } - - clearFeatureBits(Mips::FeatureCRC, "crc"); - - getTargetStreamer().emitDirectiveSetNoCRC(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoVirtDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "novirt". - - // 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; - } - - clearFeatureBits(Mips::FeatureVirt, "virt"); - - getTargetStreamer().emitDirectiveSetNoVirt(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoGINVDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "noginv". - - // 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; - } - - clearFeatureBits(Mips::FeatureGINV, "ginv"); - - getTargetStreamer().emitDirectiveSetNoGINV(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - bool MipsAsmParser::parseSetPopDirective() { MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); @@ -6774,7 +5080,7 @@ bool MipsAsmParser::parseSetPushDirective() { // Create a copy of the current assembler options environment and push it. AssemblerOptions.push_back( - llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); + make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); getTargetStreamer().emitDirectiveSetPush(); return false; @@ -6808,30 +5114,17 @@ bool MipsAsmParser::parseSetAssignment() { MCAsmParser &Parser = getParser(); if (Parser.parseIdentifier(Name)) - return reportParseError("expected identifier after .set"); + reportParseError("expected identifier after .set"); if (getLexer().isNot(AsmToken::Comma)) return reportParseError("unexpected token, expected comma"); Lex(); // Eat comma - if (getLexer().is(AsmToken::Dollar) && - getLexer().peekTok().is(AsmToken::Integer)) { - // Parse assignment of a numeric register: - // .set r1,$1 - Parser.Lex(); // Eat $. - RegisterSets[Name] = Parser.getTok(); - Parser.Lex(); // Eat identifier. - getContext().getOrCreateSymbol(Name); - } else if (!Parser.parseExpression(Value)) { - // Parse assignment of an expression including - // symbolic registers: - // .set $tmp, $BB0-$BB1 - // .set r2, $f2 - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - Sym->setVariableValue(Value); - } else { + if (Parser.parseExpression(Value)) return reportParseError("expected valid expression after comma"); - } + + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + Sym->setVariableValue(Value); return false; } @@ -6881,16 +5174,13 @@ bool MipsAsmParser::parseSetArchDirective() { .Case("mips64r3", "mips64r3") .Case("mips64r5", "mips64r5") .Case("mips64r6", "mips64r6") - .Case("octeon", "cnmips") + .Case("cnmips", "cnmips") .Case("r4000", "mips3") // This is an implementation of Mips3. .Default(""); if (ArchFeatureName.empty()) return reportParseError("unsupported architecture"); - if (ArchFeatureName == "mips64r6" && inMicroMipsMode()) - return reportParseError("mips64r6 does not support microMIPS"); - selectArch(ArchFeatureName); getTargetStreamer().emitDirectiveSetArch(Arch); return false; @@ -6909,12 +5199,7 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { setFeatureBits(Mips::FeatureDSP, "dsp"); getTargetStreamer().emitDirectiveSetDsp(); break; - case Mips::FeatureDSPR2: - setFeatureBits(Mips::FeatureDSPR2, "dspr2"); - getTargetStreamer().emitDirectiveSetDspr2(); - break; case Mips::FeatureMicroMips: - setFeatureBits(Mips::FeatureMicroMips, "micromips"); getTargetStreamer().emitDirectiveSetMicroMips(); break; case Mips::FeatureMips1: @@ -6977,18 +5262,6 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { selectArch("mips64r6"); getTargetStreamer().emitDirectiveSetMips64R6(); break; - case Mips::FeatureCRC: - setFeatureBits(Mips::FeatureCRC, "crc"); - getTargetStreamer().emitDirectiveSetCRC(); - break; - case Mips::FeatureVirt: - setFeatureBits(Mips::FeatureVirt, "virt"); - getTargetStreamer().emitDirectiveSetVirt(); - break; - case Mips::FeatureGINV: - setFeatureBits(Mips::FeatureGINV, "ginv"); - getTargetStreamer().emitDirectiveSetGINV(); - break; } return false; } @@ -6997,6 +5270,7 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) { MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::Comma)) { SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); return Error(Loc, ErrorStr); } @@ -7082,9 +5356,12 @@ bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { return false; } - if (!getTargetStreamer().emitDirectiveCpRestore( - CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI)) - return true; + // Store the $gp on the stack. + SmallVector<MCInst, 3> StoreInsts; + createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc, + StoreInsts); + + getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset); Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -7099,12 +5376,14 @@ bool MipsAsmParser::parseDirectiveCPSetup() { OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); if (ResTy == MatchOperand_NoMatch) { reportParseError("expected register containing function address"); + Parser.eatToEndOfStatement(); return false; } MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); if (!FuncRegOpnd.isGPRAsmReg()) { reportParseError(FuncRegOpnd.getStartLoc(), "invalid register"); + Parser.eatToEndOfStatement(); return false; } @@ -7123,6 +5402,7 @@ bool MipsAsmParser::parseDirectiveCPSetup() { if (Parser.parseExpression(OffsetExpr) || !OffsetExpr->evaluateAsAbsolute(OffsetVal)) { reportParseError(ExprLoc, "expected save register or stack offset"); + Parser.eatToEndOfStatement(); return false; } @@ -7132,6 +5412,7 @@ bool MipsAsmParser::parseDirectiveCPSetup() { MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]); if (!SaveOpnd.isGPRAsmReg()) { reportParseError(SaveOpnd.getStartLoc(), "invalid register"); + Parser.eatToEndOfStatement(); return false; } Save = SaveOpnd.getGPR32Reg(); @@ -7188,131 +5469,120 @@ bool MipsAsmParser::parseDirectiveNaN() { } bool MipsAsmParser::parseDirectiveSet() { - const AsmToken &Tok = getParser().getTok(); - StringRef IdVal = Tok.getString(); - SMLoc Loc = Tok.getLoc(); + MCAsmParser &Parser = getParser(); + // Get the next token. + const AsmToken &Tok = Parser.getTok(); - if (IdVal == "noat") + if (Tok.getString() == "noat") { return parseSetNoAtDirective(); - if (IdVal == "at") + } else if (Tok.getString() == "at") { return parseSetAtDirective(); - if (IdVal == "arch") + } else if (Tok.getString() == "arch") { return parseSetArchDirective(); - if (IdVal == "bopt") { - Warning(Loc, "'bopt' feature is unsupported"); - getParser().Lex(); - return false; - } - if (IdVal == "nobopt") { - // We're already running in nobopt mode, so nothing to do. - getParser().Lex(); - return false; - } - if (IdVal == "fp") + } else if (Tok.getString() == "fp") { return parseSetFpDirective(); - if (IdVal == "oddspreg") + } else if (Tok.getString() == "oddspreg") { return parseSetOddSPRegDirective(); - if (IdVal == "nooddspreg") + } else if (Tok.getString() == "nooddspreg") { return parseSetNoOddSPRegDirective(); - if (IdVal == "pop") + } else if (Tok.getString() == "pop") { return parseSetPopDirective(); - if (IdVal == "push") + } else if (Tok.getString() == "push") { return parseSetPushDirective(); - if (IdVal == "reorder") + } else if (Tok.getString() == "reorder") { return parseSetReorderDirective(); - if (IdVal == "noreorder") + } else if (Tok.getString() == "noreorder") { return parseSetNoReorderDirective(); - if (IdVal == "macro") + } else if (Tok.getString() == "macro") { return parseSetMacroDirective(); - if (IdVal == "nomacro") + } else if (Tok.getString() == "nomacro") { return parseSetNoMacroDirective(); - if (IdVal == "mips16") + } else if (Tok.getString() == "mips16") { return parseSetMips16Directive(); - if (IdVal == "nomips16") + } else if (Tok.getString() == "nomips16") { return parseSetNoMips16Directive(); - if (IdVal == "nomicromips") { - clearFeatureBits(Mips::FeatureMicroMips, "micromips"); + } else if (Tok.getString() == "nomicromips") { getTargetStreamer().emitDirectiveSetNoMicroMips(); - getParser().eatToEndOfStatement(); + Parser.eatToEndOfStatement(); return false; - } - if (IdVal == "micromips") { - if (hasMips64r6()) { - Error(Loc, ".set micromips directive is not supported with MIPS64R6"); - return false; - } + } else if (Tok.getString() == "micromips") { return parseSetFeature(Mips::FeatureMicroMips); - } - if (IdVal == "mips0") + } else if (Tok.getString() == "mips0") { return parseSetMips0Directive(); - if (IdVal == "mips1") + } else if (Tok.getString() == "mips1") { return parseSetFeature(Mips::FeatureMips1); - if (IdVal == "mips2") + } else if (Tok.getString() == "mips2") { return parseSetFeature(Mips::FeatureMips2); - if (IdVal == "mips3") + } else if (Tok.getString() == "mips3") { return parseSetFeature(Mips::FeatureMips3); - if (IdVal == "mips4") + } else if (Tok.getString() == "mips4") { return parseSetFeature(Mips::FeatureMips4); - if (IdVal == "mips5") + } else if (Tok.getString() == "mips5") { return parseSetFeature(Mips::FeatureMips5); - if (IdVal == "mips32") + } else if (Tok.getString() == "mips32") { return parseSetFeature(Mips::FeatureMips32); - if (IdVal == "mips32r2") + } else if (Tok.getString() == "mips32r2") { return parseSetFeature(Mips::FeatureMips32r2); - if (IdVal == "mips32r3") + } else if (Tok.getString() == "mips32r3") { return parseSetFeature(Mips::FeatureMips32r3); - if (IdVal == "mips32r5") + } else if (Tok.getString() == "mips32r5") { return parseSetFeature(Mips::FeatureMips32r5); - if (IdVal == "mips32r6") + } else if (Tok.getString() == "mips32r6") { return parseSetFeature(Mips::FeatureMips32r6); - if (IdVal == "mips64") + } else if (Tok.getString() == "mips64") { return parseSetFeature(Mips::FeatureMips64); - if (IdVal == "mips64r2") + } else if (Tok.getString() == "mips64r2") { return parseSetFeature(Mips::FeatureMips64r2); - if (IdVal == "mips64r3") + } else if (Tok.getString() == "mips64r3") { return parseSetFeature(Mips::FeatureMips64r3); - if (IdVal == "mips64r5") + } else if (Tok.getString() == "mips64r5") { return parseSetFeature(Mips::FeatureMips64r5); - if (IdVal == "mips64r6") { - if (inMicroMipsMode()) { - Error(Loc, "MIPS64R6 is not supported with microMIPS"); - return false; - } + } else if (Tok.getString() == "mips64r6") { return parseSetFeature(Mips::FeatureMips64r6); - } - if (IdVal == "dsp") + } else if (Tok.getString() == "dsp") { return parseSetFeature(Mips::FeatureDSP); - if (IdVal == "dspr2") - return parseSetFeature(Mips::FeatureDSPR2); - if (IdVal == "nodsp") + } else if (Tok.getString() == "nodsp") { return parseSetNoDspDirective(); - if (IdVal == "msa") + } else if (Tok.getString() == "msa") { return parseSetMsaDirective(); - if (IdVal == "nomsa") + } else if (Tok.getString() == "nomsa") { return parseSetNoMsaDirective(); - if (IdVal == "mt") - return parseSetMtDirective(); - if (IdVal == "nomt") - return parseSetNoMtDirective(); - if (IdVal == "softfloat") + } else if (Tok.getString() == "softfloat") { return parseSetSoftFloatDirective(); - if (IdVal == "hardfloat") + } else if (Tok.getString() == "hardfloat") { return parseSetHardFloatDirective(); - if (IdVal == "crc") - return parseSetFeature(Mips::FeatureCRC); - if (IdVal == "nocrc") - return parseSetNoCRCDirective(); - if (IdVal == "virt") - return parseSetFeature(Mips::FeatureVirt); - if (IdVal == "novirt") - return parseSetNoVirtDirective(); - if (IdVal == "ginv") - return parseSetFeature(Mips::FeatureGINV); - if (IdVal == "noginv") - return parseSetNoGINVDirective(); - - // It is just an identifier, look for an assignment. - return parseSetAssignment(); + } else { + // It is just an identifier, look for an assignment. + parseSetAssignment(); + return false; + } + + return true; +} + +/// parseDataDirective +/// ::= .word [ expression (, expression)* ] +bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { + MCAsmParser &Parser = getParser(); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + const MCExpr *Value; + if (getParser().parseExpression(Value)) + return true; + + getParser().getStreamer().EmitValue(Value, Size); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return Error(L, "unexpected token, expected comma"); + Parser.Lex(); + } + } + + Parser.Lex(); + return false; } /// parseDirectiveGpWord @@ -7327,7 +5597,7 @@ bool MipsAsmParser::parseDirectiveGpWord() { getParser().getStreamer().EmitGPRel32Value(Value); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), + return Error(getLexer().getLoc(), "unexpected token, expected end of statement"); Parser.Lex(); // Eat EndOfStatement token. return false; @@ -7345,79 +5615,7 @@ bool MipsAsmParser::parseDirectiveGpDWord() { getParser().getStreamer().EmitGPRel64Value(Value); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token, expected end of statement"); - Parser.Lex(); // Eat EndOfStatement token. - return false; -} - -/// parseDirectiveDtpRelWord -/// ::= .dtprelword tls_sym -bool MipsAsmParser::parseDirectiveDtpRelWord() { - MCAsmParser &Parser = getParser(); - const MCExpr *Value; - // EmitDTPRel32Value requires an expression, so we are using base class - // method to evaluate the expression. - if (getParser().parseExpression(Value)) - return true; - getParser().getStreamer().EmitDTPRel32Value(Value); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token, expected end of statement"); - Parser.Lex(); // Eat EndOfStatement token. - return false; -} - -/// parseDirectiveDtpRelDWord -/// ::= .dtpreldword tls_sym -bool MipsAsmParser::parseDirectiveDtpRelDWord() { - MCAsmParser &Parser = getParser(); - const MCExpr *Value; - // EmitDTPRel64Value requires an expression, so we are using base class - // method to evaluate the expression. - if (getParser().parseExpression(Value)) - return true; - getParser().getStreamer().EmitDTPRel64Value(Value); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token, expected end of statement"); - Parser.Lex(); // Eat EndOfStatement token. - return false; -} - -/// parseDirectiveTpRelWord -/// ::= .tprelword tls_sym -bool MipsAsmParser::parseDirectiveTpRelWord() { - MCAsmParser &Parser = getParser(); - const MCExpr *Value; - // EmitTPRel32Value requires an expression, so we are using base class - // method to evaluate the expression. - if (getParser().parseExpression(Value)) - return true; - getParser().getStreamer().EmitTPRel32Value(Value); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token, expected end of statement"); - Parser.Lex(); // Eat EndOfStatement token. - return false; -} - -/// parseDirectiveTpRelDWord -/// ::= .tpreldword tls_sym -bool MipsAsmParser::parseDirectiveTpRelDWord() { - MCAsmParser &Parser = getParser(); - const MCExpr *Value; - // EmitTPRel64Value requires an expression, so we are using base class - // method to evaluate the expression. - if (getParser().parseExpression(Value)) - return true; - getParser().getStreamer().EmitTPRel64Value(Value); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), + return Error(getLexer().getLoc(), "unexpected token, expected end of statement"); Parser.Lex(); // Eat EndOfStatement token. return false; @@ -7429,8 +5627,9 @@ bool MipsAsmParser::parseDirectiveOption() { AsmToken Tok = Parser.getTok(); // At the moment only identifiers are supported. if (Tok.isNot(AsmToken::Identifier)) { - return Error(Parser.getTok().getLoc(), - "unexpected token, expected identifier"); + Error(Parser.getTok().getLoc(), "unexpected token, expected identifier"); + Parser.eatToEndOfStatement(); + return false; } StringRef Option = Tok.getIdentifier(); @@ -7442,8 +5641,9 @@ bool MipsAsmParser::parseDirectiveOption() { getTargetStreamer().emitDirectiveOptionPic0(); Parser.Lex(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - return Error(Parser.getTok().getLoc(), - "unexpected token, expected end of statement"); + Error(Parser.getTok().getLoc(), + "unexpected token, expected end of statement"); + Parser.eatToEndOfStatement(); } return false; } @@ -7455,14 +5655,15 @@ bool MipsAsmParser::parseDirectiveOption() { getTargetStreamer().emitDirectiveOptionPic2(); Parser.Lex(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - return Error(Parser.getTok().getLoc(), - "unexpected token, expected end of statement"); + Error(Parser.getTok().getLoc(), + "unexpected token, expected end of statement"); + Parser.eatToEndOfStatement(); } return false; } // Unknown option. - Warning(Parser.getTok().getLoc(), + Warning(Parser.getTok().getLoc(), "unknown option, expected 'pic0' or 'pic2'"); Parser.eatToEndOfStatement(); return false; @@ -7485,54 +5686,12 @@ bool MipsAsmParser::parseInsnDirective() { return false; } -/// parseRSectionDirective -/// ::= .rdata -bool MipsAsmParser::parseRSectionDirective(StringRef Section) { - // 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; - } - - MCSection *ELFSection = getContext().getELFSection( - Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - getParser().getStreamer().SwitchSection(ELFSection); - - getParser().Lex(); // Eat EndOfStatement token. - return false; -} - -/// parseSSectionDirective -/// ::= .sbss -/// ::= .sdata -bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) { - // 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; - } - - MCSection *ELFSection = getContext().getELFSection( - Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL); - getParser().getStreamer().SwitchSection(ELFSection); - - getParser().Lex(); // Eat EndOfStatement token. - return false; -} - /// parseDirectiveModule /// ::= .module oddspreg /// ::= .module nooddspreg /// ::= .module fp=value /// ::= .module softfloat /// ::= .module hardfloat -/// ::= .module mt -/// ::= .module crc -/// ::= .module nocrc -/// ::= .module virt -/// ::= .module novirt -/// ::= .module ginv -/// ::= .module noginv bool MipsAsmParser::parseDirectiveModule() { MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); @@ -7571,7 +5730,8 @@ bool MipsAsmParser::parseDirectiveModule() { return false; // parseDirectiveModule has finished successfully. } else if (Option == "nooddspreg") { if (!isABI_O32()) { - return Error(L, "'.module nooddspreg' requires the O32 ABI"); + Error(L, "'.module nooddspreg' requires the O32 ABI"); + return false; } setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); @@ -7632,139 +5792,6 @@ bool MipsAsmParser::parseDirectiveModule() { } return false; // parseDirectiveModule has finished successfully. - } else if (Option == "mt") { - setModuleFeatureBits(Mips::FeatureMT, "mt"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleMT(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. - } else if (Option == "crc") { - setModuleFeatureBits(Mips::FeatureCRC, "crc"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleCRC(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. - } else if (Option == "nocrc") { - clearModuleFeatureBits(Mips::FeatureCRC, "crc"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleNoCRC(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. - } else if (Option == "virt") { - setModuleFeatureBits(Mips::FeatureVirt, "virt"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleVirt(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. - } else if (Option == "novirt") { - clearModuleFeatureBits(Mips::FeatureVirt, "virt"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleNoVirt(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. - } else if (Option == "ginv") { - setModuleFeatureBits(Mips::FeatureGINV, "ginv"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleGINV(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. - } else if (Option == "noginv") { - clearModuleFeatureBits(Mips::FeatureGINV, "ginv"); - - // Synchronize the ABI Flags information with the FeatureBits information we - // updated above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated ABI Flags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted later). - getTargetStreamer().emitDirectiveModuleNoGINV(); - - // 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; - } - - return false; // parseDirectiveModule has finished successfully. } else { return Error(L, "'" + Twine(Option) + "' is not a valid .module option."); } @@ -7878,20 +5905,15 @@ bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, } bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { - // This returns false if this function recognizes the directive - // regardless of whether it is successfully handles or reports an - // error. Otherwise it returns true to give the generic parser a - // chance at recognizing it. - MCAsmParser &Parser = getParser(); StringRef IDVal = DirectiveID.getString(); - if (IDVal == ".cpload") { - parseDirectiveCpLoad(DirectiveID.getLoc()); - return false; - } - if (IDVal == ".cprestore") { - parseDirectiveCpRestore(DirectiveID.getLoc()); + if (IDVal == ".cpload") + return parseDirectiveCpLoad(DirectiveID.getLoc()); + if (IDVal == ".cprestore") + return parseDirectiveCpRestore(DirectiveID.getLoc()); + if (IDVal == ".dword") { + parseDataDirective(8, DirectiveID.getLoc()); return false; } if (IDVal == ".ent") { @@ -8046,8 +6068,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { } if (IDVal == ".set") { - parseDirectiveSet(); - return false; + return parseDirectiveSet(); } if (IDVal == ".mask" || IDVal == ".fmask") { @@ -8121,72 +6142,39 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (IDVal == ".dtprelword") { - parseDirectiveDtpRelWord(); - return false; - } - - if (IDVal == ".dtpreldword") { - parseDirectiveDtpRelDWord(); + if (IDVal == ".word") { + parseDataDirective(4, DirectiveID.getLoc()); return false; } - if (IDVal == ".tprelword") { - parseDirectiveTpRelWord(); - return false; - } - - if (IDVal == ".tpreldword") { - parseDirectiveTpRelDWord(); - return false; - } - - if (IDVal == ".option") { - parseDirectiveOption(); - return false; - } + if (IDVal == ".option") + return parseDirectiveOption(); if (IDVal == ".abicalls") { getTargetStreamer().emitDirectiveAbiCalls(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), + Error(Parser.getTok().getLoc(), "unexpected token, expected end of statement"); + // Clear line + Parser.eatToEndOfStatement(); } return false; } - if (IDVal == ".cpsetup") { - parseDirectiveCPSetup(); - return false; - } - if (IDVal == ".cpreturn") { - parseDirectiveCPReturn(); - return false; - } - if (IDVal == ".module") { - parseDirectiveModule(); - return false; - } - if (IDVal == ".llvm_internal_mips_reallow_module_directive") { - parseInternalDirectiveReallowModule(); - return false; - } - if (IDVal == ".insn") { - parseInsnDirective(); - return false; - } - if (IDVal == ".rdata") { - parseRSectionDirective(".rodata"); - return false; - } - if (IDVal == ".sbss") { - parseSSectionDirective(IDVal, ELF::SHT_NOBITS); - return false; - } - if (IDVal == ".sdata") { - parseSSectionDirective(IDVal, ELF::SHT_PROGBITS); - return false; - } + if (IDVal == ".cpsetup") + return parseDirectiveCPSetup(); + + if (IDVal == ".cpreturn") + return parseDirectiveCPReturn(); + + if (IDVal == ".module") + return parseDirectiveModule(); + + if (IDVal == ".llvm_internal_mips_reallow_module_directive") + return parseInternalDirectiveReallowModule(); + + if (IDVal == ".insn") + return parseInsnDirective(); return true; } @@ -8205,25 +6193,12 @@ bool MipsAsmParser::parseInternalDirectiveReallowModule() { } extern "C" void LLVMInitializeMipsAsmParser() { - RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget()); - RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget()); - RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target()); - RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget()); + RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget); + RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget); + RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target); + RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget); } #define GET_REGISTER_MATCHER #define GET_MATCHER_IMPLEMENTATION -#define GET_MNEMONIC_SPELL_CHECKER #include "MipsGenAsmMatcher.inc" - -bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) { - // Find the appropriate table for this asm variant. - const MatchEntry *Start, *End; - switch (VariantID) { - default: llvm_unreachable("invalid variant!"); - case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break; - } - // Search the table. - auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode()); - return MnemonicRange.first != MnemonicRange.second; -} diff --git a/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 58f9717e1cc..e5fa7556053 100644 --- a/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -11,37 +11,28 @@ // //===----------------------------------------------------------------------===// -#include "MipsTargetStreamer.h" #include "InstPrinter/MipsInstPrinter.h" -#include "MCTargetDesc/MipsABIInfo.h" #include "MipsELFStreamer.h" -#include "MipsMCExpr.h" #include "MipsMCTargetDesc.h" #include "MipsTargetObjectFile.h" -#include "llvm/BinaryFormat/ELF.h" +#include "MipsTargetStreamer.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" using namespace llvm; -namespace { -static cl::opt<bool> RoundSectionSizes( - "mips-round-section-sizes", cl::init(false), - cl::desc("Round section sizes up to the section alignment"), cl::Hidden); -} // end anonymous namespace - MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) : MCTargetStreamer(S), ModuleDirectiveAllowed(true) { GPRInfoSet = FPRInfoSet = FrameInfoSet = false; } void MipsTargetStreamer::emitDirectiveSetMicroMips() {} void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {} -void MipsTargetStreamer::setUsesMicroMips() {} void MipsTargetStreamer::emitDirectiveSetMips16() {} void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); } @@ -50,14 +41,6 @@ void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMt() {} -void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetCRC() {} -void MipsTargetStreamer::emitDirectiveSetNoCRC() {} -void MipsTargetStreamer::emitDirectiveSetVirt() {} -void MipsTargetStreamer::emitDirectiveSetNoVirt() {} -void MipsTargetStreamer::emitDirectiveSetGINV() {} -void MipsTargetStreamer::emitDirectiveSetNoGINV() {} void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { forbidModuleDirective(); @@ -104,14 +87,11 @@ void MipsTargetStreamer::emitDirectiveSetHardFloat() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} -bool MipsTargetStreamer::emitDirectiveCpRestore( - int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { +void MipsTargetStreamer::emitDirectiveCpRestore( + SmallVector<MCInst, 3> &StoreInsts, int Offset) { forbidModuleDirective(); - return true; } void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) { @@ -127,13 +107,6 @@ void MipsTargetStreamer::emitDirectiveModuleOddSPReg() { } void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {} void MipsTargetStreamer::emitDirectiveModuleHardFloat() {} -void MipsTargetStreamer::emitDirectiveModuleMT() {} -void MipsTargetStreamer::emitDirectiveModuleCRC() {} -void MipsTargetStreamer::emitDirectiveModuleNoCRC() {} -void MipsTargetStreamer::emitDirectiveModuleVirt() {} -void MipsTargetStreamer::emitDirectiveModuleNoVirt() {} -void MipsTargetStreamer::emitDirectiveModuleGINV() {} -void MipsTargetStreamer::emitDirectiveModuleNoGINV() {} void MipsTargetStreamer::emitDirectiveSetFp( MipsABIFlagsSection::FpABIKind Value) { forbidModuleDirective(); @@ -143,236 +116,6 @@ void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() { forbidModuleDirective(); } -void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MCInst TmpInst; - TmpInst.setOpcode(Opcode); - TmpInst.addOperand(MCOperand::createReg(Reg0)); - TmpInst.setLoc(IDLoc); - getStreamer().EmitInstruction(TmpInst, *STI); -} - -void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, - SMLoc IDLoc, const MCSubtargetInfo *STI) { - MCInst TmpInst; - TmpInst.setOpcode(Opcode); - TmpInst.addOperand(MCOperand::createReg(Reg0)); - TmpInst.addOperand(Op1); - TmpInst.setLoc(IDLoc); - getStreamer().EmitInstruction(TmpInst, *STI); -} - -void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, - SMLoc IDLoc, const MCSubtargetInfo *STI) { - emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI); -} - -void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, - SMLoc IDLoc, const MCSubtargetInfo *STI) { - emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI); -} - -void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, - SMLoc IDLoc, const MCSubtargetInfo *STI) { - MCInst TmpInst; - TmpInst.setOpcode(Opcode); - TmpInst.addOperand(MCOperand::createImm(Imm1)); - TmpInst.addOperand(MCOperand::createImm(Imm2)); - TmpInst.setLoc(IDLoc); - getStreamer().EmitInstruction(TmpInst, *STI); -} - -void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, - MCOperand Op2, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MCInst TmpInst; - TmpInst.setOpcode(Opcode); - TmpInst.addOperand(MCOperand::createReg(Reg0)); - TmpInst.addOperand(MCOperand::createReg(Reg1)); - TmpInst.addOperand(Op2); - TmpInst.setLoc(IDLoc); - getStreamer().EmitInstruction(TmpInst, *STI); -} - -void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, - unsigned Reg2, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); -} - -void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, - int16_t Imm, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI); -} - -void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0, - unsigned Reg1, int16_t Imm0, int16_t Imm1, - int16_t Imm2, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MCInst TmpInst; - TmpInst.setOpcode(Opcode); - TmpInst.addOperand(MCOperand::createReg(Reg0)); - TmpInst.addOperand(MCOperand::createReg(Reg1)); - TmpInst.addOperand(MCOperand::createImm(Imm0)); - TmpInst.addOperand(MCOperand::createImm(Imm1)); - TmpInst.addOperand(MCOperand::createImm(Imm2)); - TmpInst.setLoc(IDLoc); - getStreamer().EmitInstruction(TmpInst, *STI); -} - -void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg, - unsigned TrgReg, bool Is64Bit, - const MCSubtargetInfo *STI) { - emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(), - STI); -} - -void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg, - int16_t ShiftAmount, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - if (ShiftAmount >= 32) { - emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI); - return; - } - - emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI); -} - -void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - if (hasShortDelaySlot) - emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI); - else - emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); -} - -void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) { - const FeatureBitset &Features = STI->getFeatureBits(); - if (Features[Mips::FeatureMicroMips]) - emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI); - else - emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); -} - -/// Emit the $gp restore operation for .cprestore. -void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc, - STI); -} - -/// Emit a store instruction with an immediate offset. -void MipsTargetStreamer::emitStoreWithImmOffset( - unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset, - function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - if (isInt<16>(Offset)) { - emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI); - return; - } - - // sw $8, offset($8) => lui $at, %hi(offset) - // add $at, $at, $8 - // sw $8, %lo(offset)($at) - - unsigned ATReg = GetATReg(); - if (!ATReg) - return; - - unsigned LoOffset = Offset & 0x0000ffff; - unsigned HiOffset = (Offset & 0xffff0000) >> 16; - - // If msb of LoOffset is 1(negative number) we must increment HiOffset - // to account for the sign-extension of the low part. - if (LoOffset & 0x8000) - HiOffset++; - - // Generate the base address in ATReg. - emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI); - if (BaseReg != Mips::ZERO) - emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); - // Emit the store with the adjusted base and offset. - emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI); -} - -/// Emit a store instruction with an symbol offset. Symbols are assumed to be -/// out of range for a simm16 will be expanded to appropriate instructions. -void MipsTargetStreamer::emitStoreWithSymOffset( - unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand, - MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - // sw $8, sym => lui $at, %hi(sym) - // sw $8, %lo(sym)($at) - - // Generate the base address in ATReg. - emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI); - if (BaseReg != Mips::ZERO) - emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); - // Emit the store with the adjusted base and offset. - emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI); -} - -/// Emit a load instruction with an immediate offset. DstReg and TmpReg are -/// permitted to be the same register iff DstReg is distinct from BaseReg and -/// DstReg is a GPR. It is the callers responsibility to identify such cases -/// and pass the appropriate register in TmpReg. -void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, - unsigned BaseReg, int64_t Offset, - unsigned TmpReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - if (isInt<16>(Offset)) { - emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI); - return; - } - - // 1) lw $8, offset($9) => lui $8, %hi(offset) - // add $8, $8, $9 - // lw $8, %lo(offset)($9) - // 2) lw $8, offset($8) => lui $at, %hi(offset) - // add $at, $at, $8 - // lw $8, %lo(offset)($at) - - unsigned LoOffset = Offset & 0x0000ffff; - unsigned HiOffset = (Offset & 0xffff0000) >> 16; - - // If msb of LoOffset is 1(negative number) we must increment HiOffset - // to account for the sign-extension of the low part. - if (LoOffset & 0x8000) - HiOffset++; - - // Generate the base address in TmpReg. - emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI); - if (BaseReg != Mips::ZERO) - emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); - // Emit the load with the adjusted base and offset. - emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI); -} - -/// Emit a load instruction with an symbol offset. Symbols are assumed to be -/// out of range for a simm16 will be expanded to appropriate instructions. -/// DstReg and TmpReg are permitted to be the same register iff DstReg is a -/// GPR. It is the callers responsibility to identify such cases and pass the -/// appropriate register in TmpReg. -void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, - unsigned BaseReg, - MCOperand &HiOperand, - MCOperand &LoOperand, - unsigned TmpReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - // 1) lw $8, sym => lui $8, %hi(sym) - // lw $8, %lo(sym)($8) - // 2) ldc1 $f0, sym => lui $at, %hi(sym) - // ldc1 $f0, %lo(sym)($at) - - // Generate the base address in TmpReg. - emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI); - if (BaseReg != Mips::ZERO) - emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); - // Emit the load with the adjusted base and offset. - emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI); -} - MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) : MipsTargetStreamer(S), OS(OS) {} @@ -427,46 +170,6 @@ void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() { MipsTargetStreamer::emitDirectiveSetNoMsa(); } -void MipsTargetAsmStreamer::emitDirectiveSetMt() { - OS << "\t.set\tmt\n"; - MipsTargetStreamer::emitDirectiveSetMt(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoMt() { - OS << "\t.set\tnomt\n"; - MipsTargetStreamer::emitDirectiveSetNoMt(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetCRC() { - OS << "\t.set\tcrc\n"; - MipsTargetStreamer::emitDirectiveSetCRC(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() { - OS << "\t.set\tnocrc\n"; - MipsTargetStreamer::emitDirectiveSetNoCRC(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetVirt() { - OS << "\t.set\tvirt\n"; - MipsTargetStreamer::emitDirectiveSetVirt(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() { - OS << "\t.set\tnovirt\n"; - MipsTargetStreamer::emitDirectiveSetNoVirt(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetGINV() { - OS << "\t.set\tginv\n"; - MipsTargetStreamer::emitDirectiveSetGINV(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() { - OS << "\t.set\tnoginv\n"; - MipsTargetStreamer::emitDirectiveSetNoGINV(); -} - void MipsTargetAsmStreamer::emitDirectiveSetAt() { OS << "\t.set\tat\n"; MipsTargetStreamer::emitDirectiveSetAt(); @@ -609,11 +312,6 @@ void MipsTargetAsmStreamer::emitDirectiveSetDsp() { MipsTargetStreamer::emitDirectiveSetDsp(); } -void MipsTargetAsmStreamer::emitDirectiveSetDspr2() { - OS << "\t.set\tdspr2\n"; - MipsTargetStreamer::emitDirectiveSetDspr2(); -} - void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() { OS << "\t.set\tnodsp\n"; MipsTargetStreamer::emitDirectiveSetNoDsp(); @@ -666,12 +364,10 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) { forbidModuleDirective(); } -bool MipsTargetAsmStreamer::emitDirectiveCpRestore( - int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); +void MipsTargetAsmStreamer::emitDirectiveCpRestore( + SmallVector<MCInst, 3> &StoreInsts, int Offset) { + MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset); OS << "\t.cprestore\t" << Offset << "\n"; - return true; } void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -736,48 +432,12 @@ void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() { OS << "\t.module\thardfloat\n"; } -void MipsTargetAsmStreamer::emitDirectiveModuleMT() { - OS << "\t.module\tmt\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleCRC() { - OS << "\t.module\tcrc\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() { - OS << "\t.module\tnocrc\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleVirt() { - OS << "\t.module\tvirt\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() { - OS << "\t.module\tnovirt\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleGINV() { - OS << "\t.module\tginv\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() { - OS << "\t.module\tnoginv\n"; -} - // This part is for ELF object output. MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { MCAssembler &MCA = getStreamer().getAssembler(); - - // It's possible that MCObjectFileInfo isn't fully initialized at this point - // due to an initialization order problem where LLVMTargetMachine creates the - // target streamer before TargetLoweringObjectFile calls - // InitializeMCObjectFileInfo. There doesn't seem to be a single place that - // covers all cases so this statement covers most cases and direct object - // emission must call setPic() once MCObjectFileInfo has been initialized. The - // cases we don't handle here are covered by MipsAsmPrinter. - Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent(); + Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; const FeatureBitset &Features = STI.getFeatureBits(); @@ -794,17 +454,6 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, // issues as well. unsigned EFlags = MCA.getELFHeaderEFlags(); - // FIXME: Fix a dependency issue by instantiating the ABI object to some - // default based off the triple. The triple doesn't describe the target - // fully, but any external user of the API that uses the MCTargetStreamer - // would otherwise crash on assertion failure. - - ABI = MipsABIInfo( - STI.getTargetTriple().getArch() == Triple::ArchType::mipsel || - STI.getTargetTriple().getArch() == Triple::ArchType::mips - ? MipsABIInfo::O32() - : MipsABIInfo::N64()); - // Architecture if (Features[Mips::FeatureMips64r6]) EFlags |= ELF::EF_MIPS_ARCH_64R6; @@ -833,26 +482,27 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, else EFlags |= ELF::EF_MIPS_ARCH_1; - // Machine - if (Features[Mips::FeatureCnMips]) - EFlags |= ELF::EF_MIPS_MACH_OCTEON; - // Other options. if (Features[Mips::FeatureNaN2008]) EFlags |= ELF::EF_MIPS_NAN2008; + // -mabicalls and -mplt are not implemented but we should act as if they were + // given. + EFlags |= ELF::EF_MIPS_CPIC; + MCA.setELFHeaderEFlags(EFlags); } void MipsTargetELFStreamer::emitLabel(MCSymbol *S) { auto *Symbol = cast<MCSymbolELF>(S); + if (!isMicroMipsEnabled()) + return; getStreamer().getAssembler().registerSymbol(*Symbol); uint8_t Type = Symbol->getType(); if (Type != ELF::STT_FUNC) return; - if (isMicroMipsEnabled()) - Symbol->setOther(ELF::STO_MIPS_MICROMIPS); + Symbol->setOther(ELF::STO_MIPS_MICROMIPS); } void MipsTargetELFStreamer::finish() { @@ -871,26 +521,6 @@ void MipsTargetELFStreamer::finish() { DataSection.setAlignment(std::max(16u, DataSection.getAlignment())); BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment())); - if (RoundSectionSizes) { - // Make sections sizes a multiple of the alignment. This is useful for - // verifying the output of IAS against the output of other assemblers but - // it's not necessary to produce a correct object and increases section - // size. - MCStreamer &OS = getStreamer(); - for (MCSection &S : MCA) { - MCSectionELF &Section = static_cast<MCSectionELF &>(S); - - unsigned Alignment = Section.getAlignment(); - if (Alignment) { - OS.SwitchSection(&Section); - if (Section.UseCodeAlign()) - OS.EmitCodeAlignment(Alignment, Alignment); - else - OS.EmitValueToAlignment(Alignment, 0, 1, Alignment); - } - } - } - const FeatureBitset &Features = STI.getFeatureBits(); // Update e_header flags. See the FIXME and comment above in @@ -910,13 +540,10 @@ void MipsTargetELFStreamer::finish() { } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64]) EFlags |= ELF::EF_MIPS_32BITMODE; - // -mplt is not implemented but we should act as if it was - // given. - if (!Features[Mips::FeatureNoABICalls]) - EFlags |= ELF::EF_MIPS_CPIC; - - if (Pic) - EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; + // If we've set the cpic eflag and we're n64, go ahead and set the pic + // one as well. + if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64()) + EFlags |= ELF::EF_MIPS_PIC; MCA.setELFHeaderEFlags(EFlags); @@ -949,6 +576,11 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() { void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { MicroMipsEnabled = true; + + MCAssembler &MCA = getStreamer().getAssembler(); + unsigned Flags = MCA.getELFHeaderEFlags(); + Flags |= ELF::EF_MIPS_MICROMIPS; + MCA.setELFHeaderEFlags(Flags); forbidModuleDirective(); } @@ -957,13 +589,6 @@ void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { forbidModuleDirective(); } -void MipsTargetELFStreamer::setUsesMicroMips() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Flags |= ELF::EF_MIPS_MICROMIPS; - MCA.setELFHeaderEFlags(Flags); -} - void MipsTargetELFStreamer::emitDirectiveSetMips16() { MCAssembler &MCA = getStreamer().getAssembler(); unsigned Flags = MCA.getELFHeaderEFlags(); @@ -985,7 +610,8 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { MCContext &Context = MCA.getContext(); MCStreamer &OS = getStreamer(); - MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0); + MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHT_REL); MCSymbol *Sym = Context.getOrCreateSymbol(Name); const MCSymbolRefExpr *ExprRef = @@ -1022,10 +648,10 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { const MCExpr *Size = MCBinaryExpr::createSub( MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context), ExprRef, Context); - - // The ELFObjectWriter can determine the absolute size as it has access to - // the layout information of the assembly file, so a size expression rather - // than an absolute value is ok here. + int64_t AbsSize; + if (!Size->evaluateAsAbsolute(AbsSize, MCA)) + llvm_unreachable("Function size must be evaluatable as absolute"); + Size = MCConstantExpr::create(AbsSize, Context); static_cast<MCSymbolELF *>(Sym)->setSize(Size); } @@ -1134,11 +760,8 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { MCInst TmpInst; TmpInst.setOpcode(Mips::LUi); TmpInst.addOperand(MCOperand::createReg(Mips::GP)); - const MCExpr *HiSym = MipsMCExpr::create( - MipsMCExpr::MEK_HI, - MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, - MCA.getContext()), - MCA.getContext()); + const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create( + "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext()); TmpInst.addOperand(MCOperand::createExpr(HiSym)); getStreamer().EmitInstruction(TmpInst, STI); @@ -1147,11 +770,8 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { TmpInst.setOpcode(Mips::ADDiu); TmpInst.addOperand(MCOperand::createReg(Mips::GP)); TmpInst.addOperand(MCOperand::createReg(Mips::GP)); - const MCExpr *LoSym = MipsMCExpr::create( - MipsMCExpr::MEK_LO, - MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, - MCA.getContext()), - MCA.getContext()); + const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::create( + "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext()); TmpInst.addOperand(MCOperand::createExpr(LoSym)); getStreamer().EmitInstruction(TmpInst, STI); @@ -1166,10 +786,9 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { forbidModuleDirective(); } -bool MipsTargetELFStreamer::emitDirectiveCpRestore( - int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); +void MipsTargetELFStreamer::emitDirectiveCpRestore( + SmallVector<MCInst, 3> &StoreInsts, int Offset) { + MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset); // .cprestore offset // When PIC mode is enabled and the O32 ABI is used, this directive expands // to: @@ -1179,12 +798,10 @@ bool MipsTargetELFStreamer::emitDirectiveCpRestore( // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it // is used in non-PIC mode. if (!Pic || (getABI().IsN32() || getABI().IsN64())) - return true; + return; - // Store the $gp on the stack. - emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc, - STI); - return true; + for (const MCInst &Inst : StoreInsts) + getStreamer().EmitInstruction(Inst, STI); } void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -1195,55 +812,54 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, if (!Pic || !(getABI().IsN32() || getABI().IsN64())) return; - forbidModuleDirective(); - MCAssembler &MCA = getStreamer().getAssembler(); MCInst Inst; // Either store the old $gp in a register or on the stack if (IsReg) { // move $save, $gpreg - emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI); + Inst.setOpcode(Mips::OR64); + Inst.addOperand(MCOperand::createReg(RegOrOffset)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); } else { // sd $gpreg, offset($sp) - emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI); - } - - if (getABI().IsN32()) { - MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp"); - const MipsMCExpr *HiExpr = MipsMCExpr::create( - MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()), - MCA.getContext()); - const MipsMCExpr *LoExpr = MipsMCExpr::create( - MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()), - MCA.getContext()); - - // lui $gp, %hi(__gnu_local_gp) - emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); - - // addiu $gp, $gp, %lo(__gnu_local_gp) - emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), - SMLoc(), &STI); - - return; + Inst.setOpcode(Mips::SD); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::SP)); + Inst.addOperand(MCOperand::createImm(RegOrOffset)); } + getStreamer().EmitInstruction(Inst, STI); + Inst.clear(); - const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff( - MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()), - MCA.getContext()); - const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff( - MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()), - MCA.getContext()); + const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create( + &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext()); + const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create( + &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext()); // lui $gp, %hi(%neg(%gp_rel(funcSym))) - emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); + Inst.setOpcode(Mips::LUi); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createExpr(HiExpr)); + getStreamer().EmitInstruction(Inst, STI); + Inst.clear(); // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) - emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), - SMLoc(), &STI); + Inst.setOpcode(Mips::ADDiu); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createExpr(LoExpr)); + getStreamer().EmitInstruction(Inst, STI); + Inst.clear(); // daddu $gp, $gp, $funcreg - emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI); + Inst.setOpcode(Mips::DADDu); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(RegNo)); + getStreamer().EmitInstruction(Inst, STI); + + forbidModuleDirective(); } void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, diff --git a/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td b/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td index 5729182deaf..6b09cfa4c73 100644 --- a/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -15,6 +15,19 @@ // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// +// Unsigned Operand +def uimm16_64 : Operand<i64> { + let PrintMethod = "printUnsignedImm"; +} + +// Signed Operand +def simm10_64 : Operand<i64>; + +// Transformation Function - get Imm - 32. +def Subtract32 : SDNodeXForm<imm, [{ + return getImm(N, (unsigned)N->getZExtValue() - 32); +}]>; + // shamt must fit in 6 bits. def immZExt6 : ImmLeaf<i32, [{return Imm == (Imm & 0x3f);}]>; @@ -24,7 +37,7 @@ def immSExt10_64 : PatLeaf<(i64 imm), [{ return isInt<10>(N->getSExtValue()); }]>; def immZExt16_64 : PatLeaf<(i64 imm), - [{ return isUInt<16>(N->getZExtValue()); }]>; + [{ return isInt<16>(N->getZExtValue()); }]>; def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>; @@ -58,19 +71,6 @@ def PowerOf2HI : PatLeaf<(imm), [{ return false; }]>; -def PowerOf2LO_i32 : PatLeaf<(imm), [{ - if (N->getValueType(0) == MVT::i32) { - uint64_t Imm = N->getZExtValue(); - return isPowerOf2_32(Imm) && isUInt<32>(Imm); - } - else - return false; -}]>; - -def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ - return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLT(MVT::i32); -}]>; - //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -85,19 +85,8 @@ let usesCustomInserter = 1 in { def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap<atomic_cmp_swap_64, GPR64>; } -def ATOMIC_LOAD_ADD_I64_POSTRA : Atomic2OpsPostRA<GPR64>; -def ATOMIC_LOAD_SUB_I64_POSTRA : Atomic2OpsPostRA<GPR64>; -def ATOMIC_LOAD_AND_I64_POSTRA : Atomic2OpsPostRA<GPR64>; -def ATOMIC_LOAD_OR_I64_POSTRA : Atomic2OpsPostRA<GPR64>; -def ATOMIC_LOAD_XOR_I64_POSTRA : Atomic2OpsPostRA<GPR64>; -def ATOMIC_LOAD_NAND_I64_POSTRA : Atomic2OpsPostRA<GPR64>; - -def ATOMIC_SWAP_I64_POSTRA : Atomic2OpsPostRA<GPR64>; - -def ATOMIC_CMP_SWAP_I64_POSTRA : AtomicCmpSwapPostRA<GPR64>; - /// Pseudo instructions for loading and storing accumulator registers. -let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { +let isPseudo = 1, isCodeGenOnly = 1 in { def LOAD_ACC128 : Load<"", ACC128>; def STORE_ACC128 : Store<"", ACC128>; } @@ -107,122 +96,97 @@ let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { //===----------------------------------------------------------------------===// let DecoderNamespace = "Mips64" in { /// Arithmetic Instructions (ALU Immediate) -def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd, II_DADDI>, - ADDI_FM<0x18>, ISA_MIPS3_NOT_32R6_64R6; -let AdditionalPredicates = [NotInMicroMips] in { - def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU, - immSExt16, add>, - ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3; -} +def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd>, ADDI_FM<0x18>, + ISA_MIPS3_NOT_32R6_64R6; +def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU, + immSExt16, add>, + ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3; let isCodeGenOnly = 1 in { def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>, - SLTI_FM<0xa>, GPR_64; + SLTI_FM<0xa>; def SLTiu64 : SetCC_I<"sltiu", setult, simm16_64, immSExt16, GPR64Opnd>, - SLTI_FM<0xb>, GPR_64; + SLTI_FM<0xb>; def ANDi64 : ArithLogicI<"andi", uimm16_64, GPR64Opnd, II_AND, immZExt16, and>, - ADDI_FM<0xc>, GPR_64; + ADDI_FM<0xc>; def ORi64 : ArithLogicI<"ori", uimm16_64, GPR64Opnd, II_OR, immZExt16, or>, - ADDI_FM<0xd>, GPR_64; + ADDI_FM<0xd>; def XORi64 : ArithLogicI<"xori", uimm16_64, GPR64Opnd, II_XOR, immZExt16, xor>, - ADDI_FM<0xe>, GPR_64; -def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM, GPR_64; + ADDI_FM<0xe>; +def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64>, LUI_FM; } /// Arithmetic Instructions (3-Operand, R-Type) -let AdditionalPredicates = [NotInMicroMips] in { - def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>, - ISA_MIPS3; - def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>, - ADD_FM<0, 0x2d>, ISA_MIPS3; - def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, - ADD_FM<0, 0x2f>, ISA_MIPS3; - def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>, - ISA_MIPS3; -} +def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>, + ISA_MIPS3; +def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>, ADD_FM<0, 0x2d>, + ISA_MIPS3; +def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, ADD_FM<0, 0x2f>, + ISA_MIPS3; +def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>, + ISA_MIPS3; let isCodeGenOnly = 1 in { -def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>, GPR_64; -def SLTu64 : SetCC_R<"sltu", setult, GPR64Opnd>, ADD_FM<0, 0x2b>, GPR_64; -def AND64 : ArithLogicR<"and", GPR64Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>, - GPR_64; -def OR64 : ArithLogicR<"or", GPR64Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>, - GPR_64; -def XOR64 : ArithLogicR<"xor", GPR64Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>, - GPR_64; -def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>, GPR_64; +def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>; +def SLTu64 : SetCC_R<"sltu", setult, GPR64Opnd>, ADD_FM<0, 0x2b>; +def AND64 : ArithLogicR<"and", GPR64Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>; +def OR64 : ArithLogicR<"or", GPR64Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; +def XOR64 : ArithLogicR<"xor", GPR64Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; +def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>; } /// Shift Instructions -let AdditionalPredicates = [NotInMicroMips] in { - def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl, - immZExt6>, +def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl, immZExt6>, SRA_FM<0x38, 0>, ISA_MIPS3; - def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl, - immZExt6>, +def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl, immZExt6>, SRA_FM<0x3a, 0>, ISA_MIPS3; - def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra, - immZExt6>, +def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra, immZExt6>, SRA_FM<0x3b, 0>, ISA_MIPS3; - def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>, - SRLV_FM<0x14, 0>, ISA_MIPS3; - def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>, - SRLV_FM<0x17, 0>, ISA_MIPS3; - def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>, - SRLV_FM<0x16, 0>, ISA_MIPS3; - def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>, - SRA_FM<0x3c, 0>, ISA_MIPS3; - def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>, - SRA_FM<0x3e, 0>, ISA_MIPS3; - def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>, - SRA_FM<0x3f, 0>, ISA_MIPS3; +def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>, + SRLV_FM<0x14, 0>, ISA_MIPS3; +def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>, + SRLV_FM<0x16, 0>, ISA_MIPS3; +def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>, + SRLV_FM<0x17, 0>, ISA_MIPS3; +def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>, + SRA_FM<0x3c, 0>, ISA_MIPS3; +def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>, + SRA_FM<0x3e, 0>, ISA_MIPS3; +def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>, + SRA_FM<0x3f, 0>, ISA_MIPS3; // Rotate Instructions - def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr, - immZExt6>, - SRA_FM<0x3a, 1>, ISA_MIPS64R2; - def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>, - SRLV_FM<0x16, 1>, ISA_MIPS64R2; - def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>, - SRA_FM<0x3e, 1>, ISA_MIPS64R2; -} +def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr, + immZExt6>, + SRA_FM<0x3a, 1>, ISA_MIPS64R2; +def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>, + SRLV_FM<0x16, 1>, ISA_MIPS64R2; +def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>, + SRA_FM<0x3e, 1>, ISA_MIPS64R2; /// Load and Store Instructions /// aligned let isCodeGenOnly = 1 in { -def LB64 : Load<"lb", GPR64Opnd, sextloadi8, II_LB>, LW_FM<0x20>, GPR_64; -def LBu64 : Load<"lbu", GPR64Opnd, zextloadi8, II_LBU>, LW_FM<0x24>, GPR_64; -def LH64 : Load<"lh", GPR64Opnd, sextloadi16, II_LH>, LW_FM<0x21>, GPR_64; -def LHu64 : Load<"lhu", GPR64Opnd, zextloadi16, II_LHU>, LW_FM<0x25>, GPR_64; -def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>, GPR_64; -def SB64 : Store<"sb", GPR64Opnd, truncstorei8, II_SB>, LW_FM<0x28>, GPR_64; -def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>, - GPR_64; -def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>, - GPR_64; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def LWu : MMRel, Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, - LW_FM<0x27>, ISA_MIPS3; - def LD : LoadMemory<"ld", GPR64Opnd, mem_simmptr, load, II_LD>, - LW_FM<0x37>, ISA_MIPS3; - def SD : StoreMemory<"sd", GPR64Opnd, mem_simmptr, store, II_SD>, - LW_FM<0x3f>, ISA_MIPS3; +def LB64 : Load<"lb", GPR64Opnd, sextloadi8, II_LB>, LW_FM<0x20>; +def LBu64 : Load<"lbu", GPR64Opnd, zextloadi8, II_LBU>, LW_FM<0x24>; +def LH64 : Load<"lh", GPR64Opnd, sextloadi16, II_LH>, LW_FM<0x21>; +def LHu64 : Load<"lhu", GPR64Opnd, zextloadi16, II_LHU>, LW_FM<0x25>; +def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>; +def SB64 : Store<"sb", GPR64Opnd, truncstorei8, II_SB>, LW_FM<0x28>; +def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>; +def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>; } - +def LWu : Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, LW_FM<0x27>, ISA_MIPS3; +def LD : Load<"ld", GPR64Opnd, load, II_LD>, LW_FM<0x37>, ISA_MIPS3; +def SD : Store<"sd", GPR64Opnd, store, II_SD>, LW_FM<0x3f>, ISA_MIPS3; /// load/store left/right let isCodeGenOnly = 1 in { -def LWL64 : LoadLeftRight<"lwl", MipsLWL, GPR64Opnd, II_LWL>, LW_FM<0x22>, - GPR_64; -def LWR64 : LoadLeftRight<"lwr", MipsLWR, GPR64Opnd, II_LWR>, LW_FM<0x26>, - GPR_64; -def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>, - GPR_64; -def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>, - GPR_64; +def LWL64 : LoadLeftRight<"lwl", MipsLWL, GPR64Opnd, II_LWL>, LW_FM<0x22>; +def LWR64 : LoadLeftRight<"lwr", MipsLWR, GPR64Opnd, II_LWR>, LW_FM<0x26>; +def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>; +def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>; } def LDL : LoadLeftRight<"ldl", MipsLDL, GPR64Opnd, II_LDL>, LW_FM<0x1a>, @@ -235,81 +199,39 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>, ISA_MIPS3_NOT_32R6_64R6; /// Load-linked, Store-conditional -let AdditionalPredicates = [NotInMicroMips] in { - def LLD : LLBase<"lld", GPR64Opnd, mem_simmptr>, LW_FM<0x34>, - ISA_MIPS3_NOT_32R6_64R6; -} +def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6; def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6; -let AdditionalPredicates = [NotInMicroMips], - DecoderNamespace = "Mips32_64_PTR64" in { -def LL64 : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_64, - ISA_MIPS2_NOT_32R6_64R6; -def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64, - ISA_MIPS2_NOT_32R6_64R6; -def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>, PTR_64; -} - -def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM; - /// Jump and Branch Instructions let isCodeGenOnly = 1 in { - def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>, - GPR_64; - def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>, - GPR_64; - def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>, - GPR_64; - def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>, - GPR_64; - def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>, - GPR_64; - def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>, - GPR_64; - let AdditionalPredicates = [NoIndirectJumpGuards] in - def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>; -} -let AdditionalPredicates = [NotInMicroMips], - DecoderNamespace = "Mips64" in { - def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; - def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS32R2; -} -def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>; - -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - NoIndirectJumpGuards] in { - def TAILCALLREG64 : TailCallReg<JR64, GPR64Opnd>, ISA_MIPS3_NOT_32R6_64R6, - PTR_64; - def PseudoIndirectBranch64 : PseudoIndirectBranchBase<JR64, GPR64Opnd>, - ISA_MIPS3_NOT_32R6_64R6; + def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>; + def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>; + def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>; + def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>; + def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>; + def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>; + def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>; + def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM; + def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>; + def TAILCALL64_R : TailCallReg<GPR64Opnd, JR, GPR32Opnd>; } -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - UseIndirectJumpsHazard] in { - def TAILCALLREGHB64 : TailCallReg<JR_HB64, GPR64Opnd>, - ISA_MIPS32R2_NOT_32R6_64R6, PTR_64; - def PseudoIndirectHazardBranch64 : PseudoIndirectBranchBase<JR_HB64, - GPR64Opnd>, - ISA_MIPS32R2_NOT_32R6_64R6; -} +def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>; +def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>; /// Multiply and Divide Instructions. -let AdditionalPredicates = [NotInMicroMips] in { - def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6; - def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6; -} +def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6; +def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6; def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult, II_DMULT>, ISA_MIPS3_NOT_32R6_64R6; def PseudoDMULTu : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu, II_DMULTU>, ISA_MIPS3_NOT_32R6_64R6; -let AdditionalPredicates = [NotInMicroMips] in { - def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6; - def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6; -} +def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6; +def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6; def PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem, II_DDIV, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6; def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU, @@ -338,101 +260,57 @@ def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>, } /// Count Leading -let AdditionalPredicates = [NotInMicroMips] in { - def DCLZ : CountLeading0<"dclz", GPR64Opnd, II_DCLZ>, CLO_FM<0x24>, - ISA_MIPS64_NOT_64R6; - def DCLO : CountLeading1<"dclo", GPR64Opnd, II_DCLO>, CLO_FM<0x25>, - ISA_MIPS64_NOT_64R6; +def DCLZ : CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>, ISA_MIPS64_NOT_64R6; +def DCLO : CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>, ISA_MIPS64_NOT_64R6; /// Double Word Swap Bytes/HalfWords - def DSBH : SubwordSwap<"dsbh", GPR64Opnd, II_DSBH>, SEB_FM<2, 0x24>, - ISA_MIPS64R2; - def DSHD : SubwordSwap<"dshd", GPR64Opnd, II_DSHD>, SEB_FM<5, 0x24>, - ISA_MIPS64R2; +def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>, ISA_MIPS64R2; +def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>, ISA_MIPS64R2; - def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>, - GPR_64; -} +def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>; let isCodeGenOnly = 1 in -def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM, GPR_64; +def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM; let AdditionalPredicates = [NotInMicroMips] in { - // The 'pos + size' constraints for code generation are enforced by the - // code that lowers into MipsISD::Ext. - // For assembly parsing, we alias dextu and dextm to dext, and match by - // operand were possible then check the 'pos + size' in MipsAsmParser. - // We override the generated decoder to enforce that dext always comes out - // for dextm and dextu like binutils. - let DecoderMethod = "DecodeDEXT" in { - def DEXT : ExtBase<"dext", GPR64Opnd, uimm5_report_uimm6, - uimm5_plus1_report_uimm6, immZExt5, immZExt5Plus1, - MipsExt>, EXT_FM<3>, ISA_MIPS64R2; - def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, immZExt5, - immZExt5Plus33, MipsExt>, EXT_FM<1>, ISA_MIPS64R2; - def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1, - immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>, - ISA_MIPS64R2; - } - // The 'pos + size' constraints for code generation are enforced by the - // code that lowers into MipsISD::Ins. - // For assembly parsing, we alias dinsu and dinsm to dins, and match by - // operand were possible then check the 'pos + size' in MipsAsmParser. - // We override the generated decoder to enforce that dins always comes out - // for dinsm and dinsu like binutils. - let DecoderMethod = "DecodeDINS" in { - def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1, - immZExt5, immZExt5Plus1>, EXT_FM<7>, - ISA_MIPS64R2; - def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1, - immZExt5Plus32, immZExt5Plus1>, - EXT_FM<6>, ISA_MIPS64R2; - def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64, - immZExt5, immZExtRange2To64>, - EXT_FM<5>, ISA_MIPS64R2; - } + // TODO: Add 'pos + size' constraint check to dext* instructions + // DEXT: 0 < pos + size <= 63 + // DEXTM, DEXTU: 32 < pos + size <= 64 + def DEXT : ExtBase<"dext", GPR64Opnd, uimm5, uimm5_plus1, MipsExt>, + EXT_FM<3>; + def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, MipsExt>, + EXT_FM<1>; + def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1, + MipsExt>, EXT_FM<2>; } -let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in { - def DEXT64_32 : InstSE<(outs GPR64Opnd:$rt), - (ins GPR32Opnd:$rs, uimm5_report_uimm6:$pos, - uimm5_plus1:$size), - "dext $rt, $rs, $pos, $size", [], II_EXT, FrmR, "dext">, - EXT_FM<3>, ISA_MIPS64R2; -} +def DINS : InsBase<"dins", GPR64Opnd, uimm6, MipsIns>, EXT_FM<7>; +def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32>, EXT_FM<6>; +def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5>, EXT_FM<5>; let isCodeGenOnly = 1, rs = 0, shamt = 0 in { def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt), - "dsll\t$rd, $rt, 32", [], II_DSLL>, GPR_64; - let isMoveReg = 1 in { - def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt), - "sll\t$rd, $rt, 0", [], II_SLL>, GPR_64; - def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt), - "sll\t$rd, $rt, 0", [], II_SLL>, GPR_64; - } + "dsll\t$rd, $rt, 32", [], II_DSLL>; + def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt), + "sll\t$rd, $rt, 0", [], II_SLL>; + def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt), + "sll\t$rd, $rt, 0", [], II_SLL>; } // We need the following pseudo instruction to avoid offset calculation for // long branches. See the comment in file MipsLongBranch.cpp for detailed // explanation. -// Expands to: lui $dst, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_LUi2Op_64 : PseudoSE<(outs GPR64Opnd:$dst), - (ins brtarget:$tgt), []>, GPR_64; -// Expands to: addiu $dst, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_DADDiu2Op : PseudoSE<(outs GPR64Opnd:$dst), - (ins GPR64Opnd:$src, brtarget:$tgt), []>, GPR_64; - // Expands to: daddiu $dst, $src, %PART($tgt - $baltgt) // where %PART may be %hi or %lo, depending on the relocation kind // that $tgt is annotated with. def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst), - (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, GPR_64; + (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; // Cavium Octeon cnMIPS instructions let DecoderNamespace = "CnMips", - // FIXME: The lack of HasStdEnc is probably a bug - EncodingPredicates = []<Predicate> in { + EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug + AdditionalPredicates = [HasCnMips] in { class Count1s<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), @@ -440,12 +318,11 @@ class Count1s<string opstr, RegisterOperand RO>: let TwoOperandAliasConstraint = "$rd = $rs"; } -class ExtsCins<string opstr, InstrItinClass itin, RegisterOperand RO, - PatFrag PosImm, SDPatternOperator Op = null_frag>: - InstSE<(outs RO:$rt), (ins RO:$rs, uimm5:$pos, uimm5:$lenm1), - !strconcat(opstr, "\t$rt, $rs, $pos, $lenm1"), - [(set RO:$rt, (Op RO:$rs, PosImm:$pos, imm:$lenm1))], - itin, FrmR, opstr> { +class ExtsCins<string opstr, SDPatternOperator Op = null_frag>: + InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, uimm5:$pos, uimm5:$lenm1), + !strconcat(opstr, " $rt, $rs, $pos, $lenm1"), + [(set GPR64Opnd:$rt, (Op GPR64Opnd:$rs, imm:$pos, imm:$lenm1))], + NoItinerary, FrmR, opstr> { let TwoOperandAliasConstraint = "$rt = $rs"; } @@ -479,444 +356,250 @@ class CBranchBitNum<string opstr, DAGOperand opnd, PatFrag cond_op, let Defs = [AT]; } -class MFC2OP<string asmstr, RegisterOperand RO, InstrItinClass itin> : +class MFC2OP<string asmstr, RegisterOperand RO> : InstSE<(outs RO:$rt, uimm16:$imm16), (ins), - !strconcat(asmstr, "\t$rt, $imm16"), [], itin, FrmFR>; + !strconcat(asmstr, "\t$rt, $imm16"), [], NoItinerary, FrmFR>; // Unsigned Byte Add +let Pattern = [(set GPR64Opnd:$rd, + (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))] in def BADDu : ArithLogicR<"baddu", GPR64Opnd, 1, II_BADDU>, - ADD_FM<0x1c, 0x28>, ASE_CNMIPS { - let Pattern = [(set GPR64Opnd:$rd, - (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))]; -} + ADD_FM<0x1c, 0x28>; // Branch on Bit Clear /+32 def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd, - uimm5_64_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS; + uimm5_64_report_uimm6>, BBIT_FM<0x32>; def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS; + 0x100000000>, + BBIT_FM<0x36>; // Branch on Bit Set /+32 def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd, - uimm5_64_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS; + uimm5_64_report_uimm6>, BBIT_FM<0x3a>; def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS; + 0x100000000>, BBIT_FM<0x3e>; // Multiply Doubleword to GPR +let Defs = [HI0, LO0, P0, P1, P2] in def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, - ADD_FM<0x1c, 0x03>, ASE_CNMIPS { - let Defs = [HI0, LO0, P0, P1, P2]; -} + ADD_FM<0x1c, 0x03>; -let AdditionalPredicates = [NotInMicroMips] in { - // Extract a signed bit field /+32 - def EXTS : ExtsCins<"exts", II_EXT, GPR64Opnd, immZExt5>, EXTS_FM<0x3a>, - ASE_MIPS64_CNMIPS; - def EXTS32: ExtsCins<"exts32", II_EXT, GPR64Opnd, immZExt5Plus32>, - EXTS_FM<0x3b>, ASE_MIPS64_CNMIPS; - - // Clear and insert a bit field /+32 - def CINS : ExtsCins<"cins", II_INS, GPR64Opnd, immZExt5, MipsCIns>, - EXTS_FM<0x32>, ASE_MIPS64_CNMIPS; - def CINS32: ExtsCins<"cins32", II_INS, GPR64Opnd, immZExt5Plus32, MipsCIns>, - EXTS_FM<0x33>, ASE_MIPS64_CNMIPS; - let isCodeGenOnly = 1 in { - def CINS_i32 : ExtsCins<"cins", II_INS, GPR32Opnd, immZExt5, MipsCIns>, - EXTS_FM<0x32>, ASE_MIPS64_CNMIPS; - def CINS64_32 :InstSE<(outs GPR64Opnd:$rt), - (ins GPR32Opnd:$rs, uimm5:$pos, uimm5:$lenm1), - "cins\t$rt, $rs, $pos, $lenm1", [], II_INS, FrmR, - "cins">, - EXTS_FM<0x32>, ASE_MIPS64_CNMIPS; - } -} +// Extract a signed bit field /+32 +def EXTS : ExtsCins<"exts">, EXTS_FM<0x3a>; +def EXTS32: ExtsCins<"exts32">, EXTS_FM<0x3b>; + +// Clear and insert a bit field /+32 +def CINS : ExtsCins<"cins">, EXTS_FM<0x32>; +def CINS32: ExtsCins<"cins32">, EXTS_FM<0x33>; // Move to multiplier/product register -def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>, - ASE_CNMIPS; -def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>, - ASE_CNMIPS; -def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>, - ASE_CNMIPS; -def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>, ASE_CNMIPS; -def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>, ASE_CNMIPS; -def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>, ASE_CNMIPS; +def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>; +def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>; +def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>; +def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>; +def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>; +def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>; // Count Ones in a Word/Doubleword -def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>, ASE_CNMIPS; -def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>, ASE_CNMIPS; +def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>; +def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>; // Set on equal/not equal -def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>, ASE_CNMIPS; -def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>, ASE_CNMIPS; -def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>, ASE_CNMIPS; -def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>, ASE_CNMIPS; +def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>; +def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>; +def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>; +def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>; // 192-bit x 64-bit Unsigned Multiply and Add -def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x11>, - ASE_CNMIPS { - let Defs = [P0, P1, P2]; -} +let Defs = [P0, P1, P2] in +def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>, + ADD_FM<0x1c, 0x11>; // 64-bit Unsigned Multiply and Add Move -def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x10>, - ASE_CNMIPS { - let Defs = [MPL0, P0, P1, P2]; -} +let Defs = [MPL0, P0, P1, P2] in +def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>, + ADD_FM<0x1c, 0x10>; // 64-bit Unsigned Multiply and Add -def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x0f>, - ASE_CNMIPS { - let Defs = [MPL1, MPL2, P0, P1, P2]; -} +let Defs = [MPL1, MPL2, P0, P1, P2] in +def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, + ADD_FM<0x1c, 0x0f>; // Move between CPU and coprocessor registers -def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd, II_DMFC2>, MFC2OP_FM<0x12, 1>, - ASE_CNMIPS; -def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd, II_DMTC2>, MFC2OP_FM<0x12, 5>, - ASE_CNMIPS; +def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd>, MFC2OP_FM<0x12, 1>; +def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd>, MFC2OP_FM<0x12, 5>; } } /// Move between CPU and coprocessor registers let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { -def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, - MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3; -def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, - MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3; -def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, - MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3; -def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, - MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3; +def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd>, MFC3OP_FM<0x10, 1>, ISA_MIPS3; +def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3; +def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3; +def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3; } -/// Move between CPU and guest coprocessor registers (Virtualization ASE) -let DecoderNamespace = "Mips64" in { - def DMFGC0 : MFC3OP<"dmfgc0", GPR64Opnd, COP0Opnd, II_DMFGC0>, - MFC3OP_FM<0x10, 3, 1>, ISA_MIPS64R5, ASE_VIRT; - def DMTGC0 : MTC3OP<"dmtgc0", COP0Opnd, GPR64Opnd, II_DMTGC0>, - MFC3OP_FM<0x10, 3, 3>, ISA_MIPS64R5, ASE_VIRT; -} - -let AdditionalPredicates = [UseIndirectJumpsHazard] in - def JALRHB64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR_HB64, RA_64>; - //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// -// Materialize i64 constants. -defm : MaterializeImms<i64, ZERO_64, DADDiu, LUi64, ORi64>, ISA_MIPS3, GPR_64; - -def : MipsPat<(i64 immZExt32Low16Zero:$imm), - (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16)>, ISA_MIPS3, GPR_64; - -def : MipsPat<(i64 immZExt32:$imm), - (ORi64 (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16), - (LO16 imm:$imm))>, ISA_MIPS3, GPR_64; - // extended loads -def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3, - GPR_64; -def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3, - GPR_64; -def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>, ISA_MIPS3, - GPR_64; -def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>, ISA_MIPS3, - GPR_64; +def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>; +def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>; +def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>; +def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>; // hi/lo relocs -let AdditionalPredicates = [NotInMicroMips] in -defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, ISA_MIPS3, GPR_64, - SYM_32; - -def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>, ISA_MIPS3, - GPR_64; -def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>, - ISA_MIPS3, GPR_64; - -def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>, - ISA_MIPS3, GPR_64; - -// highest/higher/hi/lo relocs -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)), - (JAL texternalsym:$dst)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)), - (LUi64 tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHighest (i64 tblockaddress:$in)), - (LUi64 tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHighest (i64 tjumptable:$in)), - (LUi64 tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHighest (i64 tconstpool:$in)), - (LUi64 tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHighest (i64 texternalsym:$in)), - (LUi64 texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64; - - def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)), - (DADDiu ZERO_64, tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHigher (i64 tblockaddress:$in)), - (DADDiu ZERO_64, tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHigher (i64 tjumptable:$in)), - (DADDiu ZERO_64, tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHigher (i64 tconstpool:$in)), - (DADDiu ZERO_64, tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(MipsHigher (i64 texternalsym:$in)), - (DADDiu ZERO_64, texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64; - - def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tblockaddress:$lo))), - (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64, - SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tjumptable:$lo))), - (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))), - (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - - def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tblockaddress:$lo))), - (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64, - SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tjumptable:$lo))), - (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))), - (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - - def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tblockaddress:$lo))), - (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64, - SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tjumptable:$lo))), - (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tconstpool:$lo))), - (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MIPS3, GPR_64, - SYM_64; -} +def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; +def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>; +def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>; +def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; +def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; +def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>; + +def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; +def : MipsPat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>; +def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; +def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; +def : MipsPat<(MipsLo tglobaltlsaddr:$in), + (DADDiu ZERO_64, tglobaltlsaddr:$in)>; +def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>; + +def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), + (DADDiu GPR64:$hi, tglobaladdr:$lo)>; +def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), + (DADDiu GPR64:$hi, tblockaddress:$lo)>; +def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), + (DADDiu GPR64:$hi, tjumptable:$lo)>; +def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), + (DADDiu GPR64:$hi, tconstpool:$lo)>; +def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), + (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>; + +def : WrapperPat<tglobaladdr, DADDiu, GPR64>; +def : WrapperPat<tconstpool, DADDiu, GPR64>; +def : WrapperPat<texternalsym, DADDiu, GPR64>; +def : WrapperPat<tblockaddress, DADDiu, GPR64>; +def : WrapperPat<tjumptable, DADDiu, GPR64>; +def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; + +defm : BrcondPats<GPR64, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, + ZERO_64>; -// gp_rel relocs -def : MipsPat<(add GPR64:$gp, (MipsGPRel tglobaladdr:$in)), - (DADDiu GPR64:$gp, tglobaladdr:$in)>, ISA_MIPS3, ABI_N64; -def : MipsPat<(add GPR64:$gp, (MipsGPRel tconstpool:$in)), - (DADDiu GPR64:$gp, tconstpool:$in)>, ISA_MIPS3, ABI_N64; - -def : WrapperPat<tglobaladdr, DADDiu, GPR64>, ISA_MIPS3, GPR_64; -def : WrapperPat<tconstpool, DADDiu, GPR64>, ISA_MIPS3, GPR_64; -def : WrapperPat<texternalsym, DADDiu, GPR64>, ISA_MIPS3, GPR_64; -def : WrapperPat<tblockaddress, DADDiu, GPR64>, ISA_MIPS3, GPR_64; -def : WrapperPat<tjumptable, DADDiu, GPR64>, ISA_MIPS3, GPR_64; -def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>, ISA_MIPS3, GPR_64; - - -defm : BrcondPats<GPR64, BEQ64, BEQ, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, - ZERO_64>, ISA_MIPS3, GPR_64; def : MipsPat<(brcond (i32 (setlt i64:$lhs, 1)), bb:$dst), - (BLEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64; + (BLEZ64 i64:$lhs, bb:$dst)>; def : MipsPat<(brcond (i32 (setgt i64:$lhs, -1)), bb:$dst), - (BGEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64; + (BGEZ64 i64:$lhs, bb:$dst)>; // setcc patterns -let AdditionalPredicates = [NotInMicroMips] in { - defm : SeteqPats<GPR64, SLTiu64, XOR64, SLTu64, ZERO_64>, ISA_MIPS3, GPR_64; - defm : SetlePats<GPR64, XORi, SLT64, SLTu64>, ISA_MIPS3, GPR_64; - defm : SetgtPats<GPR64, SLT64, SLTu64>, ISA_MIPS3, GPR_64; - defm : SetgePats<GPR64, XORi, SLT64, SLTu64>, ISA_MIPS3, GPR_64; - defm : SetgeImmPats<GPR64, XORi, SLTi64, SLTiu64>, ISA_MIPS3, GPR_64; -} +defm : SeteqPats<GPR64, SLTiu64, XOR64, SLTu64, ZERO_64>; +defm : SetlePats<GPR64, SLT64, SLTu64>; +defm : SetgtPats<GPR64, SLT64, SLTu64>; +defm : SetgePats<GPR64, SLT64, SLTu64>; +defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>; + // truncate def : MipsPat<(trunc (assertsext GPR64:$src)), - (EXTRACT_SUBREG GPR64:$src, sub_32)>, ISA_MIPS3, GPR_64; -// The forward compatibility strategy employed by MIPS requires us to treat -// values as being sign extended to an infinite number of bits. This allows -// existing software to run without modification on any future MIPS -// implementation (e.g. 128-bit, or 1024-bit). Being compatible with this -// strategy requires that truncation acts as a sign-extension for values being -// fed into instructions operating on 32-bit values. Such instructions have -// undefined results if this is not true. -// For our case, this means that we can't issue an extract_subreg for nodes -// such as (trunc:i32 (assertzext:i64 X, i32)), because the sign-bit of the -// lower subreg would not be replicated into the upper half. -def : MipsPat<(trunc (assertzext_lt_i32 GPR64:$src)), - (EXTRACT_SUBREG GPR64:$src, sub_32)>, ISA_MIPS3, GPR_64; + (EXTRACT_SUBREG GPR64:$src, sub_32)>; +def : MipsPat<(trunc (assertzext GPR64:$src)), + (EXTRACT_SUBREG GPR64:$src, sub_32)>; def : MipsPat<(i32 (trunc GPR64:$src)), - (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>, ISA_MIPS3, GPR_64; + (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; // variable shift instructions patterns def : MipsPat<(shl GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; + (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; def : MipsPat<(srl GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; + (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; def : MipsPat<(sra GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; + (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; + (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; // 32-to-64-bit extension def : MipsPat<(i64 (anyext GPR32:$src)), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>, - ISA_MIPS3, GPR_64; -def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>, - ISA_MIPS3, GPR_64; -def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>, ISA_MIPS3, - GPR_64; - -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(i64 (zext GPR32:$src)), (DEXT64_32 GPR32:$src, 0, 32)>, - ISA_MIPS64R2, GPR_64; - def : MipsPat<(i64 (zext (i32 (shl GPR32:$rt, immZExt5:$imm)))), - (CINS64_32 GPR32:$rt, imm:$imm, (immZExt5To31 imm:$imm))>, - ISA_MIPS64R2, GPR_64, ASE_MIPS64_CNMIPS; -} + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>; +def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>; +def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>; // Sign extend in register def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), - (SLL64_64 GPR64:$src)>, ISA_MIPS3, GPR_64; + (SLL64_64 GPR64:$src)>; // bswap MipsPattern -def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>, ISA_MIPS64R2; +def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>; // Carry pattern -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), - (DSUBu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, GPR_64; +def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), + (DSUBu GPR64:$lhs, GPR64:$rhs)>; +let AdditionalPredicates = [NotDSP] in { def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), - (DADDu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64; + (DADDu GPR64:$lhs, GPR64:$rhs)>; def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm), - (DADDiu GPR64:$lhs, imm:$imm)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64; + (DADDiu GPR64:$lhs, imm:$imm)>; } // Octeon bbit0/bbit1 MipsPattern +let Predicates = [HasMips64, HasCnMips] in { def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), - (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, - ISA_MIPS64R2, ASE_MIPS64_CNMIPS; + (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), - (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, - ISA_MIPS64R2, ASE_MIPS64_CNMIPS; + (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), - (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, - ISA_MIPS64R2, ASE_MIPS64_CNMIPS; + (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), - (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, - ISA_MIPS64R2, ASE_MIPS64_CNMIPS; -def : MipsPat<(brcond (i32 (seteq (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst), - (BBIT0 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), i32:$lhs, sub_32), - (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ISA_MIPS64R2, - ASE_MIPS64_CNMIPS; -def : MipsPat<(brcond (i32 (setne (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst), - (BBIT1 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), i32:$lhs, sub_32), - (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ISA_MIPS64R2, - ASE_MIPS64_CNMIPS; + (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; +} // Atomic load patterns. -def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>, ISA_MIPS3, GPR_64; -def : MipsPat<(atomic_load_16 addr:$a), (LH64 addr:$a)>, ISA_MIPS3, GPR_64; -def : MipsPat<(atomic_load_32 addr:$a), (LW64 addr:$a)>, ISA_MIPS3, GPR_64; -def : MipsPat<(atomic_load_64 addr:$a), (LD addr:$a)>, ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>; +def : MipsPat<(atomic_load_16 addr:$a), (LH64 addr:$a)>; +def : MipsPat<(atomic_load_32 addr:$a), (LW64 addr:$a)>; +def : MipsPat<(atomic_load_64 addr:$a), (LD addr:$a)>; // Atomic store patterns. -def : MipsPat<(atomic_store_8 addr:$a, GPR64:$v), (SB64 GPR64:$v, addr:$a)>, - ISA_MIPS3, GPR_64; -def : MipsPat<(atomic_store_16 addr:$a, GPR64:$v), (SH64 GPR64:$v, addr:$a)>, - ISA_MIPS3, GPR_64; -def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>, - ISA_MIPS3, GPR_64; -def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>, - ISA_MIPS3, GPR_64; - -// Patterns used for matching away redundant sign extensions. -// MIPS32 arithmetic instructions sign extend their result implicitly. -def : MipsPat<(i64 (sext (i32 (add GPR32:$src, immSExt16:$imm16)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (ADDiu GPR32:$src, immSExt16:$imm16), sub_32)>; -def : MipsPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (ADDu GPR32:$src, GPR32:$src2), sub_32)>; -def : MipsPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SUBu GPR32:$src, GPR32:$src2), sub_32)>; -def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MUL GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS3_NOT_32R6_64R6; -def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (PseudoMFHI ACC64:$src), sub_32)>; -def : MipsPat<(i64 (sext (i32 (MipsMFLO ACC64:$src)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (PseudoMFLO ACC64:$src), sub_32)>; -def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, immZExt5:$imm5)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SLL GPR32:$src, immZExt5:$imm5), sub_32)>; -def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SLLV GPR32:$src, GPR32:$src2), sub_32)>; -def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, immZExt5:$imm5)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SRL GPR32:$src, immZExt5:$imm5), sub_32)>; -def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SRLV GPR32:$src, GPR32:$src2), sub_32)>; -def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, immZExt5:$imm5)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SRA GPR32:$src, immZExt5:$imm5), sub_32)>; -def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (SRAV GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(atomic_store_8 addr:$a, GPR64:$v), (SB64 GPR64:$v, addr:$a)>; +def : MipsPat<(atomic_store_16 addr:$a, GPR64:$v), (SH64 GPR64:$v, addr:$a)>; +def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>; +def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>; //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"move $dst, $src", - (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, - GPR_64; - def : MipsInstAlias<"move $dst, $src", - (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, - GPR_64; - def : MipsInstAlias<"dadd $rs, $rt, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"dadd $rs, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"daddu $rs, $rt, $imm", - (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), - 0>, ISA_MIPS3; - def : MipsInstAlias<"daddu $rs, $imm", - (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), - 0>, ISA_MIPS3; - - defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi64, GPR64Opnd, imm64>, - ISA_MIPS3, GPR_64; - - defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi64, GPR64Opnd, imm64>, - ISA_MIPS3, GPR_64; - - defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi64, GPR64Opnd, imm64>, - ISA_MIPS3, GPR_64; -} -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"dneg $rt, $rs", - (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, - ISA_MIPS3; - def : MipsInstAlias<"dneg $rt", - (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 1>, - ISA_MIPS3; - def : MipsInstAlias<"dnegu $rt, $rs", - (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, - ISA_MIPS3; - def : MipsInstAlias<"dnegu $rt", - (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 1>, - ISA_MIPS3; -} +def : MipsInstAlias<"move $dst, $src", + (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, + GPR_64; +def : MipsInstAlias<"move $dst, $src", + (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, + GPR_64; +def : MipsInstAlias<"daddu $rs, $rt, $imm", + (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), + 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>, ISA_MIPS3; +def : MipsInstAlias<"dadd $rs, $imm", + (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), + 0>, ISA_MIPS3_NOT_32R6_64R6; +def : MipsInstAlias<"dsll $rd, $rt, $rs", + (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, + ISA_MIPS3; +def : MipsInstAlias<"dneg $rt, $rs", + (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, + ISA_MIPS3; +def : MipsInstAlias<"dneg $rt", + (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>, + ISA_MIPS3; +def : MipsInstAlias<"dnegu $rt, $rs", + (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, + ISA_MIPS3; +def : MipsInstAlias<"dsubu $rt, $rs, $imm", + (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs, + InvertedImOperand64:$imm), 0>, ISA_MIPS3; def : MipsInstAlias<"dsubi $rs, $rt, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, InvertedImOperand64:$imm), @@ -933,63 +616,29 @@ def : MipsInstAlias<"dsub $rs, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, InvertedImOperand64:$imm), 0>, ISA_MIPS3_NOT_32R6_64R6; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"dsubu $rt, $rs, $imm", - (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs, - InvertedImOperand64:$imm), 0>, ISA_MIPS3; - def : MipsInstAlias<"dsubu $rs, $imm", - (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, - InvertedImOperand64:$imm), 0>, ISA_MIPS3; -} +def : MipsInstAlias<"dsubu $rs, $imm", + (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, + InvertedImOperand64:$imm), + 0>, ISA_MIPS3; def : MipsInstAlias<"dsra $rd, $rt, $rs", (DSRAV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"dsll $rd, $rt, $rs", - (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, - ISA_MIPS3; - def : MipsInstAlias<"dsrl $rd, $rt, $rs", - (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, - ISA_MIPS3; - def : MipsInstAlias<"dsrl $rd, $rt", - (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>, - ISA_MIPS3; - def : MipsInstAlias<"dsll $rd, $rt", - (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>, - ISA_MIPS3; - def : MipsInstAlias<"dins $rt, $rs, $pos, $size", - (DINSM GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos, - uimm_range_2_64:$size), 0>, ISA_MIPS64R2; - def : MipsInstAlias<"dins $rt, $rs, $pos, $size", - (DINSU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos, - uimm5_plus1:$size), 0>, ISA_MIPS64R2; - def : MipsInstAlias<"dext $rt, $rs, $pos, $size", - (DEXTM GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos, - uimm5_plus33:$size), 0>, ISA_MIPS64R2; - def : MipsInstAlias<"dext $rt, $rs, $pos, $size", - (DEXTU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos, - uimm5_plus1:$size), 0>, ISA_MIPS64R2; - def : MipsInstAlias<"jalr.hb $rs", (JALR_HB64 RA_64, GPR64Opnd:$rs), 1>, - ISA_MIPS64; +def : MipsInstAlias<"dsrl $rd, $rt, $rs", + (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, + ISA_MIPS3; + // Two operand (implicit 0 selector) versions: - def : MipsInstAlias<"dmtc0 $rt, $rd", - (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>; - def : MipsInstAlias<"dmfc0 $rt, $rd", - (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>; - def : MipsInstAlias<"dmfgc0 $rt, $rd", - (DMFGC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>, - ISA_MIPS64R5, ASE_VIRT; - def : MipsInstAlias<"dmtgc0 $rt, $rd", - (DMTGC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>, - ISA_MIPS64R5, ASE_VIRT; -} +def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>; +def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>; def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>; -def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>, ASE_MIPS64_CNMIPS; -def : MipsInstAlias<"syncs", (SYNC 0x6), 0>, ASE_MIPS64_CNMIPS; -def : MipsInstAlias<"syncw", (SYNC 0x4), 0>, ASE_MIPS64_CNMIPS; -def : MipsInstAlias<"syncws", (SYNC 0x5), 0>, ASE_MIPS64_CNMIPS; +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>; +} // cnMIPS Aliases. @@ -1007,21 +656,21 @@ def : MipsInstAlias<"bbit1 $rs, $p, $offset", def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1", (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_CNMIPS; + ASE_CNMIPS; def : MipsInstAlias<"exts $rt, $pos, $lenm1", (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_CNMIPS; + ASE_CNMIPS; // cins with $pos 32-63 in converted to cins32 with $pos 0-31 def : MipsInstAlias<"cins $rt, $rs, $pos, $lenm1", (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_CNMIPS; + ASE_CNMIPS; def : MipsInstAlias<"cins $rt, $pos, $lenm1", (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_CNMIPS; + ASE_CNMIPS; //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions @@ -1036,116 +685,3 @@ def LoadAddrReg64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins mem:$addr), "dla\t$rt, $addr">; def LoadAddrImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins imm64:$imm64), "dla\t$rt, $imm64">; - -def DMULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - simm32_relaxed:$imm), - "dmul\t$rs, $rt, $imm">, - ISA_MIPS3_NOT_32R6_64R6; -def DMULOMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - GPR64Opnd:$rd), - "dmulo\t$rs, $rt, $rd">, - ISA_MIPS3_NOT_32R6_64R6; -def DMULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - GPR64Opnd:$rd), - "dmulou\t$rs, $rt, $rd">, - ISA_MIPS3_NOT_32R6_64R6; - -def DMULMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, - GPR64Opnd:$rd), - "dmul\t$rs, $rt, $rd"> { - let InsnPredicates = [HasMips3, NotMips64r6, NotCnMips]; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def DSDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, GPR64Opnd:$rt), - "ddiv\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; - def DSDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "ddiv\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; - def DUDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, GPR64Opnd:$rt), - "ddivu\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; - def DUDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "ddivu\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; - - // GAS expands 'div' and 'ddiv' differently when the destination - // register is $zero and the instruction is in the two operand - // form. 'ddiv' gets expanded, while 'div' is not expanded. - - def : MipsInstAlias<"ddiv $rs, $rt", (DSDivMacro GPR64Opnd:$rs, - GPR64Opnd:$rs, - GPR64Opnd:$rt), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"ddiv $rd, $imm", (DSDivIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - imm64:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; - - // GAS expands 'divu' and 'ddivu' differently when the destination - // register is $zero and the instruction is in the two operand - // form. 'ddivu' gets expanded, while 'divu' is not expanded. - - def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR64Opnd:$rt, - GPR64Opnd:$rt, - GPR64Opnd:$rs), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"ddivu $rd, $imm", (DUDivIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - imm64:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def DSRemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, GPR64Opnd:$rt), - "drem\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; - def DSRemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, simm32_relaxed:$imm), - "drem\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; - def DURemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, GPR64Opnd:$rt), - "dremu\t$rd, $rs, $rt">, - ISA_MIPS3_NOT_32R6_64R6; - def DURemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, simm32_relaxed:$imm), - "dremu\t$rd, $rs, $imm">, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"drem $rt, $rs", (DSRemMacro GPR64Opnd:$rt, - GPR64Opnd:$rt, - GPR64Opnd:$rs), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"drem $rd, $imm", (DSRemIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - simm32_relaxed:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"dremu $rt, $rs", (DURemMacro GPR64Opnd:$rt, - GPR64Opnd:$rt, - GPR64Opnd:$rs), 0>, - ISA_MIPS3_NOT_32R6_64R6; - def : MipsInstAlias<"dremu $rd, $imm", (DURemIMacro GPR64Opnd:$rd, - GPR64Opnd:$rd, - simm32_relaxed:$imm), 0>, - ISA_MIPS3_NOT_32R6_64R6; -} - -def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64; -def : MipsInstAlias<"nor\t$rs, $imm", (NORImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, - imm64:$imm)>, GPR_64; -def SLTImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs), - (ins GPR64Opnd:$rt, imm64:$imm), - "slt\t$rs, $rt, $imm">, GPR_64; -def : MipsInstAlias<"slt\t$rs, $imm", (SLTImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, - imm64:$imm)>, GPR_64; -def SLTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs), - (ins GPR64Opnd:$rt, imm64:$imm), - "sltu\t$rs, $rt, $imm">, GPR_64; -def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, - imm64:$imm)>, GPR_64; - -def : MipsInstAlias<"rdhwr $rt, $rs", - (RDHWR64 GPR64Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, GPR_64; diff --git a/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td b/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td index 46721e6cb9e..8977bf1212f 100644 --- a/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -21,7 +21,7 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisInt<4>]>; -def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; def SDT_MFLOHI : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVT<1, untyped>]>; def SDT_MTLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, @@ -59,22 +59,16 @@ def MipsTailCall : SDNode<"MipsISD::TailCall", SDT_MipsJmpLink, // Hi and Lo nodes are used to handle global addresses. Used on // MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol // static model. (nothing to do with Mips Registers Hi and Lo) - -// Hi is the odd node out, on MIPS64 it can expand to either daddiu when -// using static relocations with 64 bit symbols, or lui when using 32 bit -// symbols. -def MipsHigher : SDNode<"MipsISD::Higher", SDTIntUnaryOp>; -def MipsHighest : SDNode<"MipsISD::Highest", SDTIntUnaryOp>; def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; - def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>; -// Hi node for accessing the GOT. -def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>; +// TlsGd node is used to handle General Dynamic TLS +def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>; -// Hi node for handling TLS offsets -def MipsTlsHi : SDNode<"MipsISD::TlsHi", SDTIntUnaryOp>; +// TprelHi and TprelLo nodes are used to handle Local Exec TLS +def MipsTprelHi : SDNode<"MipsISD::TprelHi", SDTIntUnaryOp>; +def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>; // Thread pointer def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; @@ -134,7 +128,6 @@ def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain,SDNPSideEffect]>; def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>; def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>; -def MipsCIns : SDNode<"MipsISD::CIns", SDT_Ext>; def MipsLWL : SDNode<"MipsISD::LWL", SDTMipsLoadLR, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; @@ -164,8 +157,6 @@ def HasMips3_32r2 : Predicate<"Subtarget->hasMips3_32r2()">, AssemblerPredicate<"FeatureMips3_32r2">; def HasMips3 : Predicate<"Subtarget->hasMips3()">, AssemblerPredicate<"FeatureMips3">; -def NotMips3 : Predicate<"!Subtarget->hasMips3()">, - AssemblerPredicate<"!FeatureMips3">; def HasMips4_32 : Predicate<"Subtarget->hasMips4_32()">, AssemblerPredicate<"FeatureMips4_32">; def NotMips4_32 : Predicate<"!Subtarget->hasMips4_32()">, @@ -188,38 +179,26 @@ def IsGP64bit : Predicate<"Subtarget->isGP64bit()">, AssemblerPredicate<"FeatureGP64Bit">; def IsGP32bit : Predicate<"!Subtarget->isGP64bit()">, AssemblerPredicate<"!FeatureGP64Bit">; -def IsPTR64bit : Predicate<"Subtarget->isABI_N64()">, - AssemblerPredicate<"FeaturePTR64Bit">; -def IsPTR32bit : Predicate<"!Subtarget->isABI_N64()">, - AssemblerPredicate<"!FeaturePTR64Bit">; def HasMips64 : Predicate<"Subtarget->hasMips64()">, AssemblerPredicate<"FeatureMips64">; def NotMips64 : Predicate<"!Subtarget->hasMips64()">, AssemblerPredicate<"!FeatureMips64">; def HasMips64r2 : Predicate<"Subtarget->hasMips64r2()">, AssemblerPredicate<"FeatureMips64r2">; -def HasMips64r5 : Predicate<"Subtarget->hasMips64r5()">, - AssemblerPredicate<"FeatureMips64r5">; def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">, AssemblerPredicate<"FeatureMips64r6">; def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">, AssemblerPredicate<"!FeatureMips64r6">; +def HasMicroMips32r6 : Predicate<"Subtarget->inMicroMips32r6Mode()">, + AssemblerPredicate<"FeatureMicroMips,FeatureMips32r6">; +def HasMicroMips64r6 : Predicate<"Subtarget->inMicroMips64r6Mode()">, + AssemblerPredicate<"FeatureMicroMips,FeatureMips64r6">; def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; -def NotInMips16Mode : Predicate<"!Subtarget->inMips16Mode()">, - AssemblerPredicate<"!FeatureMips16">; def HasCnMips : Predicate<"Subtarget->hasCnMips()">, AssemblerPredicate<"FeatureCnMips">; -def NotCnMips : Predicate<"!Subtarget->hasCnMips()">, - AssemblerPredicate<"!FeatureCnMips">; -def IsSym32 : Predicate<"Subtarget->HasSym32()">, - AssemblerPredicate<"FeatureSym32">; -def IsSym64 : Predicate<"!Subtarget->HasSym32()">, - AssemblerPredicate<"!FeatureSym32">; -def IsN64 : Predicate<"Subtarget->isABI_N64()">; -def IsNotN64 : Predicate<"!Subtarget->isABI_N64()">; -def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">; -def RelocPIC : Predicate<"TM.isPositionIndependent()">; +def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; +def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; @@ -233,26 +212,11 @@ def IsBE : Predicate<"!Subtarget->isLittle()">; def IsNotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; def UseTCCInDIV : AssemblerPredicate<"FeatureUseTCCInDIV">; def HasEVA : Predicate<"Subtarget->hasEVA()">, - AssemblerPredicate<"FeatureEVA">; + AssemblerPredicate<"FeatureEVA,FeatureMips32r2">; def HasMSA : Predicate<"Subtarget->hasMSA()">, AssemblerPredicate<"FeatureMSA">; -def HasMadd4 : Predicate<"!Subtarget->disableMadd4()">, - AssemblerPredicate<"!FeatureMadd4">; -def HasMT : Predicate<"Subtarget->hasMT()">, - AssemblerPredicate<"FeatureMT">; -def UseIndirectJumpsHazard : Predicate<"Subtarget->useIndirectJumpsHazard()">, - AssemblerPredicate<"FeatureUseIndirectJumpsHazard">; -def NoIndirectJumpGuards : Predicate<"!Subtarget->useIndirectJumpsHazard()">, - AssemblerPredicate<"!FeatureUseIndirectJumpsHazard">; -def HasCRC : Predicate<"Subtarget->hasCRC()">, - AssemblerPredicate<"FeatureCRC">; -def HasVirt : Predicate<"Subtarget->hasVirt()">, - AssemblerPredicate<"FeatureVirt">; -def HasGINV : Predicate<"Subtarget->hasGINV()">, - AssemblerPredicate<"FeatureGINV">; -// TODO: Add support for FPOpFusion::Standard -def AllowFPOpFusion : Predicate<"TM.Options.AllowFPOpFusion ==" - " FPOpFusion::Fast">; + + //===----------------------------------------------------------------------===// // Mips GPR size adjectives. // They are mutually exclusive. @@ -261,17 +225,6 @@ def AllowFPOpFusion : Predicate<"TM.Options.AllowFPOpFusion ==" class GPR_32 { list<Predicate> GPRPredicates = [IsGP32bit]; } class GPR_64 { list<Predicate> GPRPredicates = [IsGP64bit]; } -class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; } -class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; } - -//===----------------------------------------------------------------------===// -// Mips Symbol size adjectives. -// They are mutally exculsive. -//===----------------------------------------------------------------------===// - -class SYM_32 { list<Predicate> SYMPredicates = [IsSym32]; } -class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; } - //===----------------------------------------------------------------------===// // Mips ISA/ASE membership and instruction group membership adjectives. // They are mutually exclusive. @@ -282,226 +235,109 @@ class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; } // 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 { - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS1_NOT_MIPS3 { - list<Predicate> InsnPredicates = [NotMips3]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} class ISA_MIPS1_NOT_4_32 { list<Predicate> InsnPredicates = [NotMips4_32]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } class ISA_MIPS1_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS2 { - list<Predicate> InsnPredicates = [HasMips2]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS2 { list<Predicate> InsnPredicates = [HasMips2]; } class ISA_MIPS2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS3 { - list<Predicate> InsnPredicates = [HasMips3]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS3 { list<Predicate> InsnPredicates = [HasMips3]; } class ISA_MIPS3_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS32 { - list<Predicate> InsnPredicates = [HasMips32]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS32 { list<Predicate> InsnPredicates = [HasMips32]; } class ISA_MIPS32_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips32, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS32R2 { - list<Predicate> InsnPredicates = [HasMips32r2]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS32R2 { list<Predicate> InsnPredicates = [HasMips32r2]; } class ISA_MIPS32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips32r2, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS32R5 { - list<Predicate> InsnPredicates = [HasMips32r5]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS64 { - list<Predicate> InsnPredicates = [HasMips64]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } +class ISA_MIPS32R5 { list<Predicate> InsnPredicates = [HasMips32r5]; } +class ISA_MIPS64 { list<Predicate> InsnPredicates = [HasMips64]; } class ISA_MIPS64_NOT_64R6 { list<Predicate> InsnPredicates = [HasMips64, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS64R2 { - list<Predicate> InsnPredicates = [HasMips64r2]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS64R5 { - list<Predicate> InsnPredicates = [HasMips64r5]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS32R6 { - list<Predicate> InsnPredicates = [HasMips32r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MIPS64R6 { - list<Predicate> InsnPredicates = [HasMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} -class ISA_MICROMIPS { - list<Predicate> EncodingPredicates = [InMicroMips]; -} -class ISA_MICROMIPS32R5 { - list<Predicate> InsnPredicates = [HasMips32r5]; - list<Predicate> EncodingPredicates = [InMicroMips]; } +class ISA_MIPS64R2 { list<Predicate> InsnPredicates = [HasMips64r2]; } +class ISA_MIPS32R6 { list<Predicate> InsnPredicates = [HasMips32r6]; } +class ISA_MIPS64R6 { list<Predicate> InsnPredicates = [HasMips64r6]; } +class ISA_MICROMIPS { list<Predicate> InsnPredicates = [InMicroMips]; } class ISA_MICROMIPS32R6 { - list<Predicate> InsnPredicates = [HasMips32r6]; - list<Predicate> EncodingPredicates = [InMicroMips]; + list<Predicate> InsnPredicates = [HasMicroMips32r6]; } class ISA_MICROMIPS64R6 { - list<Predicate> InsnPredicates = [HasMips64r6]; - list<Predicate> EncodingPredicates = [InMicroMips]; + list<Predicate> InsnPredicates = [HasMicroMips64r6]; } class ISA_MICROMIPS32_NOT_MIPS32R6 { - list<Predicate> InsnPredicates = [NotMips32r6]; - list<Predicate> EncodingPredicates = [InMicroMips]; + list<Predicate> InsnPredicates = [InMicroMips, NotMips32r6]; } -class ASE_EVA { list<Predicate> ASEPredicate = [HasEVA]; } -// The portions of MIPS-III that were also added to MIPS32 -class INSN_MIPS3_32 { - list<Predicate> InsnPredicates = [HasMips3_32]; - list<Predicate> EncodingPredicates = [HasStdEnc]; +class INSN_EVA { list<Predicate> InsnPredicates = [HasEVA]; } +class INSN_EVA_NOT_32R6_64R6 { + list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6, HasEVA]; } +// The portions of MIPS-III that were also added to MIPS32 +class INSN_MIPS3_32 { list<Predicate> InsnPredicates = [HasMips3_32]; } + // The portions of MIPS-III that were also added to MIPS32 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS3_32_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips3_32, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-III that were also added to MIPS32 -class INSN_MIPS3_32R2 { - list<Predicate> InsnPredicates = [HasMips3_32r2]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} - -// The portions of MIPS-IV that were also added to MIPS32. -class INSN_MIPS4_32 { - list <Predicate> InsnPredicates = [HasMips4_32]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} +class INSN_MIPS3_32R2 { list<Predicate> InsnPredicates = [HasMips3_32r2]; } // The portions of MIPS-IV that were also added to MIPS32 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS4_32_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips4_32, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-IV that were also added to MIPS32r2 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS4_32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips4_32r2, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} - -// The portions of MIPS-IV that were also added to MIPS32r2. -class INSN_MIPS4_32R2 { - list<Predicate> InsnPredicates = [HasMips4_32r2]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-V that were also added to MIPS32r2 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS5_32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips5_32r2, NotMips32r6, NotMips64r6]; - list<Predicate> EncodingPredicates = [HasStdEnc]; } class ASE_CNMIPS { - list<Predicate> ASEPredicate = [HasCnMips]; -} - -class NOT_ASE_CNMIPS { - list<Predicate> ASEPredicate = [NotCnMips]; -} - -class ASE_MIPS64_CNMIPS { - list<Predicate> ASEPredicate = [HasMips64, HasCnMips]; + list<Predicate> InsnPredicates = [HasCnMips]; } class ASE_MSA { - list<Predicate> ASEPredicate = [HasMSA]; + list<Predicate> InsnPredicates = [HasMSA]; } class ASE_MSA_NOT_MSA64 { - list<Predicate> ASEPredicate = [HasMSA, NotMips64]; + list<Predicate> InsnPredicates = [HasMSA, NotMips64]; } class ASE_MSA64 { - list<Predicate> ASEPredicate = [HasMSA, HasMips64]; -} - -class ASE_MT { - list <Predicate> ASEPredicate = [HasMT]; -} - -class ASE_CRC { - list <Predicate> ASEPredicate = [HasCRC]; -} - -class ASE_VIRT { - list <Predicate> ASEPredicate = [HasVirt]; -} - -class ASE_GINV { - list <Predicate> ASEPredicate = [HasGINV]; + list<Predicate> InsnPredicates = [HasMSA, HasMips64]; } // Class used for separating microMIPSr6 and microMIPS (r3) instruction. // It can be used only on instructions that doesn't inherit PredicateControl. -class ISA_MICROMIPS_NOT_32R6 : PredicateControl { - let InsnPredicates = [NotMips32r6]; - let EncodingPredicates = [InMicroMips]; -} - -class ASE_NOT_DSP { - list<Predicate> ASEPredicate = [NotDSP]; -} - -class MADD4 { - list<Predicate> AdditionalPredicates = [HasMadd4]; -} - -// Classses used for separating expansions that differ based on the ABI in -// use. -class ABI_N64 { - list<Predicate> AdditionalPredicates = [IsN64]; -} - -class ABI_NOT_N64 { - list<Predicate> AdditionalPredicates = [IsNotN64]; -} - -class FPOP_FUSION_FAST { - list <Predicate> AdditionalPredicates = [AllowFPOpFusion]; +class ISA_MICROMIPS_NOT_32R6_64R6 : PredicateControl { + let InsnPredicates = [InMicroMips, NotMips32r6, NotMips64r6]; } //===----------------------------------------------------------------------===// -class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl; +class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl { + let EncodingPredicates = [HasStdEnc]; +} class MipsInstAlias<string Asm, dag Result, bit Emit = 0b1> : InstAlias<Asm, Result, Emit>, PredicateControl; @@ -512,17 +348,14 @@ class IsCommutable { class IsBranch { bit isBranch = 1; - bit isCTI = 1; } class IsReturn { bit isReturn = 1; - bit isCTI = 1; } class IsCall { bit isCall = 1; - bit isCTI = 1; } class IsTailCall { @@ -532,7 +365,6 @@ class IsTailCall { bit isBarrier = 1; bit hasExtraSrcRegAllocReq = 1; bit isCodeGenOnly = 1; - bit isCTI = 1; } class IsAsCheapAsAMove { @@ -553,22 +385,13 @@ include "MipsInstrFormats.td" // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// -class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], - int Offset = 0> : AsmOperandClass { - let Name = "ConstantSImm" # Bits # "_" # Offset; - let RenderMethod = "addConstantSImmOperands<" # Bits # ", " # Offset # ">"; - let PredicateMethod = "isConstantSImm<" # Bits # ", " # Offset # ">"; - let SuperClasses = Supers; - let DiagnosticType = "SImm" # Bits # "_" # Offset; -} - -class SimmLslAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], - int Shift = 0> : AsmOperandClass { - let Name = "Simm" # Bits # "_Lsl" # Shift; +class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> + : AsmOperandClass { + let Name = "ConstantSImm" # Bits; let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">"; + let PredicateMethod = "isConstantSImm<" # Bits # ">"; let SuperClasses = Supers; - let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift; + let DiagnosticType = "SImm" # Bits; } class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], @@ -580,218 +403,49 @@ class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], let DiagnosticType = "UImm" # Bits # "_" # Offset; } -class ConstantUImmRangeAsmOperandClass<int Bottom, int Top, - list<AsmOperandClass> Supers = []> - : AsmOperandClass { - let Name = "ConstantUImmRange" # Bottom # "_" # Top; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">"; - let SuperClasses = Supers; - let DiagnosticType = "UImmRange" # Bottom # "_" # Top; -} - -class SImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> - : AsmOperandClass { - let Name = "SImm" # Bits; - let RenderMethod = "addSImmOperands<" # Bits # ">"; - let PredicateMethod = "isSImm<" # Bits # ">"; - let SuperClasses = Supers; - let DiagnosticType = "SImm" # Bits; -} - -class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> - : AsmOperandClass { - let Name = "UImm" # Bits; - let RenderMethod = "addUImmOperands<" # Bits # ">"; - let PredicateMethod = "isUImm<" # Bits # ">"; - let SuperClasses = Supers; - let DiagnosticType = "UImm" # Bits; -} - -// Generic case - only to support certain assembly pseudo instructions. -class UImmAnyAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> - : AsmOperandClass { - let Name = "ImmAny"; - let RenderMethod = "addConstantUImmOperands<32>"; - let PredicateMethod = "isSImm<" # Bits # ">"; - let SuperClasses = Supers; - let DiagnosticType = "ImmAny"; -} - -// AsmOperandClasses require a strict ordering which is difficult to manage -// as a hierarchy. Instead, we use a linear ordering and impose an order that -// is in some places arbitrary. -// -// Here the rules that are in use: -// * Wider immediates are a superset of narrower immediates: -// uimm4 < uimm5 < uimm6 -// * For the same bit-width, unsigned immediates are a superset of signed -// immediates:: -// simm4 < uimm4 < simm5 < uimm5 -// * For the same upper-bound, signed immediates are a superset of unsigned -// immediates: -// uimm3 < simm4 < uimm4 < simm4 -// * Modified immediates are a superset of ordinary immediates: -// uimm5 < uimm5_plus1 (1..32) < uimm5_plus32 (32..63) < uimm6 -// The term 'superset' starts to break down here since the uimm5_plus* classes -// are not true supersets of uimm5 (but they are still subsets of uimm6). -// * 'Relaxed' immediates are supersets of the corresponding unsigned immediate. -// uimm16 < uimm16_relaxed -// * The codeGen pattern type is arbitrarily ordered. -// uimm5 < uimm5_64, and uimm5 < vsplat_uimm5 -// This is entirely arbitrary. We need an ordering and what we pick is -// unimportant since only one is possible for a given mnemonic. - -def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> { - let Name = "UImm32_Coerced"; - let DiagnosticType = "UImm32_Coerced"; -} -def SImm32RelaxedAsmOperandClass - : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> { - let Name = "SImm32_Relaxed"; - let PredicateMethod = "isAnyImm<33>"; - let DiagnosticType = "SImm32_Relaxed"; -} -def SImm32AsmOperandClass - : SImmAsmOperandClass<32, [SImm32RelaxedAsmOperandClass]>; -def ConstantUImm26AsmOperandClass - : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>; -def ConstantUImm20AsmOperandClass - : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>; -def ConstantSImm19Lsl2AsmOperandClass : AsmOperandClass { - let Name = "SImm19Lsl2"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<19, 2>"; - let SuperClasses = [ConstantUImm20AsmOperandClass]; - let DiagnosticType = "SImm19_Lsl2"; -} -def UImm16RelaxedAsmOperandClass - : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> { - let Name = "UImm16_Relaxed"; - let PredicateMethod = "isAnyImm<16>"; - let DiagnosticType = "UImm16_Relaxed"; -} -// Similar to the relaxed classes which take an SImm and render it as -// an UImm, this takes a UImm and renders it as an SImm. -def UImm16AltRelaxedAsmOperandClass - : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> { - let Name = "UImm16_AltRelaxed"; - let PredicateMethod = "isUImm<16>"; - let DiagnosticType = "UImm16_AltRelaxed"; -} -// FIXME: One of these should probably have UImm16AsmOperandClass as the -// superclass instead of UImm16RelaxedasmOPerandClass. -def UImm16AsmOperandClass - : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>; -def SImm16RelaxedAsmOperandClass - : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> { - let Name = "SImm16_Relaxed"; - let PredicateMethod = "isAnyImm<16>"; - let DiagnosticType = "SImm16_Relaxed"; -} -def SImm16AsmOperandClass - : SImmAsmOperandClass<16, [SImm16RelaxedAsmOperandClass]>; -def ConstantSImm10Lsl3AsmOperandClass : AsmOperandClass { - let Name = "SImm10Lsl3"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<10, 3>"; - let SuperClasses = [SImm16AsmOperandClass]; - let DiagnosticType = "SImm10_Lsl3"; -} -def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass { - let Name = "SImm10Lsl2"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<10, 2>"; - let SuperClasses = [ConstantSImm10Lsl3AsmOperandClass]; - let DiagnosticType = "SImm10_Lsl2"; -} -def ConstantSImm11AsmOperandClass - : ConstantSImmAsmOperandClass<11, [ConstantSImm10Lsl2AsmOperandClass]>; -def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass { - let Name = "SImm10Lsl1"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<10, 1>"; - let SuperClasses = [ConstantSImm11AsmOperandClass]; - let DiagnosticType = "SImm10_Lsl1"; -} def ConstantUImm10AsmOperandClass - : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>; -def ConstantSImm10AsmOperandClass - : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>; -def ConstantSImm9AsmOperandClass - : ConstantSImmAsmOperandClass<9, [ConstantSImm10AsmOperandClass]>; -def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass { - let Name = "SImm7Lsl2"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<7, 2>"; - let SuperClasses = [ConstantSImm9AsmOperandClass]; - let DiagnosticType = "SImm7_Lsl2"; -} + : ConstantUImmAsmOperandClass<10, []>; def ConstantUImm8AsmOperandClass - : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>; -def ConstantUImm7Sub1AsmOperandClass - : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> { - // Specify the names since the -1 offset causes invalid identifiers otherwise. - let Name = "UImm7_N1"; - let DiagnosticType = "UImm7_N1"; -} + : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>; def ConstantUImm7AsmOperandClass - : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>; -def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass { - let Name = "UImm6Lsl2"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledUImm<6, 2>"; - let SuperClasses = [ConstantUImm7AsmOperandClass]; - let DiagnosticType = "UImm6_Lsl2"; -} + : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>; def ConstantUImm6AsmOperandClass - : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>; + : ConstantUImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>; def ConstantSImm6AsmOperandClass - : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>; + : ConstantSImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>; +def ConstantUImm5Plus1AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 1>; +def ConstantUImm5Plus32AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32>; +def ConstantUImm5Plus33AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 33>; +def ConstantUImm5Plus32NormalizeAsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32> { + let Name = "ConstantUImm5_32_Norm"; + // We must also subtract 32 when we render the operand. + let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; +} def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { let Name = "UImm5Lsl2"; let RenderMethod = "addImmOperands"; let PredicateMethod = "isScaledUImm<5, 2>"; - let SuperClasses = [ConstantSImm6AsmOperandClass]; + let SuperClasses = [ConstantUImm6AsmOperandClass]; let DiagnosticType = "UImm5_Lsl2"; } -def ConstantUImm5_Range2_64AsmOperandClass - : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm5Lsl2AsmOperandClass]>; -def ConstantUImm5Plus33AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm5_Range2_64AsmOperandClass], - 33>; def ConstantUImm5ReportUImm6AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus33AsmOperandClass]> { + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]> { let Name = "ConstantUImm5_0_Report_UImm6"; let DiagnosticType = "UImm5_0_Report_UImm6"; } -def ConstantUImm5Plus32AsmOperandClass - : ConstantUImmAsmOperandClass< - 5, [ConstantUImm5ReportUImm6AsmOperandClass], 32>; -def ConstantUImm5Plus32NormalizeAsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus32AsmOperandClass], 32> { - let Name = "ConstantUImm5_32_Norm"; - // We must also subtract 32 when we render the operand. - let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; -} -def ConstantUImm5Plus1ReportUImm6AsmOperandClass - : ConstantUImmAsmOperandClass< - 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>{ - let Name = "ConstantUImm5_Plus1_Report_UImm6"; -} -def ConstantUImm5Plus1AsmOperandClass - : ConstantUImmAsmOperandClass< - 5, [ConstantUImm5Plus1ReportUImm6AsmOperandClass], 1>; def ConstantUImm5AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>; -def ConstantSImm5AsmOperandClass - : ConstantSImmAsmOperandClass<5, [ConstantUImm5AsmOperandClass]>; + : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]>; def ConstantUImm4AsmOperandClass - : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>; -def ConstantSImm4AsmOperandClass - : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>; + : ConstantUImmAsmOperandClass< + 4, [ConstantUImm5AsmOperandClass, + ConstantUImm5Plus32AsmOperandClass, + ConstantUImm5Plus32NormalizeAsmOperandClass]>; def ConstantUImm3AsmOperandClass - : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>; + : ConstantUImmAsmOperandClass<3, [ConstantUImm4AsmOperandClass]>; def ConstantUImm2Plus1AsmOperandClass : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass], 1>; def ConstantUImm2AsmOperandClass @@ -806,9 +460,6 @@ def ConstantImmzAsmOperandClass : AsmOperandClass { let DiagnosticType = "Immz"; } -def Simm19Lsl2AsmOperand - : SimmLslAsmOperandClass<19, [], 2>; - def MipsJumpTargetAsmOperand : AsmOperandClass { let Name = "JumpTarget"; let ParserMethod = "parseJumpTarget"; @@ -827,12 +478,6 @@ def brtarget : Operand<OtherVT> { let DecoderMethod = "DecodeBranchTarget"; let ParserMatchClass = MipsJumpTargetAsmOperand; } -def brtarget1SImm16 : Operand<OtherVT> { - let EncoderMethod = "getBranchTargetOpValue1SImm16"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget1SImm16"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} def calltarget : Operand<iPTR> { let EncoderMethod = "getJumpTargetOpValue"; let ParserMatchClass = MipsJumpTargetAsmOperand; @@ -840,10 +485,22 @@ def calltarget : Operand<iPTR> { def imm64: Operand<i64>; +def simm6 : Operand<i32> { + let ParserMatchClass = ConstantSImm6AsmOperandClass; + let OperandType = "OPERAND_IMMEDIATE"; +} +def simm9 : Operand<i32>; +def simm10 : Operand<i32>; +def simm11 : Operand<i32>; + +def simm16 : Operand<i32> { + let DecoderMethod= "DecodeSimm16"; +} + def simm19_lsl2 : Operand<i32> { let EncoderMethod = "getSimm19Lsl2Encoding"; let DecoderMethod = "DecodeSimm19Lsl2"; - let ParserMatchClass = Simm19Lsl2AsmOperand; + let ParserMatchClass = MipsJumpTargetAsmOperand; } def simm18_lsl3 : Operand<i32> { @@ -852,223 +509,91 @@ def simm18_lsl3 : Operand<i32> { let ParserMatchClass = MipsJumpTargetAsmOperand; } +def simm20 : Operand<i32>; +def simm32 : Operand<i32>; + +def uimm20 : Operand<i32> { +} + +def simm16_64 : Operand<i64> { + let DecoderMethod = "DecodeSimm16"; +} + // Zero def uimmz : Operand<i32> { - let PrintMethod = "printUImm<0>"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = ConstantImmzAsmOperandClass; } -// size operand of ins instruction -def uimm_range_2_64 : Operand<i32> { - let PrintMethod = "printUImm<6, 2>"; - let EncoderMethod = "getSizeInsEncoding"; - let DecoderMethod = "DecodeInsSize"; - let ParserMatchClass = ConstantUImm5_Range2_64AsmOperandClass; -} - // Unsigned Operands -foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 26} in +foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10} in def uimm # I : Operand<i32> { - let PrintMethod = "printUImm<" # I # ">"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); } def uimm2_plus1 : Operand<i32> { - let PrintMethod = "printUImm<2, 1>"; + let PrintMethod = "printUnsignedImm"; let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>"; let DecoderMethod = "DecodeUImmWithOffset<2, 1>"; let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; } def uimm5_plus1 : Operand<i32> { - let PrintMethod = "printUImm<5, 1>"; + let PrintMethod = "printUnsignedImm"; let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>"; let DecoderMethod = "DecodeUImmWithOffset<5, 1>"; let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass; } -def uimm5_plus1_report_uimm6 : Operand<i32> { - let PrintMethod = "printUImm<6, 1>"; - let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>"; - let DecoderMethod = "DecodeUImmWithOffset<5, 1>"; - let ParserMatchClass = ConstantUImm5Plus1ReportUImm6AsmOperandClass; -} - def uimm5_plus32 : Operand<i32> { - let PrintMethod = "printUImm<5, 32>"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = ConstantUImm5Plus32AsmOperandClass; } def uimm5_plus33 : Operand<i32> { - let PrintMethod = "printUImm<5, 33>"; + let PrintMethod = "printUnsignedImm"; let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>"; let DecoderMethod = "DecodeUImmWithOffset<5, 1>"; let ParserMatchClass = ConstantUImm5Plus33AsmOperandClass; } -def uimm5_inssize_plus1 : Operand<i32> { - let PrintMethod = "printUImm<6>"; - let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass; - let EncoderMethod = "getSizeInsEncoding"; - let DecoderMethod = "DecodeInsSize"; -} - def uimm5_plus32_normalize : Operand<i32> { - let PrintMethod = "printUImm<5>"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; } def uimm5_lsl2 : Operand<OtherVT> { let EncoderMethod = "getUImm5Lsl2Encoding"; - let DecoderMethod = "DecodeUImmWithOffsetAndScale<5, 0, 4>"; + let DecoderMethod = "DecodeUImm5lsl2"; let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass; } def uimm5_plus32_normalize_64 : Operand<i64> { - let PrintMethod = "printUImm<5>"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; } -def uimm6_lsl2 : Operand<OtherVT> { - let EncoderMethod = "getUImm6Lsl2Encoding"; - let DecoderMethod = "DecodeUImmWithOffsetAndScale<6, 0, 4>"; - let ParserMatchClass = ConstantUImm6Lsl2AsmOperandClass; -} - -foreach I = {16} in - def uimm # I : Operand<i32> { - let PrintMethod = "printUImm<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass"); - } - -// Like uimm16_64 but coerces simm16 to uimm16. -def uimm16_relaxed : Operand<i32> { - let PrintMethod = "printUImm<16>"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass"); -} - foreach I = {5} in def uimm # I # _64 : Operand<i64> { - let PrintMethod = "printUImm<" # I # ">"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); } -foreach I = {16} in - def uimm # I # _64 : Operand<i64> { - let PrintMethod = "printUImm<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass"); - } - -// Like uimm16_64 but coerces simm16 to uimm16. -def uimm16_64_relaxed : Operand<i64> { - let PrintMethod = "printUImm<16>"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass"); -} - -def uimm16_altrelaxed : Operand<i32> { - let PrintMethod = "printUImm<16>"; - let ParserMatchClass = - !cast<AsmOperandClass>("UImm16AltRelaxedAsmOperandClass"); -} -// Like uimm5 but reports a less confusing error for 32-63 when -// an instruction alias permits that. -def uimm5_report_uimm6 : Operand<i32> { - let PrintMethod = "printUImm<6>"; - let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass; -} - // Like uimm5_64 but reports a less confusing error for 32-63 when // an instruction alias permits that. def uimm5_64_report_uimm6 : Operand<i64> { - let PrintMethod = "printUImm<5>"; + let PrintMethod = "printUnsignedImm"; let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass; } -foreach I = {1, 2, 3, 4} in - def uimm # I # _ptr : Operand<iPTR> { - let PrintMethod = "printUImm<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); - } - -foreach I = {1, 2, 3, 4, 5, 6, 8} in - def vsplat_uimm # I : Operand<vAny> { - let PrintMethod = "printUImm<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); - } - -// Signed operands -foreach I = {4, 5, 6, 9, 10, 11} in - def simm # I : Operand<i32> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass"); - } - -foreach I = {1, 2, 3} in - def simm10_lsl # I : Operand<i32> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, " # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantSImm10Lsl" # I # "AsmOperandClass"); - } - -foreach I = {10} in - def simm # I # _64 : Operand<i64> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass"); - } - -foreach I = {5, 10} in - def vsplat_simm # I : Operand<vAny> { - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass"); - } - -def simm7_lsl2 : Operand<OtherVT> { - let EncoderMethod = "getSImm7Lsl2Encoding"; - let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>"; - let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass; +def uimm16 : Operand<i32> { + let PrintMethod = "printUnsignedImm"; } -foreach I = {16, 32} in - def simm # I : Operand<i32> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm" # I # "AsmOperandClass"); - } - -// Like simm16 but coerces uimm16 to simm16. -def simm16_relaxed : Operand<i32> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm16RelaxedAsmOperandClass"); -} - -def simm16_64 : Operand<i64> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass"); -} - -// like simm32 but coerces simm32 to uimm32. -def uimm32_coerced : Operand<i32> { - let ParserMatchClass = !cast<AsmOperandClass>("UImm32CoercedAsmOperandClass"); -} -// Like simm32 but coerces uimm32 to simm32. -def simm32_relaxed : Operand<i32> { - let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>"; - let ParserMatchClass = !cast<AsmOperandClass>("SImm32RelaxedAsmOperandClass"); -} - -// This is almost the same as a uimm7 but 0x7f is interpreted as -1. -def li16_imm : Operand<i32> { - let DecoderMethod = "DecodeLi16Imm"; - let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass; +def pcrel16 : Operand<i32> { } def MipsMemAsmOperand : AsmOperandClass { @@ -1082,44 +607,22 @@ def MipsMemSimm9AsmOperand : AsmOperandClass { let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<9>"; - let DiagnosticType = "MemSImm9"; } -def MipsMemSimm10AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm10"; +def MipsMemSimm9GPRAsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm9GPR"; let SuperClasses = [MipsMemAsmOperand]; let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<10>"; - let DiagnosticType = "MemSImm10"; + let PredicateMethod = "isMemWithSimmOffsetGPR<9>"; } -def MipsMemSimm12AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm12"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<12>"; - let DiagnosticType = "MemSImm12"; -} - -foreach I = {1, 2, 3} in - def MipsMemSimm10Lsl # I # AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm10_" # I; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<10, " # I # ">"; - let DiagnosticType = "MemSImm10Lsl" # I; - } - def MipsMemSimm11AsmOperand : AsmOperandClass { let Name = "MemOffsetSimm11"; let SuperClasses = [MipsMemAsmOperand]; let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<11>"; - let DiagnosticType = "MemSImm11"; } def MipsMemSimm16AsmOperand : AsmOperandClass { @@ -1128,16 +631,6 @@ def MipsMemSimm16AsmOperand : AsmOperandClass { let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<16>"; - let DiagnosticType = "MemSImm16"; -} - -def MipsMemSimmPtrAsmOperand : AsmOperandClass { - let Name = "MemOffsetSimmPtr"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithPtrSizeOffset"; - let DiagnosticType = "MemSImmPtr"; } def MipsInvertedImmoperand : AsmOperandClass { @@ -1171,52 +664,30 @@ def mem_msa : mem_generic { let EncoderMethod = "getMSAMemEncoding"; } -def simm12 : Operand<i32> { - let DecoderMethod = "DecodeSimm12"; -} - def mem_simm9 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm9); let EncoderMethod = "getMemEncoding"; let ParserMatchClass = MipsMemSimm9AsmOperand; } -def mem_simm10 : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm10); +def mem_simm9gpr : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm9); let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm10AsmOperand; + let ParserMatchClass = MipsMemSimm9GPRAsmOperand; } -foreach I = {1, 2, 3} in - def mem_simm10_lsl # I : mem_generic { - let MIOperandInfo = (ops ptr_rc, !cast<Operand>("simm10_lsl" # I)); - let EncoderMethod = "getMemEncoding<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("MipsMemSimm10Lsl" # I # "AsmOperand"); - } - def mem_simm11 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm11); let EncoderMethod = "getMemEncoding"; let ParserMatchClass = MipsMemSimm11AsmOperand; } -def mem_simm12 : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm12); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm12AsmOperand; -} - def mem_simm16 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncoding"; let ParserMatchClass = MipsMemSimm16AsmOperand; } -def mem_simmptr : mem_generic { - let ParserMatchClass = MipsMemSimmPtrAsmOperand; -} - def mem_ea : Operand<iPTR> { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -1260,8 +731,9 @@ def immSExt8 : PatLeaf<(imm), [{ return isInt<8>(N->getSExtValue()); }]>; // e.g. addi, andi def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; -// Node immediate fits as 7-bit zero extended on target immediate. -def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>; +// Node immediate fits as 15-bit sign extended on target immediate. +// e.g. addi, andi +def immSExt15 : PatLeaf<(imm), [{ return isInt<15>(N->getSExtValue()); }]>; // Node immediate fits as 16-bit zero extended on target immediate. // The LO16 param means that only the lower 16 bits of the node @@ -1275,64 +747,19 @@ def immZExt16 : PatLeaf<(imm), [{ }], LO16>; // Immediate can be loaded with LUi (32-bit int with lower 16-bit cleared). -def immSExt32Low16Zero : PatLeaf<(imm), [{ +def immLow16Zero : PatLeaf<(imm), [{ int64_t Val = N->getSExtValue(); return isInt<32>(Val) && !(Val & 0xffff); }]>; -// Zero-extended 32-bit unsigned int with lower 16-bit cleared. -def immZExt32Low16Zero : PatLeaf<(imm), [{ - uint64_t Val = N->getZExtValue(); - return isUInt<32>(Val) && !(Val & 0xffff); -}]>; - -// Note immediate fits as a 32 bit signed extended on target immediate. -def immSExt32 : PatLeaf<(imm), [{ return isInt<32>(N->getSExtValue()); }]>; - -// Note immediate fits as a 32 bit zero extended on target immediate. -def immZExt32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>; - // shamt field must fit in 5 bits. def immZExt5 : ImmLeaf<i32, [{return Imm == (Imm & 0x1f);}]>; -def immZExt5Plus1 : PatLeaf<(imm), [{ - return isUInt<5>(N->getZExtValue() - 1); -}]>; -def immZExt5Plus32 : PatLeaf<(imm), [{ - return isUInt<5>(N->getZExtValue() - 32); -}]>; -def immZExt5Plus33 : PatLeaf<(imm), [{ - return isUInt<5>(N->getZExtValue() - 33); -}]>; - -def immZExt5To31 : SDNodeXForm<imm, [{ - return getImm(N, 31 - N->getZExtValue()); -}]>; - // True if (N + 1) fits in 16-bit field. def immSExt16Plus1 : PatLeaf<(imm), [{ return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1); }]>; -def immZExtRange2To64 : PatLeaf<(imm), [{ - return isUInt<7>(N->getZExtValue()) && (N->getZExtValue() >= 2) && - (N->getZExtValue() <= 64); -}]>; - -def ORiPred : PatLeaf<(imm), [{ - return isUInt<16>(N->getZExtValue()) && !isInt<16>(N->getSExtValue()); -}], LO16>; - -def LUiPred : PatLeaf<(imm), [{ - int64_t Val = N->getSExtValue(); - return !isInt<16>(Val) && isInt<32>(Val) && !(Val & 0xffff); -}]>; - -def LUiORiPred : PatLeaf<(imm), [{ - int64_t SVal = N->getSExtValue(); - return isInt<32>(SVal) && (SVal & 0xffff); -}]>; - // Mips Address Mode! SDNode frameindex could possibily be a match // since load and store instructions from stack used it. def addr : @@ -1341,16 +768,13 @@ def addr : def addrRegImm : ComplexPattern<iPTR, 2, "selectAddrRegImm", [frameindex]>; +def addrRegReg : + ComplexPattern<iPTR, 2, "selectAddrRegReg", [frameindex]>; + def addrDefault : ComplexPattern<iPTR, 2, "selectAddrDefault", [frameindex]>; -def addrimm10 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10", [frameindex]>; -def addrimm10lsl1 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10Lsl1", - [frameindex]>; -def addrimm10lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10Lsl2", - [frameindex]>; -def addrimm10lsl3 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10Lsl3", - [frameindex]>; +def addrimm10 : ComplexPattern<iPTR, 2, "selectIntAddrMSA", [frameindex]>; //===----------------------------------------------------------------------===// // Instructions specific format @@ -1425,36 +849,27 @@ class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>: } // Memory Load/Store -class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO, - SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, - ComplexPattern Addr = addr> : - InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), +class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : + InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let canFoldAsLoad = 1; - string BaseOpcode = opstr; let mayLoad = 1; } -class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - LoadMemory<opstr, RO, mem, OpNode, Itin, Addr>; - class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO, SDPatternOperator OpNode = null_frag, InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : InstSE<(outs), (ins RO:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RO:$rt, Addr:$addr)], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; - string BaseOpcode = opstr; let mayStore = 1; } class Store<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr, - DAGOperand MO = mem> : - StoreMemory<opstr, RO, MO, OpNode, Itin, Addr>; + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : + StoreMemory<opstr, RO, mem, OpNode, Itin, Addr>; // Load/Store Left/Right let canFoldAsLoad = 1 in @@ -1465,7 +880,6 @@ class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, [(set RO:$rt, (OpNode addr:$addr, RO:$src))], Itin, FrmI> { let DecoderMethod = "DecodeMem"; string Constraints = "$src = $rt"; - let BaseOpcode = opstr; } class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, @@ -1473,14 +887,12 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RO:$rt, addr:$addr)], Itin, FrmI> { let DecoderMethod = "DecodeMem"; - let BaseOpcode = opstr; } // COP2 Load/Store class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs RC:$rt), (ins mem_simm16:$addr), - !strconcat(opstr, "\t$rt, $addr"), + 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; @@ -1488,8 +900,7 @@ class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, class SW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs), (ins RC:$rt, mem_simm16:$addr), - !strconcat(opstr, "\t$rt, $addr"), + 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; @@ -1514,49 +925,27 @@ class SW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, // 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)], II_BCC, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; - bit isCTI = 1; -} - -class CBranchLikely<string opstr, DAGOperand opnd, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, RO:$rt, opnd:$offset), - !strconcat(opstr, "\t$rs, $rt, $offset"), [], II_BCC, FrmI, opstr> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let Defs = [AT]; - bit isCTI = 1; } 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)], II_BCCZ, FrmI, opstr> { let isBranch = 1; let isTerminator = 1; - let hasDelaySlot = 1; - let Defs = [AT]; - bit isCTI = 1; -} - -class CBranchZeroLikely<string opstr, DAGOperand opnd, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZ, FrmI, opstr> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; let Defs = [AT]; - bit isCTI = 1; } // SetCC @@ -1583,24 +972,22 @@ class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator, let hasDelaySlot = 1; let DecoderMethod = "DecodeJumpTarget"; let Defs = [AT]; - bit isCTI = 1; } // Unconditional branch -class UncondBranch<Instruction BEQInst, DAGOperand opnd> : +class UncondBranch<Instruction BEQInst> : PseudoSE<(outs), (ins brtarget:$offset), [(br bb:$offset)], II_B>, - PseudoInstExpansion<(BEQInst ZERO, ZERO, opnd:$offset)> { + PseudoInstExpansion<(BEQInst ZERO, ZERO, brtarget:$offset)> { let isBranch = 1; let isTerminator = 1; let isBarrier = 1; let hasDelaySlot = 1; let AdditionalPredicates = [RelocPIC]; let Defs = [AT]; - bit isCTI = 1; } // Base class for indirect branch and return instruction classes. -let isTerminator=1, isBarrier=1, hasDelaySlot = 1, isCTI = 1 in +let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in class JumpFR<string opstr, RegisterOperand RO, SDPatternOperator operator = null_frag>: InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR, @@ -1613,7 +1000,7 @@ class IndirectBranch<string opstr, RegisterOperand RO> : JumpFR<opstr, RO> { } // Jump and Link (Call) -let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in { +let isCall=1, hasDelaySlot=1, Defs = [RA] in { class JumpLink<string opstr, DAGOperand opnd> : InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), [(MipsJmpLink tglobaladdr:$target)], II_JAL, FrmJ, opstr> { @@ -1623,101 +1010,89 @@ let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in { class JumpLinkRegPseudo<RegisterOperand RO, Instruction JALRInst, Register RetReg, RegisterOperand ResRO = RO>: PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>, - PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)> { - let hasPostISelHook = 1; - } + PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>; class JumpLinkReg<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], II_JALR, FrmR, opstr> { - let hasPostISelHook = 1; - } + [], II_JALR, FrmR, opstr>; class BGEZAL_FT<string opstr, DAGOperand opnd, - RegisterOperand RO> : + RegisterOperand RO, bit DelaySlot = 1> : InstSE<(outs), (ins RO:$rs, opnd:$offset), !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZAL, FrmI, opstr> { - let hasDelaySlot = 1; + let hasDelaySlot = DelaySlot; } } let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { - class TailCall<Instruction JumpInst, DAGOperand Opnd> : + hasExtraSrcRegAllocReq = 1, Defs = [AT] in { + class TailCall<Instruction JumpInst> : PseudoSE<(outs), (ins calltarget:$target), [], II_J>, - PseudoInstExpansion<(JumpInst Opnd:$target)>; + PseudoInstExpansion<(JumpInst jmptarget:$target)>; - class TailCallReg<Instruction JumpInst, RegisterOperand RO> : + class TailCallReg<RegisterOperand RO, Instruction JRInst, + RegisterOperand ResRO = RO> : PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, - PseudoInstExpansion<(JumpInst RO:$rs)> { - let hasPostISelHook = 1; - } + PseudoInstExpansion<(JRInst ResRO:$rs)>; } -class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> : - PseudoSE<(outs), (ins opnd:$offset), [], II_BCCZAL>, - PseudoInstExpansion<(RealInst ZERO, opnd:$offset)> { +class BAL_BR_Pseudo<Instruction RealInst> : + PseudoSE<(outs), (ins brtarget:$offset), [], II_BCCZAL>, + PseudoInstExpansion<(RealInst ZERO, brtarget:$offset)> { let isBranch = 1; let isTerminator = 1; let isBarrier = 1; let hasDelaySlot = 1; let Defs = [RA]; - bit isCTI = 1; } -let isCTI = 1 in { // Syscall -class SYS_FT<string opstr, Operand ImmOp, InstrItinClass itin = NoItinerary> : - InstSE<(outs), (ins ImmOp:$code_), - !strconcat(opstr, "\t$code_"), [], itin, FrmI, opstr>; +class SYS_FT<string opstr> : + InstSE<(outs), (ins uimm20:$code_), + !strconcat(opstr, "\t$code_"), [], NoItinerary, FrmI, opstr>; // Break class BRK_FT<string opstr> : InstSE<(outs), (ins uimm10:$code_1, uimm10:$code_2), - !strconcat(opstr, "\t$code_1, $code_2"), [], II_BREAK, + !strconcat(opstr, "\t$code_1, $code_2"), [], NoItinerary, FrmOther, opstr>; // (D)Eret -class ER_FT<string opstr, InstrItinClass itin = NoItinerary> : +class ER_FT<string opstr> : InstSE<(outs), (ins), - opstr, [], itin, FrmOther, opstr>; - -// Wait -class WAIT_FT<string opstr> : - InstSE<(outs), (ins), opstr, [], II_WAIT, FrmOther, opstr>; -} + opstr, [], NoItinerary, FrmOther, opstr>; // Interrupts -class DEI_FT<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary> : +class DEI_FT<string opstr, RegisterOperand RO> : InstSE<(outs RO:$rt), (ins), - !strconcat(opstr, "\t$rt"), [], itin, FrmOther, opstr>; + !strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther, opstr>; + +// Wait +class WAIT_FT<string opstr> : + InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>; // Sync let hasSideEffects = 1 in class SYNC_FT<string opstr> : - InstSE<(outs), (ins uimm5:$stype), "sync $stype", - [(MipsSync immZExt5:$stype)], II_SYNC, FrmOther, opstr>; + InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)], + NoItinerary, FrmOther, opstr>; -class SYNCI_FT<string opstr, DAGOperand MO> : - InstSE<(outs), (ins MO:$addr), !strconcat(opstr, "\t$addr"), [], - II_SYNCI, 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, isCTI = 1 in { -class TEQ_FT<string opstr, RegisterOperand RO, Operand ImmOp, - InstrItinClass itin = NoItinerary> : - InstSE<(outs), (ins RO:$rs, RO:$rt, ImmOp:$code_), - !strconcat(opstr, "\t$rs, $rt, $code_"), [], itin, FrmI, opstr>; - -class TEQI_FT<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary> : - InstSE<(outs), (ins RO:$rs, simm16:$imm16), - !strconcat(opstr, "\t$rs, $imm16"), [], itin, FrmOther, opstr>; -} - +let hasSideEffects = 1 in +class TEQ_FT<string opstr, RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_), + !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, + FrmI, opstr>; + +class TEQI_FT<string opstr, RegisterOperand RO> : + InstSE<(outs), (ins RO:$rs, uimm16:$imm16), + !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr>; // Mul, Div class Mult<string opstr, InstrItinClass itin, RegisterOperand RO, list<Register> DefRegs> : @@ -1772,7 +1147,6 @@ class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>: FrmR, opstr> { let Uses = [UseReg]; let hasSideEffects = 0; - let isMoveReg = 1; } class PseudoMTLOHI<RegisterClass DstRC, RegisterClass SrcRC> @@ -1785,28 +1159,24 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>: FrmR, opstr> { let Defs = DefRegs; let hasSideEffects = 0; - let isMoveReg = 1; } class EffectiveAddress<string opstr, RegisterOperand RO> : InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, addr:$addr)], II_ADDIU, FrmI, + [(set RO:$rt, addr:$addr)], NoItinerary, FrmI, !strconcat(opstr, "_lea")> { let isCodeGenOnly = 1; - let hasNoSchedulingInfo = 1; let DecoderMethod = "DecodeMem"; } // Count Leading Ones/Zeros in Word -class CountLeading0<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary>: +class CountLeading0<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz RO:$rs))], itin, FrmR, opstr>; + [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>; -class CountLeading1<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary>: +class CountLeading1<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz (not RO:$rs)))], itin, FrmR, opstr>; + [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>; // Sign Extend in Register. class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO, @@ -1824,26 +1194,23 @@ class SubwordSwap<string opstr, RegisterOperand RO, // Read Hardware class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> : - InstSE<(outs CPURegOperand:$rt), (ins RO:$rd, uimm8:$sel), - "rdhwr\t$rt, $rd, $sel", [], II_RDHWR, FrmR, "rdhwr">; + InstSE<(outs CPURegOperand:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [], + II_RDHWR, FrmR, "rdhwr">; // Ext and Ins class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, - Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm, - SDPatternOperator Op = null_frag> : + Operand SizeOpnd, SDPatternOperator Op = null_frag> : InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size), - !strconcat(opstr, "\t$rt, $rs, $pos, $size"), - [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT, - FrmR, opstr>; + !strconcat(opstr, " $rt, $rs, $pos, $size"), + [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], II_EXT, + FrmR, opstr>, ISA_MIPS32R2; -// 'ins' and its' 64 bit variants are matched by C++ code. class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, - Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm>: - InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src), - !strconcat(opstr, "\t$rt, $rs, $pos, $size"), - [(set RO:$rt, (null_frag RO:$rs, PosImm:$pos, SizeImm:$size, - RO:$src))], - II_INS, FrmR, opstr> { + SDPatternOperator Op = null_frag>: + InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src), + !strconcat(opstr, " $rt, $rs, $pos, $size"), + [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))], + II_INS, FrmR, opstr>, ISA_MIPS32R2 { let Constraints = "$src = $rt"; } @@ -1852,73 +1219,40 @@ class Atomic2Ops<PatFrag Op, RegisterClass DRC> : PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>; -class Atomic2OpsPostRA<RegisterClass RC> : - PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> { - let mayLoad = 1; - let mayStore = 1; -} - -class Atomic2OpsSubwordPostRA<RegisterClass RC> : - PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2, - RC:$shiftamnt), []>; - // Atomic Compare & Swap. -// Atomic compare and swap is lowered into two stages. The first stage happens -// during ISelLowering, which produces the PostRA version of this instruction. class AtomicCmpSwap<PatFrag Op, RegisterClass DRC> : PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap), [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>; -class AtomicCmpSwapPostRA<RegisterClass RC> : - PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> { - let mayLoad = 1; - let mayStore = 1; -} - -class AtomicCmpSwapSubwordPostRA<RegisterClass RC> : - PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$mask, RC:$ShiftCmpVal, - RC:$mask2, RC:$ShiftNewVal, RC:$ShiftAmt), []> { - let mayLoad = 1; - let mayStore = 1; -} - - -class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> : - InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), - [], II_LL, FrmI, opstr> { +class LLBase<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + [], NoItinerary, FrmI> { let DecoderMethod = "DecodeMem"; let mayLoad = 1; } class SCBase<string opstr, RegisterOperand RO> : InstSE<(outs RO:$dst), (ins RO:$rt, mem:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_SC, FrmI> { + !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { let DecoderMethod = "DecodeMem"; let mayStore = 1; let Constraints = "$rt = $dst"; } -class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD, - InstrItinClass itin> : - InstSE<(outs RO:$rt), (ins RD:$rd, uimm3:$sel), - !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> { - let BaseOpcode = asmstr; -} +class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> : + InstSE<(outs RO:$rt), (ins RD:$rd, uimm16:$sel), + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; -class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD, - InstrItinClass itin> : - InstSE<(outs RO:$rd), (ins RD:$rt, uimm3:$sel), - !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> { - let BaseOpcode = asmstr; -} +class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> : + InstSE<(outs RO:$rd), (ins RD:$rt, uimm16:$sel), + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; class TrapBase<Instruction RealInst> - : PseudoSE<(outs), (ins), [(trap)], II_TRAP>, + : PseudoSE<(outs), (ins), [(trap)], NoItinerary>, PseudoInstExpansion<(RealInst 0, 0)> { let isBarrier = 1; let isTerminator = 1; let isCodeGenOnly = 1; - let isCTI = 1; } //===----------------------------------------------------------------------===// @@ -1926,17 +1260,15 @@ class TrapBase<Instruction RealInst> //===----------------------------------------------------------------------===// // Return RA. -let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in { - let hasDelaySlot=1 in - def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in +def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; - let hasSideEffects=1 in - def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; -} +let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, hasSideEffects=1 in +def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { -def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - [(callseq_start timm:$amt1, timm:$amt2)]>; +def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt), + [(callseq_start timm:$amt)]>; def ADJCALLSTACKUP : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_end timm:$amt1, timm:$amt2)]>; } @@ -1968,38 +1300,10 @@ let usesCustomInserter = 1 in { def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, GPR32>; def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, GPR32>; def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, GPR32>; - } -def ATOMIC_LOAD_ADD_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_ADD_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_ADD_I32_POSTRA : Atomic2OpsPostRA<GPR32>; -def ATOMIC_LOAD_SUB_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_SUB_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_SUB_I32_POSTRA : Atomic2OpsPostRA<GPR32>; -def ATOMIC_LOAD_AND_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_AND_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_AND_I32_POSTRA : Atomic2OpsPostRA<GPR32>; -def ATOMIC_LOAD_OR_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_OR_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_OR_I32_POSTRA : Atomic2OpsPostRA<GPR32>; -def ATOMIC_LOAD_XOR_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_XOR_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_XOR_I32_POSTRA : Atomic2OpsPostRA<GPR32>; -def ATOMIC_LOAD_NAND_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_NAND_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_LOAD_NAND_I32_POSTRA : Atomic2OpsPostRA<GPR32>; - -def ATOMIC_SWAP_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_SWAP_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; -def ATOMIC_SWAP_I32_POSTRA : Atomic2OpsPostRA<GPR32>; - -def ATOMIC_CMP_SWAP_I8_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>; -def ATOMIC_CMP_SWAP_I16_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>; -def ATOMIC_CMP_SWAP_I32_POSTRA : AtomicCmpSwapPostRA<GPR32>; - /// Pseudo instructions for loading and storing accumulator registers. -let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { +let isPseudo = 1, isCodeGenOnly = 1 in { def LOAD_ACC64 : Load<"", ACC64>; def STORE_ACC64 : Store<"", ACC64>; } @@ -2008,19 +1312,13 @@ let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { // branches. See the comment in file MipsLongBranch.cpp for detailed // explanation. -// Expands to: lui $dst, %highest/%higher/%hi/%lo($tgt - $baltgt) +// Expands to: lui $dst, %hi($tgt - $baltgt) def LONG_BRANCH_LUi : PseudoSE<(outs GPR32Opnd:$dst), (ins brtarget:$tgt, brtarget:$baltgt), []>; -// Expands to: lui $dst, highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_LUi2Op : PseudoSE<(outs GPR32Opnd:$dst), - (ins brtarget:$tgt), []>; -// Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt - $baltgt) +// Expands to: addiu $dst, $src, %lo($tgt - $baltgt) def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; -// Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst), - (ins GPR32Opnd:$src, brtarget:$tgt), []>; //===----------------------------------------------------------------------===// // Instruction definition @@ -2031,273 +1329,242 @@ def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst), /// Arithmetic Instructions (ALU Immediate) let AdditionalPredicates = [NotInMicroMips] in { - def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd, - II_ADDIU, immSExt16, add>, - ADDI_FM<0x9>, IsAsCheapAsAMove, ISA_MIPS1; - - def ANDi : MMRel, StdMMR6Rel, - ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, - ADDI_FM<0xc>, ISA_MIPS1; - def ORi : MMRel, StdMMR6Rel, - ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, - ADDI_FM<0xd>, ISA_MIPS1; - def XORi : MMRel, StdMMR6Rel, - ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, - ADDI_FM<0xe>, ISA_MIPS1; - def ADDi : MMRel, ArithLogicI<"addi", simm16_relaxed, GPR32Opnd, II_ADDI>, - ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6; - def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, - SLTI_FM<0xa>, ISA_MIPS1; - def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, - SLTI_FM<0xb>, ISA_MIPS1; - - def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM, - ISA_MIPS1; - - /// Arithmetic Instructions (3-Operand, R-Type) - def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, - ADD_FM<0, 0x21>, ISA_MIPS1; - def SUBu : MMRel, StdMMR6Rel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, - ADD_FM<0, 0x23>, ISA_MIPS1; - - let Defs = [HI0, LO0] in - def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, - ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6; - - def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd, 1, II_ADD>, - ADD_FM<0, 0x20>, ISA_MIPS1; - def SUB : MMRel, StdMMR6Rel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, - ADD_FM<0, 0x22>, ISA_MIPS1; - - def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>, - ISA_MIPS1; - def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>, - ISA_MIPS1; - def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, - ADD_FM<0, 0x24>, ISA_MIPS1; - def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, - ADD_FM<0, 0x25>, ISA_MIPS1; - def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, - ADD_FM<0, 0x26>, ISA_MIPS1; - def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>, - ISA_MIPS1; +def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16, GPR32Opnd, + II_ADDIU, immSExt16, 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, StdMMR6Rel, + ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, + ADDI_FM<0xc>; +} +def ORi : MMRel, StdMMR6Rel, + ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, + ADDI_FM<0xd>; +def XORi : MMRel, StdMMR6Rel, + ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, + ADDI_FM<0xe>; +def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM; +let AdditionalPredicates = [NotInMicroMips] in { +/// Arithmetic Instructions (3-Operand, R-Type) +def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, + ADD_FM<0, 0x21>; +def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, + ADD_FM<0, 0x23>; +} +let Defs = [HI0, LO0] in +def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, + ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6; +def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; +def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>; +def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>; +def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>; +let AdditionalPredicates = [NotInMicroMips] in { +def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, + ADD_FM<0, 0x24>; +def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, + ADD_FM<0, 0x25>; +def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, + ADD_FM<0, 0x26>; } +def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; +/// Shift Instructions let AdditionalPredicates = [NotInMicroMips] in { - /// Shift Instructions - def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl, - immZExt5>, SRA_FM<0, 0>, ISA_MIPS1; - def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl, - immZExt5>, SRA_FM<2, 0>, ISA_MIPS1; - def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra, - immZExt5>, SRA_FM<3, 0>, ISA_MIPS1; - def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>, - SRLV_FM<4, 0>, ISA_MIPS1; - def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>, - SRLV_FM<6, 0>, ISA_MIPS1; - def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>, - SRLV_FM<7, 0>, ISA_MIPS1; - - // Rotate Instructions - def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr, - immZExt5>, - SRA_FM<2, 1>, ISA_MIPS32R2; - def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>, - SRLV_FM<6, 1>, ISA_MIPS32R2; -} +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>, + SRLV_FM<4, 0>; +def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>, + SRLV_FM<6, 0>; +def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>, + SRLV_FM<7, 0>; + +// Rotate Instructions +def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr, + immZExt5>, + SRA_FM<2, 1>, ISA_MIPS32R2; +def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>, + SRLV_FM<6, 1>, ISA_MIPS32R2; /// Load and Store Instructions /// aligned +def LB : Load<"lb", GPR32Opnd, sextloadi8, II_LB>, MMRel, LW_FM<0x20>; +def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel, + LW_FM<0x24>; +def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel, + LW_FM<0x21>; +def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; +let AdditionalPredicates = [NotInMicroMips] in { +def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, + LW_FM<0x23>; +} +def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, + LW_FM<0x28>; +def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; let AdditionalPredicates = [NotInMicroMips] in { - def LB : LoadMemory<"lb", GPR32Opnd, mem_simmptr, sextloadi8, II_LB>, MMRel, - LW_FM<0x20>, ISA_MIPS1; - def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simmptr, zextloadi8, II_LBU, - addrDefault>, MMRel, LW_FM<0x24>, ISA_MIPS1; - def LH : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16, II_LH, - addrDefault>, MMRel, LW_FM<0x21>, ISA_MIPS1; - def LHu : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16, II_LHU>, - MMRel, LW_FM<0x25>, ISA_MIPS1; - def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, - LW_FM<0x23>, ISA_MIPS1; - def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, - LW_FM<0x28>, ISA_MIPS1; - def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>, - ISA_MIPS1; - def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1; +def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>; } /// load/store left/right -let AdditionalPredicates = [NotInMicroMips] in { -def LWL : MMRel, LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>, +let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug + AdditionalPredicates = [NotInMicroMips] in { +def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>, ISA_MIPS1_NOT_32R6_64R6; -def LWR : MMRel, LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>, +def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>, ISA_MIPS1_NOT_32R6_64R6; -def SWL : MMRel, StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>, +def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>, ISA_MIPS1_NOT_32R6_64R6; -def SWR : MMRel, StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, +def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, ISA_MIPS1_NOT_32R6_64R6; +} +let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions -def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>, +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 SWC2 : StdMMR6Rel, SW_FT2<"swc2", COP2Opnd, II_SWC2, store>, - LW_FM<0x3a>, ISA_MIPS1_NOT_32R6_64R6; -def LDC2 : StdMMR6Rel, LW_FT2<"ldc2", COP2Opnd, II_LDC2, load>, LW_FM<0x36>, +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; -def SDC2 : StdMMR6Rel, SW_FT2<"sdc2", COP2Opnd, II_SDC2, store>, - LW_FM<0x3e>, ISA_MIPS2_NOT_32R6_64R6; // COP3 Memory Instructions let DecoderNamespace = "COP3_" in { - def LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, LW_FM<0x33>, - ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS; - def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, LW_FM<0x3b>, - ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS; - def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, LW_FM<0x37>, - ISA_MIPS2, NOT_ASE_CNMIPS; - def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, LW_FM<0x3f>, - ISA_MIPS2, NOT_ASE_CNMIPS; + 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, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS2; - def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci", mem_simm16>, SYNCI_FM, - ISA_MIPS32R2; } -let AdditionalPredicates = [NotInMicroMips] in { - def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm10, II_TEQ>, TEQ_FM<0x34>, - ISA_MIPS2; - def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm10, II_TGE>, TEQ_FM<0x30>, - ISA_MIPS2; - def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm10, II_TGEU>, TEQ_FM<0x31>, - ISA_MIPS2; - def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm10, II_TLT>, TEQ_FM<0x32>, - ISA_MIPS2; - def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm10, II_TLTU>, TEQ_FM<0x33>, - ISA_MIPS2; - def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm10, II_TNE>, TEQ_FM<0x36>, - ISA_MIPS2; - - def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM<0xc>, - ISA_MIPS2_NOT_32R6_64R6; - def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM<0x8>, - ISA_MIPS2_NOT_32R6_64R6; - def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, TEQI_FM<0x9>, - ISA_MIPS2_NOT_32R6_64R6; - def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM<0xa>, - ISA_MIPS2_NOT_32R6_64R6; - def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, TEQI_FM<0xb>, - ISA_MIPS2_NOT_32R6_64R6; - def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM<0xe>, - ISA_MIPS2_NOT_32R6_64R6; -} +def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; +def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; let AdditionalPredicates = [NotInMicroMips] in { - def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>, ISA_MIPS1; - def SYSCALL : MMRel, SYS_FT<"syscall", uimm20, II_SYSCALL>, SYS_FM<0xc>, - ISA_MIPS1; - def TRAP : TrapBase<BREAK>, ISA_MIPS1; - def SDBBP : MMRel, SYS_FT<"sdbbp", uimm20, II_SDBBP>, SDBBP_FM, - ISA_MIPS32_NOT_32R6_64R6; + 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 ERET : MMRel, ER_FT<"eret", II_ERET>, ER_FM<0x18, 0x0>, INSN_MIPS3_32; - def ERETNC : MMRel, ER_FT<"eretnc", II_ERETNC>, ER_FM<0x18, 0x1>, - ISA_MIPS32R5; - def DERET : MMRel, ER_FT<"deret", II_DERET>, ER_FM<0x1f, 0x0>, ISA_MIPS32; +def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>, + ISA_MIPS2_NOT_32R6_64R6; +def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>, + ISA_MIPS2_NOT_32R6_64R6; +def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>, + ISA_MIPS2_NOT_32R6_64R6; +def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>, + ISA_MIPS2_NOT_32R6_64R6; +def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>, + ISA_MIPS2_NOT_32R6_64R6; +def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>, + ISA_MIPS2_NOT_32R6_64R6; - def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd, II_EI>, EI_FM<1>, - ISA_MIPS32R2; - def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd, II_DI>, EI_FM<0>, - ISA_MIPS32R2; +let AdditionalPredicates = [NotInMicroMips] in { +def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>; +} +def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>; +def TRAP : TrapBase<BREAK>; +def SDBBP : MMRel, SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; - def WAIT : MMRel, StdMMR6Rel, WAIT_FT<"wait">, WAIT_FM, INSN_MIPS3_32; +let AdditionalPredicates = [NotInMicroMips] in { + def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18, 0x0>, INSN_MIPS3_32; + def ERETNC : MMRel, ER_FT<"eretnc">, ER_FM<0x18, 0x1>, ISA_MIPS32R5; + def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f, 0x0>, ISA_MIPS32; } let AdditionalPredicates = [NotInMicroMips] in { + def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>, ISA_MIPS32R2; + def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>, ISA_MIPS32R2; +} + +let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug + AdditionalPredicates = [NotInMicroMips] in { +def WAIT : WAIT_FT<"wait">, WAIT_FM; + /// Load-linked, Store-conditional -def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_32, ISA_MIPS2_NOT_32R6_64R6; -def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_32, ISA_MIPS2_NOT_32R6_64R6; +def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6; +def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6; } + /// Jump and Branch Instructions -let AdditionalPredicates = [NotInMicroMips, RelocNotPIC] in def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>, - IsBranch, ISA_MIPS1; - -let AdditionalPredicates = [NotInMicroMips] in { -def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6; -def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>, - ISA_MIPS1; -def BEQL : MMRel, CBranchLikely<"beql", brtarget, GPR32Opnd>, + AdditionalRequires<[RelocStatic]>, IsBranch; +def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6; +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>, - ISA_MIPS1; -def BNEL : MMRel, CBranchLikely<"bnel", brtarget, GPR32Opnd>, +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>, ISA_MIPS1; -def BGEZL : MMRel, CBranchZeroLikely<"bgezl", brtarget, 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>, ISA_MIPS1; -def BGTZL : MMRel, CBranchZeroLikely<"bgtzl", brtarget, 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>, ISA_MIPS1; -def BLEZL : MMRel, CBranchZeroLikely<"blezl", brtarget, 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>, ISA_MIPS1; -def BLTZL : MMRel, CBranchZeroLikely<"bltzl", brtarget, 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, brtarget>, ISA_MIPS1; - -def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>, ISA_MIPS1; - -} +def B : UncondBranch<BEQ>; -let AdditionalPredicates = [NotInMicroMips, NoIndirectJumpGuards] in { - def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM, ISA_MIPS1; - def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>, ISA_MIPS1; +def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>; +let AdditionalPredicates = [NotInMicroMips] in { + def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM; + def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>; } -let AdditionalPredicates = [NotInMicroMips] in { - def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>, - ISA_MIPS32_NOT_32R6_64R6; - def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, - ISA_MIPS1_NOT_32R6_64R6; - def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd>, - 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>, - BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6; - def BAL_BR : BAL_BR_Pseudo<BGEZAL, brtarget>, ISA_MIPS1; -} -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips] in { - def TAILCALL : TailCall<J, jmptarget>, ISA_MIPS1; -} -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - NoIndirectJumpGuards] in - def TAILCALLREG : TailCallReg<JR, GPR32Opnd>, ISA_MIPS1_NOT_32R6_64R6; +def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>, + ISA_MIPS32_NOT_32R6_64R6; +def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, + ISA_MIPS1_NOT_32R6_64R6; +def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd, 0>, + 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>; // Indirect branches are matched as PseudoIndirectBranch/PseudoIndirectBranch64 // then are expanded to JR, JR64, JALR, or JALR64 depending on the ISA. -class PseudoIndirectBranchBase<Instruction JumpInst, RegisterOperand RO> : +class PseudoIndirectBranchBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)], - II_IndirectBranchPseudo>, - PseudoInstExpansion<(JumpInst RO:$rs)> { + II_IndirectBranchPseudo> { let isTerminator=1; let isBarrier=1; let hasDelaySlot = 1; let isBranch = 1; let isIndirectBranch = 1; - bit isCTI = 1; } -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - NoIndirectJumpGuards] in - def PseudoIndirectBranch : PseudoIndirectBranchBase<JR, GPR32Opnd>, - ISA_MIPS1_NOT_32R6_64R6; +def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>; // Return instructions are matched as a RetRA instruction, then are expanded // into PseudoReturn/PseudoReturn64 after register allocation. Finally, @@ -2312,7 +1579,6 @@ class PseudoReturnBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs), let isCodeGenOnly = 1; let hasCtrlDep = 1; let hasExtraSrcRegAllocReq = 1; - bit isCTI = 1; } def PseudoReturn : PseudoReturnBase<GPR32Opnd>; @@ -2330,7 +1596,7 @@ def SDT_MipsEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>; def MIPSehret : SDNode<"MipsISD::EH_RETURN", SDT_MipsEHRET, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in { +let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { def MIPSeh_return32 : MipsPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst), [(MIPSehret GPR32:$spoff, GPR32:$dst)]>; def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff, @@ -2339,61 +1605,63 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in } /// Multiply and Divide Instructions. -let AdditionalPredicates = [NotInMicroMips] in { - def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6; - def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6; - def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6; - def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6; - def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>, - ISA_MIPS1_NOT_32R6_64R6; - def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>, - ISA_MIPS1_NOT_32R6_64R6; - def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>, - ISA_MIPS1_NOT_32R6_64R6; - def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>, - ISA_MIPS1_NOT_32R6_64R6; +def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6; +def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6; +def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6; +def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6; + +def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>, + ISA_MIPS1_NOT_32R6_64R6; +def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>, + ISA_MIPS1_NOT_32R6_64R6; +let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug + AdditionalPredicates = [NotInMicroMips] in { +def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>, + ISA_MIPS1_NOT_32R6_64R6; +def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>, + ISA_MIPS1_NOT_32R6_64R6; +} - /// Sign Ext In Register Instructions. - def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, - SEB_FM<0x10, 0x20>, ISA_MIPS32R2; - def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, - SEB_FM<0x18, 0x20>, ISA_MIPS32R2; +/// Sign Ext In Register Instructions. +def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, + SEB_FM<0x10, 0x20>, ISA_MIPS32R2; +def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, + SEB_FM<0x18, 0x20>, ISA_MIPS32R2; - /// Count Leading - def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM<0x20>, - ISA_MIPS32_NOT_32R6_64R6; - def CLO : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM<0x21>, - ISA_MIPS32_NOT_32R6_64R6; +/// Count Leading +def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>, + ISA_MIPS32_NOT_32R6_64R6; +def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>, + ISA_MIPS32_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { /// Word Swap Bytes Within Halfwords def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, SEB_FM<2, 0x20>, ISA_MIPS32R2; +} - /// No operation. - def NOP : PseudoSE<(outs), (ins), []>, - PseudoInstExpansion<(SLL ZERO, ZERO, 0)>, ISA_MIPS1; +/// No operation. +def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; - // FrameIndexes are legalized when they are operands from load/store - // instructions. The same not happens for stack address copies, so an - // add op with mem ComplexPattern is used and the stack address copy - // can be matched. It's similar to Sparc LEA_ADDRi - let AdditionalPredicates = [NotInMicroMips] in - def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>, ISA_MIPS1; +// FrameIndexes are legalized when they are operands from load/store +// instructions. The same not happens for stack address copies, so an +// add op with mem ComplexPattern is used and the stack address copy +// can be matched. It's similar to Sparc LEA_ADDRi +def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; - // MADD*/MSUB* - def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, - ISA_MIPS32_NOT_32R6_64R6; - def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, - ISA_MIPS32_NOT_32R6_64R6; - def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, - ISA_MIPS32_NOT_32R6_64R6; - def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, - ISA_MIPS32_NOT_32R6_64R6; -} +// MADD*/MSUB* +def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, + ISA_MIPS32_NOT_32R6_64R6; +def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, + ISA_MIPS32_NOT_32R6_64R6; +def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, + ISA_MIPS32_NOT_32R6_64R6; +def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, + ISA_MIPS32_NOT_32R6_64R6; let AdditionalPredicates = [NotDSP] in { def PseudoMULT : MultDivPseudo<MULT, ACC64, GPR32Opnd, MipsMult, II_MULT>, @@ -2413,44 +1681,29 @@ def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>, ISA_MIPS32_NOT_32R6_64R6; } +def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV, + 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; +def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU, + 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; let AdditionalPredicates = [NotInMicroMips] in { - def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV, - 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; - def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU, - 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; - def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM, ISA_MIPS1; - // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction - def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, - immZExt5, immZExt5Plus1, MipsExt>, - EXT_FM<0>, ISA_MIPS32R2; - def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5, - uimm5_inssize_plus1, immZExt5, - immZExt5Plus1>, - EXT_FM<4>, ISA_MIPS32R2; +def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM; } +// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction +def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, MipsExt>, + EXT_FM<0>; +def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>; + /// Move Control Registers From/To CPU Registers -let AdditionalPredicates = [NotInMicroMips] in { - def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>, - MFC3OP_FM<0x10, 4, 0>, ISA_MIPS1; - def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>, - MFC3OP_FM<0x10, 0, 0>, ISA_MIPS1; - def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>, - MFC3OP_FM<0x12, 0, 0>, ISA_MIPS1; - def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>, - MFC3OP_FM<0x12, 4, 0>, ISA_MIPS1; -} - -class Barrier<string asmstr, InstrItinClass itin = NoItinerary> : - InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>; -let AdditionalPredicates = [NotInMicroMips] in { - def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM<1>, - ISA_MIPS1; - def EHB : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM<3>, ISA_MIPS1; +def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32; +def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32; +def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd>, MFC3OP_FM<0x12, 0>; +def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd>, MFC3OP_FM<0x12, 4>; - let isCTI = 1 in - def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause", II_PAUSE>, BARRIER_FM<5>, - ISA_MIPS32R2; -} +class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary, + FrmOther, asmstr>; +def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop">, BARRIER_FM<1>; +def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>; +def PAUSE : MMRel, StdMMR6Rel, 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 @@ -2471,64 +1724,46 @@ class JALR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { list<dag> Pattern = []; } -class JR_HB_DESC<RegisterOperand RO> : - InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, JR_HB_DESC_BASE<"jr.hb", RO> { +class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, + JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { let isBranch=1; let isIndirectBranch=1; let hasDelaySlot=1; let isTerminator=1; let isBarrier=1; - bit isCTI = 1; } -class JALR_HB_DESC<RegisterOperand RO> : - InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, JALR_HB_DESC_BASE<"jalr.hb", - RO> { +class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, + JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> { let isIndirectBranch=1; let hasDelaySlot=1; - bit isCTI = 1; } class JR_HB_ENC : JR_HB_FM<8>; class JALR_HB_ENC : JALR_HB_FM<9>; -def JR_HB : JR_HB_DESC<GPR32Opnd>, JR_HB_ENC, ISA_MIPS32R2_NOT_32R6_64R6; -def JALR_HB : JALR_HB_DESC<GPR32Opnd>, JALR_HB_ENC, ISA_MIPS32; +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; -let AdditionalPredicates = [NotInMicroMips, UseIndirectJumpsHazard] in - def JALRHBPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR_HB, RA>; +class TLB<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary, + 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>; - -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - UseIndirectJumpsHazard] in { - def TAILCALLREGHB : TailCallReg<JR_HB, GPR32Opnd>, ISA_MIPS32_NOT_32R6_64R6; - def PseudoIndirectHazardBranch : PseudoIndirectBranchBase<JR_HB, GPR32Opnd>, - ISA_MIPS32R2_NOT_32R6_64R6; -} - -class TLB<string asmstr, InstrItinClass itin = NoItinerary> : - InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>; -let AdditionalPredicates = [NotInMicroMips] in { - def TLBP : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM<0x08>, ISA_MIPS1; - def TLBR : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM<0x01>, ISA_MIPS1; - def TLBWI : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM<0x02>, ISA_MIPS1; - def TLBWR : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM<0x06>, ISA_MIPS1; -} -class CacheOp<string instr_asm, Operand MemOpnd, - InstrItinClass itin = NoItinerary> : +class CacheOp<string instr_asm, Operand MemOpnd> : InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), - !strconcat(instr_asm, "\t$hint, $addr"), [], itin, FrmOther, + !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther, instr_asm> { let DecoderMethod = "DecodeCacheOp"; } -let AdditionalPredicates = [NotInMicroMips] in { - def CACHE : MMRel, CacheOp<"cache", mem, II_CACHE>, CACHEOP_FM<0b101111>, - INSN_MIPS3_32_NOT_32R6_64R6; - def PREF : MMRel, CacheOp<"pref", mem, II_PREF>, CACHEOP_FM<0b110011>, - INSN_MIPS3_32_NOT_32R6_64R6; -} -// FIXME: We are missing the prefx instruction. +def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, + INSN_MIPS3_32_NOT_32R6_64R6; +def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, + INSN_MIPS3_32_NOT_32R6_64R6; + def ROL : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), "rol\t$rs, $rt, $rd">; @@ -2573,193 +1808,87 @@ def : MipsInstAlias<"dror $rd, $rs", def : MipsInstAlias<"dror $rd, $imm", (DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; -def ABSMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), - "abs\t$rd, $rs">; - -def SEQMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "seq $rd, $rs, $rt">, NOT_ASE_CNMIPS; - -def : MipsInstAlias<"seq $rd, $rs", - (SEQMacro GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, - NOT_ASE_CNMIPS; - -def SEQIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32_relaxed:$imm), - "seq $rd, $rs, $imm">, NOT_ASE_CNMIPS; - -def : MipsInstAlias<"seq $rd, $imm", - (SEQIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>, - NOT_ASE_CNMIPS; - -def MULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, - simm32_relaxed:$imm), - "mul\t$rd, $rs, $imm">, - ISA_MIPS1_NOT_32R6_64R6; -def MULOMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, - GPR32Opnd:$rt), - "mulo\t$rd, $rs, $rt">, - ISA_MIPS1_NOT_32R6_64R6; -def MULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, - GPR32Opnd:$rt), - "mulou\t$rd, $rs, $rt">, - ISA_MIPS1_NOT_32R6_64R6; - -// Virtualization ASE -class HYPCALL_FT<string opstr> : - InstSE<(outs), (ins uimm10:$code_), - !strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther, opstr> { - let BaseOpcode = opstr; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def MFGC0 : MMRel, MFC3OP<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, - MFC3OP_FM<0x10, 3, 0>, ISA_MIPS32R5, ASE_VIRT; - def MTGC0 : MMRel, MTC3OP<"mtgc0", COP0Opnd, GPR32Opnd, II_MTGC0>, - MFC3OP_FM<0x10, 3, 2>, ISA_MIPS32R5, ASE_VIRT; - def MFHGC0 : MMRel, MFC3OP<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFHGC0>, - MFC3OP_FM<0x10, 3, 4>, ISA_MIPS32R5, ASE_VIRT; - def MTHGC0 : MMRel, MTC3OP<"mthgc0", COP0Opnd, GPR32Opnd, II_MTHGC0>, - MFC3OP_FM<0x10, 3, 6>, ISA_MIPS32R5, ASE_VIRT; - def TLBGINV : MMRel, TLB<"tlbginv", II_TLBGINV>, COP0_TLB_FM<0b001011>, - ISA_MIPS32R5, ASE_VIRT; - def TLBGINVF : MMRel, TLB<"tlbginvf", II_TLBGINVF>, COP0_TLB_FM<0b001100>, - ISA_MIPS32R5, ASE_VIRT; - def TLBGP : MMRel, TLB<"tlbgp", II_TLBGP>, COP0_TLB_FM<0b010000>, - ISA_MIPS32R5, ASE_VIRT; - def TLBGR : MMRel, TLB<"tlbgr", II_TLBGR>, COP0_TLB_FM<0b001001>, - ISA_MIPS32R5, ASE_VIRT; - def TLBGWI : MMRel, TLB<"tlbgwi", II_TLBGWI>, COP0_TLB_FM<0b001010>, - ISA_MIPS32R5, ASE_VIRT; - def TLBGWR : MMRel, TLB<"tlbgwr", II_TLBGWR>, COP0_TLB_FM<0b001110>, - ISA_MIPS32R5, ASE_VIRT; - def HYPCALL : MMRel, HYPCALL_FT<"hypcall">, - HYPCALL_FM<0b101000>, ISA_MIPS32R5, ASE_VIRT; -} - //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// - -multiclass OneOrTwoOperandMacroImmediateAlias<string Memnomic, - Instruction Opcode, - RegisterOperand RO = GPR32Opnd, - Operand Imm = simm32_relaxed> { - def : MipsInstAlias<!strconcat(Memnomic, " $rs, $rt, $imm"), - (Opcode RO:$rs, - RO:$rt, - Imm:$imm), 0>; - def : MipsInstAlias<!strconcat(Memnomic, " $rs, $imm"), - (Opcode RO:$rs, - RO:$rs, - Imm:$imm), 0>; +def : MipsInstAlias<"move $dst, $src", + (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, + GPR_32 { + let AdditionalPredicates = [NotInMicroMips]; } - +def : MipsInstAlias<"move $dst, $src", + (ADDu GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, + GPR_32 { + let AdditionalPredicates = [NotInMicroMips]; +} +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>, + 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", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; +def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; +let Predicates = [NotInMicroMips] in { +def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; +} +def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32; +def : MipsInstAlias<"not $rt, $rs", + (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; +def : MipsInstAlias<"neg $rt, $rs", + (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; +def : MipsInstAlias<"negu $rt", + (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 0>; +def : MipsInstAlias<"negu $rt, $rs", + (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; +def : MipsInstAlias<"slt $rs, $rt, $imm", + (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; +def : MipsInstAlias<"sltu $rt, $rs, $imm", + (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm16:$imm), 0>; +def : MipsInstAlias<"xor $rs, $rt, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; +def : MipsInstAlias<"xor $rs, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; +def : MipsInstAlias<"or $rs, $rt, $imm", + (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; +def : MipsInstAlias<"or $rs, $imm", + (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; +let AdditionalPredicates = [NotInMicroMips] in { +def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; +} +def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>; +def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>; +def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>; +let AdditionalPredicates = [NotInMicroMips] in { +def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; +} +def : MipsInstAlias<"bnez $rs,$offset", + (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"bnezl $rs,$offset", + (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"beqz $rs,$offset", + (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"beqzl $rs,$offset", + (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; + +def : MipsInstAlias<"break", (BREAK 0, 0), 1>; +def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"move $dst, $src", - (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, - GPR_32, ISA_MIPS1; - def : MipsInstAlias<"move $dst, $src", - (ADDu GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, - GPR_32, ISA_MIPS1; - - def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 1>, - ISA_MIPS1_NOT_32R6_64R6; - - def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>, ISA_MIPS1; - - def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; - - def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, - ISA_MIPS32; - - def : MipsInstAlias<"neg $rt, $rs", - (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1; - def : MipsInstAlias<"neg $rt", - (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1; - def : MipsInstAlias<"negu $rt, $rs", - (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1; - def : MipsInstAlias<"negu $rt", - (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1; - def : MipsInstAlias< - "sgt $rd, $rs, $rt", - (SLT GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; - def : MipsInstAlias< - "sgt $rs, $rt", - (SLT GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; - def : MipsInstAlias< - "sgtu $rd, $rs, $rt", - (SLTu GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; - def : MipsInstAlias< - "sgtu $$rs, $rt", - (SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; - def : MipsInstAlias< - "not $rt, $rs", - (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, ISA_MIPS1; - def : MipsInstAlias< - "not $rt", - (NOR GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, ISA_MIPS1; - - def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>, ISA_MIPS1; - - defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6; - - defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>, ISA_MIPS1; - - defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi>, ISA_MIPS1, GPR_32; - - defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi>, ISA_MIPS1, GPR_32; - - defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi>, ISA_MIPS1, GPR_32; - - defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi>, ISA_MIPS1, GPR_32; - - defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu>, ISA_MIPS1, GPR_32; - - def : MipsInstAlias<"mfgc0 $rt, $rd", - (MFGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, - ISA_MIPS32R5, ASE_VIRT; - def : MipsInstAlias<"mtgc0 $rt, $rd", - (MTGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, - ISA_MIPS32R5, ASE_VIRT; - def : MipsInstAlias<"mfhgc0 $rt, $rd", - (MFHGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, - ISA_MIPS32R5, ASE_VIRT; - def : MipsInstAlias<"mthgc0 $rt, $rd", - (MTHGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, - ISA_MIPS32R5, ASE_VIRT; - def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, - ISA_MIPS1; - def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, - ISA_MIPS1; - def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>, - ISA_MIPS1; - def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>, - ISA_MIPS1; - - def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>, - ISA_MIPS1; - - def : MipsInstAlias<"bnez $rs,$offset", - (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, - ISA_MIPS1; - def : MipsInstAlias<"bnezl $rs,$offset", - (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, - ISA_MIPS2; - def : MipsInstAlias<"beqz $rs,$offset", - (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, - ISA_MIPS1; - def : MipsInstAlias<"beqzl $rs,$offset", - (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, - ISA_MIPS2; - - def : MipsInstAlias<"syscall", (SYSCALL 0), 1>, ISA_MIPS1; - - def : MipsInstAlias<"break", (BREAK 0, 0), 1>, ISA_MIPS1; - def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>, ISA_MIPS1; def : MipsInstAlias<"ei", (EI ZERO), 1>, ISA_MIPS32R2; def : MipsInstAlias<"di", (DI ZERO), 1>, ISA_MIPS32R2; - +} +let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"teq $rs, $rt", (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; def : MipsInstAlias<"tge $rs, $rt", @@ -2772,10 +1901,9 @@ let AdditionalPredicates = [NotInMicroMips] in { (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<"rdhwr $rt, $rs", - (RDHWR GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, ISA_MIPS1; - } +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>, ISA_MIPS1_NOT_32R6_64R6; @@ -2787,48 +1915,21 @@ def : MipsInstAlias<"subu, $rd, $rs, $imm", InvertedImOperand:$imm), 0>; def : MipsInstAlias<"subu $rs, $imm", (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm), 0>; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"sll $rd, $rt, $rs", - (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"sra $rd, $rt, $rs", - (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"srl $rd, $rt, $rs", - (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"sll $rd, $rt", - (SLLV GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; - def : MipsInstAlias<"sra $rd, $rt", - (SRAV GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; - def : MipsInstAlias<"srl $rd, $rt", - (SRLV GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; - def : MipsInstAlias<"seh $rd", (SEH GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MIPS32R2; - def : MipsInstAlias<"seb $rd", (SEB GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MIPS32R2; -} +def : MipsInstAlias<"sra $rd, $rt, $rs", + (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"srl $rd, $rt, $rs", + (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6; -let AdditionalPredicates = [NotInMicroMips] in - def : MipsInstAlias<"sync", (SYNC 0), 1>, ISA_MIPS2; - -def : MipsInstAlias<"mulo $rs, $rt", - (MULOMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"mulou $rs, $rt", - (MULOUMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, - ISA_MIPS1_NOT_32R6_64R6; - -let AdditionalPredicates = [NotInMicroMips] in - def : MipsInstAlias<"hypcall", (HYPCALL 0), 1>, ISA_MIPS32R5, ASE_VIRT; - +def : MipsInstAlias<"sync", + (SYNC 0), 1>, ISA_MIPS2; //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// -// We use uimm32_coerced to accept a 33 bit signed number that is rendered into -// a 32 bit number. class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadImm32 : LoadImmediate32<"li", uimm32_coerced, GPR32Opnd>; +def LoadImm32 : LoadImmediate32<"li", simm32, GPR32Opnd>; class LoadAddressFromReg32<string instr_asm, Operand MemOpnd, RegisterOperand RO> : @@ -2839,21 +1940,17 @@ def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>; class LoadAddressFromImm32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadAddrImm32 : LoadAddressFromImm32<"la", i32imm, GPR32Opnd>; +def LoadAddrImm32 : LoadAddressFromImm32<"la", simm32, GPR32Opnd>; def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), "jal\t$rd, $rs"> ; def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), "jal\t$rs"> ; -class NORIMM_DESC_BASE<RegisterOperand RO, DAGOperand Imm> : - MipsAsmPseudoInst<(outs RO:$rs), (ins RO:$rt, Imm:$imm), - "nor\t$rs, $rt, $imm">; -def NORImm : NORIMM_DESC_BASE<GPR32Opnd, simm32_relaxed>, GPR_32; -def : MipsInstAlias<"nor\t$rs, $imm", (NORImm GPR32Opnd:$rs, GPR32Opnd:$rs, - simm32_relaxed:$imm)>, GPR_32; +def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "nor\t$rs, $rt, $imm"> ; -let hasDelaySlot = 1, isCTI = 1 in { +let hasDelaySlot = 1 in { def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins imm64:$imm64, brtarget:$offset), "bne\t$rt, $imm64, $offset">; @@ -2884,14 +1981,10 @@ def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6; def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; -let isCTI = 1 in class CondBranchImmPseudo<string instr_asm> : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), !strconcat(instr_asm, "\t$rs, $imm, $offset")>; -def BEQLImmMacro : CondBranchImmPseudo<"beql">, ISA_MIPS2_NOT_32R6_64R6; -def BNELImmMacro : CondBranchImmPseudo<"bnel">, ISA_MIPS2_NOT_32R6_64R6; - def BLTImmMacro : CondBranchImmPseudo<"blt">; def BLEImmMacro : CondBranchImmPseudo<"ble">; def BGEImmMacro : CondBranchImmPseudo<"bge">; @@ -2915,76 +2008,17 @@ def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; // Once the tablegen-erated errors are made better, this needs to be fixed and // predicates needs to be restored. -def SDivMacro : MipsAsmPseudoInst<(outs GPR32NonZeroOpnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "div\t$rd, $rs, $rt">, - ISA_MIPS1_NOT_32R6_64R6; -def SDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32:$imm), - "div\t$rd, $rs, $imm">, - ISA_MIPS1_NOT_32R6_64R6; -def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "divu\t$rd, $rs, $rt">, - ISA_MIPS1_NOT_32R6_64R6; -def UDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32:$imm), - "divu\t$rd, $rs, $imm">, - ISA_MIPS1_NOT_32R6_64R6; - - -def : MipsInstAlias<"div $rs, $rt", (SDIV GPR32ZeroOpnd:$rs, - GPR32Opnd:$rt), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"div $rs, $rt", (SDivMacro GPR32NonZeroOpnd:$rs, - GPR32NonZeroOpnd:$rs, - GPR32Opnd:$rt), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"div $rd, $imm", (SDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, - simm32:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; +def SDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "div\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"divu $rt, $rs", (UDIV GPR32ZeroOpnd:$rt, - GPR32Opnd:$rs), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32NonZeroOpnd:$rt, - GPR32NonZeroOpnd:$rt, - GPR32Opnd:$rs), 0>, - ISA_MIPS1_NOT_32R6_64R6; +def UDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "divu\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, - simm32:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; +def DSDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "ddiv\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6; -def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "rem\t$rd, $rs, $rt">, - ISA_MIPS1_NOT_32R6_64R6; -def SRemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32_relaxed:$imm), - "rem\t$rd, $rs, $imm">, - ISA_MIPS1_NOT_32R6_64R6; -def URemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "remu\t$rd, $rs, $rt">, - ISA_MIPS1_NOT_32R6_64R6; -def URemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32_relaxed:$imm), - "remu\t$rd, $rs, $imm">, - ISA_MIPS1_NOT_32R6_64R6; - -def : MipsInstAlias<"rem $rt, $rs", (SRemMacro GPR32Opnd:$rt, GPR32Opnd:$rt, - GPR32Opnd:$rs), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"rem $rd, $imm", (SRemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, - simm32_relaxed:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"remu $rt, $rs", (URemMacro GPR32Opnd:$rt, GPR32Opnd:$rt, - GPR32Opnd:$rs), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"remu $rd, $imm", (URemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, - simm32_relaxed:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; +def DUDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "ddivu\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6; def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; @@ -2995,18 +2029,6 @@ def Ulhu : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), def Ulw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), "ulw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; -def Ush : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), - "ush\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; - -def Usw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), - "usw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; - -def LDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), - (ins mem_simm16:$addr), "ld $rt, $addr">, - ISA_MIPS1_NOT_MIPS3; -def SDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), - (ins mem_simm16:$addr), "sd $rt, $addr">, - ISA_MIPS1_NOT_MIPS3; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// @@ -3018,39 +2040,29 @@ class LoadRegImmPat<Instruction LoadInst, ValueType ValTy, PatFrag Node> : class StoreRegImmPat<Instruction StoreInst, ValueType ValTy> : MipsPat<(store ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>; -// Materialize constants. -multiclass MaterializeImms<ValueType VT, Register ZEROReg, - Instruction ADDiuOp, Instruction LUiOp, - Instruction ORiOp> { - -// Constant synthesis previously relied on the ordering of the patterns below. -// By making the predicates they use non-overlapping, the patterns were -// reordered so that the effect of the newly introduced predicates can be -// observed. - -// Arbitrary immediates -def : MipsPat<(VT LUiORiPred:$imm), (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>; - -// Bits 32-16 set, sign/zero extended. -def : MipsPat<(VT LUiPred:$imm), (LUiOp (HI16 imm:$imm))>; - // Small immediates -def : MipsPat<(VT ORiPred:$imm), (ORiOp ZEROReg, imm:$imm)>; -def : MipsPat<(VT immSExt16:$imm), (ADDiuOp ZEROReg, imm:$imm)>; +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))>; -let AdditionalPredicates = [NotInMicroMips] in - defm : MaterializeImms<i32, ZERO, ADDiu, LUi, ORi>, ISA_MIPS1; +// Arbitrary immediates +def : MipsPat<(i32 imm:$imm), + (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>; // Carry MipsPatterns -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), - (SUBu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1; +def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), + (SUBu GPR32:$lhs, GPR32:$rhs)>; +let AdditionalPredicates = [NotDSP] in { + def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs), + (ADDu GPR32:$lhs, GPR32:$rhs)>; + def : MipsPat<(addc GPR32:$src, immSExt16:$imm), + (ADDiu GPR32:$src, imm:$imm)>; } -def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs), - (ADDu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1, ASE_NOT_DSP; -def : MipsPat<(addc GPR32:$src, immSExt16:$imm), - (ADDiu GPR32:$src, imm:$imm)>, ISA_MIPS1, ASE_NOT_DSP; // Support multiplication for pre-Mips32 targets that don't have // the MUL instruction. @@ -3064,128 +2076,110 @@ def : MipsPat<(MipsSync (i32 immz)), // Call def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), - (JAL texternalsym:$dst)>, ISA_MIPS1; + (JAL texternalsym:$dst)>; //def : MipsPat<(MipsJmpLink GPR32:$dst), // (JALR GPR32:$dst)>; // Tail call -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), - (TAILCALL tglobaladdr:$dst)>, ISA_MIPS1; - def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), - (TAILCALL texternalsym:$dst)>, ISA_MIPS1; -} +def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), + (TAILCALL tglobaladdr:$dst)>; +def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), + (TAILCALL texternalsym:$dst)>; // hi/lo relocs -multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, - Register ZeroReg, RegisterOperand GPROpnd> { - def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>; - def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>; - def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>; - def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>; - def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>; - - def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; - def : MipsPat<(MipsLo tblockaddress:$in), - (Addiu ZeroReg, tblockaddress:$in)>; - def : MipsPat<(MipsLo tjumptable:$in), (Addiu ZeroReg, tjumptable:$in)>; - def : MipsPat<(MipsLo tconstpool:$in), (Addiu ZeroReg, tconstpool:$in)>; - def : MipsPat<(MipsLo tglobaltlsaddr:$in), - (Addiu ZeroReg, tglobaltlsaddr:$in)>; - def : MipsPat<(MipsLo texternalsym:$in), (Addiu ZeroReg, texternalsym:$in)>; - - def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)), - (Addiu GPROpnd:$hi, tglobaladdr:$lo)>; - def : MipsPat<(add GPROpnd:$hi, (MipsLo tblockaddress:$lo)), - (Addiu GPROpnd:$hi, tblockaddress:$lo)>; - def : MipsPat<(add GPROpnd:$hi, (MipsLo tjumptable:$lo)), - (Addiu GPROpnd:$hi, tjumptable:$lo)>; - def : MipsPat<(add GPROpnd:$hi, (MipsLo tconstpool:$lo)), - (Addiu GPROpnd:$hi, tconstpool:$lo)>; - def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaltlsaddr:$lo)), - (Addiu GPROpnd:$hi, tglobaltlsaddr:$lo)>; -} +def : MipsPat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; +def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; +def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; +def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; +def : MipsPat<(MipsHi texternalsym:$in), (LUi texternalsym:$in)>; + +def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; +def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; +def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; +def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; +def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; +def : MipsPat<(MipsLo texternalsym:$in), (ADDiu ZERO, texternalsym:$in)>; + +def : MipsPat<(add GPR32:$hi, (MipsLo tglobaladdr:$lo)), + (ADDiu GPR32:$hi, tglobaladdr:$lo)>; +def : MipsPat<(add GPR32:$hi, (MipsLo tblockaddress:$lo)), + (ADDiu GPR32:$hi, tblockaddress:$lo)>; +def : MipsPat<(add GPR32:$hi, (MipsLo tjumptable:$lo)), + (ADDiu GPR32:$hi, tjumptable:$lo)>; +def : MipsPat<(add GPR32:$hi, (MipsLo tconstpool:$lo)), + (ADDiu GPR32:$hi, tconstpool:$lo)>; +def : MipsPat<(add GPR32:$hi, (MipsLo tglobaltlsaddr:$lo)), + (ADDiu GPR32:$hi, tglobaltlsaddr:$lo)>; + +// gp_rel relocs +def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), + (ADDiu GPR32:$gp, tglobaladdr:$in)>; +def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), + (ADDiu GPR32:$gp, tconstpool:$in)>; // wrapper_pic class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: - MipsPat<(MipsWrapper RC:$gp, node:$in), (ADDiuOp RC:$gp, node:$in)>; - -let AdditionalPredicates = [NotInMicroMips] in { - defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>, ISA_MIPS1; - - def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>, ISA_MIPS1; - def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>, - ISA_MIPS1; + MipsPat<(MipsWrapper RC:$gp, node:$in), + (ADDiuOp RC:$gp, node:$in)>; - def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>, - ISA_MIPS1; +def : WrapperPat<tglobaladdr, ADDiu, GPR32>; +def : WrapperPat<tconstpool, ADDiu, GPR32>; +def : WrapperPat<texternalsym, ADDiu, GPR32>; +def : WrapperPat<tblockaddress, ADDiu, GPR32>; +def : WrapperPat<tjumptable, ADDiu, GPR32>; +def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>; - // gp_rel relocs - def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), - (ADDiu GPR32:$gp, tglobaladdr:$in)>, ISA_MIPS1, ABI_NOT_N64; - def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), - (ADDiu GPR32:$gp, tconstpool:$in)>, ISA_MIPS1, ABI_NOT_N64; - - def : WrapperPat<tglobaladdr, ADDiu, GPR32>, ISA_MIPS1; - def : WrapperPat<tconstpool, ADDiu, GPR32>, ISA_MIPS1; - def : WrapperPat<texternalsym, ADDiu, GPR32>, ISA_MIPS1; - def : WrapperPat<tblockaddress, ADDiu, GPR32>, ISA_MIPS1; - def : WrapperPat<tjumptable, ADDiu, GPR32>, ISA_MIPS1; - def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>, ISA_MIPS1; - - // Mips does not have "not", so we expand our way - def : MipsPat<(not GPR32:$in), - (NOR GPR32Opnd:$in, ZERO)>, ISA_MIPS1; +let AdditionalPredicates = [NotInMicroMips] in { +// Mips does not have "not", so we expand our way +def : MipsPat<(not GPR32:$in), + (NOR GPR32Opnd:$in, ZERO)>; } // extended loads -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>, ISA_MIPS1; - def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>, ISA_MIPS1; - def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>, ISA_MIPS1; +def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; +def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; +def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; - // peepholes - def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>, ISA_MIPS1; -} +// peepholes +def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; // brcond patterns -multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BEQOp1, - Instruction BNEOp, Instruction SLTOp, Instruction SLTuOp, - Instruction SLTiOp, Instruction SLTiuOp, - Register ZEROReg> { +multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BNEOp, + Instruction SLTOp, Instruction SLTuOp, Instruction SLTiOp, + Instruction SLTiuOp, Register ZEROReg> { def : MipsPat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst), (BNEOp RC:$lhs, ZEROReg, bb:$dst)>; def : MipsPat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst), (BEQOp RC:$lhs, ZEROReg, bb:$dst)>; def : MipsPat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst), - (BEQOp1 (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; + (BEQ (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), - (BEQOp1 (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; + (BEQ (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setge RC:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQOp1 (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; + (BEQ (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQOp1 (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; + (BEQ (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setgt RC:$lhs, immSExt16Plus1:$rhs)), bb:$dst), - (BEQOp1 (SLTiOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>; + (BEQ (SLTiOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setugt RC:$lhs, immSExt16Plus1:$rhs)), bb:$dst), - (BEQOp1 (SLTiuOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>; + (BEQ (SLTiuOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst), - (BEQOp1 (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; + (BEQ (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; def : MipsPat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), - (BEQOp1 (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; + (BEQ (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; def : MipsPat<(brcond RC:$cond, bb:$dst), (BNEOp RC:$cond, ZEROReg, bb:$dst)>; } -let AdditionalPredicates = [NotInMicroMips] in { - defm : BrcondPats<GPR32, BEQ, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>, - ISA_MIPS1; - def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), - (BLEZ i32:$lhs, bb:$dst)>, ISA_MIPS1; - def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), - (BGEZ i32:$lhs, bb:$dst)>, ISA_MIPS1; -} + +defm : BrcondPats<GPR32, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>; + +def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), + (BLEZ i32:$lhs, bb:$dst)>; +def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), + (BGEZ i32:$lhs, bb:$dst)>; // setcc patterns multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp, @@ -3200,12 +2194,11 @@ multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp, (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>; } -multiclass SetlePats<RegisterClass RC, Instruction XORiOp, Instruction SLTOp, - Instruction SLTuOp> { +multiclass SetlePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { def : MipsPat<(setle RC:$lhs, RC:$rhs), - (XORiOp (SLTOp RC:$rhs, RC:$lhs), 1)>; + (XORi (SLTOp RC:$rhs, RC:$lhs), 1)>; def : MipsPat<(setule RC:$lhs, RC:$rhs), - (XORiOp (SLTuOp RC:$rhs, RC:$lhs), 1)>; + (XORi (SLTuOp RC:$rhs, RC:$lhs), 1)>; } multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { @@ -3215,56 +2208,48 @@ multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { (SLTuOp RC:$rhs, RC:$lhs)>; } -multiclass SetgePats<RegisterClass RC, Instruction XORiOp, Instruction SLTOp, - Instruction SLTuOp> { +multiclass SetgePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { def : MipsPat<(setge RC:$lhs, RC:$rhs), - (XORiOp (SLTOp RC:$lhs, RC:$rhs), 1)>; + (XORi (SLTOp RC:$lhs, RC:$rhs), 1)>; def : MipsPat<(setuge RC:$lhs, RC:$rhs), - (XORiOp (SLTuOp RC:$lhs, RC:$rhs), 1)>; + (XORi (SLTuOp RC:$lhs, RC:$rhs), 1)>; } -multiclass SetgeImmPats<RegisterClass RC, Instruction XORiOp, - Instruction SLTiOp, Instruction SLTiuOp> { +multiclass SetgeImmPats<RegisterClass RC, Instruction SLTiOp, + Instruction SLTiuOp> { def : MipsPat<(setge RC:$lhs, immSExt16:$rhs), - (XORiOp (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>; + (XORi (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>; def : MipsPat<(setuge RC:$lhs, immSExt16:$rhs), - (XORiOp (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>; + (XORi (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>; } -let AdditionalPredicates = [NotInMicroMips] in { - defm : SeteqPats<GPR32, SLTiu, XOR, SLTu, ZERO>, ISA_MIPS1; - defm : SetlePats<GPR32, XORi, SLT, SLTu>, ISA_MIPS1; - defm : SetgtPats<GPR32, SLT, SLTu>, ISA_MIPS1; - defm : SetgePats<GPR32, XORi, SLT, SLTu>, ISA_MIPS1; - defm : SetgeImmPats<GPR32, XORi, SLTi, SLTiu>, ISA_MIPS1; +defm : SeteqPats<GPR32, SLTiu, XOR, SLTu, ZERO>; +defm : SetlePats<GPR32, SLT, SLTu>; +defm : SetgtPats<GPR32, SLT, SLTu>; +defm : SetgePats<GPR32, SLT, SLTu>; +defm : SetgeImmPats<GPR32, SLTi, SLTiu>; - // bswap pattern - def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>, ISA_MIPS32R2; -} +// bswap pattern +def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; // Load halfword/word patterns. -let AdditionalPredicates = [NotInMicroMips] in { - let AddedComplexity = 40 in { - def : LoadRegImmPat<LBu, i32, zextloadi8>, ISA_MIPS1; - def : LoadRegImmPat<LHu, i32, zextloadi16>, ISA_MIPS1; - def : LoadRegImmPat<LB, i32, sextloadi8>, ISA_MIPS1; - def : LoadRegImmPat<LH, i32, sextloadi16>, ISA_MIPS1; - def : LoadRegImmPat<LW, i32, load>, ISA_MIPS1; +let AddedComplexity = 40 in { + def : LoadRegImmPat<LBu, i32, zextloadi8>; + def : LoadRegImmPat<LH, i32, sextloadi16>; + let AdditionalPredicates = [NotInMicroMips] in { + def : LoadRegImmPat<LW, i32, load>; } +} - // Atomic load patterns. - def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>, ISA_MIPS1; - def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>, ISA_MIPS1; - def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>, ISA_MIPS1; +// Atomic load patterns. +def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>; +def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>; +def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>; - // Atomic store patterns. - def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>, - ISA_MIPS1; - def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>, - ISA_MIPS1; - def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>, - ISA_MIPS1; -} +// Atomic store patterns. +def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>; +def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>; +def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>; //===----------------------------------------------------------------------===// // Floating Point Support @@ -3295,10 +2280,6 @@ include "MipsMSAInstrInfo.td" include "MipsEVAInstrFormats.td" include "MipsEVAInstrInfo.td" -// MT -include "MipsMTInstrFormats.td" -include "MipsMTInstrInfo.td" - // Micromips include "MicroMipsInstrFormats.td" include "MicroMipsInstrInfo.td" @@ -3308,6 +2289,10 @@ include "MicroMipsInstrFPU.td" include "MicroMips32r6InstrFormats.td" include "MicroMips32r6InstrInfo.td" +// Micromips64 r6 +include "MicroMips64r6InstrFormats.td" +include "MicroMips64r6InstrInfo.td" + // Micromips DSP include "MicroMipsDSPInstrFormats.td" include "MicroMipsDSPInstrInfo.td" diff --git a/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h b/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h index a282366f6d4..b3222f5d89e 100644 --- a/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ b/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h @@ -13,7 +13,6 @@ #include "MCTargetDesc/MipsABIFlagsSection.h" #include "MCTargetDesc/MipsABIInfo.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" @@ -25,12 +24,8 @@ struct MipsABIFlagsSection; class MipsTargetStreamer : public MCTargetStreamer { public: MipsTargetStreamer(MCStreamer &S); - - virtual void setPic(bool Value) {} - virtual void emitDirectiveSetMicroMips(); virtual void emitDirectiveSetNoMicroMips(); - virtual void setUsesMicroMips(); virtual void emitDirectiveSetMips16(); virtual void emitDirectiveSetNoMips16(); @@ -40,14 +35,6 @@ public: virtual void emitDirectiveSetNoMacro(); virtual void emitDirectiveSetMsa(); virtual void emitDirectiveSetNoMsa(); - virtual void emitDirectiveSetMt(); - virtual void emitDirectiveSetNoMt(); - virtual void emitDirectiveSetCRC(); - virtual void emitDirectiveSetNoCRC(); - virtual void emitDirectiveSetVirt(); - virtual void emitDirectiveSetNoVirt(); - virtual void emitDirectiveSetGINV(); - virtual void emitDirectiveSetNoGINV(); virtual void emitDirectiveSetAt(); virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); @@ -83,7 +70,6 @@ public: virtual void emitDirectiveSetMips64R5(); virtual void emitDirectiveSetMips64R6(); virtual void emitDirectiveSetDsp(); - virtual void emitDirectiveSetDspr2(); virtual void emitDirectiveSetNoDsp(); virtual void emitDirectiveSetPop(); virtual void emitDirectiveSetPush(); @@ -92,9 +78,8 @@ public: // PIC support virtual void emitDirectiveCpLoad(unsigned RegNo); - virtual bool emitDirectiveCpRestore(int Offset, - function_ref<unsigned()> GetATReg, - SMLoc IDLoc, const MCSubtargetInfo *STI); + virtual void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts, + int Offset); virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); virtual void emitDirectiveCpreturn(unsigned SaveLocation, @@ -105,67 +90,9 @@ public: virtual void emitDirectiveModuleOddSPReg(); virtual void emitDirectiveModuleSoftFloat(); virtual void emitDirectiveModuleHardFloat(); - virtual void emitDirectiveModuleMT(); virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value); virtual void emitDirectiveSetOddSPReg(); virtual void emitDirectiveSetNoOddSPReg(); - virtual void emitDirectiveModuleCRC(); - virtual void emitDirectiveModuleNoCRC(); - virtual void emitDirectiveModuleVirt(); - virtual void emitDirectiveModuleNoVirt(); - virtual void emitDirectiveModuleGINV(); - virtual void emitDirectiveModuleNoGINV(); - - void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, - SMLoc IDLoc, const MCSubtargetInfo *STI); - void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, - SMLoc IDLoc, const MCSubtargetInfo *STI); - void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, - SMLoc IDLoc, const MCSubtargetInfo *STI); - void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0, - int16_t Imm1, int16_t Imm2, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, bool Is64Bit, - const MCSubtargetInfo *STI); - void emitDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, - SMLoc IDLoc, const MCSubtargetInfo *STI); - void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI); - - /// Emit a store instruction with an offset. If the offset is out of range - /// then it will be synthesized using the assembler temporary. - /// - /// GetATReg() is a callback that can be used to obtain the current assembler - /// temporary and is only called when the assembler temporary is required. It - /// must handle the case where no assembler temporary is available (typically - /// by reporting an error). - void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg, - unsigned BaseReg, int64_t Offset, - function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg, - unsigned BaseReg, MCOperand &HiOperand, - MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg, - int64_t Offset, unsigned TmpReg, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg, - MCOperand &HiOperand, MCOperand &LoOperand, - unsigned ATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI); - void emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI); void forbidModuleDirective() { ModuleDirectiveAllowed = false; } void reallowModuleDirective() { ModuleDirectiveAllowed = true; } @@ -223,14 +150,6 @@ public: void emitDirectiveSetNoMacro() override; void emitDirectiveSetMsa() override; void emitDirectiveSetNoMsa() override; - void emitDirectiveSetMt() override; - void emitDirectiveSetNoMt() override; - void emitDirectiveSetCRC() override; - void emitDirectiveSetNoCRC() override; - void emitDirectiveSetVirt() override; - void emitDirectiveSetNoVirt() override; - void emitDirectiveSetGINV() override; - void emitDirectiveSetNoGINV() override; void emitDirectiveSetAt() override; void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; @@ -266,7 +185,6 @@ public: void emitDirectiveSetMips64R5() override; void emitDirectiveSetMips64R6() override; void emitDirectiveSetDsp() override; - void emitDirectiveSetDspr2() override; void emitDirectiveSetNoDsp() override; void emitDirectiveSetPop() override; void emitDirectiveSetPush() override; @@ -275,16 +193,8 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; - - /// Emit a .cprestore directive. If the offset is out of range then it will - /// be synthesized using the assembler temporary. - /// - /// GetATReg() is a callback that can be used to obtain the current assembler - /// temporary and is only called when the assembler temporary is required. It - /// must handle the case where no assembler temporary is available (typically - /// by reporting an error). - bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, - SMLoc IDLoc, const MCSubtargetInfo *STI) override; + void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts, + int Offset) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; void emitDirectiveCpreturn(unsigned SaveLocation, @@ -295,13 +205,6 @@ public: void emitDirectiveModuleOddSPReg() override; void emitDirectiveModuleSoftFloat() override; void emitDirectiveModuleHardFloat() override; - void emitDirectiveModuleMT() override; - void emitDirectiveModuleCRC() override; - void emitDirectiveModuleNoCRC() override; - void emitDirectiveModuleVirt() override; - void emitDirectiveModuleNoVirt() override; - void emitDirectiveModuleGINV() override; - void emitDirectiveModuleNoGINV() override; void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override; void emitDirectiveSetOddSPReg() override; void emitDirectiveSetNoOddSPReg() override; @@ -318,15 +221,12 @@ public: MCELFStreamer &getStreamer(); MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); - void setPic(bool Value) override { Pic = Value; } - void emitLabel(MCSymbol *Symbol) override; void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void finish() override; void emitDirectiveSetMicroMips() override; void emitDirectiveSetNoMicroMips() override; - void setUsesMicroMips() override; void emitDirectiveSetMips16() override; void emitDirectiveSetNoReorder() override; @@ -346,8 +246,8 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; - bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, - SMLoc IDLoc, const MCSubtargetInfo *STI) override; + void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts, + int Offset) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; void emitDirectiveCpreturn(unsigned SaveLocation, |