diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
| -rw-r--r-- | contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 8530 | 
1 files changed, 0 insertions, 8530 deletions
diff --git a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp deleted file mode 100644 index 989cba13efe8..000000000000 --- a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ /dev/null @@ -1,8530 +0,0 @@ -//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsABIFlagsSection.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsMCExpr.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsTargetStreamer.h" -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.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/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCParser/MCAsmParserUtils.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/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 MipsAssemblerOptions *Opts) { -    ATReg = Opts->getATRegIndex(); -    Reorder = Opts->isReorder(); -    Macro = Opts->isMacro(); -    Features = Opts->getFeatures(); -  } - -  unsigned getATRegIndex() const { return ATReg; } -  bool setATRegIndex(unsigned Reg) { -    if (Reg > 31) -      return false; - -    ATReg = Reg; -    return true; -  } - -  bool isReorder() const { return Reorder; } -  void setReorder() { Reorder = true; } -  void setNoReorder() { Reorder = false; } - -  bool isMacro() const { return Macro; } -  void setMacro() { Macro = true; } -  void setNoMacro() { Macro = false; } - -  const FeatureBitset &getFeatures() const { return Features; } -  void setFeatures(const FeatureBitset &Features_) { Features = Features_; } - -  // Set of features that are either architecture features or referenced -  // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6). -  // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). -  // The reason we need this mask is explained in the selectArch function. -  // FIXME: Ideally we would like TableGen to generate this information. -  static const FeatureBitset AllArchRelatedMask; - -private: -  unsigned ATReg = 1; -  bool Reorder = true; -  bool Macro = true; -  FeatureBitset Features; -}; - -} // end anonymous namespace - -const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { -    Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3, -    Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4, -    Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5, -    Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2, -    Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6, -    Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3, -    Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips, -    Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, -    Mips::FeatureNaN2008 -}; - -namespace { - -class MipsAsmParser : public MCTargetAsmParser { -  MipsTargetStreamer &getTargetStreamer() { -    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); -    return static_cast<MipsTargetStreamer &>(TS); -  } - -  MipsABIInfo ABI; -  SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions; -  MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a -                       // nullptr, which indicates that no function is currently -                       // selected. This usually happens after an '.end func' -                       // directive. -  bool IsLittleEndian; -  bool IsPicEnabled; -  bool IsCpRestoreSet; -  int CpRestoreOffset; -  unsigned GPReg; -  unsigned CpSaveLocation; -  /// 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, -                               OperandVector &Operands, MCStreamer &Out, -                               uint64_t &ErrorInfo, -                               bool MatchingInlineAsm) override; - -  /// Parse a register as used in CFI directives -  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - -  bool parseParenSuffix(StringRef Name, OperandVector &Operands); - -  bool parseBracketSuffix(StringRef Name, OperandVector &Operands); - -  bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID); - -  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, -                        SMLoc NameLoc, OperandVector &Operands) override; - -  bool ParseDirective(AsmToken DirectiveID) override; - -  OperandMatchResultTy parseMemOperand(OperandVector &Operands); -  OperandMatchResultTy -  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 parseRegisterList(OperandVector &Operands); - -  bool searchSymbolAlias(OperandVector &Operands); - -  bool parseOperand(OperandVector &, StringRef Mnemonic); - -  enum MacroExpanderResultTy { -    MER_NotAMacro, -    MER_Success, -    MER_Fail, -  }; - -  // Expands assembly pseudo instructions. -  MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, -                                             MCStreamer &Out, -                                             const MCSubtargetInfo *STI); - -  bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                         const MCSubtargetInfo *STI); - -  bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, -                     bool Is32BitImm, bool IsAddress, SMLoc IDLoc, -                     MCStreamer &Out, const MCSubtargetInfo *STI); - -  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); - -  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); - -  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); - -  bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                               const MCSubtargetInfo *STI); - -  bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                            const MCSubtargetInfo *STI); - -  bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                       const MCSubtargetInfo *STI); - -  bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                          const MCSubtargetInfo *STI); - -  bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                    const MCSubtargetInfo *STI, const bool IsMips64, -                    const bool Signed); - -  bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc, -                   MCStreamer &Out, const MCSubtargetInfo *STI); - -  bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out, -                 const MCSubtargetInfo *STI); - -  bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                 const MCSubtargetInfo *STI); - -  bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                 const MCSubtargetInfo *STI); - -  bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                 const MCSubtargetInfo *STI); - -  bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                    const MCSubtargetInfo *STI); - -  bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                    const MCSubtargetInfo *STI); - -  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); - -  bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                             const MCSubtargetInfo *STI, bool IsLoad); - -  bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                           const MCSubtargetInfo *STI); - -  bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                 const MCSubtargetInfo *STI); - -  bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                  const MCSubtargetInfo *STI); - -  bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                       const MCSubtargetInfo *STI); - -  bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                     const MCSubtargetInfo *STI); - -  bool reportParseError(Twine ErrorMsg); -  bool reportParseError(SMLoc Loc, Twine ErrorMsg); - -  bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); - -  bool isEvaluated(const MCExpr *Expr); -  bool parseSetMips0Directive(); -  bool parseSetArchDirective(); -  bool parseSetFeature(uint64_t Feature); -  bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup. -  bool parseDirectiveCpLoad(SMLoc Loc); -  bool parseDirectiveCpLocal(SMLoc Loc); -  bool parseDirectiveCpRestore(SMLoc Loc); -  bool parseDirectiveCPSetup(); -  bool parseDirectiveCPReturn(); -  bool parseDirectiveNaN(); -  bool parseDirectiveSet(); -  bool parseDirectiveOption(); -  bool parseInsnDirective(); -  bool parseRSectionDirective(StringRef Section); -  bool parseSSectionDirective(StringRef Section, unsigned Type); - -  bool parseSetAtDirective(); -  bool parseSetNoAtDirective(); -  bool parseSetMacroDirective(); -  bool parseSetNoMacroDirective(); -  bool parseSetMsaDirective(); -  bool parseSetNoMsaDirective(); -  bool parseSetNoDspDirective(); -  bool parseSetReorderDirective(); -  bool parseSetNoReorderDirective(); -  bool parseSetMips16Directive(); -  bool parseSetNoMips16Directive(); -  bool parseSetFpDirective(); -  bool parseSetOddSPRegDirective(); -  bool parseSetNoOddSPRegDirective(); -  bool parseSetPopDirective(); -  bool parseSetPushDirective(); -  bool parseSetSoftFloatDirective(); -  bool parseSetHardFloatDirective(); -  bool parseSetMtDirective(); -  bool parseSetNoMtDirective(); -  bool parseSetNoCRCDirective(); -  bool parseSetNoVirtDirective(); -  bool parseSetNoGINVDirective(); - -  bool parseSetAssignment(); - -  bool parseDirectiveGpWord(); -  bool parseDirectiveGpDWord(); -  bool parseDirectiveDtpRelWord(); -  bool parseDirectiveDtpRelDWord(); -  bool parseDirectiveTpRelWord(); -  bool parseDirectiveTpRelDWord(); -  bool parseDirectiveModule(); -  bool parseDirectiveModuleFP(); -  bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, -                       StringRef Directive); - -  bool parseInternalDirectiveReallowModule(); - -  bool eatComma(StringRef ErrorStr); - -  int matchCPURegisterName(StringRef Symbol); - -  int matchHWRegsRegisterName(StringRef Symbol); - -  int matchFPURegisterName(StringRef Name); - -  int matchFCCRegisterName(StringRef Name); - -  int matchACRegisterName(StringRef Name); - -  int matchMSA128RegisterName(StringRef Name); - -  int matchMSA128CtrlRegisterName(StringRef Name); - -  unsigned getReg(int RC, 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); - -  // Helper function that checks if the value of a vector index is within the -  // boundaries of accepted values for each RegisterKind -  // Example: INSERT.B $w0[n], $1 => 16 > n >= 0 -  bool validateMSAIndex(int Val, int RegKind); - -  // Selects a new architecture by updating the FeatureBits with the necessary -  // info including implied dependencies. -  // Internally, it clears all the feature bits related to *any* architecture -  // and selects the new one using the ToggleFeature functionality of the -  // MCSubtargetInfo object that handles implied dependencies. The reason we -  // clear all the arch related bits manually is because ToggleFeature only -  // clears the features that imply the feature being cleared and not the -  // features implied by the feature being cleared. This is easier to see -  // with an example: -  //  -------------------------------------------------- -  // | Feature         | Implies                        | -  // | -------------------------------------------------| -  // | FeatureMips1    | None                           | -  // | FeatureMips2    | FeatureMips1                   | -  // | FeatureMips3    | FeatureMips2 | FeatureMipsGP64 | -  // | FeatureMips4    | FeatureMips3                   | -  // | ...             |                                | -  //  -------------------------------------------------- -  // -  // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 | -  // FeatureMipsGP64 | FeatureMips1) -  // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). -  void selectArch(StringRef ArchFeature) { -    MCSubtargetInfo &STI = copySTI(); -    FeatureBitset FeatureBits = STI.getFeatureBits(); -    FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; -    STI.setFeatureBits(FeatureBits); -    setAvailableFeatures( -        ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature))); -    AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); -  } - -  void setFeatureBits(uint64_t Feature, StringRef FeatureString) { -    if (!(getSTI().getFeatureBits()[Feature])) { -      MCSubtargetInfo &STI = copySTI(); -      setAvailableFeatures( -          ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); -      AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); -    } -  } - -  void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { -    if (getSTI().getFeatureBits()[Feature]) { -      MCSubtargetInfo &STI = copySTI(); -      setAvailableFeatures( -          ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); -      AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); -    } -  } - -  void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { -    setFeatureBits(Feature, FeatureString); -    AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); -  } - -  void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { -    clearFeatureBits(Feature, FeatureString); -    AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); -  } - -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 -  }; - -  MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, -                const MCInstrInfo &MII, const MCTargetOptions &Options) -    : MCTargetAsmParser(Options, sti, MII), -        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())); - -    // Remember the initial assembler options. The user can not modify these. -    AssemblerOptions.push_back( -        llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits())); - -    // Create an assembler options environment for the user to modify. -    AssemblerOptions.push_back( -        llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits())); - -    getTargetStreamer().updateABIInfo(*this); - -    if (!isABI_O32() && !useOddSPReg() != 0) -      report_fatal_error("-mno-odd-spreg requires the O32 ABI"); - -    CurrentFn = nullptr; - -    IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent(); - -    IsCpRestoreSet = false; -    CpRestoreOffset = -1; -    GPReg = ABI.GetGlobalPtr(); - -    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); -  } - -  /// True if all of $fcc0 - $fcc7 exist for the current ISA. -  bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } - -  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(); } -  bool isABI_O32() const { return ABI.IsO32(); } -  bool isABI_FPXX() const { -    return getSTI().getFeatureBits()[Mips::FeatureFPXX]; -  } - -  bool useOddSPReg() const { -    return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]); -  } - -  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]; -  } - -  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]); -  } - -  bool hasCnMipsP() const { -    return (getSTI().getFeatureBits()[Mips::FeatureCnMipsP]); -  } - -  bool inPicMode() { -    return IsPicEnabled; -  } - -  bool inMips16Mode() const { -    return getSTI().getFeatureBits()[Mips::FeatureMips16]; -  } - -  bool useTraps() const { -    return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV]; -  } - -  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); - -  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); -    } -  } -}; - -/// MipsOperand - Instances of this class represent a parsed Mips machine -/// instruction. -class MipsOperand : public MCParsedAsmOperand { -public: -  /// Broad categories of register classes -  /// The exact class is finalized by the render method. -  enum RegKind { -    RegKind_GPR = 1,      /// GPR32 and GPR64 (depending on isGP64bit()) -    RegKind_FGR = 2,      /// FGR32, FGR64, AFGR64 (depending on context and -                          /// isFP64bit()) -    RegKind_FCC = 4,      /// FCC -    RegKind_MSA128 = 8,   /// MSA128[BHWD] (makes no difference which) -    RegKind_MSACtrl = 16, /// MSA control registers -    RegKind_COP2 = 32,    /// COP2 -    RegKind_ACC = 64,     /// HI32DSP, LO32DSP, and ACC64DSP (depending on -                          /// context). -    RegKind_CCR = 128,    /// CCR -    RegKind_HWRegs = 256, /// HWRegs -    RegKind_COP3 = 512,   /// COP3 -    RegKind_COP0 = 1024,  /// COP0 -    /// Potentially any (e.g. $1) -    RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 | -                      RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC | -                      RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0 -  }; - -private: -  enum KindTy { -    k_Immediate,     /// An immediate (possibly involving symbol references) -    k_Memory,        /// Base + Offset Memory Address -    k_RegisterIndex, /// A register index in one or more RegKind. -    k_Token,         /// A simple token -    k_RegList,       /// A physical register list -  } 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; - -  struct Token { -    const char *Data; -    unsigned Length; -  }; - -  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; -  }; - -  struct ImmOp { -    const MCExpr *Val; -  }; - -  struct MemOp { -    MipsOperand *Base; -    const MCExpr *Off; -  }; - -  struct RegListOp { -    SmallVector<unsigned, 10> *List; -  }; - -  union { -    struct Token Tok; -    struct RegIdxOp RegIdx; -    struct ImmOp Imm; -    struct MemOp Mem; -    struct RegListOp RegList; -  }; - -  SMLoc StartLoc, EndLoc; - -  /// Internal constructor for register kinds -  static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str, -                                                RegKind RegKind, -                                                const MCRegisterInfo *RegInfo, -                                                SMLoc S, SMLoc E, -                                                MipsAsmParser &Parser) { -    auto Op = llvm::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; -  } - -public: -  /// Coerce the register to GPR32 and return the real register for the current -  /// target. -  unsigned getGPR32Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); -    AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc); -    unsigned ClassID = Mips::GPR32RegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to GPR32 and return the real register for the current -  /// target. -  unsigned getGPRMM16Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); -    unsigned ClassID = Mips::GPR32RegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to GPR64 and return the real register for the current -  /// target. -  unsigned getGPR64Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); -    unsigned ClassID = Mips::GPR64RegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -private: -  /// Coerce the register to AFGR64 and return the real register for the current -  /// target. -  unsigned getAFGR64Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); -    if (RegIdx.Index % 2 != 0) -      AsmParser.Warning(StartLoc, "Float register should be even."); -    return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID) -        .getRegister(RegIdx.Index / 2); -  } - -  /// Coerce the register to FGR64 and return the real register for the current -  /// target. -  unsigned getFGR64Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); -    return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID) -        .getRegister(RegIdx.Index); -  } - -  /// Coerce the register to FGR32 and return the real register for the current -  /// target. -  unsigned getFGR32Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); -    return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID) -        .getRegister(RegIdx.Index); -  } - -  /// Coerce the register to FCC and return the real register for the current -  /// target. -  unsigned getFCCReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!"); -    return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID) -        .getRegister(RegIdx.Index); -  } - -  /// Coerce the register to MSA128 and return the real register for the current -  /// target. -  unsigned getMSA128Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!"); -    // It doesn't matter which of the MSA128[BHWD] classes we use. They are all -    // identical -    unsigned ClassID = Mips::MSA128BRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to MSACtrl and return the real register for the -  /// current target. -  unsigned getMSACtrlReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!"); -    unsigned ClassID = Mips::MSACtrlRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to COP0 and return the real register for the -  /// current target. -  unsigned getCOP0Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!"); -    unsigned ClassID = Mips::COP0RegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to COP2 and return the real register for the -  /// current target. -  unsigned getCOP2Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!"); -    unsigned ClassID = Mips::COP2RegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to COP3 and return the real register for the -  /// current target. -  unsigned getCOP3Reg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!"); -    unsigned ClassID = Mips::COP3RegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to ACC64DSP and return the real register for the -  /// current target. -  unsigned getACC64DSPReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); -    unsigned ClassID = Mips::ACC64DSPRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to HI32DSP and return the real register for the -  /// current target. -  unsigned getHI32DSPReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); -    unsigned ClassID = Mips::HI32DSPRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to LO32DSP and return the real register for the -  /// current target. -  unsigned getLO32DSPReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); -    unsigned ClassID = Mips::LO32DSPRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to CCR and return the real register for the -  /// current target. -  unsigned getCCRReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!"); -    unsigned ClassID = Mips::CCRRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -  /// Coerce the register to HWRegs and return the real register for the -  /// current target. -  unsigned getHWRegsReg() const { -    assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!"); -    unsigned ClassID = Mips::HWRegsRegClassID; -    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); -  } - -public: -  void addExpr(MCInst &Inst, const MCExpr *Expr) const { -    // Add as immediate when possible.  Null MCExpr = 0. -    if (!Expr) -      Inst.addOperand(MCOperand::createImm(0)); -    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) -      Inst.addOperand(MCOperand::createImm(CE->getValue())); -    else -      Inst.addOperand(MCOperand::createExpr(Expr)); -  } - -  void addRegOperands(MCInst &Inst, unsigned N) const { -    llvm_unreachable("Use a custom parser instead"); -  } - -  /// 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())); -  } - -  void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -  } - -  void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); -  } - -  void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    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 -  void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getGPR64Reg())); -  } - -  void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    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())); -  } - -  void addFGR32AsmRegOperands(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. -    // 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"); -  } - -  void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getFCCReg())); -  } - -  void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getMSA128Reg())); -  } - -  void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getMSACtrlReg())); -  } - -  void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getCOP0Reg())); -  } - -  void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getCOP2Reg())); -  } - -  void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getCOP3Reg())); -  } - -  void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getACC64DSPReg())); -  } - -  void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getHI32DSPReg())); -  } - -  void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getLO32DSPReg())); -  } - -  void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getCCRReg())); -  } - -  void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    Inst.addOperand(MCOperand::createReg(getHWRegsReg())); -  } - -  template <unsigned Bits, int Offset = 0, int AdjustOffset = 0> -  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 += Offset; -    Imm += AdjustOffset; -    Inst.addOperand(MCOperand::createImm(Imm)); -  } - -  void addImmOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); -    const MCExpr *Expr = getImm(); -    addExpr(Inst, Expr); -  } - -  void addMemOperands(MCInst &Inst, unsigned N) const { -    assert(N == 2 && "Invalid number of operands!"); - -    Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit() -                                             ? getMemBase()->getGPR64Reg() -                                             : getMemBase()->getGPR32Reg())); - -    const MCExpr *Expr = getMemOff(); -    addExpr(Inst, Expr); -  } - -  void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const { -    assert(N == 2 && "Invalid number of operands!"); - -    Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg())); - -    const MCExpr *Expr = getMemOff(); -    addExpr(Inst, Expr); -  } - -  void addRegListOperands(MCInst &Inst, unsigned N) const { -    assert(N == 1 && "Invalid number of operands!"); - -    for (auto RegNo : getRegList()) -      Inst.addOperand(MCOperand::createReg(RegNo)); -  } - -  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; -  } - -  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); -  } - -  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 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()); -  } - -  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()); -  } - -  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; - -    int Size = RegList.List->size(); -    if (Size < 2 || Size > 5) -      return false; - -    unsigned R0 = RegList.List->front(); -    unsigned R1 = RegList.List->back(); -    if (!((R0 == Mips::S0 && R1 == Mips::RA) || -          (R0 == Mips::S0_64 && R1 == Mips::RA_64))) -      return false; - -    int PrevReg = *RegList.List->begin(); -    for (int i = 1; i < Size - 1; i++) { -      int Reg = (*(RegList.List))[i]; -      if ( Reg != PrevReg + 1) -        return false; -      PrevReg = Reg; -    } - -    return true; -  } - -  bool isInvNum() const { return Kind == k_Immediate; } - -  bool isLSAImm() const { -    if (!isConstantImm()) -      return false; -    int64_t Val = getConstantImm(); -    return 1 <= Val && Val <= 4; -  } - -  bool isRegList() const { return Kind == k_RegList; } - -  StringRef getToken() const { -    assert(Kind == k_Token && "Invalid access!"); -    return StringRef(Tok.Data, Tok.Length); -  } - -  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. -    if (Kind == k_RegisterIndex && RegIdx.Index == 0 && -        RegIdx.Kind & RegKind_GPR) -      return getGPR32Reg(); // FIXME: GPR64 too - -    llvm_unreachable("Invalid access!"); -    return 0; -  } - -  const MCExpr *getImm() const { -    assert((Kind == k_Immediate) && "Invalid access!"); -    return Imm.Val; -  } - -  int64_t getConstantImm() const { -    const MCExpr *Val = getImm(); -    int64_t Value = 0; -    (void)Val->evaluateAsAbsolute(Value); -    return Value; -  } - -  MipsOperand *getMemBase() const { -    assert((Kind == k_Memory) && "Invalid access!"); -    return Mem.Base; -  } - -  const MCExpr *getMemOff() const { -    assert((Kind == k_Memory) && "Invalid access!"); -    return Mem.Off; -  } - -  int64_t getConstantMemOff() const { -    return static_cast<const MCConstantExpr *>(getMemOff())->getValue(); -  } - -  const SmallVectorImpl<unsigned> &getRegList() const { -    assert((Kind == k_RegList) && "Invalid access!"); -    return *(RegList.List); -  } - -  static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, -                                                  MipsAsmParser &Parser) { -    auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser); -    Op->Tok.Data = Str.data(); -    Op->Tok.Length = Str.size(); -    Op->StartLoc = S; -    Op->EndLoc = S; -    return Op; -  } - -  /// 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); -  } - -  /// 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); -  } - -  /// 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); -  } - -  /// 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, -                  SMLoc S, SMLoc E, MipsAsmParser &Parser) { -    return CreateReg(Index, Str, 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); -  } - -  /// 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); -  } - -  /// 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); -  } - -  /// 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); -  } - -  static std::unique_ptr<MipsOperand> -  CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) { -    auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser); -    Op->Imm.Val = Val; -    Op->StartLoc = S; -    Op->EndLoc = E; -    return Op; -  } - -  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); -    Op->Mem.Base = Base.release(); -    Op->Mem.Off = Off; -    Op->StartLoc = S; -    Op->EndLoc = E; -    return Op; -  } - -  static std::unique_ptr<MipsOperand> -  CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc, -                MipsAsmParser &Parser) { -    assert(Regs.size() > 0 && "Empty list not allowed"); - -    auto Op = llvm::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; -  } - -  bool isGPRAsmReg() const { -    return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; -  } - -  bool isMM16AsmReg() const { -    if (!(isRegIdx() && RegIdx.Kind)) -      return false; -    return ((RegIdx.Index >= 2 && RegIdx.Index <= 7) -            || RegIdx.Index == 16 || RegIdx.Index == 17); - -  } -  bool isMM16AsmRegZero() const { -    if (!(isRegIdx() && RegIdx.Kind)) -      return false; -    return (RegIdx.Index == 0 || -            (RegIdx.Index >= 2 && RegIdx.Index <= 7) || -            RegIdx.Index == 17); -  } - -  bool 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; -    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; -  } - -  /// getStartLoc - Get the location of the first token of this operand. -  SMLoc getStartLoc() const override { return StartLoc; } -  /// getEndLoc - Get the location of the last token of this operand. -  SMLoc getEndLoc() const override { return EndLoc; } - -  void print(raw_ostream &OS) const override { -    switch (Kind) { -    case k_Immediate: -      OS << "Imm<"; -      OS << *Imm.Val; -      OS << ">"; -      break; -    case k_Memory: -      OS << "Mem<"; -      Mem.Base->print(OS); -      OS << ", "; -      OS << *Mem.Off; -      OS << ">"; -      break; -    case k_RegisterIndex: -      OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", " -         << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">"; -      break; -    case k_Token: -      OS << getToken(); -      break; -    case k_RegList: -      OS << "RegList< "; -      for (auto Reg : (*RegList.List)) -        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; -    } -    } -  } -}; // class MipsOperand - -} // end anonymous 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: -    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; -  } -} - -static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) { -  if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) { -    return &SRExpr->getSymbol(); -  } - -  if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) { -    const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS()); -    const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS()); - -    if (LHSSym) -      return LHSSym; - -    if (RHSSym) -      return RHSSym; - -    return nullptr; -  } - -  if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr)) -    return getSingleMCSymbol(UExpr->getSubExpr()); - -  return nullptr; -} - -static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { -  if (isa<MCSymbolRefExpr>(Expr)) -    return 1; - -  if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) -    return countMCSymbolRefExpr(BExpr->getLHS()) + -           countMCSymbolRefExpr(BExpr->getRHS()); - -  if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr)) -    return countMCSymbolRefExpr(UExpr->getSubExpr()); - -  return 0; -} - -bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, -                                       MCStreamer &Out, -                                       const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); -  bool ExpandedJalSym = false; - -  Inst.setLoc(IDLoc); - -  if (MCID.isBranch() || MCID.isCall()) { -    const unsigned Opcode = Inst.getOpcode(); -    MCOperand Offset; - -    switch (Opcode) { -    default: -      break; -    case Mips::BBIT0: -    case Mips::BBIT032: -    case Mips::BBIT1: -    case Mips::BBIT132: -      assert(hasCnMips() && "instruction only valid for octeon cpus"); -      LLVM_FALLTHROUGH; - -    case Mips::BEQ: -    case Mips::BNE: -    case Mips::BEQ_MM: -    case Mips::BNE_MM: -      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(inMicroMipsMode() ? 17 : 18, Offset.getImm())) -        return Error(IDLoc, "branch target out of range"); -      if (OffsetToAlignment(Offset.getImm(), -                            1LL << (inMicroMipsMode() ? 1 : 2))) -        return Error(IDLoc, "branch to misaligned address"); -      break; -    case Mips::BGEZ: -    case Mips::BGTZ: -    case Mips::BLEZ: -    case Mips::BLTZ: -    case Mips::BGEZAL: -    case Mips::BLTZAL: -    case Mips::BC1F: -    case Mips::BC1T: -    case Mips::BGEZ_MM: -    case Mips::BGTZ_MM: -    case Mips::BLEZ_MM: -    case Mips::BLTZ_MM: -    case Mips::BGEZAL_MM: -    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()) -        break; // We'll deal with this situation later on when applying fixups. -      if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) -        return Error(IDLoc, "branch target out of range"); -      if (OffsetToAlignment(Offset.getImm(), -                            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: -    case Mips::BNEZC16_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 (!isInt<8>(Offset.getImm())) -        return Error(IDLoc, "branch target out of range"); -      if (OffsetToAlignment(Offset.getImm(), 2LL)) -        return Error(IDLoc, "branch to misaligned address"); -      break; -    } -  } - -  // SSNOP is deprecated on MIPS32r6/MIPS64r6 -  // We still accept it but it is a normal nop. -  if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) { -    std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; -    Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a " -                                                      "nop instruction"); -  } - -  if (hasCnMips()) { -    const unsigned Opcode = Inst.getOpcode(); -    MCOperand Opnd; -    int Imm; - -    switch (Opcode) { -      default: -        break; - -      case Mips::BBIT0: -      case Mips::BBIT032: -      case Mips::BBIT1: -      case Mips::BBIT132: -        assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); -        // The offset is handled above -        Opnd = Inst.getOperand(1); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 || -                              Opcode == Mips::BBIT1 ? 63 : 31)) -          return Error(IDLoc, "immediate operand value out of range"); -        if (Imm > 31) { -          Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032 -                                               : Mips::BBIT132); -          Inst.getOperand(1).setImm(Imm - 32); -        } -        break; - -      case Mips::SEQi: -      case Mips::SNEi: -        assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (!isInt<10>(Imm)) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -    } -  } - -  // 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) && -      inPicMode()) { -    warnIfNoMacro(IDLoc); - -    const MCExpr *JalExpr = Inst.getOperand(0).getExpr(); - -    // We can do this expansion if there's only 1 symbol in the argument -    // expression. -    if (countMCSymbolRefExpr(JalExpr) > 1) -      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. -    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 (isABI_O32()) { -        // If it's a local symbol and the O32 ABI is being used, we expand to: -        //  lw $25, 0($gp) -        //    R_(MICRO)MIPS_GOT16  label -        //  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, GPReg, -                     MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); -        TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, -                     MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); -      } 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()); - -        TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, -                     GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc, -                     STI); -      } -    } 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()); - -      TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg, -                   MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); -    } - -    MCInst JalrInst; -    if (IsCpRestoreSet && inMicroMipsMode()) -      JalrInst.setOpcode(Mips::JALRS_MM); -    else -      JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); -    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); -    } - -    Inst = JalrInst; -    ExpandedJalSym = true; -  } - -  bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0; -  if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { -    // 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++) { -      const MCOperandInfo &OpInfo = MCID.OpInfo[i]; -      if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || -          (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { -        MCOperand &Op = Inst.getOperand(i); -        if (Op.isImm()) { -          int64_t MemOffset = Op.getImm(); -          if (MemOffset < -32768 || MemOffset > 32767) { -            // Offset can't exceed 16bit value. -            expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); -            return getParser().hasPendingError(); -          } -        } else if (Op.isExpr()) { -          const MCExpr *Expr = Op.getExpr(); -          if (Expr->getKind() == MCExpr::SymbolRef) { -            const MCSymbolRefExpr *SR = -                static_cast<const MCSymbolRefExpr *>(Expr); -            if (SR->getKind() == MCSymbolRefExpr::VK_None) { -              // Expand symbol. -              expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); -              return getParser().hasPendingError(); -            } -          } else if (!isEvaluated(Expr)) { -            expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); -            return getParser().hasPendingError(); -          } -        } -      } -    } // for -  }   // if load/store - -  if (inMicroMipsMode()) { -    if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) { -      // Try to create 16-bit GP relative load instruction. -      for (unsigned i = 0; i < MCID.getNumOperands(); i++) { -        const MCOperandInfo &OpInfo = MCID.OpInfo[i]; -        if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || -            (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { -          MCOperand &Op = Inst.getOperand(i); -          if (Op.isImm()) { -            int MemOffset = Op.getImm(); -            MCOperand &DstReg = Inst.getOperand(0); -            MCOperand &BaseReg = Inst.getOperand(1); -            if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) && -                getContext().getRegisterInfo()->getRegClass( -                  Mips::GPRMM16RegClassID).contains(DstReg.getReg()) && -                (BaseReg.getReg() == Mips::GP || -                BaseReg.getReg() == Mips::GP_64)) { - -              TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, -                           IDLoc, STI); -              return false; -            } -          } -        } -      } // for -    }   // if load - -    // TODO: Handle this with the AsmOperandClass.PredicateMethod. - -    MCOperand Opnd; -    int Imm; - -    switch (Inst.getOpcode()) { -      default: -        break; -      case Mips::ADDIUSP_MM: -        Opnd = Inst.getOperand(0); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) || -            Imm % 4 != 0) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::SLL16_MM: -      case Mips::SRL16_MM: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < 1 || Imm > 8) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::LI16_MM: -        Opnd = Inst.getOperand(1); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < -1 || Imm > 126) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::ADDIUR2_MM: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (!(Imm == 1 || Imm == -1 || -              ((Imm % 4 == 0) && Imm < 28 && Imm > 0))) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::ANDI16_MM: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || -              Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || -              Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535)) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::LBU16_MM: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < -1 || Imm > 14) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::SB16_MM: -      case Mips::SB16_MMR6: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < 0 || Imm > 15) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::LHU16_MM: -      case Mips::SH16_MM: -      case Mips::SH16_MMR6: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < 0 || Imm > 30 || (Imm % 2 != 0)) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::LW16_MM: -      case Mips::SW16_MM: -      case Mips::SW16_MMR6: -        Opnd = Inst.getOperand(2); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        Imm = Opnd.getImm(); -        if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) -          return Error(IDLoc, "immediate operand value out of range"); -        break; -      case Mips::ADDIUPC_MM: -        Opnd = Inst.getOperand(1); -        if (!Opnd.isImm()) -          return Error(IDLoc, "expected immediate operand kind"); -        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); -  switch (ExpandResult) { -  case MER_NotAMacro: -    Out.EmitInstruction(Inst, *STI); -    break; -  case MER_Success: -    break; -  case MER_Fail: -    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 ((Inst.getOpcode() == Mips::JalOneReg || -       Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && -      isPicAndNotNxxAbi()) { -    if (IsCpRestoreSet) { -      // We need a NOP between the JALR and the LW: -      // 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); - -      // Load the $gp from the stack. -      TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI); -    } else -      Warning(IDLoc, "no .cprestore used in PIC mode"); -  } - -  return false; -} - -MipsAsmParser::MacroExpanderResultTy -MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                                    const MCSubtargetInfo *STI) { -  switch (Inst.getOpcode()) { -  default: -    return MER_NotAMacro; -  case Mips::LoadImm32: -    return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::LoadImm64: -    return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::LoadAddrImm32: -  case Mips::LoadAddrImm64: -    assert(Inst.getOperand(0).isReg() && "expected register operand kind"); -    assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) && -           "expected immediate operand kind"); - -    return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister, -                             Inst.getOperand(1), -                             Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, -                             Out, STI) -               ? MER_Fail -               : MER_Success; -  case Mips::LoadAddrReg32: -  case Mips::LoadAddrReg64: -    assert(Inst.getOperand(0).isReg() && "expected register operand kind"); -    assert(Inst.getOperand(1).isReg() && "expected register operand kind"); -    assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) && -           "expected immediate operand kind"); - -    return expandLoadAddress(Inst.getOperand(0).getReg(), -                             Inst.getOperand(1).getReg(), Inst.getOperand(2), -                             Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, -                             Out, STI) -               ? MER_Fail -               : MER_Success; -  case Mips::B_MM_Pseudo: -  case Mips::B_MMR6_Pseudo: -    return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail -                                                             : MER_Success; -  case Mips::SWM_MM: -  case Mips::LWM_MM: -    return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail -                                                          : MER_Success; -  case Mips::JalOneReg: -  case Mips::JalTwoReg: -    return expandJalWithRegs(Inst, IDLoc, Out, STI) ? 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; -  case Mips::BLT: -  case Mips::BLE: -  case Mips::BGE: -  case Mips::BGT: -  case Mips::BLTU: -  case Mips::BLEU: -  case Mips::BGEU: -  case Mips::BGTU: -  case Mips::BLTL: -  case Mips::BLEL: -  case Mips::BGEL: -  case Mips::BGTL: -  case Mips::BLTUL: -  case Mips::BLEUL: -  case Mips::BGEUL: -  case Mips::BGTUL: -  case Mips::BLTImmMacro: -  case Mips::BLEImmMacro: -  case Mips::BGEImmMacro: -  case Mips::BGTImmMacro: -  case Mips::BLTUImmMacro: -  case Mips::BLEUImmMacro: -  case Mips::BGEUImmMacro: -  case Mips::BGTUImmMacro: -  case Mips::BLTLImmMacro: -  case Mips::BLELImmMacro: -  case Mips::BGELImmMacro: -  case Mips::BGTLImmMacro: -  case Mips::BLTULImmMacro: -  case Mips::BLEULImmMacro: -  case Mips::BGEULImmMacro: -  case Mips::BGTULImmMacro: -    return expandCondBranches(Inst, IDLoc, Out, STI) ? 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; -  case Mips::DSDivMacro: -  case Mips::DSDivIMacro: -  case Mips::DSRemMacro: -  case Mips::DSRemIMacro: -    return expandDivRem(Inst, IDLoc, Out, STI, 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; -  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; -  case Mips::Ulh: -    return expandUlh(Inst, true, IDLoc, Out, STI) ? 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; -  case Mips::Ulw: -  case Mips::Usw: -    return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::NORImm: -  case Mips::NORImm64: -    return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::SGE: -  case Mips::SGEU: -    return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::SGEImm: -  case Mips::SGEUImm: -  case Mips::SGEImm64: -  case Mips::SGEUImm64: -    return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::SGTImm: -  case Mips::SGTUImm: -  case Mips::SGTImm64: -  case Mips::SGTUImm64: -    return expandSgtImm(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: -    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 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: -    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 MER_NotAMacro; -  case Mips::ROL: -  case Mips::ROR: -    return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::ROLImm: -  case Mips::RORImm: -    return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  case Mips::DROL: -  case Mips::DROR: -    return expandDRotation(Inst, IDLoc, Out, STI) ? 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::SDC1_M1: -    return expandStoreDM1Macro(Inst, IDLoc, Out, STI) -               ? 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; -  case Mips::SaaAddr: -  case Mips::SaadAddr: -    return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; -  } -} - -bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, -                                      MCStreamer &Out, -                                      const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); - -  // Create a JALR instruction which is going to replace the pseudo-JAL. -  MCInst JalrInst; -  JalrInst.setLoc(IDLoc); -  const MCOperand FirstRegOp = Inst.getOperand(0); -  const unsigned Opcode = Inst.getOpcode(); - -  if (Opcode == Mips::JalOneReg) { -    // jal $rs => jalr $rs -    if (IsCpRestoreSet && inMicroMipsMode()) { -      JalrInst.setOpcode(Mips::JALRS16_MM); -      JalrInst.addOperand(FirstRegOp); -    } else if (inMicroMipsMode()) { -      JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM); -      JalrInst.addOperand(FirstRegOp); -    } else { -      JalrInst.setOpcode(Mips::JALR); -      JalrInst.addOperand(MCOperand::createReg(Mips::RA)); -      JalrInst.addOperand(FirstRegOp); -    } -  } else if (Opcode == Mips::JalTwoReg) { -    // jal $rd, $rs => jalr $rd, $rs -    if (IsCpRestoreSet && inMicroMipsMode()) -      JalrInst.setOpcode(Mips::JALRS_MM); -    else -      JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); -    JalrInst.addOperand(FirstRegOp); -    const MCOperand SecondRegOp = Inst.getOperand(1); -    JalrInst.addOperand(SecondRegOp); -  } -  Out.EmitInstruction(JalrInst, *STI); - -  // 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); - -  return false; -} - -/// Can the value be represented by a unsigned N-bit value and a shift left? -template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) { -  unsigned BitNum = findFirstSet(x); - -  return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum); -} - -/// Load (or add) an immediate into a register. -/// -/// @param ImmValue     The immediate to load. -/// @param DstReg       The register that will hold the immediate. -/// @param SrcReg       A register to add to the immediate or Mips::NoRegister -///                     for a simple initialization. -/// @param Is32BitImm   Is ImmValue 32-bit or 64-bit? -/// @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. -bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, -                                  unsigned SrcReg, bool Is32BitImm, -                                  bool IsAddress, SMLoc IDLoc, MCStreamer &Out, -                                  const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); - -  if (!Is32BitImm && !isGP64bit()) { -    Error(IDLoc, "instruction requires a 64-bit architecture"); -    return true; -  } - -  if (Is32BitImm) { -    if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { -      // Sign extend up to 64-bit so that the predicates match the hardware -      // behaviour. In particular, isInt<16>(0xffff8000) and similar should be -      // true. -      ImmValue = SignExtend64<32>(ImmValue); -    } else { -      Error(IDLoc, "instruction requires a 32-bit immediate"); -      return true; -    } -  } - -  unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg(); -  unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu; - -  bool UseSrcReg = false; -  if (SrcReg != Mips::NoRegister) -    UseSrcReg = true; - -  unsigned TmpReg = DstReg; -  if (UseSrcReg && -      getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { -    // At this point we need AT to perform the expansions and we exit if it is -    // not available. -    unsigned ATReg = getATReg(IDLoc); -    if (!ATReg) -      return true; -    TmpReg = ATReg; -  } - -  if (isInt<16>(ImmValue)) { -    if (!UseSrcReg) -      SrcReg = ZeroReg; - -    // This doesn't quite follow the usual ABI expectations for N32 but matches -    // 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); -      return false; -    } - -    TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI); -    return false; -  } - -  if (isUInt<16>(ImmValue)) { -    unsigned TmpReg = DstReg; -    if (SrcReg == DstReg) { -      TmpReg = getATReg(IDLoc); -      if (!TmpReg) -        return true; -    } - -    TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI); -    if (UseSrcReg) -      TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI); -    return false; -  } - -  if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { -    warnIfNoMacro(IDLoc); - -    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); -        if (UseSrcReg) -          TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); -        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); -      if (Bits15To0) -        TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); -      if (UseSrcReg) -        TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); -      return false; -    } - -    TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI); -    if (Bits15To0) -      TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); -    if (UseSrcReg) -      TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); -    return false; -  } - -  if (isShiftedUIntAtAnyPosition<16>(ImmValue)) { -    if (Is32BitImm) { -      Error(IDLoc, "instruction requires a 32-bit immediate"); -      return true; -    } - -    // Traditionally, these immediates are shifted as little as possible and as -    // such we align the most significant bit to bit 15 of our temporary. -    unsigned FirstSet = findFirstSet((uint64_t)ImmValue); -    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); - -    if (UseSrcReg) -      TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - -    return false; -  } - -  warnIfNoMacro(IDLoc); - -  // The remaining case is packed with a sequence of dsll and ori with zeros -  // being omitted and any neighbouring dsll's being coalesced. -  // The highest 32-bit's are equivalent to a 32-bit immediate load. - -  // 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)) -    return false; - -  // Shift and accumulate into the register. If a 16-bit chunk is zero, then -  // skip it and defer the shift to the next chunk. -  unsigned ShiftCarriedForwards = 16; -  for (int BitNum = 16; BitNum >= 0; BitNum -= 16) { -    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); -      ShiftCarriedForwards = 0; -    } - -    ShiftCarriedForwards += 16; -  } -  ShiftCarriedForwards -= 16; - -  // Finish any remaining shifts left by trailing zeros. -  if (ShiftCarriedForwards) -    TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI); - -  if (UseSrcReg) -    TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - -  return false; -} - -bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, -                                  MCStreamer &Out, const MCSubtargetInfo *STI) { -  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)) -    return true; - -  return false; -} - -bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, -                                      const MCOperand &Offset, -                                      bool Is32BitAddress, SMLoc IDLoc, -                                      MCStreamer &Out, -                                      const MCSubtargetInfo *STI) { -  // 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. -    //        We currently can't do this because we depend on the equality -    //        operator and N64 can end up with a GPR32/GPR64 mismatch. -    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()) { -    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; -  } - -  return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true, -                       IDLoc, Out, STI); -} - -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; -  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, GPReg, 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, GPReg, 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, GPReg, 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, GPReg, 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); - -    return false; -  } - -  const MipsMCExpr *HiExpr = -      MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext()); -  const MipsMCExpr *LoExpr = -      MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); - -  // 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); - -    if (canUseATReg() && UseSrcReg && RdRegIsRsReg) { -      unsigned ATReg = getATReg(IDLoc); - -      // If $rs is the same as $rd: -      // (d)la $rd, sym($rd) => lui    $at, %highest(sym) -      //                        daddiu $at, $at, %higher(sym) -      //                        dsll   $at, $at, 16 -      //                        daddiu $at, $at, %hi(sym) -      //                        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); - -      return false; -    } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) { -      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) || -               (canUseATReg() && DstReg == getATReg(IDLoc))) { -      // 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); - -      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; -    } -  } - -  // And now, the 32-bit symbol address expansion: -  // If $rs is the same as $rd: -  // (d)la $rd, sym($rd)     => lui   $at, %hi(sym) -  //                            ori   $at, $at, %lo(sym) -  //                            addu  $rd, $at, $rd -  // Otherwise, if the $rs is different from $rd or if $rs isn't specified: -  // (d)la $rd, sym/sym($rs) => lui   $rd, %hi(sym) -  //                            ori   $rd, $rd, %lo(sym) -  //                            (addu $rd, $rd, $rs) -  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.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI); -  TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), -               IDLoc, STI); - -  if (UseSrcReg) -    TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); -  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, GPReg, MCOperand::createExpr(GotExpr), -                   IDLoc, STI); -    } else { //isABI_N64() -      TOut.emitRRX(Mips::LD, ATReg, GPReg, 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); - -    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(); - -  assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && -         "unexpected number of operands"); - -  MCOperand Offset = Inst.getOperand(0); -  if (Offset.isExpr()) { -    Inst.clear(); -    Inst.setOpcode(Mips::BEQ_MM); -    Inst.addOperand(MCOperand::createReg(Mips::ZERO)); -    Inst.addOperand(MCOperand::createReg(Mips::ZERO)); -    Inst.addOperand(MCOperand::createExpr(Offset.getExpr())); -  } else { -    assert(Offset.isImm() && "expected immediate operand kind"); -    if (isInt<11>(Offset.getImm())) { -      // If offset fits into 11 bits then this instruction becomes microMIPS -      // 16-bit unconditional branch instruction. -      if (inMicroMipsMode()) -        Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM); -    } else { -      if (!isInt<17>(Offset.getImm())) -        return Error(IDLoc, "branch target out of range"); -      if (OffsetToAlignment(Offset.getImm(), 1LL << 1)) -        return Error(IDLoc, "branch to misaligned address"); -      Inst.clear(); -      Inst.setOpcode(Mips::BEQ_MM); -      Inst.addOperand(MCOperand::createReg(Mips::ZERO)); -      Inst.addOperand(MCOperand::createReg(Mips::ZERO)); -      Inst.addOperand(MCOperand::createImm(Offset.getImm())); -    } -  } -  Out.EmitInstruction(Inst, *STI); - -  // 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); - -  return false; -} - -bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                                    const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  const MCOperand &DstRegOp = Inst.getOperand(0); -  assert(DstRegOp.isReg() && "expected register operand kind"); - -  const MCOperand &ImmOp = Inst.getOperand(1); -  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; - -  unsigned OpCode = 0; -  switch(Inst.getOpcode()) { -    case Mips::BneImm: -      OpCode = Mips::BNE; -      break; -    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 { -    warnIfNoMacro(IDLoc); - -    unsigned ATReg = getATReg(IDLoc); -    if (!ATReg) -      return true; - -    if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true, -                      IDLoc, Out, STI)) -      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); -  } -  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; - -  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) -      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); -    return; -  } - -  assert(OffsetOp.isExpr() && "expected expression operand kind"); -  if (inPicMode()) { -    // FIXME: -    // a) Fix lw/sw $reg, symbol($reg) instruction expanding. -    // b) If expression includes offset (sym + number), do not -    //    encode the offset into a relocation. Take it in account -    //    in the last load/store instruction. -    // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations -    //    do not exceed 16-bit. -    // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead -    //    of R_MIPS_GOT_DISP in appropriate cases to reduce number -    //    of GOT entries. -    expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), -                      IDLoc, Out, STI); -    TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); -  } else { -    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) { -  unsigned OpNum = Inst.getNumOperands(); -  unsigned Opcode = Inst.getOpcode(); -  unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; - -  assert(Inst.getOperand(OpNum - 1).isImm() && -         Inst.getOperand(OpNum - 2).isReg() && -         Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); - -  if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && -      Inst.getOperand(OpNum - 1).getImm() >= 0 && -      (Inst.getOperand(OpNum - 2).getReg() == Mips::SP || -       Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) && -      (Inst.getOperand(OpNum - 3).getReg() == Mips::RA || -       Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) { -    // It can be implemented as SWM16 or LWM16 instruction. -    if (inMicroMipsMode() && hasMips32r6()) -      NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6; -    else -      NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; -  } - -  Inst.setOpcode(NewOpcode); -  Out.EmitInstruction(Inst, *STI); -  return false; -} - -bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, -                                       MCStreamer &Out, -                                       const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  bool EmittedNoMacroWarning = false; -  unsigned PseudoOpcode = Inst.getOpcode(); -  unsigned SrcReg = Inst.getOperand(0).getReg(); -  const MCOperand &TrgOp = Inst.getOperand(1); -  const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr(); - -  unsigned ZeroSrcOpcode, ZeroTrgOpcode; -  bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality; - -  unsigned TrgReg; -  if (TrgOp.isReg()) -    TrgReg = TrgOp.getReg(); -  else if (TrgOp.isImm()) { -    warnIfNoMacro(IDLoc); -    EmittedNoMacroWarning = true; - -    TrgReg = getATReg(IDLoc); -    if (!TrgReg) -      return true; - -    switch(PseudoOpcode) { -    default: -      llvm_unreachable("unknown opcode for branch pseudo-instruction"); -    case Mips::BLTImmMacro: -      PseudoOpcode = Mips::BLT; -      break; -    case Mips::BLEImmMacro: -      PseudoOpcode = Mips::BLE; -      break; -    case Mips::BGEImmMacro: -      PseudoOpcode = Mips::BGE; -      break; -    case Mips::BGTImmMacro: -      PseudoOpcode = Mips::BGT; -      break; -    case Mips::BLTUImmMacro: -      PseudoOpcode = Mips::BLTU; -      break; -    case Mips::BLEUImmMacro: -      PseudoOpcode = Mips::BLEU; -      break; -    case Mips::BGEUImmMacro: -      PseudoOpcode = Mips::BGEU; -      break; -    case Mips::BGTUImmMacro: -      PseudoOpcode = Mips::BGTU; -      break; -    case Mips::BLTLImmMacro: -      PseudoOpcode = Mips::BLTL; -      break; -    case Mips::BLELImmMacro: -      PseudoOpcode = Mips::BLEL; -      break; -    case Mips::BGELImmMacro: -      PseudoOpcode = Mips::BGEL; -      break; -    case Mips::BGTLImmMacro: -      PseudoOpcode = Mips::BGTL; -      break; -    case Mips::BLTULImmMacro: -      PseudoOpcode = Mips::BLTUL; -      break; -    case Mips::BLEULImmMacro: -      PseudoOpcode = Mips::BLEUL; -      break; -    case Mips::BGEULImmMacro: -      PseudoOpcode = Mips::BGEUL; -      break; -    case Mips::BGTULImmMacro: -      PseudoOpcode = Mips::BGTUL; -      break; -    } - -    if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(), -                      false, IDLoc, Out, STI)) -      return true; -  } - -  switch (PseudoOpcode) { -  case Mips::BLT: -  case Mips::BLTU: -  case Mips::BLTL: -  case Mips::BLTUL: -    AcceptsEquality = false; -    ReverseOrderSLT = false; -    IsUnsigned = -        ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); -    IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL)); -    ZeroSrcOpcode = Mips::BGTZ; -    ZeroTrgOpcode = Mips::BLTZ; -    break; -  case Mips::BLE: -  case Mips::BLEU: -  case Mips::BLEL: -  case Mips::BLEUL: -    AcceptsEquality = true; -    ReverseOrderSLT = true; -    IsUnsigned = -        ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); -    IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL)); -    ZeroSrcOpcode = Mips::BGEZ; -    ZeroTrgOpcode = Mips::BLEZ; -    break; -  case Mips::BGE: -  case Mips::BGEU: -  case Mips::BGEL: -  case Mips::BGEUL: -    AcceptsEquality = true; -    ReverseOrderSLT = false; -    IsUnsigned = -        ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); -    IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL)); -    ZeroSrcOpcode = Mips::BLEZ; -    ZeroTrgOpcode = Mips::BGEZ; -    break; -  case Mips::BGT: -  case Mips::BGTU: -  case Mips::BGTL: -  case Mips::BGTUL: -    AcceptsEquality = false; -    ReverseOrderSLT = true; -    IsUnsigned = -        ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); -    IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL)); -    ZeroSrcOpcode = Mips::BLTZ; -    ZeroTrgOpcode = Mips::BGTZ; -    break; -  default: -    llvm_unreachable("unknown opcode for branch pseudo-instruction"); -  } - -  bool IsTrgRegZero = (TrgReg == Mips::ZERO); -  bool IsSrcRegZero = (SrcReg == Mips::ZERO); -  if (IsSrcRegZero && IsTrgRegZero) { -    // FIXME: All of these Opcode-specific if's are needed for compatibility -    // 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); -      return false; -    } -    if (PseudoOpcode == Mips::BLE) { -      TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), -                  IDLoc, STI); -      Warning(IDLoc, "branch is always taken"); -      return false; -    } -    if (PseudoOpcode == Mips::BGE) { -      TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), -                  IDLoc, STI); -      Warning(IDLoc, "branch is always taken"); -      return false; -    } -    if (PseudoOpcode == Mips::BGT) { -      TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), -                  IDLoc, STI); -      return false; -    } -    if (PseudoOpcode == Mips::BGTU) { -      TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, -                   MCOperand::createExpr(OffsetExpr), IDLoc, STI); -      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); -      Warning(IDLoc, "branch is always taken"); -      return false; -    } -    // If both registers are $0 and the pseudo-branch does not accept -    // equality, it will never be taken, so we don't have to emit anything. -    return false; -  } -  if (IsSrcRegZero || IsTrgRegZero) { -    if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) || -        (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) { -      // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or -      // if the $rt is $0 and the pseudo-branch is BLTU (x < 0), -      // the pseudo-branch will never be taken, so we don't emit anything. -      // This only applies to unsigned pseudo-branches. -      return false; -    } -    if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) || -        (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) { -      // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or -      // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0), -      // 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); -      Warning(IDLoc, "branch is always taken"); -      return false; -    } -    if (IsUnsigned) { -      // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or -      // if the $rt is $0 and the pseudo-branch is BGTU (x > 0), -      // the pseudo-branch will be taken only when the non-zero register is -      // different from 0, so we emit a BNEZ. -      // -      // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or -      // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0), -      // the pseudo-branch will be taken only when the non-zero register is -      // equal to 0, so we emit a BEQZ. -      // -      // 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); -      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); -    return false; -  } - -  // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the -  // expansions. If it is not available, we return. -  unsigned ATRegNum = getATReg(IDLoc); -  if (!ATRegNum) -    return true; - -  if (!EmittedNoMacroWarning) -    warnIfNoMacro(IDLoc); - -  // SLT fits well with 2 of our 4 pseudo-branches: -  //   BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and -  //   BGT, where $rs > $rt, translates into "slt $at, $rt, $rs". -  // If the result of the SLT is 1, we branch, and if it's 0, we don't. -  // 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. -  // 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 -  // opposites. -  // -  // 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); -  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(); - -  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); -  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(); - -  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 (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; -    } 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); -      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); -      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; - -  if (UseTraps) { -    TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); -  } else { -    // Branch to the li instruction. -    BrTarget = Context.createTempSymbol(); -    LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); -    TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI); -  } - -  TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); - -  if (!UseTraps) -    TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); - -  if (!Signed) { -    if (!UseTraps) -      TOut.getStreamer().EmitLabel(BrTarget); - -    TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); -    return false; -  } - -  unsigned ATReg = getATReg(IDLoc); -  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); - -  if (IsMips64) { -    TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI); -    TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI); -  } else { -    TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI); -  } - -  if (UseTraps) -    TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI); -  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); -  } - -  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); - -  return false; -} - -bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, -                              MCStreamer &Out, const MCSubtargetInfo *STI) { -  if (hasMips32r6() || hasMips64r6()) { -    return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); -  } - -  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); - -  unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg; -  unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg; - -  unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg; -  unsigned SllReg = IsLargeOffset ? DstReg : ATReg; - -  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); - -  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"); -  } - -  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(); - -  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 ? 1 : (OffsetValue + 1); -  int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue; -  if (isLittle()) -    std::swap(FirstOffset, SecondOffset); - -  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); -  } - -  return false; -} - -bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                              const MCSubtargetInfo *STI) { -  if (hasMips32r6() || hasMips64r6()) { -    return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); -  } - -  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(); - -  // 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)) -      return true; -  } - -  if (DoMove) -    std::swap(DstReg, TmpReg); - -  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); - -  if (DoMove) -    TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI); - -  return false; -} - -bool MipsAsmParser::expandSge(MCInst &Inst, 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 DstReg = Inst.getOperand(0).getReg(); -  unsigned SrcReg = Inst.getOperand(1).getReg(); -  unsigned OpReg = Inst.getOperand(2).getReg(); -  unsigned OpCode; - -  warnIfNoMacro(IDLoc); - -  switch (Inst.getOpcode()) { -  case Mips::SGE: -    OpCode = Mips::SLT; -    break; -  case Mips::SGEU: -    OpCode = Mips::SLTu; -    break; -  default: -    llvm_unreachable("unexpected 'sge' opcode"); -  } - -  // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg)) -  TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI); -  TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); - -  return false; -} - -bool MipsAsmParser::expandSgeImm(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - -  unsigned DstReg = Inst.getOperand(0).getReg(); -  unsigned SrcReg = Inst.getOperand(1).getReg(); -  int64_t ImmValue = Inst.getOperand(2).getImm(); -  unsigned OpRegCode, OpImmCode; - -  warnIfNoMacro(IDLoc); - -  switch (Inst.getOpcode()) { -  case Mips::SGEImm: -  case Mips::SGEImm64: -    OpRegCode = Mips::SLT; -    OpImmCode = Mips::SLTi; -    break; -  case Mips::SGEUImm: -  case Mips::SGEUImm64: -    OpRegCode = Mips::SLTu; -    OpImmCode = Mips::SLTiu; -    break; -  default: -    llvm_unreachable("unexpected 'sge' opcode with immediate"); -  } - -  // $SrcReg >= Imm is equal to (not ($SrcReg < Imm)) -  if (isInt<16>(ImmValue)) { -    // Use immediate version of STL. -    TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI); -    TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); -  } else { -    unsigned ImmReg = DstReg; -    if (DstReg == SrcReg) { -      unsigned ATReg = getATReg(Inst.getLoc()); -      if (!ATReg) -        return true; -      ImmReg = ATReg; -    } - -    if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), -                      false, IDLoc, Out, STI)) -      return true; - -    TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI); -    TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); -  } - -  return false; -} - -bool MipsAsmParser::expandSgtImm(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - -  unsigned DstReg = Inst.getOperand(0).getReg(); -  unsigned SrcReg = Inst.getOperand(1).getReg(); -  unsigned ImmReg = DstReg; -  int64_t ImmValue = Inst.getOperand(2).getImm(); -  unsigned OpCode; - -  warnIfNoMacro(IDLoc); - -  switch (Inst.getOpcode()) { -  case Mips::SGTImm: -  case Mips::SGTImm64: -    OpCode = Mips::SLT; -    break; -  case Mips::SGTUImm: -  case Mips::SGTUImm64: -    OpCode = Mips::SLTu; -    break; -  default: -    llvm_unreachable("unexpected 'sgt' opcode with immediate"); -  } - -  if (DstReg == SrcReg) { -    unsigned ATReg = getATReg(Inst.getLoc()); -    if (!ATReg) -      return true; -    ImmReg = ATReg; -  } - -  if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), -                    false, IDLoc, Out, STI)) -    return true; - -  // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg -  TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI); - -  return false; -} - -bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - -  unsigned ATReg = Mips::NoRegister; -  unsigned FinalDstReg = Mips::NoRegister; -  unsigned DstReg = Inst.getOperand(0).getReg(); -  unsigned SrcReg = Inst.getOperand(1).getReg(); -  int64_t ImmValue = Inst.getOperand(2).getImm(); - -  bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue)); - -  unsigned FinalOpcode = Inst.getOpcode(); - -  if (DstReg == SrcReg) { -    ATReg = getATReg(Inst.getLoc()); -    if (!ATReg) -      return true; -    FinalDstReg = DstReg; -    DstReg = ATReg; -  } - -  if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, -                     Inst.getLoc(), Out, STI)) { -    switch (FinalOpcode) { -    default: -      llvm_unreachable("unimplemented expansion"); -    case Mips::ADDi: -      FinalOpcode = Mips::ADD; -      break; -    case Mips::ADDiu: -      FinalOpcode = Mips::ADDu; -      break; -    case Mips::ANDi: -      FinalOpcode = Mips::AND; -      break; -    case Mips::NORImm: -      FinalOpcode = Mips::NOR; -      break; -    case Mips::ORi: -      FinalOpcode = Mips::OR; -      break; -    case Mips::SLTi: -      FinalOpcode = Mips::SLT; -      break; -    case Mips::SLTiu: -      FinalOpcode = Mips::SLTu; -      break; -    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); -    else -      TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI); -    return false; -  } -  return true; -} - -bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                                   const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  unsigned ATReg = Mips::NoRegister; -  unsigned DReg = Inst.getOperand(0).getReg(); -  unsigned SReg = Inst.getOperand(1).getReg(); -  unsigned TReg = Inst.getOperand(2).getReg(); -  unsigned TmpReg = DReg; - -  unsigned FirstShift = Mips::NOP; -  unsigned SecondShift = Mips::NOP; - -  if (hasMips32r2()) { -    if (DReg == SReg) { -      TmpReg = getATReg(Inst.getLoc()); -      if (!TmpReg) -        return true; -    } - -    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); -      return false; -    } - -    if (Inst.getOpcode() == Mips::ROR) { -      TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); -      return false; -    } - -    return true; -  } - -  if (hasMips32()) { -    switch (Inst.getOpcode()) { -    default: -      llvm_unreachable("unexpected instruction opcode"); -    case Mips::ROL: -      FirstShift = Mips::SRLV; -      SecondShift = Mips::SLLV; -      break; -    case Mips::ROR: -      FirstShift = Mips::SLLV; -      SecondShift = Mips::SRLV; -      break; -    } - -    ATReg = getATReg(Inst.getLoc()); -    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); - -    return false; -  } - -  return true; -} - -bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, -                                      MCStreamer &Out, -                                      const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  unsigned ATReg = Mips::NoRegister; -  unsigned DReg = Inst.getOperand(0).getReg(); -  unsigned SReg = Inst.getOperand(1).getReg(); -  int64_t ImmValue = Inst.getOperand(2).getImm(); - -  unsigned FirstShift = Mips::NOP; -  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); -      return false; -    } - -    if (Inst.getOpcode() == Mips::RORImm) { -      TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI); -      return false; -    } - -    return true; -  } - -  if (hasMips32()) { -    if (ImmValue == 0) { -      TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI); -      return false; -    } - -    switch (Inst.getOpcode()) { -    default: -      llvm_unreachable("unexpected instruction opcode"); -    case Mips::ROLImm: -      FirstShift = Mips::SLL; -      SecondShift = Mips::SRL; -      break; -    case Mips::RORImm: -      FirstShift = Mips::SRL; -      SecondShift = Mips::SLL; -      break; -    } - -    ATReg = getATReg(Inst.getLoc()); -    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); - -    return false; -  } - -  return true; -} - -bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                                    const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  unsigned ATReg = Mips::NoRegister; -  unsigned DReg = Inst.getOperand(0).getReg(); -  unsigned SReg = Inst.getOperand(1).getReg(); -  unsigned TReg = Inst.getOperand(2).getReg(); -  unsigned TmpReg = DReg; - -  unsigned FirstShift = Mips::NOP; -  unsigned SecondShift = Mips::NOP; - -  if (hasMips64r2()) { -    if (TmpReg == SReg) { -      TmpReg = getATReg(Inst.getLoc()); -      if (!TmpReg) -        return true; -    } - -    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); -      return false; -    } - -    if (Inst.getOpcode() == Mips::DROR) { -      TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); -      return false; -    } - -    return true; -  } - -  if (hasMips64()) { -    switch (Inst.getOpcode()) { -    default: -      llvm_unreachable("unexpected instruction opcode"); -    case Mips::DROL: -      FirstShift = Mips::DSRLV; -      SecondShift = Mips::DSLLV; -      break; -    case Mips::DROR: -      FirstShift = Mips::DSLLV; -      SecondShift = Mips::DSRLV; -      break; -    } - -    ATReg = getATReg(Inst.getLoc()); -    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); - -    return false; -  } - -  return true; -} - -bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, -                                       MCStreamer &Out, -                                       const MCSubtargetInfo *STI) { -  MipsTargetStreamer &TOut = getTargetStreamer(); -  unsigned ATReg = Mips::NoRegister; -  unsigned DReg = Inst.getOperand(0).getReg(); -  unsigned SReg = Inst.getOperand(1).getReg(); -  int64_t ImmValue = Inst.getOperand(2).getImm() % 64; - -  unsigned FirstShift = Mips::NOP; -  unsigned SecondShift = Mips::NOP; - -  MCInst TmpInst; - -  if (hasMips64r2()) { -    unsigned FinalOpcode = Mips::NOP; -    if (ImmValue == 0) -      FinalOpcode = Mips::DROTR; -    else if (ImmValue % 32 == 0) -      FinalOpcode = Mips::DROTR32; -    else if ((ImmValue >= 1) && (ImmValue <= 32)) { -      if (Inst.getOpcode() == Mips::DROLImm) -        FinalOpcode = Mips::DROTR32; -      else -        FinalOpcode = Mips::DROTR; -    } else if (ImmValue >= 33) { -      if (Inst.getOpcode() == Mips::DROLImm) -        FinalOpcode = Mips::DROTR; -      else -        FinalOpcode = Mips::DROTR32; -    } - -    uint64_t ShiftValue = ImmValue % 32; -    if (Inst.getOpcode() == Mips::DROLImm) -      ShiftValue = (32 - ImmValue % 32) % 32; - -    TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI); - -    return false; -  } - -  if (hasMips64()) { -    if (ImmValue == 0) { -      TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI); -      return false; -    } - -    switch (Inst.getOpcode()) { -    default: -      llvm_unreachable("unexpected instruction opcode"); -    case Mips::DROLImm: -      if ((ImmValue >= 1) && (ImmValue <= 31)) { -        FirstShift = Mips::DSLL; -        SecondShift = Mips::DSRL32; -      } -      if (ImmValue == 32) { -        FirstShift = Mips::DSLL32; -        SecondShift = Mips::DSRL32; -      } -      if ((ImmValue >= 33) && (ImmValue <= 63)) { -        FirstShift = Mips::DSLL32; -        SecondShift = Mips::DSRL; -      } -      break; -    case Mips::DRORImm: -      if ((ImmValue >= 1) && (ImmValue <= 31)) { -        FirstShift = Mips::DSRL; -        SecondShift = Mips::DSLL32; -      } -      if (ImmValue == 32) { -        FirstShift = Mips::DSRL32; -        SecondShift = Mips::DSLL32; -      } -      if ((ImmValue >= 33) && (ImmValue <= 63)) { -        FirstShift = Mips::DSRL32; -        SecondShift = Mips::DSLL; -      } -      break; -    } - -    ATReg = getATReg(Inst.getLoc()); -    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); - -    return false; -  } - -  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); -  else -    TOut.emitEmptyDelaySlot(false, IDLoc, STI); -  TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI); - -  return false; -} - -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; -} - -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); -  } - -  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; -} - - -// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2); -//                                       swc1 $<reg>, offset+4($reg2)' -// or if little endian to 'swc1 $<reg>, offset($reg2); -//                         swc1 $<reg+1>, offset+4($reg2)' -// for Mips1. -bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, -                                        MCStreamer &Out, -                                        const MCSubtargetInfo *STI) { -  if (!isABI_O32()) -    return true; - -  warnIfNoMacro(IDLoc); - -  MipsTargetStreamer &TOut = getTargetStreamer(); -  unsigned Opcode = Mips::SWC1; -  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 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; - -  if (!IsLittleEndian) -    std::swap(FirstReg, SecondReg); - -  TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); -  TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); - -  return false; -} - -bool MipsAsmParser::expandSeq(MCInst &Inst, 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 DstReg = Inst.getOperand(0).getReg(); -  unsigned SrcReg = Inst.getOperand(1).getReg(); -  unsigned OpReg = Inst.getOperand(2).getReg(); - -  warnIfNoMacro(IDLoc); - -  if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) { -    TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI); -    TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); -    return false; -  } - -  unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg; -  TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI); -  return false; -} - -bool MipsAsmParser::expandSeqI(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - -  unsigned DstReg = Inst.getOperand(0).getReg(); -  unsigned SrcReg = Inst.getOperand(1).getReg(); -  int64_t Imm = Inst.getOperand(2).getImm(); - -  warnIfNoMacro(IDLoc); - -  if (Imm == 0) { -    TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI); -    return false; -  } - -  if (SrcReg == Mips::ZERO) { -    Warning(IDLoc, "comparison is always false"); -    TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, -                 DstReg, SrcReg, SrcReg, IDLoc, STI); -    return false; -  } - -  unsigned Opc; -  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, DstReg, SrcReg, ATReg, IDLoc, STI); -    TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); -    return false; -  } - -  TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI); -  TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 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; -} - -bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, -                                  const MCSubtargetInfo *STI) { -  assert(Inst.getNumOperands() == 3 && "expected three operands"); -  assert(Inst.getOperand(0).isReg() && "expected register operand kind"); -  assert(Inst.getOperand(1).isReg() && "expected register operand kind"); - -  warnIfNoMacro(IDLoc); - -  MipsTargetStreamer &TOut = getTargetStreamer(); -  unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD; -  unsigned RtReg = Inst.getOperand(0).getReg(); -  unsigned BaseReg = Inst.getOperand(1).getReg(); -  const MCOperand &BaseOp = Inst.getOperand(2); - -  if (BaseOp.isImm()) { -    int64_t ImmValue = BaseOp.getImm(); -    if (ImmValue == 0) { -      TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI); -      return false; -    } -  } - -  unsigned ATReg = getATReg(IDLoc); -  if (!ATReg) -    return true; - -  if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI)) -    return true; - -  TOut.emitRR(Opcode, RtReg, ATReg, 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; -  } -} - -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; - -  return Match_Success; - -} - -static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, -                            uint64_t ErrorInfo) { -  if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { -    SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); -    if (ErrorLoc == SMLoc()) -      return Loc; -    return ErrorLoc; -  } -  return Loc; -} - -bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, -                                            OperandVector &Operands, -                                            MCStreamer &Out, -                                            uint64_t &ErrorInfo, -                                            bool MatchingInlineAsm) { -  MCInst Inst; -  unsigned MatchResult = -      MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); - -  switch (MatchResult) { -  case Match_Success: -    if (processInstruction(Inst, IDLoc, Out, STI)) -      return true; -    return false; -  case Match_MissingFeature: -    Error(IDLoc, "instruction requires a CPU feature not currently enabled"); -    return true; -  case Match_InvalidOperand: { -    SMLoc ErrorLoc = IDLoc; -    if (ErrorInfo != ~0ULL) { -      if (ErrorInfo >= Operands.size()) -        return Error(IDLoc, "too few operands for instruction"); - -      ErrorLoc = Operands[ErrorInfo]->getStartLoc(); -      if (ErrorLoc == SMLoc()) -        ErrorLoc = IDLoc; -    } - -    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: -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected 1-bit unsigned immediate"); -  case Match_UImm2_0: -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected 2-bit unsigned immediate"); -  case Match_UImm2_1: -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected immediate in range 1 .. 4"); -  case Match_UImm3_0: -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected 3-bit unsigned immediate"); -  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"); -  case Match_UImm5_32: -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected immediate in range 32 .. 63"); -  case Match_UImm5_33: -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected immediate in range 33 .. 64"); -  case Match_UImm5_0_Report_UImm6: -    // This is used on UImm5 operands that have a corresponding UImm5_32 -    // operand to avoid confusing the user. -    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), -                 "expected 6-bit unsigned immediate"); -  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: -    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!"); -} - -void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) { -  if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex) -    Warning(Loc, "used $at (currently $" + Twine(RegIndex) + -                     ") without \".set noat\""); -} - -void MipsAsmParser::warnIfNoMacro(SMLoc Loc) { -  if (!AssemblerOptions.back()->isMacro()) -    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) { -  getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg, -                                  Range, SMFixIt(Range, FixMsg), -                                  ShowColors); -} - -int MipsAsmParser::matchCPURegisterName(StringRef Name) { -  int CC; - -  CC = StringSwitch<unsigned>(Name) -           .Case("zero", 0) -           .Cases("at", "AT", 1) -           .Case("a0", 4) -           .Case("a1", 5) -           .Case("a2", 6) -           .Case("a3", 7) -           .Case("v0", 2) -           .Case("v1", 3) -           .Case("s0", 16) -           .Case("s1", 17) -           .Case("s2", 18) -           .Case("s3", 19) -           .Case("s4", 20) -           .Case("s5", 21) -           .Case("s6", 22) -           .Case("s7", 23) -           .Case("k0", 26) -           .Case("k1", 27) -           .Case("gp", 28) -           .Case("sp", 29) -           .Case("fp", 30) -           .Case("s8", 30) -           .Case("ra", 31) -           .Case("t0", 8) -           .Case("t1", 9) -           .Case("t2", 10) -           .Case("t3", 11) -           .Case("t4", 12) -           .Case("t5", 13) -           .Case("t6", 14) -           .Case("t7", 15) -           .Case("t8", 24) -           .Case("t9", 25) -           .Default(-1); - -  if (!(isABI_N32() || isABI_N64())) -    return CC; - -  if (12 <= CC && CC <= 15) { -    // Name is one of t4-t7 -    AsmToken RegTok = getLexer().peekTok(); -    SMRange RegRange = RegTok.getLocRange(); - -    StringRef FixedName = StringSwitch<StringRef>(Name) -                              .Case("t4", "t0") -                              .Case("t5", "t1") -                              .Case("t6", "t2") -                              .Case("t7", "t3") -                              .Default(""); -    assert(FixedName != "" &&  "Register name is not one of t4-t7."); - -    printWarningWithFixIt("register names $t4-$t7 are only available in O32.", -                          "Did you mean $" + FixedName + "?", RegRange); -  } - -  // Although SGI documentation just cuts out t0-t3 for n32/n64, -  // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 -  // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. -  if (8 <= CC && CC <= 11) -    CC += 4; - -  if (CC == -1) -    CC = StringSwitch<unsigned>(Name) -             .Case("a4", 8) -             .Case("a5", 9) -             .Case("a6", 10) -             .Case("a7", 11) -             .Case("kt0", 26) -             .Case("kt1", 27) -             .Default(-1); - -  return CC; -} - -int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) { -  int CC; - -  CC = StringSwitch<unsigned>(Name) -            .Case("hwr_cpunum", 0) -            .Case("hwr_synci_step", 1) -            .Case("hwr_cc", 2) -            .Case("hwr_ccres", 3) -            .Case("hwr_ulr", 29) -            .Default(-1); - -  return CC; -} - -int MipsAsmParser::matchFPURegisterName(StringRef Name) { -  if (Name[0] == 'f') { -    StringRef NumString = Name.substr(1); -    unsigned IntVal; -    if (NumString.getAsInteger(10, IntVal)) -      return -1;     // This is not an integer. -    if (IntVal > 31) // Maximum index for fpu register. -      return -1; -    return IntVal; -  } -  return -1; -} - -int MipsAsmParser::matchFCCRegisterName(StringRef Name) { -  if (Name.startswith("fcc")) { -    StringRef NumString = Name.substr(3); -    unsigned IntVal; -    if (NumString.getAsInteger(10, IntVal)) -      return -1;    // This is not an integer. -    if (IntVal > 7) // There are only 8 fcc registers. -      return -1; -    return IntVal; -  } -  return -1; -} - -int MipsAsmParser::matchACRegisterName(StringRef Name) { -  if (Name.startswith("ac")) { -    StringRef NumString = Name.substr(2); -    unsigned IntVal; -    if (NumString.getAsInteger(10, IntVal)) -      return -1;    // This is not an integer. -    if (IntVal > 3) // There are only 3 acc registers. -      return -1; -    return IntVal; -  } -  return -1; -} - -int MipsAsmParser::matchMSA128RegisterName(StringRef Name) { -  unsigned IntVal; - -  if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal)) -    return -1; - -  if (IntVal > 31) -    return -1; - -  return IntVal; -} - -int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { -  int CC; - -  CC = StringSwitch<unsigned>(Name) -           .Case("msair", 0) -           .Case("msacsr", 1) -           .Case("msaaccess", 2) -           .Case("msasave", 3) -           .Case("msamodify", 4) -           .Case("msarequest", 5) -           .Case("msamap", 6) -           .Case("msaunmap", 7) -           .Default(-1); - -  return CC; -} - -bool MipsAsmParser::canUseATReg() { -  return AssemblerOptions.back()->getATRegIndex() != 0; -} - -unsigned MipsAsmParser::getATReg(SMLoc Loc) { -  unsigned ATIndex = AssemblerOptions.back()->getATRegIndex(); -  if (ATIndex == 0) { -    reportParseError(Loc, -                     "pseudo-instruction requires $at, which is not available"); -    return 0; -  } -  unsigned AT = getReg( -      (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex); -  return AT; -} - -unsigned MipsAsmParser::getReg(int RC, int RegNo) { -  return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); -} - -bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { -  MCAsmParser &Parser = getParser(); -  LLVM_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. -  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); -  if (ResTy == MatchOperand_Success) -    return false; -  // If there wasn't a custom match, try the generic matcher below. Otherwise, -  // there was a match, but an error occurred, in which case, just return that -  // the operand parsing failed. -  if (ResTy == MatchOperand_ParseFail) -    return true; - -  LLVM_DEBUG(dbgs() << ".. Generic Parser\n"); - -  switch (getLexer().getKind()) { -  case AsmToken::Dollar: { -    // Parse the register. -    SMLoc S = Parser.getTok().getLoc(); - -    // Almost all registers have been parsed by custom parsers. There is only -    // one exception to this. $zero (and it's alias $0) will reach this point -    // for div, divu, and similar instructions because it is not an operand -    // to the instruction definition but an explicit register. Special case -    // this situation for now. -    if (parseAnyRegister(Operands) != MatchOperand_NoMatch) -      return false; - -    // Maybe it is a symbol reference. -    StringRef Identifier; -    if (Parser.parseIdentifier(Identifier)) -      return true; - -    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -    MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier); -    // Otherwise create a symbol reference. -    const MCExpr *Res = -        MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - -    Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); -    return false; -  } -  default: { -    LLVM_DEBUG(dbgs() << ".. generic integer expression\n"); - -    const MCExpr *Expr; -    SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. -    if (getParser().parseExpression(Expr)) -      return true; - -    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - -    Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this)); -    return false; -  } -  } // switch(getLexer().getKind()) -  return true; -} - -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::Unary: -    return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); -  case MCExpr::Target: -    return true; -  } -  return false; -} - -bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, -                                  SMLoc &EndLoc) { -  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; -  OperandMatchResultTy ResTy = parseAnyRegister(Operands); -  if (ResTy == MatchOperand_Success) { -    assert(Operands.size() == 1); -    MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front()); -    StartLoc = Operand.getStartLoc(); -    EndLoc = Operand.getEndLoc(); - -    // AFAIK, we only support numeric registers and named GPR's in CFI -    // directives. -    // Don't worry about eating tokens before failing. Using an unrecognised -    // register is a parse error. -    if (Operand.isGPRAsmReg()) { -      // Resolve to GPR32 or GPR64 appropriately. -      RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); -    } - -    return (RegNo == (unsigned)-1); -  } - -  assert(Operands.size() == 0); -  return (RegNo == (unsigned)-1); -} - -bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { -  SMLoc S; - -  if (isParenExpr) -    return getParser().parseParenExprOfDepth(0, Res, S); -  return getParser().parseExpression(Res); -} - -OperandMatchResultTy -MipsAsmParser::parseMemOperand(OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  LLVM_DEBUG(dbgs() << "parseMemOperand\n"); -  const MCExpr *IdVal = nullptr; -  SMLoc S; -  bool isParenExpr = false; -  OperandMatchResultTy Res = MatchOperand_NoMatch; -  // First operand is the offset. -  S = Parser.getTok().getLoc(); - -  if (getLexer().getKind() == AsmToken::LParen) { -    Parser.Lex(); -    isParenExpr = true; -  } - -  if (getLexer().getKind() != AsmToken::Dollar) { -    if (parseMemOffset(IdVal, isParenExpr)) -      return MatchOperand_ParseFail; - -    const AsmToken &Tok = Parser.getTok(); // Get the next token. -    if (Tok.isNot(AsmToken::LParen)) { -      MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]); -      if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") { -        SMLoc E = -            SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -        Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); -        return MatchOperand_Success; -      } -      if (Tok.is(AsmToken::EndOfStatement)) { -        SMLoc E = -            SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - -        // 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); -        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()); -    } - -    Parser.Lex(); // Eat the '(' token. -  } - -  Res = parseAnyRegister(Operands); -  if (Res != MatchOperand_Success) -    return Res; - -  if (Parser.getTok().isNot(AsmToken::RParen)) { -    Error(Parser.getTok().getLoc(), "')' expected"); -    return MatchOperand_ParseFail; -  } - -  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - -  Parser.Lex(); // Eat the ')' token. - -  if (!IdVal) -    IdVal = MCConstantExpr::create(0, getContext()); - -  // Replace the register operand with the memory operand. -  std::unique_ptr<MipsOperand> op( -      static_cast<MipsOperand *>(Operands.back().release())); -  // Remove the register from the operands. -  // "op" will be managed by k_Memory. -  Operands.pop_back(); -  // Add the memory operand. -  if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) { -    int64_t Imm; -    if (IdVal->evaluateAsAbsolute(Imm)) -      IdVal = MCConstantExpr::create(Imm, getContext()); -    else if (BE->getLHS()->getKind() != MCExpr::SymbolRef) -      IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), -                                   getContext()); -  } - -  Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this)); -  return MatchOperand_Success; -} - -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 (Expr->getKind() == MCExpr::SymbolRef) { -      const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); -      StringRef DefSymbol = Ref->getSymbol().getName(); -      if (DefSymbol.startswith("$")) { -        OperandMatchResultTy ResTy = -            matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); -        if (ResTy == MatchOperand_Success) { -          Parser.Lex(); -          return true; -        } -        if (ResTy == MatchOperand_ParseFail) -          llvm_unreachable("Should never ParseFail"); -      } -    } -  } 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; -      } -    } -  } - -  return false; -} - -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)); -    return MatchOperand_Success; -  } - -  Index = matchHWRegsRegisterName(Identifier); -  if (Index != -1) { -    Operands.push_back(MipsOperand::createHWRegsReg( -        Index, Identifier, 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)); -    return MatchOperand_Success; -  } - -  Index = matchFCCRegisterName(Identifier); -  if (Index != -1) { -    Operands.push_back(MipsOperand::createFCCReg( -        Index, Identifier, 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)); -    return MatchOperand_Success; -  } - -  Index = matchMSA128RegisterName(Identifier); -  if (Index != -1) { -    Operands.push_back(MipsOperand::createMSA128Reg( -        Index, Identifier, 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)); -    return MatchOperand_Success; -  } - -  return MatchOperand_NoMatch; -} - -OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, -                                             const AsmToken &Token, SMLoc S) { -  if (Token.is(AsmToken::Identifier)) { -    LLVM_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"); -    } -    Operands.push_back(MipsOperand::createNumericReg( -        RegNum, Token.getString(), getContext().getRegisterInfo(), S, -        Token.getLoc(), *this)); -    return MatchOperand_Success; -  } - -  LLVM_DEBUG(dbgs() << Token.getKind() << "\n"); - -  return MatchOperand_NoMatch; -} - -OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { -  auto Token = getLexer().peekTok(false); -  return matchAnyRegisterWithoutDollar(Operands, Token, S); -} - -OperandMatchResultTy -MipsAsmParser::parseAnyRegister(OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  LLVM_DEBUG(dbgs() << "parseAnyRegister\n"); - -  auto Token = Parser.getTok(); - -  SMLoc S = Token.getLoc(); - -  if (Token.isNot(AsmToken::Dollar)) { -    LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); -    if (Token.is(AsmToken::Identifier)) { -      if (searchSymbolAlias(Operands)) -        return MatchOperand_Success; -    } -    LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); -    return MatchOperand_NoMatch; -  } -  LLVM_DEBUG(dbgs() << ".. $\n"); - -  OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); -  if (ResTy == MatchOperand_Success) { -    Parser.Lex(); // $ -    Parser.Lex(); // identifier -  } -  return ResTy; -} - -OperandMatchResultTy -MipsAsmParser::parseJumpTarget(OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  LLVM_DEBUG(dbgs() << "parseJumpTarget\n"); - -  SMLoc S = getLexer().getLoc(); - -  // Registers are a valid target and have priority over symbols. -  OperandMatchResultTy 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 -    return MatchOperand_ParseFail; -  } -  Operands.push_back( -      MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this)); -  return MatchOperand_Success; -} - -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. -  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; -  int64_t Val = MCE->getValue(); -  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); -  Operands.push_back(MipsOperand::CreateImm( -      MCConstantExpr::create(0 - Val, getContext()), S, E, *this)); -  return MatchOperand_Success; -} - -OperandMatchResultTy -MipsAsmParser::parseRegisterList(OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  SmallVector<unsigned, 10> Regs; -  unsigned RegNo; -  unsigned PrevReg = Mips::NoRegister; -  bool RegRange = false; -  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; - -  if (Parser.getTok().isNot(AsmToken::Dollar)) -    return MatchOperand_ParseFail; - -  SMLoc S = Parser.getTok().getLoc(); -  while (parseAnyRegister(TmpOperands) == MatchOperand_Success) { -    SMLoc E = getLexer().getLoc(); -    MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back()); -    RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg(); -    if (RegRange) { -      // Remove last register operand because registers from register range -      // should be inserted first. -      if ((isGP64bit() && RegNo == Mips::RA_64) || -          (!isGP64bit() && RegNo == Mips::RA)) { -        Regs.push_back(RegNo); -      } else { -        unsigned TmpReg = PrevReg + 1; -        while (TmpReg <= RegNo) { -          if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) || -              (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) && -               isGP64bit())) { -            Error(E, "invalid register operand"); -            return MatchOperand_ParseFail; -          } - -          PrevReg = TmpReg; -          Regs.push_back(TmpReg++); -        } -      } - -      RegRange = false; -    } else { -      if ((PrevReg == Mips::NoRegister) && -          ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) || -          (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) { -        Error(E, "$16 or $31 expected"); -        return MatchOperand_ParseFail; -      } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA || -                    (RegNo >= Mips::S0 && RegNo <= Mips::S7)) && -                    !isGP64bit()) || -                   ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 || -                    (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) && -                    isGP64bit()))) { -        Error(E, "invalid register operand"); -        return MatchOperand_ParseFail; -      } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) && -                 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) || -                  (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && -                   isGP64bit()))) { -        Error(E, "consecutive register numbers expected"); -        return MatchOperand_ParseFail; -      } - -      Regs.push_back(RegNo); -    } - -    if (Parser.getTok().is(AsmToken::Minus)) -      RegRange = true; - -    if (!Parser.getTok().isNot(AsmToken::Minus) && -        !Parser.getTok().isNot(AsmToken::Comma)) { -      Error(E, "',' or '-' expected"); -      return MatchOperand_ParseFail; -    } - -    Lex(); // Consume comma or minus -    if (Parser.getTok().isNot(AsmToken::Dollar)) -      break; - -    PrevReg = RegNo; -  } - -  SMLoc E = Parser.getTok().getLoc(); -  Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); -  parseMemOperand(Operands); -  return MatchOperand_Success; -} - -/// Sometimes (i.e. load/stores) the operand may be followed immediately by -/// either this. -/// ::= '(', register, ')' -/// handle it before we iterate so we don't get tripped up by the lack of -/// a comma. -bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  if (getLexer().is(AsmToken::LParen)) { -    Operands.push_back( -        MipsOperand::CreateToken("(", getLexer().getLoc(), *this)); -    Parser.Lex(); -    if (parseOperand(Operands, Name)) { -      SMLoc Loc = getLexer().getLoc(); -      return Error(Loc, "unexpected token in argument list"); -    } -    if (Parser.getTok().isNot(AsmToken::RParen)) { -      SMLoc Loc = getLexer().getLoc(); -      return Error(Loc, "unexpected token, expected ')'"); -    } -    Operands.push_back( -        MipsOperand::CreateToken(")", getLexer().getLoc(), *this)); -    Parser.Lex(); -  } -  return false; -} - -/// Sometimes (i.e. in MSA) the operand may be followed immediately by -/// either one of these. -/// ::= '[', register, ']' -/// ::= '[', integer, ']' -/// handle it before we iterate so we don't get tripped up by the lack of -/// a comma. -bool MipsAsmParser::parseBracketSuffix(StringRef Name, -                                       OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  if (getLexer().is(AsmToken::LBrac)) { -    Operands.push_back( -        MipsOperand::CreateToken("[", getLexer().getLoc(), *this)); -    Parser.Lex(); -    if (parseOperand(Operands, Name)) { -      SMLoc Loc = getLexer().getLoc(); -      return Error(Loc, "unexpected token in argument list"); -    } -    if (Parser.getTok().isNot(AsmToken::RBrac)) { -      SMLoc Loc = getLexer().getLoc(); -      return Error(Loc, "unexpected token, expected ']'"); -    } -    Operands.push_back( -        MipsOperand::CreateToken("]", getLexer().getLoc(), *this)); -    Parser.Lex(); -  } -  return false; -} - -static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, -                                          unsigned VariantID = 0); - -bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, -                                     SMLoc NameLoc, OperandVector &Operands) { -  MCAsmParser &Parser = getParser(); -  LLVM_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)) { -    FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); -    std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS); -    return Error(NameLoc, "unknown instruction" + Suggestion); -  } -  // First operand in MCInst is instruction mnemonic. -  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); - -  // Read the remaining operands. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    // Read the first operand. -    if (parseOperand(Operands, Name)) { -      SMLoc Loc = getLexer().getLoc(); -      return Error(Loc, "unexpected token in argument list"); -    } -    if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands)) -      return true; -    // AFAIK, parenthesis suffixes are never on the first operand - -    while (getLexer().is(AsmToken::Comma)) { -      Parser.Lex(); // Eat the comma. -      // Parse and remember the operand. -      if (parseOperand(Operands, Name)) { -        SMLoc Loc = getLexer().getLoc(); -        return Error(Loc, "unexpected token in argument list"); -      } -      // Parse bracket and parenthesis suffixes before we iterate -      if (getLexer().is(AsmToken::LBrac)) { -        if (parseBracketSuffix(Name, Operands)) -          return true; -      } else if (getLexer().is(AsmToken::LParen) && -                 parseParenSuffix(Name, Operands)) -        return true; -    } -  } -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    SMLoc Loc = getLexer().getLoc(); -    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) { -  SMLoc Loc = getLexer().getLoc(); -  return Error(Loc, ErrorMsg); -} - -bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { -  return Error(Loc, ErrorMsg); -} - -bool MipsAsmParser::parseSetNoAtDirective() { -  MCAsmParser &Parser = getParser(); -  // Line should look like: ".set noat". - -  // Set the $at register to $0. -  AssemblerOptions.back()->setATRegIndex(0); - -  Parser.Lex(); // Eat "noat". - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  getTargetStreamer().emitDirectiveSetNoAt(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetAtDirective() { -  // Line can be: ".set at", which sets $at to $1 -  //          or  ".set at=$reg", which sets $at to $reg. -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); // Eat "at". - -  if (getLexer().is(AsmToken::EndOfStatement)) { -    // No register was specified, so we set $at to $1. -    AssemblerOptions.back()->setATRegIndex(1); - -    getTargetStreamer().emitDirectiveSetAt(); -    Parser.Lex(); // Consume the EndOfStatement. -    return false; -  } - -  if (getLexer().isNot(AsmToken::Equal)) { -    reportParseError("unexpected token, expected equals sign"); -    return false; -  } -  Parser.Lex(); // Eat "=". - -  if (getLexer().isNot(AsmToken::Dollar)) { -    if (getLexer().is(AsmToken::EndOfStatement)) { -      reportParseError("no register specified"); -      return false; -    } else { -      reportParseError("unexpected token, expected dollar sign '$'"); -      return false; -    } -  } -  Parser.Lex(); // Eat "$". - -  // Find out what "reg" is. -  unsigned AtRegNo; -  const AsmToken &Reg = Parser.getTok(); -  if (Reg.is(AsmToken::Identifier)) { -    AtRegNo = matchCPURegisterName(Reg.getIdentifier()); -  } else if (Reg.is(AsmToken::Integer)) { -    AtRegNo = Reg.getIntVal(); -  } else { -    reportParseError("unexpected token, expected identifier or integer"); -    return false; -  } - -  // Check if $reg is a valid register. If it is, set $at to $reg. -  if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) { -    reportParseError("invalid register"); -    return false; -  } -  Parser.Lex(); // Eat "reg". - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo); - -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetReorderDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } -  AssemblerOptions.back()->setReorder(); -  getTargetStreamer().emitDirectiveSetReorder(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetNoReorderDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } -  AssemblerOptions.back()->setNoReorder(); -  getTargetStreamer().emitDirectiveSetNoReorder(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetMacroDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } -  AssemblerOptions.back()->setMacro(); -  getTargetStreamer().emitDirectiveSetMacro(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetNoMacroDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } -  if (AssemblerOptions.back()->isReorder()) { -    reportParseError("`noreorder' must be set before `nomacro'"); -    return false; -  } -  AssemblerOptions.back()->setNoMacro(); -  getTargetStreamer().emitDirectiveSetNoMacro(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetMsaDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  setFeatureBits(Mips::FeatureMSA, "msa"); -  getTargetStreamer().emitDirectiveSetMsa(); -  return false; -} - -bool MipsAsmParser::parseSetNoMsaDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  clearFeatureBits(Mips::FeatureMSA, "msa"); -  getTargetStreamer().emitDirectiveSetNoMsa(); -  return false; -} - -bool MipsAsmParser::parseSetNoDspDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); // Eat "nodsp". - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  clearFeatureBits(Mips::FeatureDSP, "dsp"); -  getTargetStreamer().emitDirectiveSetNoDsp(); -  return false; -} - -bool MipsAsmParser::parseSetMips16Directive() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); // Eat "mips16". - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  setFeatureBits(Mips::FeatureMips16, "mips16"); -  getTargetStreamer().emitDirectiveSetMips16(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetNoMips16Directive() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); // Eat "nomips16". - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  clearFeatureBits(Mips::FeatureMips16, "mips16"); -  getTargetStreamer().emitDirectiveSetNoMips16(); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetFpDirective() { -  MCAsmParser &Parser = getParser(); -  MipsABIFlagsSection::FpABIKind FpAbiVal; -  // Line can be: .set fp=32 -  //              .set fp=xx -  //              .set fp=64 -  Parser.Lex(); // Eat fp token -  AsmToken Tok = Parser.getTok(); -  if (Tok.isNot(AsmToken::Equal)) { -    reportParseError("unexpected token, expected equals sign '='"); -    return false; -  } -  Parser.Lex(); // Eat '=' token. -  Tok = Parser.getTok(); - -  if (!parseFpABIValue(FpAbiVal, ".set")) -    return false; - -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } -  getTargetStreamer().emitDirectiveSetFp(FpAbiVal); -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseSetOddSPRegDirective() { -  MCAsmParser &Parser = getParser(); - -  Parser.Lex(); // Eat "oddspreg". -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); -  getTargetStreamer().emitDirectiveSetOddSPReg(); -  return false; -} - -bool MipsAsmParser::parseSetNoOddSPRegDirective() { -  MCAsmParser &Parser = getParser(); - -  Parser.Lex(); // Eat "nooddspreg". -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); -  getTargetStreamer().emitDirectiveSetNoOddSPReg(); -  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(); - -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  // Always keep an element on the options "stack" to prevent the user -  // from changing the initial options. This is how we remember them. -  if (AssemblerOptions.size() == 2) -    return reportParseError(Loc, ".set pop with no .set push"); - -  MCSubtargetInfo &STI = copySTI(); -  AssemblerOptions.pop_back(); -  setAvailableFeatures( -      ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures())); -  STI.setFeatureBits(AssemblerOptions.back()->getFeatures()); - -  getTargetStreamer().emitDirectiveSetPop(); -  return false; -} - -bool MipsAsmParser::parseSetPushDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  // Create a copy of the current assembler options environment and push it. -  AssemblerOptions.push_back( -        llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); - -  getTargetStreamer().emitDirectiveSetPush(); -  return false; -} - -bool MipsAsmParser::parseSetSoftFloatDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  setFeatureBits(Mips::FeatureSoftFloat, "soft-float"); -  getTargetStreamer().emitDirectiveSetSoftFloat(); -  return false; -} - -bool MipsAsmParser::parseSetHardFloatDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  clearFeatureBits(Mips::FeatureSoftFloat, "soft-float"); -  getTargetStreamer().emitDirectiveSetHardFloat(); -  return false; -} - -bool MipsAsmParser::parseSetAssignment() { -  StringRef Name; -  MCAsmParser &Parser = getParser(); - -  if (Parser.parseIdentifier(Name)) -    return 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); -    return false; -  } - -  MCSymbol *Sym; -  const MCExpr *Value; -  if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, -                                               Parser, Sym, Value)) -    return true; -  Sym->setVariableValue(Value); - -  return false; -} - -bool MipsAsmParser::parseSetMips0Directive() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  // Reset assembler options to their initial values. -  MCSubtargetInfo &STI = copySTI(); -  setAvailableFeatures( -      ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures())); -  STI.setFeatureBits(AssemblerOptions.front()->getFeatures()); -  AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures()); - -  getTargetStreamer().emitDirectiveSetMips0(); -  return false; -} - -bool MipsAsmParser::parseSetArchDirective() { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::Equal)) -    return reportParseError("unexpected token, expected equals sign"); - -  Parser.Lex(); -  StringRef Arch = getParser().parseStringToEndOfStatement().trim(); -  if (Arch.empty()) -    return reportParseError("expected arch identifier"); - -  StringRef ArchFeatureName = -      StringSwitch<StringRef>(Arch) -          .Case("mips1", "mips1") -          .Case("mips2", "mips2") -          .Case("mips3", "mips3") -          .Case("mips4", "mips4") -          .Case("mips5", "mips5") -          .Case("mips32", "mips32") -          .Case("mips32r2", "mips32r2") -          .Case("mips32r3", "mips32r3") -          .Case("mips32r5", "mips32r5") -          .Case("mips32r6", "mips32r6") -          .Case("mips64", "mips64") -          .Case("mips64r2", "mips64r2") -          .Case("mips64r3", "mips64r3") -          .Case("mips64r5", "mips64r5") -          .Case("mips64r6", "mips64r6") -          .Case("octeon", "cnmips") -          .Case("octeon+", "cnmipsp") -          .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; -} - -bool MipsAsmParser::parseSetFeature(uint64_t Feature) { -  MCAsmParser &Parser = getParser(); -  Parser.Lex(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return reportParseError("unexpected token, expected end of statement"); - -  switch (Feature) { -  default: -    llvm_unreachable("Unimplemented feature"); -  case Mips::FeatureDSP: -    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: -    selectArch("mips1"); -    getTargetStreamer().emitDirectiveSetMips1(); -    break; -  case Mips::FeatureMips2: -    selectArch("mips2"); -    getTargetStreamer().emitDirectiveSetMips2(); -    break; -  case Mips::FeatureMips3: -    selectArch("mips3"); -    getTargetStreamer().emitDirectiveSetMips3(); -    break; -  case Mips::FeatureMips4: -    selectArch("mips4"); -    getTargetStreamer().emitDirectiveSetMips4(); -    break; -  case Mips::FeatureMips5: -    selectArch("mips5"); -    getTargetStreamer().emitDirectiveSetMips5(); -    break; -  case Mips::FeatureMips32: -    selectArch("mips32"); -    getTargetStreamer().emitDirectiveSetMips32(); -    break; -  case Mips::FeatureMips32r2: -    selectArch("mips32r2"); -    getTargetStreamer().emitDirectiveSetMips32R2(); -    break; -  case Mips::FeatureMips32r3: -    selectArch("mips32r3"); -    getTargetStreamer().emitDirectiveSetMips32R3(); -    break; -  case Mips::FeatureMips32r5: -    selectArch("mips32r5"); -    getTargetStreamer().emitDirectiveSetMips32R5(); -    break; -  case Mips::FeatureMips32r6: -    selectArch("mips32r6"); -    getTargetStreamer().emitDirectiveSetMips32R6(); -    break; -  case Mips::FeatureMips64: -    selectArch("mips64"); -    getTargetStreamer().emitDirectiveSetMips64(); -    break; -  case Mips::FeatureMips64r2: -    selectArch("mips64r2"); -    getTargetStreamer().emitDirectiveSetMips64R2(); -    break; -  case Mips::FeatureMips64r3: -    selectArch("mips64r3"); -    getTargetStreamer().emitDirectiveSetMips64R3(); -    break; -  case Mips::FeatureMips64r5: -    selectArch("mips64r5"); -    getTargetStreamer().emitDirectiveSetMips64R5(); -    break; -  case Mips::FeatureMips64r6: -    selectArch("mips64r6"); -    getTargetStreamer().emitDirectiveSetMips64R6(); -    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; -} - -bool MipsAsmParser::eatComma(StringRef ErrorStr) { -  MCAsmParser &Parser = getParser(); -  if (getLexer().isNot(AsmToken::Comma)) { -    SMLoc Loc = getLexer().getLoc(); -    return Error(Loc, ErrorStr); -  } - -  Parser.Lex(); // Eat the comma. -  return true; -} - -// Used to determine if .cpload, .cprestore, and .cpsetup have any effect. -// In this class, it is only used for .cprestore. -// FIXME: Only keep track of IsPicEnabled in one place, instead of in both -// MipsTargetELFStreamer and MipsAsmParser. -bool MipsAsmParser::isPicAndNotNxxAbi() { -  return inPicMode() && !(isABI_N32() || isABI_N64()); -} - -bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { -  if (AssemblerOptions.back()->isReorder()) -    Warning(Loc, ".cpload should be inside a noreorder section"); - -  if (inMips16Mode()) { -    reportParseError(".cpload is not supported in Mips16 mode"); -    return false; -  } - -  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; -  OperandMatchResultTy ResTy = parseAnyRegister(Reg); -  if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { -    reportParseError("expected register containing function address"); -    return false; -  } - -  MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); -  if (!RegOpnd.isGPRAsmReg()) { -    reportParseError(RegOpnd.getStartLoc(), "invalid register"); -    return false; -  } - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg()); -  return false; -} - -bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) { -  if (!isABI_N32() && !isABI_N64()) { -    reportParseError(".cplocal is allowed only in N32 or N64 mode"); -    return false; -  } - -  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; -  OperandMatchResultTy ResTy = parseAnyRegister(Reg); -  if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { -    reportParseError("expected register containing global pointer"); -    return false; -  } - -  MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); -  if (!RegOpnd.isGPRAsmReg()) { -    reportParseError(RegOpnd.getStartLoc(), "invalid register"); -    return false; -  } - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } -  getParser().Lex(); // Consume the EndOfStatement. - -  unsigned NewReg = RegOpnd.getGPR32Reg(); -  if (IsPicEnabled) -    GPReg = NewReg; - -  getTargetStreamer().emitDirectiveCpLocal(NewReg); -  return false; -} - -bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { -  MCAsmParser &Parser = getParser(); - -  // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it -  // is used in non-PIC mode. - -  if (inMips16Mode()) { -    reportParseError(".cprestore is not supported in Mips16 mode"); -    return false; -  } - -  // Get the stack offset value. -  const MCExpr *StackOffset; -  int64_t StackOffsetVal; -  if (Parser.parseExpression(StackOffset)) { -    reportParseError("expected stack offset value"); -    return false; -  } - -  if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) { -    reportParseError("stack offset is not an absolute expression"); -    return false; -  } - -  if (StackOffsetVal < 0) { -    Warning(Loc, ".cprestore with negative stack offset has no effect"); -    IsCpRestoreSet = false; -  } else { -    IsCpRestoreSet = true; -    CpRestoreOffset = StackOffsetVal; -  } - -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  if (!getTargetStreamer().emitDirectiveCpRestore( -          CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI)) -    return true; -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseDirectiveCPSetup() { -  MCAsmParser &Parser = getParser(); -  unsigned FuncReg; -  unsigned Save; -  bool SaveIsReg = true; - -  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; -  OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); -  if (ResTy == MatchOperand_NoMatch) { -    reportParseError("expected register containing function address"); -    return false; -  } - -  MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); -  if (!FuncRegOpnd.isGPRAsmReg()) { -    reportParseError(FuncRegOpnd.getStartLoc(), "invalid register"); -    return false; -  } - -  FuncReg = FuncRegOpnd.getGPR32Reg(); -  TmpReg.clear(); - -  if (!eatComma("unexpected token, expected comma")) -    return true; - -  ResTy = parseAnyRegister(TmpReg); -  if (ResTy == MatchOperand_NoMatch) { -    const MCExpr *OffsetExpr; -    int64_t OffsetVal; -    SMLoc ExprLoc = getLexer().getLoc(); - -    if (Parser.parseExpression(OffsetExpr) || -        !OffsetExpr->evaluateAsAbsolute(OffsetVal)) { -      reportParseError(ExprLoc, "expected save register or stack offset"); -      return false; -    } - -    Save = OffsetVal; -    SaveIsReg = false; -  } else { -    MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]); -    if (!SaveOpnd.isGPRAsmReg()) { -      reportParseError(SaveOpnd.getStartLoc(), "invalid register"); -      return false; -    } -    Save = SaveOpnd.getGPR32Reg(); -  } - -  if (!eatComma("unexpected token, expected comma")) -    return true; - -  const MCExpr *Expr; -  if (Parser.parseExpression(Expr)) { -    reportParseError("expected expression"); -    return false; -  } - -  if (Expr->getKind() != MCExpr::SymbolRef) { -    reportParseError("expected symbol"); -    return false; -  } -  const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); - -  CpSaveLocation = Save; -  CpSaveLocationIsRegister = SaveIsReg; - -  getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(), -                                           SaveIsReg); -  return false; -} - -bool MipsAsmParser::parseDirectiveCPReturn() { -  getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation, -                                            CpSaveLocationIsRegister); -  return false; -} - -bool MipsAsmParser::parseDirectiveNaN() { -  MCAsmParser &Parser = getParser(); -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    const AsmToken &Tok = Parser.getTok(); - -    if (Tok.getString() == "2008") { -      Parser.Lex(); -      getTargetStreamer().emitDirectiveNaN2008(); -      return false; -    } else if (Tok.getString() == "legacy") { -      Parser.Lex(); -      getTargetStreamer().emitDirectiveNaNLegacy(); -      return false; -    } -  } -  // If we don't recognize the option passed to the .nan -  // directive (e.g. no option or unknown option), emit an error. -  reportParseError("invalid option in .nan directive"); -  return false; -} - -bool MipsAsmParser::parseDirectiveSet() { -  const AsmToken &Tok = getParser().getTok(); -  StringRef IdVal = Tok.getString(); -  SMLoc Loc = Tok.getLoc(); - -  if (IdVal == "noat") -    return parseSetNoAtDirective(); -  if (IdVal == "at") -    return parseSetAtDirective(); -  if (IdVal == "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") -    return parseSetFpDirective(); -  if (IdVal == "oddspreg") -    return parseSetOddSPRegDirective(); -  if (IdVal == "nooddspreg") -    return parseSetNoOddSPRegDirective(); -  if (IdVal == "pop") -    return parseSetPopDirective(); -  if (IdVal == "push") -    return parseSetPushDirective(); -  if (IdVal == "reorder") -    return parseSetReorderDirective(); -  if (IdVal == "noreorder") -    return parseSetNoReorderDirective(); -  if (IdVal == "macro") -    return parseSetMacroDirective(); -  if (IdVal == "nomacro") -    return parseSetNoMacroDirective(); -  if (IdVal == "mips16") -    return parseSetMips16Directive(); -  if (IdVal == "nomips16") -    return parseSetNoMips16Directive(); -  if (IdVal == "nomicromips") { -    clearFeatureBits(Mips::FeatureMicroMips, "micromips"); -    getTargetStreamer().emitDirectiveSetNoMicroMips(); -    getParser().eatToEndOfStatement(); -    return false; -  } -  if (IdVal == "micromips") { -    if (hasMips64r6()) { -      Error(Loc, ".set micromips directive is not supported with MIPS64R6"); -      return false; -    } -    return parseSetFeature(Mips::FeatureMicroMips); -  } -  if (IdVal == "mips0") -    return parseSetMips0Directive(); -  if (IdVal == "mips1") -    return parseSetFeature(Mips::FeatureMips1); -  if (IdVal == "mips2") -    return parseSetFeature(Mips::FeatureMips2); -  if (IdVal == "mips3") -    return parseSetFeature(Mips::FeatureMips3); -  if (IdVal == "mips4") -    return parseSetFeature(Mips::FeatureMips4); -  if (IdVal == "mips5") -    return parseSetFeature(Mips::FeatureMips5); -  if (IdVal == "mips32") -    return parseSetFeature(Mips::FeatureMips32); -  if (IdVal == "mips32r2") -    return parseSetFeature(Mips::FeatureMips32r2); -  if (IdVal == "mips32r3") -    return parseSetFeature(Mips::FeatureMips32r3); -  if (IdVal == "mips32r5") -    return parseSetFeature(Mips::FeatureMips32r5); -  if (IdVal == "mips32r6") -    return parseSetFeature(Mips::FeatureMips32r6); -  if (IdVal == "mips64") -    return parseSetFeature(Mips::FeatureMips64); -  if (IdVal == "mips64r2") -    return parseSetFeature(Mips::FeatureMips64r2); -  if (IdVal == "mips64r3") -    return parseSetFeature(Mips::FeatureMips64r3); -  if (IdVal == "mips64r5") -    return parseSetFeature(Mips::FeatureMips64r5); -  if (IdVal == "mips64r6") { -    if (inMicroMipsMode()) { -      Error(Loc, "MIPS64R6 is not supported with microMIPS"); -      return false; -    } -    return parseSetFeature(Mips::FeatureMips64r6); -  } -  if (IdVal == "dsp") -    return parseSetFeature(Mips::FeatureDSP); -  if (IdVal == "dspr2") -    return parseSetFeature(Mips::FeatureDSPR2); -  if (IdVal == "nodsp") -    return parseSetNoDspDirective(); -  if (IdVal == "msa") -    return parseSetMsaDirective(); -  if (IdVal == "nomsa") -    return parseSetNoMsaDirective(); -  if (IdVal == "mt") -    return parseSetMtDirective(); -  if (IdVal == "nomt") -    return parseSetNoMtDirective(); -  if (IdVal == "softfloat") -    return parseSetSoftFloatDirective(); -  if (IdVal == "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(); -} - -/// parseDirectiveGpWord -///  ::= .gpword local_sym -bool MipsAsmParser::parseDirectiveGpWord() { -  MCAsmParser &Parser = getParser(); -  const MCExpr *Value; -  // EmitGPRel32Value requires an expression, so we are using base class -  // method to evaluate the expression. -  if (getParser().parseExpression(Value)) -    return true; -  getParser().getStreamer().EmitGPRel32Value(Value); - -  if (getLexer().isNot(AsmToken::EndOfStatement)) -    return Error(getLexer().getLoc(), -                "unexpected token, expected end of statement"); -  Parser.Lex(); // Eat EndOfStatement token. -  return false; -} - -/// parseDirectiveGpDWord -///  ::= .gpdword local_sym -bool MipsAsmParser::parseDirectiveGpDWord() { -  MCAsmParser &Parser = getParser(); -  const MCExpr *Value; -  // EmitGPRel64Value requires an expression, so we are using base class -  // method to evaluate the expression. -  if (getParser().parseExpression(Value)) -    return true; -  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(), -                "unexpected token, expected end of statement"); -  Parser.Lex(); // Eat EndOfStatement token. -  return false; -} - -bool MipsAsmParser::parseDirectiveOption() { -  MCAsmParser &Parser = getParser(); -  // Get the option token. -  AsmToken Tok = Parser.getTok(); -  // At the moment only identifiers are supported. -  if (Tok.isNot(AsmToken::Identifier)) { -    return Error(Parser.getTok().getLoc(), -                 "unexpected token, expected identifier"); -  } - -  StringRef Option = Tok.getIdentifier(); - -  if (Option == "pic0") { -    // MipsAsmParser needs to know if the current PIC mode changes. -    IsPicEnabled = false; - -    getTargetStreamer().emitDirectiveOptionPic0(); -    Parser.Lex(); -    if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { -      return Error(Parser.getTok().getLoc(), -                   "unexpected token, expected end of statement"); -    } -    return false; -  } - -  if (Option == "pic2") { -    // MipsAsmParser needs to know if the current PIC mode changes. -    IsPicEnabled = true; - -    getTargetStreamer().emitDirectiveOptionPic2(); -    Parser.Lex(); -    if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { -      return Error(Parser.getTok().getLoc(), -                   "unexpected token, expected end of statement"); -    } -    return false; -  } - -  // Unknown option. -  Warning(Parser.getTok().getLoc(), -          "unknown option, expected 'pic0' or 'pic2'"); -  Parser.eatToEndOfStatement(); -  return false; -} - -/// parseInsnDirective -///  ::= .insn -bool MipsAsmParser::parseInsnDirective() { -  // 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; -  } - -  // The actual label marking happens in -  // MipsELFStreamer::createPendingLabelRelocs(). -  getTargetStreamer().emitDirectiveInsn(); - -  getParser().Lex(); // Eat EndOfStatement token. -  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(); -  SMLoc L = Lexer.getLoc(); - -  if (!getTargetStreamer().isModuleDirectiveAllowed()) { -    // TODO : get a better message. -    reportParseError(".module directive must appear before any code"); -    return false; -  } - -  StringRef Option; -  if (Parser.parseIdentifier(Option)) { -    reportParseError("expected .module option identifier"); -    return false; -  } - -  if (Option == "oddspreg") { -    clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); - -    // Synchronize the abiflags information with the FeatureBits information we -    // changed above. -    getTargetStreamer().updateABIInfo(*this); - -    // If printing assembly, use the recently updated abiflags information. -    // If generating ELF, don't do anything (the .MIPS.abiflags section gets -    // emitted at the end). -    getTargetStreamer().emitDirectiveModuleOddSPReg(); - -    // 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 == "nooddspreg") { -    if (!isABI_O32()) { -      return Error(L, "'.module nooddspreg' requires the O32 ABI"); -    } - -    setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); - -    // Synchronize the abiflags information with the FeatureBits information we -    // changed above. -    getTargetStreamer().updateABIInfo(*this); - -    // If printing assembly, use the recently updated abiflags information. -    // If generating ELF, don't do anything (the .MIPS.abiflags section gets -    // emitted at the end). -    getTargetStreamer().emitDirectiveModuleOddSPReg(); - -    // 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 == "fp") { -    return parseDirectiveModuleFP(); -  } else if (Option == "softfloat") { -    setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); - -    // 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().emitDirectiveModuleSoftFloat(); - -    // 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 == "hardfloat") { -    clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); - -    // 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().emitDirectiveModuleHardFloat(); - -    // 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 == "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."); -  } -} - -/// parseDirectiveModuleFP -///  ::= =32 -///  ::= =xx -///  ::= =64 -bool MipsAsmParser::parseDirectiveModuleFP() { -  MCAsmParser &Parser = getParser(); -  MCAsmLexer &Lexer = getLexer(); - -  if (Lexer.isNot(AsmToken::Equal)) { -    reportParseError("unexpected token, expected equals sign '='"); -    return false; -  } -  Parser.Lex(); // Eat '=' token. - -  MipsABIFlagsSection::FpABIKind FpABI; -  if (!parseFpABIValue(FpABI, ".module")) -    return false; - -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  // Synchronize the abiflags information with the FeatureBits information we -  // changed above. -  getTargetStreamer().updateABIInfo(*this); - -  // If printing assembly, use the recently updated abiflags information. -  // If generating ELF, don't do anything (the .MIPS.abiflags section gets -  // emitted at the end). -  getTargetStreamer().emitDirectiveModuleFP(); - -  Parser.Lex(); // Consume the EndOfStatement. -  return false; -} - -bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, -                                    StringRef Directive) { -  MCAsmParser &Parser = getParser(); -  MCAsmLexer &Lexer = getLexer(); -  bool ModuleLevelOptions = Directive == ".module"; - -  if (Lexer.is(AsmToken::Identifier)) { -    StringRef Value = Parser.getTok().getString(); -    Parser.Lex(); - -    if (Value != "xx") { -      reportParseError("unsupported value, expected 'xx', '32' or '64'"); -      return false; -    } - -    if (!isABI_O32()) { -      reportParseError("'" + Directive + " fp=xx' requires the O32 ABI"); -      return false; -    } - -    FpABI = MipsABIFlagsSection::FpABIKind::XX; -    if (ModuleLevelOptions) { -      setModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); -      clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); -    } else { -      setFeatureBits(Mips::FeatureFPXX, "fpxx"); -      clearFeatureBits(Mips::FeatureFP64Bit, "fp64"); -    } -    return true; -  } - -  if (Lexer.is(AsmToken::Integer)) { -    unsigned Value = Parser.getTok().getIntVal(); -    Parser.Lex(); - -    if (Value != 32 && Value != 64) { -      reportParseError("unsupported value, expected 'xx', '32' or '64'"); -      return false; -    } - -    if (Value == 32) { -      if (!isABI_O32()) { -        reportParseError("'" + Directive + " fp=32' requires the O32 ABI"); -        return false; -      } - -      FpABI = MipsABIFlagsSection::FpABIKind::S32; -      if (ModuleLevelOptions) { -        clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); -        clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); -      } else { -        clearFeatureBits(Mips::FeatureFPXX, "fpxx"); -        clearFeatureBits(Mips::FeatureFP64Bit, "fp64"); -      } -    } else { -      FpABI = MipsABIFlagsSection::FpABIKind::S64; -      if (ModuleLevelOptions) { -        clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); -        setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); -      } else { -        clearFeatureBits(Mips::FeatureFPXX, "fpxx"); -        setFeatureBits(Mips::FeatureFP64Bit, "fp64"); -      } -    } - -    return true; -  } - -  return false; -} - -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()); -    return false; -  } -  if (IDVal == ".cplocal") { -    parseDirectiveCpLocal(DirectiveID.getLoc()); -    return false; -  } -  if (IDVal == ".ent") { -    StringRef SymbolName; - -    if (Parser.parseIdentifier(SymbolName)) { -      reportParseError("expected identifier after .ent"); -      return false; -    } - -    // There's an undocumented extension that allows an integer to -    // follow the name of the procedure which AFAICS is ignored by GAS. -    // Example: .ent foo,2 -    if (getLexer().isNot(AsmToken::EndOfStatement)) { -      if (getLexer().isNot(AsmToken::Comma)) { -        // Even though we accept this undocumented extension for compatibility -        // reasons, the additional integer argument does not actually change -        // the behaviour of the '.ent' directive, so we would like to discourage -        // its use. We do this by not referring to the extended version in -        // error messages which are not directly related to its use. -        reportParseError("unexpected token, expected end of statement"); -        return false; -      } -      Parser.Lex(); // Eat the comma. -      const MCExpr *DummyNumber; -      int64_t DummyNumberVal; -      // If the user was explicitly trying to use the extended version, -      // we still give helpful extension-related error messages. -      if (Parser.parseExpression(DummyNumber)) { -        reportParseError("expected number after comma"); -        return false; -      } -      if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) { -        reportParseError("expected an absolute expression after comma"); -        return false; -      } -    } - -    // If this is not the end of the statement, report an error. -    if (getLexer().isNot(AsmToken::EndOfStatement)) { -      reportParseError("unexpected token, expected end of statement"); -      return false; -    } - -    MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); - -    getTargetStreamer().emitDirectiveEnt(*Sym); -    CurrentFn = Sym; -    IsCpRestoreSet = false; -    return false; -  } - -  if (IDVal == ".end") { -    StringRef SymbolName; - -    if (Parser.parseIdentifier(SymbolName)) { -      reportParseError("expected identifier after .end"); -      return false; -    } - -    if (getLexer().isNot(AsmToken::EndOfStatement)) { -      reportParseError("unexpected token, expected end of statement"); -      return false; -    } - -    if (CurrentFn == nullptr) { -      reportParseError(".end used without .ent"); -      return false; -    } - -    if ((SymbolName != CurrentFn->getName())) { -      reportParseError(".end symbol does not match .ent symbol"); -      return false; -    } - -    getTargetStreamer().emitDirectiveEnd(SymbolName); -    CurrentFn = nullptr; -    IsCpRestoreSet = false; -    return false; -  } - -  if (IDVal == ".frame") { -    // .frame $stack_reg, frame_size_in_bytes, $return_reg -    SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; -    OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); -    if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { -      reportParseError("expected stack register"); -      return false; -    } - -    MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); -    if (!StackRegOpnd.isGPRAsmReg()) { -      reportParseError(StackRegOpnd.getStartLoc(), -                       "expected general purpose register"); -      return false; -    } -    unsigned StackReg = StackRegOpnd.getGPR32Reg(); - -    if (Parser.getTok().is(AsmToken::Comma)) -      Parser.Lex(); -    else { -      reportParseError("unexpected token, expected comma"); -      return false; -    } - -    // Parse the frame size. -    const MCExpr *FrameSize; -    int64_t FrameSizeVal; - -    if (Parser.parseExpression(FrameSize)) { -      reportParseError("expected frame size value"); -      return false; -    } - -    if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) { -      reportParseError("frame size not an absolute expression"); -      return false; -    } - -    if (Parser.getTok().is(AsmToken::Comma)) -      Parser.Lex(); -    else { -      reportParseError("unexpected token, expected comma"); -      return false; -    } - -    // Parse the return register. -    TmpReg.clear(); -    ResTy = parseAnyRegister(TmpReg); -    if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { -      reportParseError("expected return register"); -      return false; -    } - -    MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); -    if (!ReturnRegOpnd.isGPRAsmReg()) { -      reportParseError(ReturnRegOpnd.getStartLoc(), -                       "expected general purpose register"); -      return false; -    } - -    // If this is not the end of the statement, report an error. -    if (getLexer().isNot(AsmToken::EndOfStatement)) { -      reportParseError("unexpected token, expected end of statement"); -      return false; -    } - -    getTargetStreamer().emitFrame(StackReg, FrameSizeVal, -                                  ReturnRegOpnd.getGPR32Reg()); -    IsCpRestoreSet = false; -    return false; -  } - -  if (IDVal == ".set") { -    parseDirectiveSet(); -    return false; -  } - -  if (IDVal == ".mask" || IDVal == ".fmask") { -    // .mask bitmask, frame_offset -    // bitmask: One bit for each register used. -    // frame_offset: Offset from Canonical Frame Address ($sp on entry) where -    //               first register is expected to be saved. -    // Examples: -    //   .mask 0x80000000, -4 -    //   .fmask 0x80000000, -4 -    // - -    // Parse the bitmask -    const MCExpr *BitMask; -    int64_t BitMaskVal; - -    if (Parser.parseExpression(BitMask)) { -      reportParseError("expected bitmask value"); -      return false; -    } - -    if (!BitMask->evaluateAsAbsolute(BitMaskVal)) { -      reportParseError("bitmask not an absolute expression"); -      return false; -    } - -    if (Parser.getTok().is(AsmToken::Comma)) -      Parser.Lex(); -    else { -      reportParseError("unexpected token, expected comma"); -      return false; -    } - -    // Parse the frame_offset -    const MCExpr *FrameOffset; -    int64_t FrameOffsetVal; - -    if (Parser.parseExpression(FrameOffset)) { -      reportParseError("expected frame offset value"); -      return false; -    } - -    if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) { -      reportParseError("frame offset not an absolute expression"); -      return false; -    } - -    // If this is not the end of the statement, report an error. -    if (getLexer().isNot(AsmToken::EndOfStatement)) { -      reportParseError("unexpected token, expected end of statement"); -      return false; -    } - -    if (IDVal == ".mask") -      getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal); -    else -      getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal); -    return false; -  } - -  if (IDVal == ".nan") -    return parseDirectiveNaN(); - -  if (IDVal == ".gpword") { -    parseDirectiveGpWord(); -    return false; -  } - -  if (IDVal == ".gpdword") { -    parseDirectiveGpDWord(); -    return false; -  } - -  if (IDVal == ".dtprelword") { -    parseDirectiveDtpRelWord(); -    return false; -  } - -  if (IDVal == ".dtpreldword") { -    parseDirectiveDtpRelDWord(); -    return false; -  } - -  if (IDVal == ".tprelword") { -    parseDirectiveTpRelWord(); -    return false; -  } - -  if (IDVal == ".tpreldword") { -    parseDirectiveTpRelDWord(); -    return false; -  } - -  if (IDVal == ".option") { -    parseDirectiveOption(); -    return false; -  } - -  if (IDVal == ".abicalls") { -    getTargetStreamer().emitDirectiveAbiCalls(); -    if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { -      Error(Parser.getTok().getLoc(), -            "unexpected token, expected end of statement"); -    } -    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; -  } - -  return true; -} - -bool MipsAsmParser::parseInternalDirectiveReallowModule() { -  // If this is not the end of the statement, report an error. -  if (getLexer().isNot(AsmToken::EndOfStatement)) { -    reportParseError("unexpected token, expected end of statement"); -    return false; -  } - -  getTargetStreamer().reallowModuleDirective(); - -  getParser().Lex(); // Eat EndOfStatement token. -  return false; -} - -extern "C" void LLVMInitializeMipsAsmParser() { -  RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget()); -  RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget()); -  RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target()); -  RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget()); -} - -#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; -}  | 
