xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIFlagsSection.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCExpr.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h"
140b57cec5SDimitry Andric #include "MipsTargetStreamer.h"
150b57cec5SDimitry Andric #include "TargetInfo/MipsTargetInfo.h"
160b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
220b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
2781ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
390b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
400b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
41349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
428bcb0991SDimitry Andric #include "llvm/Support/Alignment.h"
430b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
440b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
450b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
460b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
470b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
480b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
490b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
500b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
510b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
5206c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
5306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
540b57cec5SDimitry Andric #include <algorithm>
550b57cec5SDimitry Andric #include <cassert>
560b57cec5SDimitry Andric #include <cstdint>
570b57cec5SDimitry Andric #include <memory>
580b57cec5SDimitry Andric #include <string>
590b57cec5SDimitry Andric #include <utility>
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric using namespace llvm;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric #define DEBUG_TYPE "mips-asm-parser"
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric namespace llvm {
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric class MCInstrInfo;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric } // end namespace llvm
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric extern cl::opt<bool> EmitJalrReloc;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric namespace {
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric class MipsAssemblerOptions {
760b57cec5SDimitry Andric public:
MipsAssemblerOptions(const FeatureBitset & Features_)770b57cec5SDimitry Andric   MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
780b57cec5SDimitry Andric 
MipsAssemblerOptions(const MipsAssemblerOptions * Opts)790b57cec5SDimitry Andric   MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
800b57cec5SDimitry Andric     ATReg = Opts->getATRegIndex();
810b57cec5SDimitry Andric     Reorder = Opts->isReorder();
820b57cec5SDimitry Andric     Macro = Opts->isMacro();
830b57cec5SDimitry Andric     Features = Opts->getFeatures();
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric 
getATRegIndex() const860b57cec5SDimitry Andric   unsigned getATRegIndex() const { return ATReg; }
setATRegIndex(unsigned Reg)870b57cec5SDimitry Andric   bool setATRegIndex(unsigned Reg) {
880b57cec5SDimitry Andric     if (Reg > 31)
890b57cec5SDimitry Andric       return false;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     ATReg = Reg;
920b57cec5SDimitry Andric     return true;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
isReorder() const950b57cec5SDimitry Andric   bool isReorder() const { return Reorder; }
setReorder()960b57cec5SDimitry Andric   void setReorder() { Reorder = true; }
setNoReorder()970b57cec5SDimitry Andric   void setNoReorder() { Reorder = false; }
980b57cec5SDimitry Andric 
isMacro() const990b57cec5SDimitry Andric   bool isMacro() const { return Macro; }
setMacro()1000b57cec5SDimitry Andric   void setMacro() { Macro = true; }
setNoMacro()1010b57cec5SDimitry Andric   void setNoMacro() { Macro = false; }
1020b57cec5SDimitry Andric 
getFeatures() const1030b57cec5SDimitry Andric   const FeatureBitset &getFeatures() const { return Features; }
setFeatures(const FeatureBitset & Features_)1040b57cec5SDimitry Andric   void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   // Set of features that are either architecture features or referenced
1070b57cec5SDimitry Andric   // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
1080b57cec5SDimitry Andric   // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
1090b57cec5SDimitry Andric   // The reason we need this mask is explained in the selectArch function.
1100b57cec5SDimitry Andric   // FIXME: Ideally we would like TableGen to generate this information.
1110b57cec5SDimitry Andric   static const FeatureBitset AllArchRelatedMask;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric private:
1140b57cec5SDimitry Andric   unsigned ATReg = 1;
1150b57cec5SDimitry Andric   bool Reorder = true;
1160b57cec5SDimitry Andric   bool Macro = true;
1170b57cec5SDimitry Andric   FeatureBitset Features;
1180b57cec5SDimitry Andric };
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric } // end anonymous namespace
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
1230b57cec5SDimitry Andric     Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
1240b57cec5SDimitry Andric     Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
1250b57cec5SDimitry Andric     Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
1260b57cec5SDimitry Andric     Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
1270b57cec5SDimitry Andric     Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
1280b57cec5SDimitry Andric     Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
1290b57cec5SDimitry Andric     Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
1300b57cec5SDimitry Andric     Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit,
1310b57cec5SDimitry Andric     Mips::FeatureNaN2008
1320b57cec5SDimitry Andric };
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric namespace {
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric class MipsAsmParser : public MCTargetAsmParser {
getTargetStreamer()1370b57cec5SDimitry Andric   MipsTargetStreamer &getTargetStreamer() {
138480093f4SDimitry Andric     assert(getParser().getStreamer().getTargetStreamer() &&
139480093f4SDimitry Andric            "do not have a target streamer");
1400b57cec5SDimitry Andric     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1410b57cec5SDimitry Andric     return static_cast<MipsTargetStreamer &>(TS);
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   MipsABIInfo ABI;
1450b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
1460b57cec5SDimitry Andric   MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
1470b57cec5SDimitry Andric                        // nullptr, which indicates that no function is currently
1480b57cec5SDimitry Andric                        // selected. This usually happens after an '.end func'
1490b57cec5SDimitry Andric                        // directive.
1500b57cec5SDimitry Andric   bool IsLittleEndian;
1510b57cec5SDimitry Andric   bool IsPicEnabled;
1520b57cec5SDimitry Andric   bool IsCpRestoreSet;
1534c2d3b02SDimitry Andric   bool CurForbiddenSlotAttr;
1540b57cec5SDimitry Andric   int CpRestoreOffset;
1550b57cec5SDimitry Andric   unsigned GPReg;
1560b57cec5SDimitry Andric   unsigned CpSaveLocation;
1570b57cec5SDimitry Andric   /// If true, then CpSaveLocation is a register, otherwise it's an offset.
1580b57cec5SDimitry Andric   bool     CpSaveLocationIsRegister;
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   // Map of register aliases created via the .set directive.
1610b57cec5SDimitry Andric   StringMap<AsmToken> RegisterSets;
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   // Print a warning along with its fix-it message at the given range.
1640b57cec5SDimitry Andric   void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1650b57cec5SDimitry Andric                              SMRange Range, bool ShowColors = true);
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
1700b57cec5SDimitry Andric #include "MipsGenAsmMatcher.inc"
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   unsigned
1730b57cec5SDimitry Andric   checkEarlyTargetMatchPredicate(MCInst &Inst,
1740b57cec5SDimitry Andric                                  const OperandVector &Operands) override;
1750b57cec5SDimitry Andric   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1780b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
1790b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
1800b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   /// Parse a register as used in CFI directives
1835f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1845f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1855ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   bool parseParenSuffix(StringRef Name, OperandVector &Operands);
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1940b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
1970b57cec5SDimitry Andric 
19806c3fb27SDimitry Andric   ParseStatus parseMemOperand(OperandVector &Operands);
19906c3fb27SDimitry Andric   ParseStatus matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
2000b57cec5SDimitry Andric                                                 StringRef Identifier, SMLoc S);
20106c3fb27SDimitry Andric   ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands,
20206c3fb27SDimitry Andric                                             const AsmToken &Token, SMLoc S);
20306c3fb27SDimitry Andric   ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
20406c3fb27SDimitry Andric   ParseStatus parseAnyRegister(OperandVector &Operands);
20506c3fb27SDimitry Andric   ParseStatus parseImm(OperandVector &Operands);
20606c3fb27SDimitry Andric   ParseStatus parseJumpTarget(OperandVector &Operands);
20706c3fb27SDimitry Andric   ParseStatus parseInvNum(OperandVector &Operands);
20806c3fb27SDimitry Andric   ParseStatus parseRegisterList(OperandVector &Operands);
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   bool searchSymbolAlias(OperandVector &Operands);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   bool parseOperand(OperandVector &, StringRef Mnemonic);
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   enum MacroExpanderResultTy {
2150b57cec5SDimitry Andric     MER_NotAMacro,
2160b57cec5SDimitry Andric     MER_Success,
2170b57cec5SDimitry Andric     MER_Fail,
2180b57cec5SDimitry Andric   };
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   // Expands assembly pseudo instructions.
2210b57cec5SDimitry Andric   MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
2220b57cec5SDimitry Andric                                              MCStreamer &Out,
2230b57cec5SDimitry Andric                                              const MCSubtargetInfo *STI);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2260b57cec5SDimitry Andric                          const MCSubtargetInfo *STI);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
2290b57cec5SDimitry Andric                      bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
2300b57cec5SDimitry Andric                      MCStreamer &Out, const MCSubtargetInfo *STI);
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
2330b57cec5SDimitry Andric                                unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
2340b57cec5SDimitry Andric                                MCStreamer &Out, const MCSubtargetInfo *STI);
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2390b57cec5SDimitry Andric                      MCStreamer &Out, const MCSubtargetInfo *STI);
2400b57cec5SDimitry Andric 
241c14a5a88SDimitry Andric   bool expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2420b57cec5SDimitry Andric                                 const MCSubtargetInfo *STI);
243c14a5a88SDimitry Andric   bool expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244c14a5a88SDimitry Andric                                 const MCSubtargetInfo *STI);
245c14a5a88SDimitry Andric   bool expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246c14a5a88SDimitry Andric                                 const MCSubtargetInfo *STI);
247c14a5a88SDimitry Andric   bool expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU, SMLoc IDLoc,
248c14a5a88SDimitry Andric                                 MCStreamer &Out, const MCSubtargetInfo *STI);
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2510b57cec5SDimitry Andric                          const MCOperand &Offset, bool Is32BitAddress,
2520b57cec5SDimitry Andric                          SMLoc IDLoc, MCStreamer &Out,
2530b57cec5SDimitry Andric                          const MCSubtargetInfo *STI);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2560b57cec5SDimitry Andric                                   const MCSubtargetInfo *STI);
2570b57cec5SDimitry Andric 
258480093f4SDimitry Andric   void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259480093f4SDimitry Andric                        const MCSubtargetInfo *STI, bool IsLoad);
260480093f4SDimitry Andric   void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2610b57cec5SDimitry Andric                       const MCSubtargetInfo *STI, bool IsLoad);
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2640b57cec5SDimitry Andric                                const MCSubtargetInfo *STI);
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2670b57cec5SDimitry Andric                             const MCSubtargetInfo *STI);
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2700b57cec5SDimitry Andric                        const MCSubtargetInfo *STI);
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2730b57cec5SDimitry Andric                           const MCSubtargetInfo *STI);
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2760b57cec5SDimitry Andric                     const MCSubtargetInfo *STI, const bool IsMips64,
2770b57cec5SDimitry Andric                     const bool Signed);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
2800b57cec5SDimitry Andric                    MCStreamer &Out, const MCSubtargetInfo *STI);
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
2830b57cec5SDimitry Andric                  const MCSubtargetInfo *STI);
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2860b57cec5SDimitry Andric                  const MCSubtargetInfo *STI);
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2890b57cec5SDimitry Andric                  const MCSubtargetInfo *STI);
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2920b57cec5SDimitry Andric                  const MCSubtargetInfo *STI);
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2950b57cec5SDimitry Andric                     const MCSubtargetInfo *STI);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2980b57cec5SDimitry Andric                     const MCSubtargetInfo *STI);
2990b57cec5SDimitry Andric 
3005ffd83dbSDimitry Andric   bool expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3015ffd83dbSDimitry Andric                  const MCSubtargetInfo *STI);
3025ffd83dbSDimitry Andric 
3035ffd83dbSDimitry Andric   bool expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3045ffd83dbSDimitry Andric                     const MCSubtargetInfo *STI);
3055ffd83dbSDimitry Andric 
3060b57cec5SDimitry Andric   bool expandRotation(MCInst &Inst, SMLoc IDLoc,
3070b57cec5SDimitry Andric                       MCStreamer &Out, const MCSubtargetInfo *STI);
3080b57cec5SDimitry Andric   bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3090b57cec5SDimitry Andric                          const MCSubtargetInfo *STI);
3100b57cec5SDimitry Andric   bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3110b57cec5SDimitry Andric                        const MCSubtargetInfo *STI);
3120b57cec5SDimitry Andric   bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3130b57cec5SDimitry Andric                           const MCSubtargetInfo *STI);
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3160b57cec5SDimitry Andric                  const MCSubtargetInfo *STI);
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3190b57cec5SDimitry Andric                     const MCSubtargetInfo *STI);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3220b57cec5SDimitry Andric                   const MCSubtargetInfo *STI);
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3250b57cec5SDimitry Andric                    const MCSubtargetInfo *STI);
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3280b57cec5SDimitry Andric                        const MCSubtargetInfo *STI);
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3310b57cec5SDimitry Andric                              const MCSubtargetInfo *STI, bool IsLoad);
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3340b57cec5SDimitry Andric                            const MCSubtargetInfo *STI);
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3370b57cec5SDimitry Andric                  const MCSubtargetInfo *STI);
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3400b57cec5SDimitry Andric                   const MCSubtargetInfo *STI);
3410b57cec5SDimitry Andric 
3425ffd83dbSDimitry Andric   bool expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3435ffd83dbSDimitry Andric                  const MCSubtargetInfo *STI);
3445ffd83dbSDimitry Andric 
3455ffd83dbSDimitry Andric   bool expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3465ffd83dbSDimitry Andric                   const MCSubtargetInfo *STI);
3475ffd83dbSDimitry Andric 
3480b57cec5SDimitry Andric   bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3490b57cec5SDimitry Andric                        const MCSubtargetInfo *STI);
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3520b57cec5SDimitry Andric                      const MCSubtargetInfo *STI);
3530b57cec5SDimitry Andric 
354e8d8bef9SDimitry Andric   bool reportParseError(const Twine &ErrorMsg);
355e8d8bef9SDimitry Andric   bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   bool parseSetMips0Directive();
3600b57cec5SDimitry Andric   bool parseSetArchDirective();
3610b57cec5SDimitry Andric   bool parseSetFeature(uint64_t Feature);
3620b57cec5SDimitry Andric   bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
3635ffd83dbSDimitry Andric   bool parseDirectiveCpAdd(SMLoc Loc);
3640b57cec5SDimitry Andric   bool parseDirectiveCpLoad(SMLoc Loc);
3650b57cec5SDimitry Andric   bool parseDirectiveCpLocal(SMLoc Loc);
3660b57cec5SDimitry Andric   bool parseDirectiveCpRestore(SMLoc Loc);
3670b57cec5SDimitry Andric   bool parseDirectiveCPSetup();
3680b57cec5SDimitry Andric   bool parseDirectiveCPReturn();
3690b57cec5SDimitry Andric   bool parseDirectiveNaN();
3700b57cec5SDimitry Andric   bool parseDirectiveSet();
3710b57cec5SDimitry Andric   bool parseDirectiveOption();
3720b57cec5SDimitry Andric   bool parseInsnDirective();
3730b57cec5SDimitry Andric   bool parseRSectionDirective(StringRef Section);
3740b57cec5SDimitry Andric   bool parseSSectionDirective(StringRef Section, unsigned Type);
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   bool parseSetAtDirective();
3770b57cec5SDimitry Andric   bool parseSetNoAtDirective();
3780b57cec5SDimitry Andric   bool parseSetMacroDirective();
3790b57cec5SDimitry Andric   bool parseSetNoMacroDirective();
3800b57cec5SDimitry Andric   bool parseSetMsaDirective();
3810b57cec5SDimitry Andric   bool parseSetNoMsaDirective();
3820b57cec5SDimitry Andric   bool parseSetNoDspDirective();
3835ffd83dbSDimitry Andric   bool parseSetNoMips3DDirective();
3840b57cec5SDimitry Andric   bool parseSetReorderDirective();
3850b57cec5SDimitry Andric   bool parseSetNoReorderDirective();
3860b57cec5SDimitry Andric   bool parseSetMips16Directive();
3870b57cec5SDimitry Andric   bool parseSetNoMips16Directive();
3880b57cec5SDimitry Andric   bool parseSetFpDirective();
3890b57cec5SDimitry Andric   bool parseSetOddSPRegDirective();
3900b57cec5SDimitry Andric   bool parseSetNoOddSPRegDirective();
3910b57cec5SDimitry Andric   bool parseSetPopDirective();
3920b57cec5SDimitry Andric   bool parseSetPushDirective();
3930b57cec5SDimitry Andric   bool parseSetSoftFloatDirective();
3940b57cec5SDimitry Andric   bool parseSetHardFloatDirective();
3950b57cec5SDimitry Andric   bool parseSetMtDirective();
3960b57cec5SDimitry Andric   bool parseSetNoMtDirective();
3970b57cec5SDimitry Andric   bool parseSetNoCRCDirective();
3980b57cec5SDimitry Andric   bool parseSetNoVirtDirective();
3990b57cec5SDimitry Andric   bool parseSetNoGINVDirective();
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   bool parseSetAssignment();
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   bool parseDirectiveGpWord();
4040b57cec5SDimitry Andric   bool parseDirectiveGpDWord();
4050b57cec5SDimitry Andric   bool parseDirectiveDtpRelWord();
4060b57cec5SDimitry Andric   bool parseDirectiveDtpRelDWord();
4070b57cec5SDimitry Andric   bool parseDirectiveTpRelWord();
4080b57cec5SDimitry Andric   bool parseDirectiveTpRelDWord();
4090b57cec5SDimitry Andric   bool parseDirectiveModule();
4100b57cec5SDimitry Andric   bool parseDirectiveModuleFP();
4110b57cec5SDimitry Andric   bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
4120b57cec5SDimitry Andric                        StringRef Directive);
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   bool parseInternalDirectiveReallowModule();
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   bool eatComma(StringRef ErrorStr);
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   int matchCPURegisterName(StringRef Symbol);
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   int matchHWRegsRegisterName(StringRef Symbol);
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   int matchFPURegisterName(StringRef Name);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   int matchFCCRegisterName(StringRef Name);
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   int matchACRegisterName(StringRef Name);
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   int matchMSA128RegisterName(StringRef Name);
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   int matchMSA128CtrlRegisterName(StringRef Name);
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   unsigned getReg(int RC, int RegNo);
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   /// Returns the internal register number for the current AT. Also checks if
4350b57cec5SDimitry Andric   /// the current AT is unavailable (set to $0) and gives an error if it is.
4360b57cec5SDimitry Andric   /// This should be used in pseudo-instruction expansions which need AT.
4370b57cec5SDimitry Andric   unsigned getATReg(SMLoc Loc);
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   bool canUseATReg();
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4420b57cec5SDimitry Andric                           const MCSubtargetInfo *STI);
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   // Helper function that checks if the value of a vector index is within the
4450b57cec5SDimitry Andric   // boundaries of accepted values for each RegisterKind
4460b57cec5SDimitry Andric   // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
4470b57cec5SDimitry Andric   bool validateMSAIndex(int Val, int RegKind);
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   // Selects a new architecture by updating the FeatureBits with the necessary
4500b57cec5SDimitry Andric   // info including implied dependencies.
4510b57cec5SDimitry Andric   // Internally, it clears all the feature bits related to *any* architecture
4520b57cec5SDimitry Andric   // and selects the new one using the ToggleFeature functionality of the
4530b57cec5SDimitry Andric   // MCSubtargetInfo object that handles implied dependencies. The reason we
4540b57cec5SDimitry Andric   // clear all the arch related bits manually is because ToggleFeature only
4550b57cec5SDimitry Andric   // clears the features that imply the feature being cleared and not the
4560b57cec5SDimitry Andric   // features implied by the feature being cleared. This is easier to see
4570b57cec5SDimitry Andric   // with an example:
4580b57cec5SDimitry Andric   //  --------------------------------------------------
4590b57cec5SDimitry Andric   // | Feature         | Implies                        |
4600b57cec5SDimitry Andric   // | -------------------------------------------------|
4610b57cec5SDimitry Andric   // | FeatureMips1    | None                           |
4620b57cec5SDimitry Andric   // | FeatureMips2    | FeatureMips1                   |
4630b57cec5SDimitry Andric   // | FeatureMips3    | FeatureMips2 | FeatureMipsGP64 |
4640b57cec5SDimitry Andric   // | FeatureMips4    | FeatureMips3                   |
4650b57cec5SDimitry Andric   // | ...             |                                |
4660b57cec5SDimitry Andric   //  --------------------------------------------------
4670b57cec5SDimitry Andric   //
4680b57cec5SDimitry Andric   // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
4690b57cec5SDimitry Andric   // FeatureMipsGP64 | FeatureMips1)
4700b57cec5SDimitry Andric   // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
selectArch(StringRef ArchFeature)4710b57cec5SDimitry Andric   void selectArch(StringRef ArchFeature) {
4720b57cec5SDimitry Andric     MCSubtargetInfo &STI = copySTI();
4730b57cec5SDimitry Andric     FeatureBitset FeatureBits = STI.getFeatureBits();
4740b57cec5SDimitry Andric     FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
4750b57cec5SDimitry Andric     STI.setFeatureBits(FeatureBits);
4760b57cec5SDimitry Andric     setAvailableFeatures(
4770b57cec5SDimitry Andric         ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
4780b57cec5SDimitry Andric     AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
4790b57cec5SDimitry Andric   }
4800b57cec5SDimitry Andric 
setFeatureBits(uint64_t Feature,StringRef FeatureString)4810b57cec5SDimitry Andric   void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
48206c3fb27SDimitry Andric     if (!(getSTI().hasFeature(Feature))) {
4830b57cec5SDimitry Andric       MCSubtargetInfo &STI = copySTI();
4840b57cec5SDimitry Andric       setAvailableFeatures(
4850b57cec5SDimitry Andric           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
4860b57cec5SDimitry Andric       AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
4870b57cec5SDimitry Andric     }
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric 
clearFeatureBits(uint64_t Feature,StringRef FeatureString)4900b57cec5SDimitry Andric   void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
49106c3fb27SDimitry Andric     if (getSTI().hasFeature(Feature)) {
4920b57cec5SDimitry Andric       MCSubtargetInfo &STI = copySTI();
4930b57cec5SDimitry Andric       setAvailableFeatures(
4940b57cec5SDimitry Andric           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
4950b57cec5SDimitry Andric       AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
4960b57cec5SDimitry Andric     }
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
setModuleFeatureBits(uint64_t Feature,StringRef FeatureString)4990b57cec5SDimitry Andric   void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
5000b57cec5SDimitry Andric     setFeatureBits(Feature, FeatureString);
5010b57cec5SDimitry Andric     AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
5020b57cec5SDimitry Andric   }
5030b57cec5SDimitry Andric 
clearModuleFeatureBits(uint64_t Feature,StringRef FeatureString)5040b57cec5SDimitry Andric   void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
5050b57cec5SDimitry Andric     clearFeatureBits(Feature, FeatureString);
5060b57cec5SDimitry Andric     AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric public:
5100b57cec5SDimitry Andric   enum MipsMatchResultTy {
5110b57cec5SDimitry Andric     Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
5120b57cec5SDimitry Andric     Match_RequiresDifferentOperands,
5130b57cec5SDimitry Andric     Match_RequiresNoZeroRegister,
5140b57cec5SDimitry Andric     Match_RequiresSameSrcAndDst,
5150b57cec5SDimitry Andric     Match_NoFCCRegisterForCurrentISA,
5160b57cec5SDimitry Andric     Match_NonZeroOperandForSync,
5170b57cec5SDimitry Andric     Match_NonZeroOperandForMTCX,
5180b57cec5SDimitry Andric     Match_RequiresPosSizeRange0_32,
5190b57cec5SDimitry Andric     Match_RequiresPosSizeRange33_64,
5200b57cec5SDimitry Andric     Match_RequiresPosSizeUImm6,
5210b57cec5SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
5220b57cec5SDimitry Andric #include "MipsGenAsmMatcher.inc"
5230b57cec5SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
5240b57cec5SDimitry Andric   };
5250b57cec5SDimitry Andric 
MipsAsmParser(const MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)5260b57cec5SDimitry Andric   MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
5270b57cec5SDimitry Andric                 const MCInstrInfo &MII, const MCTargetOptions &Options)
5280b57cec5SDimitry Andric     : MCTargetAsmParser(Options, sti, MII),
5290b57cec5SDimitry Andric         ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
5300b57cec5SDimitry Andric                                           sti.getCPU(), Options)) {
5310b57cec5SDimitry Andric     MCAsmParserExtension::Initialize(parser);
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric     parser.addAliasForDirective(".asciiz", ".asciz");
5340b57cec5SDimitry Andric     parser.addAliasForDirective(".hword", ".2byte");
5350b57cec5SDimitry Andric     parser.addAliasForDirective(".word", ".4byte");
5360b57cec5SDimitry Andric     parser.addAliasForDirective(".dword", ".8byte");
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     // Initialize the set of available features.
5390b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric     // Remember the initial assembler options. The user can not modify these.
5420b57cec5SDimitry Andric     AssemblerOptions.push_back(
5438bcb0991SDimitry Andric         std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric     // Create an assembler options environment for the user to modify.
5460b57cec5SDimitry Andric     AssemblerOptions.push_back(
5478bcb0991SDimitry Andric         std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric     if (!isABI_O32() && !useOddSPReg() != 0)
5520b57cec5SDimitry Andric       report_fatal_error("-mno-odd-spreg requires the O32 ABI");
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     CurrentFn = nullptr;
5550b57cec5SDimitry Andric 
5564c2d3b02SDimitry Andric     CurForbiddenSlotAttr = false;
5570b57cec5SDimitry Andric     IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric     IsCpRestoreSet = false;
5600b57cec5SDimitry Andric     CpRestoreOffset = -1;
5610b57cec5SDimitry Andric     GPReg = ABI.GetGlobalPtr();
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric     const Triple &TheTriple = sti.getTargetTriple();
5640b57cec5SDimitry Andric     IsLittleEndian = TheTriple.isLittleEndian();
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric     if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
5670b57cec5SDimitry Andric       report_fatal_error("microMIPS64R6 is not supported", false);
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric     if (!isABI_O32() && inMicroMipsMode())
5700b57cec5SDimitry Andric       report_fatal_error("microMIPS64 is not supported", false);
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   /// True if all of $fcc0 - $fcc7 exist for the current ISA.
hasEightFccRegisters() const5740b57cec5SDimitry Andric   bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
5750b57cec5SDimitry Andric 
isGP64bit() const5760b57cec5SDimitry Andric   bool isGP64bit() const {
57706c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureGP64Bit);
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
isFP64bit() const5800b57cec5SDimitry Andric   bool isFP64bit() const {
58106c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureFP64Bit);
5820b57cec5SDimitry Andric   }
5830b57cec5SDimitry Andric 
isJalrRelocAvailable(const MCExpr * JalExpr)584480093f4SDimitry Andric   bool isJalrRelocAvailable(const MCExpr *JalExpr) {
585480093f4SDimitry Andric     if (!EmitJalrReloc)
586480093f4SDimitry Andric       return false;
587480093f4SDimitry Andric     MCValue Res;
588480093f4SDimitry Andric     if (!JalExpr->evaluateAsRelocatable(Res, nullptr, nullptr))
589480093f4SDimitry Andric       return false;
590480093f4SDimitry Andric     if (Res.getSymB() != nullptr)
591480093f4SDimitry Andric       return false;
592480093f4SDimitry Andric     if (Res.getConstant() != 0)
593480093f4SDimitry Andric       return ABI.IsN32() || ABI.IsN64();
594480093f4SDimitry Andric     return true;
595480093f4SDimitry Andric   }
596480093f4SDimitry Andric 
getABI() const5970b57cec5SDimitry Andric   const MipsABIInfo &getABI() const { return ABI; }
isABI_N32() const5980b57cec5SDimitry Andric   bool isABI_N32() const { return ABI.IsN32(); }
isABI_N64() const5990b57cec5SDimitry Andric   bool isABI_N64() const { return ABI.IsN64(); }
isABI_O32() const6000b57cec5SDimitry Andric   bool isABI_O32() const { return ABI.IsO32(); }
isABI_FPXX() const6010b57cec5SDimitry Andric   bool isABI_FPXX() const {
60206c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureFPXX);
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric 
useOddSPReg() const6050b57cec5SDimitry Andric   bool useOddSPReg() const {
60606c3fb27SDimitry Andric     return !(getSTI().hasFeature(Mips::FeatureNoOddSPReg));
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric 
inMicroMipsMode() const6090b57cec5SDimitry Andric   bool inMicroMipsMode() const {
61006c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMicroMips);
6110b57cec5SDimitry Andric   }
6120b57cec5SDimitry Andric 
hasMips1() const6130b57cec5SDimitry Andric   bool hasMips1() const {
61406c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips1);
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric 
hasMips2() const6170b57cec5SDimitry Andric   bool hasMips2() const {
61806c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips2);
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric 
hasMips3() const6210b57cec5SDimitry Andric   bool hasMips3() const {
62206c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips3);
6230b57cec5SDimitry Andric   }
6240b57cec5SDimitry Andric 
hasMips4() const6250b57cec5SDimitry Andric   bool hasMips4() const {
62606c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips4);
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric 
hasMips5() const6290b57cec5SDimitry Andric   bool hasMips5() const {
63006c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips5);
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric 
hasMips32() const6330b57cec5SDimitry Andric   bool hasMips32() const {
63406c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips32);
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
hasMips64() const6370b57cec5SDimitry Andric   bool hasMips64() const {
63806c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips64);
6390b57cec5SDimitry Andric   }
6400b57cec5SDimitry Andric 
hasMips32r2() const6410b57cec5SDimitry Andric   bool hasMips32r2() const {
64206c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips32r2);
6430b57cec5SDimitry Andric   }
6440b57cec5SDimitry Andric 
hasMips64r2() const6450b57cec5SDimitry Andric   bool hasMips64r2() const {
64606c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips64r2);
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric 
hasMips32r3() const6490b57cec5SDimitry Andric   bool hasMips32r3() const {
65006c3fb27SDimitry Andric     return (getSTI().hasFeature(Mips::FeatureMips32r3));
6510b57cec5SDimitry Andric   }
6520b57cec5SDimitry Andric 
hasMips64r3() const6530b57cec5SDimitry Andric   bool hasMips64r3() const {
65406c3fb27SDimitry Andric     return (getSTI().hasFeature(Mips::FeatureMips64r3));
6550b57cec5SDimitry Andric   }
6560b57cec5SDimitry Andric 
hasMips32r5() const6570b57cec5SDimitry Andric   bool hasMips32r5() const {
65806c3fb27SDimitry Andric     return (getSTI().hasFeature(Mips::FeatureMips32r5));
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric 
hasMips64r5() const6610b57cec5SDimitry Andric   bool hasMips64r5() const {
66206c3fb27SDimitry Andric     return (getSTI().hasFeature(Mips::FeatureMips64r5));
6630b57cec5SDimitry Andric   }
6640b57cec5SDimitry Andric 
hasMips32r6() const6650b57cec5SDimitry Andric   bool hasMips32r6() const {
66606c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips32r6);
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric 
hasMips64r6() const6690b57cec5SDimitry Andric   bool hasMips64r6() const {
67006c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips64r6);
6710b57cec5SDimitry Andric   }
6720b57cec5SDimitry Andric 
hasDSP() const6730b57cec5SDimitry Andric   bool hasDSP() const {
67406c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureDSP);
6750b57cec5SDimitry Andric   }
6760b57cec5SDimitry Andric 
hasDSPR2() const6770b57cec5SDimitry Andric   bool hasDSPR2() const {
67806c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureDSPR2);
6790b57cec5SDimitry Andric   }
6800b57cec5SDimitry Andric 
hasDSPR3() const6810b57cec5SDimitry Andric   bool hasDSPR3() const {
68206c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureDSPR3);
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric 
hasMSA() const6850b57cec5SDimitry Andric   bool hasMSA() const {
68606c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMSA);
6870b57cec5SDimitry Andric   }
6880b57cec5SDimitry Andric 
hasCnMips() const6890b57cec5SDimitry Andric   bool hasCnMips() const {
69006c3fb27SDimitry Andric     return (getSTI().hasFeature(Mips::FeatureCnMips));
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric 
hasCnMipsP() const6930b57cec5SDimitry Andric   bool hasCnMipsP() const {
69406c3fb27SDimitry Andric     return (getSTI().hasFeature(Mips::FeatureCnMipsP));
6950b57cec5SDimitry Andric   }
6960b57cec5SDimitry Andric 
inPicMode()6970b57cec5SDimitry Andric   bool inPicMode() {
6980b57cec5SDimitry Andric     return IsPicEnabled;
6990b57cec5SDimitry Andric   }
7000b57cec5SDimitry Andric 
inMips16Mode() const7010b57cec5SDimitry Andric   bool inMips16Mode() const {
70206c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMips16);
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric 
useTraps() const7050b57cec5SDimitry Andric   bool useTraps() const {
70606c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureUseTCCInDIV);
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric 
useSoftFloat() const7090b57cec5SDimitry Andric   bool useSoftFloat() const {
71006c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureSoftFloat);
7110b57cec5SDimitry Andric   }
hasMT() const7120b57cec5SDimitry Andric   bool hasMT() const {
71306c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureMT);
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric 
hasCRC() const7160b57cec5SDimitry Andric   bool hasCRC() const {
71706c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureCRC);
7180b57cec5SDimitry Andric   }
7190b57cec5SDimitry Andric 
hasVirt() const7200b57cec5SDimitry Andric   bool hasVirt() const {
72106c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureVirt);
7220b57cec5SDimitry Andric   }
7230b57cec5SDimitry Andric 
hasGINV() const7240b57cec5SDimitry Andric   bool hasGINV() const {
72506c3fb27SDimitry Andric     return getSTI().hasFeature(Mips::FeatureGINV);
7260b57cec5SDimitry Andric   }
7270b57cec5SDimitry Andric 
hasForbiddenSlot(const MCInstrDesc & MCID) const7284c2d3b02SDimitry Andric   bool hasForbiddenSlot(const MCInstrDesc &MCID) const {
7294c2d3b02SDimitry Andric     return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);
7304c2d3b02SDimitry Andric   }
7314c2d3b02SDimitry Andric 
SafeInForbiddenSlot(const MCInstrDesc & MCID) const7324c2d3b02SDimitry Andric   bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {
7334c2d3b02SDimitry Andric     return !(MCID.TSFlags & MipsII::IsCTI);
7344c2d3b02SDimitry Andric   }
7354c2d3b02SDimitry Andric 
7364c2d3b02SDimitry Andric   void onEndOfFile() override;
7374c2d3b02SDimitry Andric 
7380b57cec5SDimitry Andric   /// Warn if RegIndex is the same as the current AT.
7390b57cec5SDimitry Andric   void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   void warnIfNoMacro(SMLoc Loc);
7420b57cec5SDimitry Andric 
isLittle() const7430b57cec5SDimitry Andric   bool isLittle() const { return IsLittleEndian; }
7440b57cec5SDimitry Andric 
createTargetUnaryExpr(const MCExpr * E,AsmToken::TokenKind OperatorToken,MCContext & Ctx)7450b57cec5SDimitry Andric   const MCExpr *createTargetUnaryExpr(const MCExpr *E,
7460b57cec5SDimitry Andric                                       AsmToken::TokenKind OperatorToken,
7470b57cec5SDimitry Andric                                       MCContext &Ctx) override {
7480b57cec5SDimitry Andric     switch(OperatorToken) {
7490b57cec5SDimitry Andric     default:
7500b57cec5SDimitry Andric       llvm_unreachable("Unknown token");
7510b57cec5SDimitry Andric       return nullptr;
7520b57cec5SDimitry Andric     case AsmToken::PercentCall16:
7530b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
7540b57cec5SDimitry Andric     case AsmToken::PercentCall_Hi:
7550b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
7560b57cec5SDimitry Andric     case AsmToken::PercentCall_Lo:
7570b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
7580b57cec5SDimitry Andric     case AsmToken::PercentDtprel_Hi:
7590b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
7600b57cec5SDimitry Andric     case AsmToken::PercentDtprel_Lo:
7610b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
7620b57cec5SDimitry Andric     case AsmToken::PercentGot:
7630b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
7640b57cec5SDimitry Andric     case AsmToken::PercentGot_Disp:
7650b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
7660b57cec5SDimitry Andric     case AsmToken::PercentGot_Hi:
7670b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
7680b57cec5SDimitry Andric     case AsmToken::PercentGot_Lo:
7690b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
7700b57cec5SDimitry Andric     case AsmToken::PercentGot_Ofst:
7710b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
7720b57cec5SDimitry Andric     case AsmToken::PercentGot_Page:
7730b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
7740b57cec5SDimitry Andric     case AsmToken::PercentGottprel:
7750b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
7760b57cec5SDimitry Andric     case AsmToken::PercentGp_Rel:
7770b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
7780b57cec5SDimitry Andric     case AsmToken::PercentHi:
7790b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
7800b57cec5SDimitry Andric     case AsmToken::PercentHigher:
7810b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
7820b57cec5SDimitry Andric     case AsmToken::PercentHighest:
7830b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
7840b57cec5SDimitry Andric     case AsmToken::PercentLo:
7850b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
7860b57cec5SDimitry Andric     case AsmToken::PercentNeg:
7870b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
7880b57cec5SDimitry Andric     case AsmToken::PercentPcrel_Hi:
7890b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
7900b57cec5SDimitry Andric     case AsmToken::PercentPcrel_Lo:
7910b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
7920b57cec5SDimitry Andric     case AsmToken::PercentTlsgd:
7930b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
7940b57cec5SDimitry Andric     case AsmToken::PercentTlsldm:
7950b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
7960b57cec5SDimitry Andric     case AsmToken::PercentTprel_Hi:
7970b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
7980b57cec5SDimitry Andric     case AsmToken::PercentTprel_Lo:
7990b57cec5SDimitry Andric       return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
8000b57cec5SDimitry Andric     }
8010b57cec5SDimitry Andric   }
802bdd1243dSDimitry Andric 
803bdd1243dSDimitry Andric   bool areEqualRegs(const MCParsedAsmOperand &Op1,
804bdd1243dSDimitry Andric                     const MCParsedAsmOperand &Op2) const override;
8050b57cec5SDimitry Andric };
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric /// MipsOperand - Instances of this class represent a parsed Mips machine
8080b57cec5SDimitry Andric /// instruction.
8090b57cec5SDimitry Andric class MipsOperand : public MCParsedAsmOperand {
8100b57cec5SDimitry Andric public:
8110b57cec5SDimitry Andric   /// Broad categories of register classes
8120b57cec5SDimitry Andric   /// The exact class is finalized by the render method.
8130b57cec5SDimitry Andric   enum RegKind {
8140b57cec5SDimitry Andric     RegKind_GPR = 1,      /// GPR32 and GPR64 (depending on isGP64bit())
8150b57cec5SDimitry Andric     RegKind_FGR = 2,      /// FGR32, FGR64, AFGR64 (depending on context and
8160b57cec5SDimitry Andric                           /// isFP64bit())
8170b57cec5SDimitry Andric     RegKind_FCC = 4,      /// FCC
8180b57cec5SDimitry Andric     RegKind_MSA128 = 8,   /// MSA128[BHWD] (makes no difference which)
8190b57cec5SDimitry Andric     RegKind_MSACtrl = 16, /// MSA control registers
8200b57cec5SDimitry Andric     RegKind_COP2 = 32,    /// COP2
8210b57cec5SDimitry Andric     RegKind_ACC = 64,     /// HI32DSP, LO32DSP, and ACC64DSP (depending on
8220b57cec5SDimitry Andric                           /// context).
8230b57cec5SDimitry Andric     RegKind_CCR = 128,    /// CCR
8240b57cec5SDimitry Andric     RegKind_HWRegs = 256, /// HWRegs
8250b57cec5SDimitry Andric     RegKind_COP3 = 512,   /// COP3
8260b57cec5SDimitry Andric     RegKind_COP0 = 1024,  /// COP0
8270b57cec5SDimitry Andric     /// Potentially any (e.g. $1)
8280b57cec5SDimitry Andric     RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
8290b57cec5SDimitry Andric                       RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
8300b57cec5SDimitry Andric                       RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
8310b57cec5SDimitry Andric   };
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric private:
8340b57cec5SDimitry Andric   enum KindTy {
8350b57cec5SDimitry Andric     k_Immediate,     /// An immediate (possibly involving symbol references)
8360b57cec5SDimitry Andric     k_Memory,        /// Base + Offset Memory Address
8370b57cec5SDimitry Andric     k_RegisterIndex, /// A register index in one or more RegKind.
8380b57cec5SDimitry Andric     k_Token,         /// A simple token
8390b57cec5SDimitry Andric     k_RegList,       /// A physical register list
8400b57cec5SDimitry Andric   } Kind;
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric public:
MipsOperand(KindTy K,MipsAsmParser & Parser)84304eeddc0SDimitry Andric   MipsOperand(KindTy K, MipsAsmParser &Parser) : Kind(K), AsmParser(Parser) {}
8440b57cec5SDimitry Andric 
~MipsOperand()8450b57cec5SDimitry Andric   ~MipsOperand() override {
8460b57cec5SDimitry Andric     switch (Kind) {
8470b57cec5SDimitry Andric     case k_Memory:
8480b57cec5SDimitry Andric       delete Mem.Base;
8490b57cec5SDimitry Andric       break;
8500b57cec5SDimitry Andric     case k_RegList:
8510b57cec5SDimitry Andric       delete RegList.List;
8520b57cec5SDimitry Andric       break;
8530b57cec5SDimitry Andric     case k_Immediate:
8540b57cec5SDimitry Andric     case k_RegisterIndex:
8550b57cec5SDimitry Andric     case k_Token:
8560b57cec5SDimitry Andric       break;
8570b57cec5SDimitry Andric     }
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric private:
8610b57cec5SDimitry Andric   /// For diagnostics, and checking the assembler temporary
8620b57cec5SDimitry Andric   MipsAsmParser &AsmParser;
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   struct Token {
8650b57cec5SDimitry Andric     const char *Data;
8660b57cec5SDimitry Andric     unsigned Length;
8670b57cec5SDimitry Andric   };
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   struct RegIdxOp {
8700b57cec5SDimitry Andric     unsigned Index; /// Index into the register class
8710b57cec5SDimitry Andric     RegKind Kind;   /// Bitfield of the kinds it could possibly be
8720b57cec5SDimitry Andric     struct Token Tok; /// The input token this operand originated from.
8730b57cec5SDimitry Andric     const MCRegisterInfo *RegInfo;
8740b57cec5SDimitry Andric   };
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric   struct ImmOp {
8770b57cec5SDimitry Andric     const MCExpr *Val;
8780b57cec5SDimitry Andric   };
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric   struct MemOp {
8810b57cec5SDimitry Andric     MipsOperand *Base;
8820b57cec5SDimitry Andric     const MCExpr *Off;
8830b57cec5SDimitry Andric   };
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   struct RegListOp {
8860b57cec5SDimitry Andric     SmallVector<unsigned, 10> *List;
8870b57cec5SDimitry Andric   };
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   union {
8900b57cec5SDimitry Andric     struct Token Tok;
8910b57cec5SDimitry Andric     struct RegIdxOp RegIdx;
8920b57cec5SDimitry Andric     struct ImmOp Imm;
8930b57cec5SDimitry Andric     struct MemOp Mem;
8940b57cec5SDimitry Andric     struct RegListOp RegList;
8950b57cec5SDimitry Andric   };
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric   /// Internal constructor for register kinds
CreateReg(unsigned Index,StringRef Str,RegKind RegKind,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)9000b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
9010b57cec5SDimitry Andric                                                 RegKind RegKind,
9020b57cec5SDimitry Andric                                                 const MCRegisterInfo *RegInfo,
9030b57cec5SDimitry Andric                                                 SMLoc S, SMLoc E,
9040b57cec5SDimitry Andric                                                 MipsAsmParser &Parser) {
9058bcb0991SDimitry Andric     auto Op = std::make_unique<MipsOperand>(k_RegisterIndex, Parser);
9060b57cec5SDimitry Andric     Op->RegIdx.Index = Index;
9070b57cec5SDimitry Andric     Op->RegIdx.RegInfo = RegInfo;
9080b57cec5SDimitry Andric     Op->RegIdx.Kind = RegKind;
9090b57cec5SDimitry Andric     Op->RegIdx.Tok.Data = Str.data();
9100b57cec5SDimitry Andric     Op->RegIdx.Tok.Length = Str.size();
9110b57cec5SDimitry Andric     Op->StartLoc = S;
9120b57cec5SDimitry Andric     Op->EndLoc = E;
9130b57cec5SDimitry Andric     return Op;
9140b57cec5SDimitry Andric   }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric public:
9170b57cec5SDimitry Andric   /// Coerce the register to GPR32 and return the real register for the current
9180b57cec5SDimitry Andric   /// target.
getGPR32Reg() const9190b57cec5SDimitry Andric   unsigned getGPR32Reg() const {
9200b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
9210b57cec5SDimitry Andric     AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
9220b57cec5SDimitry Andric     unsigned ClassID = Mips::GPR32RegClassID;
9230b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9240b57cec5SDimitry Andric   }
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric   /// Coerce the register to GPR32 and return the real register for the current
9270b57cec5SDimitry Andric   /// target.
getGPRMM16Reg() const9280b57cec5SDimitry Andric   unsigned getGPRMM16Reg() const {
9290b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
9300b57cec5SDimitry Andric     unsigned ClassID = Mips::GPR32RegClassID;
9310b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9320b57cec5SDimitry Andric   }
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   /// Coerce the register to GPR64 and return the real register for the current
9350b57cec5SDimitry Andric   /// target.
getGPR64Reg() const9360b57cec5SDimitry Andric   unsigned getGPR64Reg() const {
9370b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
9380b57cec5SDimitry Andric     unsigned ClassID = Mips::GPR64RegClassID;
9390b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9400b57cec5SDimitry Andric   }
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric private:
9430b57cec5SDimitry Andric   /// Coerce the register to AFGR64 and return the real register for the current
9440b57cec5SDimitry Andric   /// target.
getAFGR64Reg() const9450b57cec5SDimitry Andric   unsigned getAFGR64Reg() const {
9460b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
9470b57cec5SDimitry Andric     if (RegIdx.Index % 2 != 0)
9480b57cec5SDimitry Andric       AsmParser.Warning(StartLoc, "Float register should be even.");
9490b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
9500b57cec5SDimitry Andric         .getRegister(RegIdx.Index / 2);
9510b57cec5SDimitry Andric   }
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   /// Coerce the register to FGR64 and return the real register for the current
9540b57cec5SDimitry Andric   /// target.
getFGR64Reg() const9550b57cec5SDimitry Andric   unsigned getFGR64Reg() const {
9560b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
9570b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
9580b57cec5SDimitry Andric         .getRegister(RegIdx.Index);
9590b57cec5SDimitry Andric   }
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   /// Coerce the register to FGR32 and return the real register for the current
9620b57cec5SDimitry Andric   /// target.
getFGR32Reg() const9630b57cec5SDimitry Andric   unsigned getFGR32Reg() const {
9640b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
9650b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
9660b57cec5SDimitry Andric         .getRegister(RegIdx.Index);
9670b57cec5SDimitry Andric   }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   /// Coerce the register to FCC and return the real register for the current
9700b57cec5SDimitry Andric   /// target.
getFCCReg() const9710b57cec5SDimitry Andric   unsigned getFCCReg() const {
9720b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
9730b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
9740b57cec5SDimitry Andric         .getRegister(RegIdx.Index);
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   /// Coerce the register to MSA128 and return the real register for the current
9780b57cec5SDimitry Andric   /// target.
getMSA128Reg() const9790b57cec5SDimitry Andric   unsigned getMSA128Reg() const {
9800b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
9810b57cec5SDimitry Andric     // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
9820b57cec5SDimitry Andric     // identical
9830b57cec5SDimitry Andric     unsigned ClassID = Mips::MSA128BRegClassID;
9840b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   /// Coerce the register to MSACtrl and return the real register for the
9880b57cec5SDimitry Andric   /// current target.
getMSACtrlReg() const9890b57cec5SDimitry Andric   unsigned getMSACtrlReg() const {
9900b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
9910b57cec5SDimitry Andric     unsigned ClassID = Mips::MSACtrlRegClassID;
9920b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9930b57cec5SDimitry Andric   }
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   /// Coerce the register to COP0 and return the real register for the
9960b57cec5SDimitry Andric   /// current target.
getCOP0Reg() const9970b57cec5SDimitry Andric   unsigned getCOP0Reg() const {
9980b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
9990b57cec5SDimitry Andric     unsigned ClassID = Mips::COP0RegClassID;
10000b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10010b57cec5SDimitry Andric   }
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   /// Coerce the register to COP2 and return the real register for the
10040b57cec5SDimitry Andric   /// current target.
getCOP2Reg() const10050b57cec5SDimitry Andric   unsigned getCOP2Reg() const {
10060b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
10070b57cec5SDimitry Andric     unsigned ClassID = Mips::COP2RegClassID;
10080b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10090b57cec5SDimitry Andric   }
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric   /// Coerce the register to COP3 and return the real register for the
10120b57cec5SDimitry Andric   /// current target.
getCOP3Reg() const10130b57cec5SDimitry Andric   unsigned getCOP3Reg() const {
10140b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
10150b57cec5SDimitry Andric     unsigned ClassID = Mips::COP3RegClassID;
10160b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   /// Coerce the register to ACC64DSP and return the real register for the
10200b57cec5SDimitry Andric   /// current target.
getACC64DSPReg() const10210b57cec5SDimitry Andric   unsigned getACC64DSPReg() const {
10220b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
10230b57cec5SDimitry Andric     unsigned ClassID = Mips::ACC64DSPRegClassID;
10240b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10250b57cec5SDimitry Andric   }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   /// Coerce the register to HI32DSP and return the real register for the
10280b57cec5SDimitry Andric   /// current target.
getHI32DSPReg() const10290b57cec5SDimitry Andric   unsigned getHI32DSPReg() const {
10300b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
10310b57cec5SDimitry Andric     unsigned ClassID = Mips::HI32DSPRegClassID;
10320b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10330b57cec5SDimitry Andric   }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   /// Coerce the register to LO32DSP and return the real register for the
10360b57cec5SDimitry Andric   /// current target.
getLO32DSPReg() const10370b57cec5SDimitry Andric   unsigned getLO32DSPReg() const {
10380b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
10390b57cec5SDimitry Andric     unsigned ClassID = Mips::LO32DSPRegClassID;
10400b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10410b57cec5SDimitry Andric   }
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric   /// Coerce the register to CCR and return the real register for the
10440b57cec5SDimitry Andric   /// current target.
getCCRReg() const10450b57cec5SDimitry Andric   unsigned getCCRReg() const {
10460b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
10470b57cec5SDimitry Andric     unsigned ClassID = Mips::CCRRegClassID;
10480b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10490b57cec5SDimitry Andric   }
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric   /// Coerce the register to HWRegs and return the real register for the
10520b57cec5SDimitry Andric   /// current target.
getHWRegsReg() const10530b57cec5SDimitry Andric   unsigned getHWRegsReg() const {
10540b57cec5SDimitry Andric     assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
10550b57cec5SDimitry Andric     unsigned ClassID = Mips::HWRegsRegClassID;
10560b57cec5SDimitry Andric     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10570b57cec5SDimitry Andric   }
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric public:
addExpr(MCInst & Inst,const MCExpr * Expr) const10600b57cec5SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
10610b57cec5SDimitry Andric     // Add as immediate when possible.  Null MCExpr = 0.
10620b57cec5SDimitry Andric     if (!Expr)
10630b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(0));
10640b57cec5SDimitry Andric     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
10650b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
10660b57cec5SDimitry Andric     else
10670b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
10680b57cec5SDimitry Andric   }
10690b57cec5SDimitry Andric 
addRegOperands(MCInst & Inst,unsigned N) const10700b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
10710b57cec5SDimitry Andric     llvm_unreachable("Use a custom parser instead");
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   /// Render the operand to an MCInst as a GPR32
10750b57cec5SDimitry Andric   /// Asserts if the wrong number of operands are requested, or the operand
10760b57cec5SDimitry Andric   /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR32ZeroAsmRegOperands(MCInst & Inst,unsigned N) const10770b57cec5SDimitry Andric   void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
10780b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
10790b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric 
addGPR32NonZeroAsmRegOperands(MCInst & Inst,unsigned N) const10820b57cec5SDimitry Andric   void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
10830b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
10840b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
10850b57cec5SDimitry Andric   }
10860b57cec5SDimitry Andric 
addGPR32AsmRegOperands(MCInst & Inst,unsigned N) const10870b57cec5SDimitry Andric   void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
10880b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
10890b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric 
addGPRMM16AsmRegOperands(MCInst & Inst,unsigned N) const10920b57cec5SDimitry Andric   void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
10930b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
10940b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
10950b57cec5SDimitry Andric   }
10960b57cec5SDimitry Andric 
addGPRMM16AsmRegZeroOperands(MCInst & Inst,unsigned N) const10970b57cec5SDimitry Andric   void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
10980b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
10990b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11000b57cec5SDimitry Andric   }
11010b57cec5SDimitry Andric 
addGPRMM16AsmRegMovePOperands(MCInst & Inst,unsigned N) const11020b57cec5SDimitry Andric   void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
11030b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11040b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
addGPRMM16AsmRegMovePPairFirstOperands(MCInst & Inst,unsigned N) const11070b57cec5SDimitry Andric   void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
11080b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11090b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11100b57cec5SDimitry Andric   }
11110b57cec5SDimitry Andric 
addGPRMM16AsmRegMovePPairSecondOperands(MCInst & Inst,unsigned N) const11120b57cec5SDimitry Andric   void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
11130b57cec5SDimitry Andric                                                unsigned N) const {
11140b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11150b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11160b57cec5SDimitry Andric   }
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric   /// Render the operand to an MCInst as a GPR64
11190b57cec5SDimitry Andric   /// Asserts if the wrong number of operands are requested, or the operand
11200b57cec5SDimitry Andric   /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR64AsmRegOperands(MCInst & Inst,unsigned N) const11210b57cec5SDimitry Andric   void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11220b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11230b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
11240b57cec5SDimitry Andric   }
11250b57cec5SDimitry Andric 
addAFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11260b57cec5SDimitry Andric   void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11270b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11280b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
11290b57cec5SDimitry Andric   }
11300b57cec5SDimitry Andric 
addStrictlyAFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11310b57cec5SDimitry Andric   void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11320b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11330b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
11340b57cec5SDimitry Andric   }
11350b57cec5SDimitry Andric 
addStrictlyFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11360b57cec5SDimitry Andric   void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11370b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11380b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
11390b57cec5SDimitry Andric   }
11400b57cec5SDimitry Andric 
addFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11410b57cec5SDimitry Andric   void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11420b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11430b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
11440b57cec5SDimitry Andric   }
11450b57cec5SDimitry Andric 
addFGR32AsmRegOperands(MCInst & Inst,unsigned N) const11460b57cec5SDimitry Andric   void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
11470b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11480b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
11490b57cec5SDimitry Andric     // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
11500b57cec5SDimitry Andric     // FIXME: This should propagate failure up to parseStatement.
11510b57cec5SDimitry Andric     if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
11520b57cec5SDimitry Andric       AsmParser.getParser().printError(
11530b57cec5SDimitry Andric           StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
11540b57cec5SDimitry Andric                     "registers");
11550b57cec5SDimitry Andric   }
11560b57cec5SDimitry Andric 
addStrictlyFGR32AsmRegOperands(MCInst & Inst,unsigned N) const11570b57cec5SDimitry Andric   void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
11580b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11590b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
11600b57cec5SDimitry Andric     // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
11610b57cec5SDimitry Andric     if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
11620b57cec5SDimitry Andric       AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
11630b57cec5SDimitry Andric                                 "registers");
11640b57cec5SDimitry Andric   }
11650b57cec5SDimitry Andric 
addFCCAsmRegOperands(MCInst & Inst,unsigned N) const11660b57cec5SDimitry Andric   void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
11670b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11680b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getFCCReg()));
11690b57cec5SDimitry Andric   }
11700b57cec5SDimitry Andric 
addMSA128AsmRegOperands(MCInst & Inst,unsigned N) const11710b57cec5SDimitry Andric   void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
11720b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11730b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
11740b57cec5SDimitry Andric   }
11750b57cec5SDimitry Andric 
addMSACtrlAsmRegOperands(MCInst & Inst,unsigned N) const11760b57cec5SDimitry Andric   void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
11770b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11780b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
11790b57cec5SDimitry Andric   }
11800b57cec5SDimitry Andric 
addCOP0AsmRegOperands(MCInst & Inst,unsigned N) const11810b57cec5SDimitry Andric   void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
11820b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11830b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
11840b57cec5SDimitry Andric   }
11850b57cec5SDimitry Andric 
addCOP2AsmRegOperands(MCInst & Inst,unsigned N) const11860b57cec5SDimitry Andric   void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
11870b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11880b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
11890b57cec5SDimitry Andric   }
11900b57cec5SDimitry Andric 
addCOP3AsmRegOperands(MCInst & Inst,unsigned N) const11910b57cec5SDimitry Andric   void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
11920b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11930b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
11940b57cec5SDimitry Andric   }
11950b57cec5SDimitry Andric 
addACC64DSPAsmRegOperands(MCInst & Inst,unsigned N) const11960b57cec5SDimitry Andric   void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
11970b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11980b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
11990b57cec5SDimitry Andric   }
12000b57cec5SDimitry Andric 
addHI32DSPAsmRegOperands(MCInst & Inst,unsigned N) const12010b57cec5SDimitry Andric   void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
12020b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12030b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
12040b57cec5SDimitry Andric   }
12050b57cec5SDimitry Andric 
addLO32DSPAsmRegOperands(MCInst & Inst,unsigned N) const12060b57cec5SDimitry Andric   void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
12070b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12080b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
12090b57cec5SDimitry Andric   }
12100b57cec5SDimitry Andric 
addCCRAsmRegOperands(MCInst & Inst,unsigned N) const12110b57cec5SDimitry Andric   void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
12120b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12130b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getCCRReg()));
12140b57cec5SDimitry Andric   }
12150b57cec5SDimitry Andric 
addHWRegsAsmRegOperands(MCInst & Inst,unsigned N) const12160b57cec5SDimitry Andric   void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
12170b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12180b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
12190b57cec5SDimitry Andric   }
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric   template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
addConstantUImmOperands(MCInst & Inst,unsigned N) const12220b57cec5SDimitry Andric   void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
12230b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12240b57cec5SDimitry Andric     uint64_t Imm = getConstantImm() - Offset;
12250b57cec5SDimitry Andric     Imm &= (1ULL << Bits) - 1;
12260b57cec5SDimitry Andric     Imm += Offset;
12270b57cec5SDimitry Andric     Imm += AdjustOffset;
12280b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(Imm));
12290b57cec5SDimitry Andric   }
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric   template <unsigned Bits>
addSImmOperands(MCInst & Inst,unsigned N) const12320b57cec5SDimitry Andric   void addSImmOperands(MCInst &Inst, unsigned N) const {
12330b57cec5SDimitry Andric     if (isImm() && !isConstantImm()) {
12340b57cec5SDimitry Andric       addExpr(Inst, getImm());
12350b57cec5SDimitry Andric       return;
12360b57cec5SDimitry Andric     }
12370b57cec5SDimitry Andric     addConstantSImmOperands<Bits, 0, 0>(Inst, N);
12380b57cec5SDimitry Andric   }
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric   template <unsigned Bits>
addUImmOperands(MCInst & Inst,unsigned N) const12410b57cec5SDimitry Andric   void addUImmOperands(MCInst &Inst, unsigned N) const {
12420b57cec5SDimitry Andric     if (isImm() && !isConstantImm()) {
12430b57cec5SDimitry Andric       addExpr(Inst, getImm());
12440b57cec5SDimitry Andric       return;
12450b57cec5SDimitry Andric     }
12460b57cec5SDimitry Andric     addConstantUImmOperands<Bits, 0, 0>(Inst, N);
12470b57cec5SDimitry Andric   }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric   template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
addConstantSImmOperands(MCInst & Inst,unsigned N) const12500b57cec5SDimitry Andric   void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
12510b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12520b57cec5SDimitry Andric     int64_t Imm = getConstantImm() - Offset;
12530b57cec5SDimitry Andric     Imm = SignExtend64<Bits>(Imm);
12540b57cec5SDimitry Andric     Imm += Offset;
12550b57cec5SDimitry Andric     Imm += AdjustOffset;
12560b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(Imm));
12570b57cec5SDimitry Andric   }
12580b57cec5SDimitry Andric 
addImmOperands(MCInst & Inst,unsigned N) const12590b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
12600b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12610b57cec5SDimitry Andric     const MCExpr *Expr = getImm();
12620b57cec5SDimitry Andric     addExpr(Inst, Expr);
12630b57cec5SDimitry Andric   }
12640b57cec5SDimitry Andric 
addMemOperands(MCInst & Inst,unsigned N) const12650b57cec5SDimitry Andric   void addMemOperands(MCInst &Inst, unsigned N) const {
12660b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands!");
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
12690b57cec5SDimitry Andric                                              ? getMemBase()->getGPR64Reg()
12700b57cec5SDimitry Andric                                              : getMemBase()->getGPR32Reg()));
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric     const MCExpr *Expr = getMemOff();
12730b57cec5SDimitry Andric     addExpr(Inst, Expr);
12740b57cec5SDimitry Andric   }
12750b57cec5SDimitry Andric 
addMicroMipsMemOperands(MCInst & Inst,unsigned N) const12760b57cec5SDimitry Andric   void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
12770b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands!");
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric     const MCExpr *Expr = getMemOff();
12820b57cec5SDimitry Andric     addExpr(Inst, Expr);
12830b57cec5SDimitry Andric   }
12840b57cec5SDimitry Andric 
addRegListOperands(MCInst & Inst,unsigned N) const12850b57cec5SDimitry Andric   void addRegListOperands(MCInst &Inst, unsigned N) const {
12860b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric     for (auto RegNo : getRegList())
12890b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createReg(RegNo));
12900b57cec5SDimitry Andric   }
12910b57cec5SDimitry Andric 
isReg() const12920b57cec5SDimitry Andric   bool isReg() const override {
12930b57cec5SDimitry Andric     // As a special case until we sort out the definition of div/divu, accept
12940b57cec5SDimitry Andric     // $0/$zero here so that MCK_ZERO works correctly.
12950b57cec5SDimitry Andric     return isGPRAsmReg() && RegIdx.Index == 0;
12960b57cec5SDimitry Andric   }
12970b57cec5SDimitry Andric 
isRegIdx() const12980b57cec5SDimitry Andric   bool isRegIdx() const { return Kind == k_RegisterIndex; }
isImm() const12990b57cec5SDimitry Andric   bool isImm() const override { return Kind == k_Immediate; }
13000b57cec5SDimitry Andric 
isConstantImm() const13010b57cec5SDimitry Andric   bool isConstantImm() const {
13020b57cec5SDimitry Andric     int64_t Res;
13030b57cec5SDimitry Andric     return isImm() && getImm()->evaluateAsAbsolute(Res);
13040b57cec5SDimitry Andric   }
13050b57cec5SDimitry Andric 
isConstantImmz() const13060b57cec5SDimitry Andric   bool isConstantImmz() const {
13070b57cec5SDimitry Andric     return isConstantImm() && getConstantImm() == 0;
13080b57cec5SDimitry Andric   }
13090b57cec5SDimitry Andric 
isConstantUImm() const13100b57cec5SDimitry Andric   template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
13110b57cec5SDimitry Andric     return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
13120b57cec5SDimitry Andric   }
13130b57cec5SDimitry Andric 
isSImm() const13140b57cec5SDimitry Andric   template <unsigned Bits> bool isSImm() const {
13150b57cec5SDimitry Andric     return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
13160b57cec5SDimitry Andric   }
13170b57cec5SDimitry Andric 
isUImm() const13180b57cec5SDimitry Andric   template <unsigned Bits> bool isUImm() const {
13190b57cec5SDimitry Andric     return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
13200b57cec5SDimitry Andric   }
13210b57cec5SDimitry Andric 
isAnyImm() const13220b57cec5SDimitry Andric   template <unsigned Bits> bool isAnyImm() const {
13230b57cec5SDimitry Andric     return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
13240b57cec5SDimitry Andric                               isUInt<Bits>(getConstantImm()))
13250b57cec5SDimitry Andric                            : isImm();
13260b57cec5SDimitry Andric   }
13270b57cec5SDimitry Andric 
isConstantSImm() const13280b57cec5SDimitry Andric   template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
13290b57cec5SDimitry Andric     return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
13300b57cec5SDimitry Andric   }
13310b57cec5SDimitry Andric 
isConstantUImmRange() const13320b57cec5SDimitry Andric   template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
13330b57cec5SDimitry Andric     return isConstantImm() && getConstantImm() >= Bottom &&
13340b57cec5SDimitry Andric            getConstantImm() <= Top;
13350b57cec5SDimitry Andric   }
13360b57cec5SDimitry Andric 
isToken() const13370b57cec5SDimitry Andric   bool isToken() const override {
13380b57cec5SDimitry Andric     // Note: It's not possible to pretend that other operand kinds are tokens.
13390b57cec5SDimitry Andric     // The matcher emitter checks tokens first.
13400b57cec5SDimitry Andric     return Kind == k_Token;
13410b57cec5SDimitry Andric   }
13420b57cec5SDimitry Andric 
isMem() const13430b57cec5SDimitry Andric   bool isMem() const override { return Kind == k_Memory; }
13440b57cec5SDimitry Andric 
isConstantMemOff() const13450b57cec5SDimitry Andric   bool isConstantMemOff() const {
13460b57cec5SDimitry Andric     return isMem() && isa<MCConstantExpr>(getMemOff());
13470b57cec5SDimitry Andric   }
13480b57cec5SDimitry Andric 
13490b57cec5SDimitry Andric   // Allow relocation operators.
13500b57cec5SDimitry Andric   template <unsigned Bits, unsigned ShiftAmount = 0>
isMemWithSimmOffset() const13510b57cec5SDimitry Andric   bool isMemWithSimmOffset() const {
13520b57cec5SDimitry Andric     if (!isMem())
13530b57cec5SDimitry Andric       return false;
13540b57cec5SDimitry Andric     if (!getMemBase()->isGPRAsmReg())
13550b57cec5SDimitry Andric       return false;
13560b57cec5SDimitry Andric     if (isa<MCTargetExpr>(getMemOff()) ||
13570b57cec5SDimitry Andric         (isConstantMemOff() &&
13580b57cec5SDimitry Andric          isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
13590b57cec5SDimitry Andric       return true;
13600b57cec5SDimitry Andric     MCValue Res;
13610b57cec5SDimitry Andric     bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
13620b57cec5SDimitry Andric     return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
13630b57cec5SDimitry Andric   }
13640b57cec5SDimitry Andric 
isMemWithPtrSizeOffset() const13650b57cec5SDimitry Andric   bool isMemWithPtrSizeOffset() const {
13660b57cec5SDimitry Andric     if (!isMem())
13670b57cec5SDimitry Andric       return false;
13680b57cec5SDimitry Andric     if (!getMemBase()->isGPRAsmReg())
13690b57cec5SDimitry Andric       return false;
13700b57cec5SDimitry Andric     const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
13710b57cec5SDimitry Andric     if (isa<MCTargetExpr>(getMemOff()) ||
13720b57cec5SDimitry Andric         (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
13730b57cec5SDimitry Andric       return true;
13740b57cec5SDimitry Andric     MCValue Res;
13750b57cec5SDimitry Andric     bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
13760b57cec5SDimitry Andric     return IsReloc && isIntN(PtrBits, Res.getConstant());
13770b57cec5SDimitry Andric   }
13780b57cec5SDimitry Andric 
isMemWithGRPMM16Base() const13790b57cec5SDimitry Andric   bool isMemWithGRPMM16Base() const {
13800b57cec5SDimitry Andric     return isMem() && getMemBase()->isMM16AsmReg();
13810b57cec5SDimitry Andric   }
13820b57cec5SDimitry Andric 
isMemWithUimmOffsetSP() const13830b57cec5SDimitry Andric   template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
13840b57cec5SDimitry Andric     return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
13850b57cec5SDimitry Andric       && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
13860b57cec5SDimitry Andric   }
13870b57cec5SDimitry Andric 
isMemWithUimmWordAlignedOffsetSP() const13880b57cec5SDimitry Andric   template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
13890b57cec5SDimitry Andric     return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
13900b57cec5SDimitry Andric       && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
13910b57cec5SDimitry Andric       && (getMemBase()->getGPR32Reg() == Mips::SP);
13920b57cec5SDimitry Andric   }
13930b57cec5SDimitry Andric 
isMemWithSimmWordAlignedOffsetGP() const13940b57cec5SDimitry Andric   template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
13950b57cec5SDimitry Andric     return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
13960b57cec5SDimitry Andric       && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
13970b57cec5SDimitry Andric       && (getMemBase()->getGPR32Reg() == Mips::GP);
13980b57cec5SDimitry Andric   }
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric   template <unsigned Bits, unsigned ShiftLeftAmount>
isScaledUImm() const14010b57cec5SDimitry Andric   bool isScaledUImm() const {
14020b57cec5SDimitry Andric     return isConstantImm() &&
14030b57cec5SDimitry Andric            isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
14040b57cec5SDimitry Andric   }
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   template <unsigned Bits, unsigned ShiftLeftAmount>
isScaledSImm() const14070b57cec5SDimitry Andric   bool isScaledSImm() const {
14080b57cec5SDimitry Andric     if (isConstantImm() &&
14090b57cec5SDimitry Andric         isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
14100b57cec5SDimitry Andric       return true;
14110b57cec5SDimitry Andric     // Operand can also be a symbol or symbol plus
14120b57cec5SDimitry Andric     // offset in case of relocations.
14130b57cec5SDimitry Andric     if (Kind != k_Immediate)
14140b57cec5SDimitry Andric       return false;
14150b57cec5SDimitry Andric     MCValue Res;
14160b57cec5SDimitry Andric     bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
14170b57cec5SDimitry Andric     return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
14180b57cec5SDimitry Andric   }
14190b57cec5SDimitry Andric 
isRegList16() const14200b57cec5SDimitry Andric   bool isRegList16() const {
14210b57cec5SDimitry Andric     if (!isRegList())
14220b57cec5SDimitry Andric       return false;
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric     int Size = RegList.List->size();
14250b57cec5SDimitry Andric     if (Size < 2 || Size > 5)
14260b57cec5SDimitry Andric       return false;
14270b57cec5SDimitry Andric 
14280b57cec5SDimitry Andric     unsigned R0 = RegList.List->front();
14290b57cec5SDimitry Andric     unsigned R1 = RegList.List->back();
14300b57cec5SDimitry Andric     if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
14310b57cec5SDimitry Andric           (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
14320b57cec5SDimitry Andric       return false;
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric     int PrevReg = *RegList.List->begin();
14350b57cec5SDimitry Andric     for (int i = 1; i < Size - 1; i++) {
14360b57cec5SDimitry Andric       int Reg = (*(RegList.List))[i];
14370b57cec5SDimitry Andric       if ( Reg != PrevReg + 1)
14380b57cec5SDimitry Andric         return false;
14390b57cec5SDimitry Andric       PrevReg = Reg;
14400b57cec5SDimitry Andric     }
14410b57cec5SDimitry Andric 
14420b57cec5SDimitry Andric     return true;
14430b57cec5SDimitry Andric   }
14440b57cec5SDimitry Andric 
isInvNum() const14450b57cec5SDimitry Andric   bool isInvNum() const { return Kind == k_Immediate; }
14460b57cec5SDimitry Andric 
isLSAImm() const14470b57cec5SDimitry Andric   bool isLSAImm() const {
14480b57cec5SDimitry Andric     if (!isConstantImm())
14490b57cec5SDimitry Andric       return false;
14500b57cec5SDimitry Andric     int64_t Val = getConstantImm();
14510b57cec5SDimitry Andric     return 1 <= Val && Val <= 4;
14520b57cec5SDimitry Andric   }
14530b57cec5SDimitry Andric 
isRegList() const14540b57cec5SDimitry Andric   bool isRegList() const { return Kind == k_RegList; }
14550b57cec5SDimitry Andric 
getToken() const14560b57cec5SDimitry Andric   StringRef getToken() const {
14570b57cec5SDimitry Andric     assert(Kind == k_Token && "Invalid access!");
14580b57cec5SDimitry Andric     return StringRef(Tok.Data, Tok.Length);
14590b57cec5SDimitry Andric   }
14600b57cec5SDimitry Andric 
getReg() const1461*0fca6ea1SDimitry Andric   MCRegister getReg() const override {
14620b57cec5SDimitry Andric     // As a special case until we sort out the definition of div/divu, accept
14630b57cec5SDimitry Andric     // $0/$zero here so that MCK_ZERO works correctly.
14640b57cec5SDimitry Andric     if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
14650b57cec5SDimitry Andric         RegIdx.Kind & RegKind_GPR)
14660b57cec5SDimitry Andric       return getGPR32Reg(); // FIXME: GPR64 too
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric     llvm_unreachable("Invalid access!");
14690b57cec5SDimitry Andric     return 0;
14700b57cec5SDimitry Andric   }
14710b57cec5SDimitry Andric 
getImm() const14720b57cec5SDimitry Andric   const MCExpr *getImm() const {
14730b57cec5SDimitry Andric     assert((Kind == k_Immediate) && "Invalid access!");
14740b57cec5SDimitry Andric     return Imm.Val;
14750b57cec5SDimitry Andric   }
14760b57cec5SDimitry Andric 
getConstantImm() const14770b57cec5SDimitry Andric   int64_t getConstantImm() const {
14780b57cec5SDimitry Andric     const MCExpr *Val = getImm();
14790b57cec5SDimitry Andric     int64_t Value = 0;
14800b57cec5SDimitry Andric     (void)Val->evaluateAsAbsolute(Value);
14810b57cec5SDimitry Andric     return Value;
14820b57cec5SDimitry Andric   }
14830b57cec5SDimitry Andric 
getMemBase() const14840b57cec5SDimitry Andric   MipsOperand *getMemBase() const {
14850b57cec5SDimitry Andric     assert((Kind == k_Memory) && "Invalid access!");
14860b57cec5SDimitry Andric     return Mem.Base;
14870b57cec5SDimitry Andric   }
14880b57cec5SDimitry Andric 
getMemOff() const14890b57cec5SDimitry Andric   const MCExpr *getMemOff() const {
14900b57cec5SDimitry Andric     assert((Kind == k_Memory) && "Invalid access!");
14910b57cec5SDimitry Andric     return Mem.Off;
14920b57cec5SDimitry Andric   }
14930b57cec5SDimitry Andric 
getConstantMemOff() const14940b57cec5SDimitry Andric   int64_t getConstantMemOff() const {
14950b57cec5SDimitry Andric     return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
14960b57cec5SDimitry Andric   }
14970b57cec5SDimitry Andric 
getRegList() const14980b57cec5SDimitry Andric   const SmallVectorImpl<unsigned> &getRegList() const {
14990b57cec5SDimitry Andric     assert((Kind == k_RegList) && "Invalid access!");
15000b57cec5SDimitry Andric     return *(RegList.List);
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric 
CreateToken(StringRef Str,SMLoc S,MipsAsmParser & Parser)15030b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
15040b57cec5SDimitry Andric                                                   MipsAsmParser &Parser) {
15058bcb0991SDimitry Andric     auto Op = std::make_unique<MipsOperand>(k_Token, Parser);
15060b57cec5SDimitry Andric     Op->Tok.Data = Str.data();
15070b57cec5SDimitry Andric     Op->Tok.Length = Str.size();
15080b57cec5SDimitry Andric     Op->StartLoc = S;
15090b57cec5SDimitry Andric     Op->EndLoc = S;
15100b57cec5SDimitry Andric     return Op;
15110b57cec5SDimitry Andric   }
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric   /// Create a numeric register (e.g. $1). The exact register remains
15140b57cec5SDimitry Andric   /// unresolved until an instruction successfully matches
15150b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createNumericReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15160b57cec5SDimitry Andric   createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15170b57cec5SDimitry Andric                    SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15180b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
15190b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
15200b57cec5SDimitry Andric   }
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric   /// Create a register that is definitely a GPR.
15230b57cec5SDimitry Andric   /// This is typically only used for named registers such as $gp.
15240b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createGPRReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15250b57cec5SDimitry Andric   createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15260b57cec5SDimitry Andric                SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15270b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
15280b57cec5SDimitry Andric   }
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric   /// Create a register that is definitely a FGR.
15310b57cec5SDimitry Andric   /// This is typically only used for named registers such as $f0.
15320b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createFGRReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15330b57cec5SDimitry Andric   createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15340b57cec5SDimitry Andric                SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15350b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
15360b57cec5SDimitry Andric   }
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric   /// Create a register that is definitely a HWReg.
15390b57cec5SDimitry Andric   /// This is typically only used for named registers such as $hwr_cpunum.
15400b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createHWRegsReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15410b57cec5SDimitry Andric   createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15420b57cec5SDimitry Andric                   SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15430b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
15440b57cec5SDimitry Andric   }
15450b57cec5SDimitry Andric 
15460b57cec5SDimitry Andric   /// Create a register that is definitely an FCC.
15470b57cec5SDimitry Andric   /// This is typically only used for named registers such as $fcc0.
15480b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createFCCReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15490b57cec5SDimitry Andric   createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15500b57cec5SDimitry Andric                SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15510b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
15520b57cec5SDimitry Andric   }
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   /// Create a register that is definitely an ACC.
15550b57cec5SDimitry Andric   /// This is typically only used for named registers such as $ac0.
15560b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createACCReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15570b57cec5SDimitry Andric   createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15580b57cec5SDimitry Andric                SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15590b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
15600b57cec5SDimitry Andric   }
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric   /// Create a register that is definitely an MSA128.
15630b57cec5SDimitry Andric   /// This is typically only used for named registers such as $w0.
15640b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createMSA128Reg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15650b57cec5SDimitry Andric   createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15660b57cec5SDimitry Andric                   SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15670b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
15680b57cec5SDimitry Andric   }
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric   /// Create a register that is definitely an MSACtrl.
15710b57cec5SDimitry Andric   /// This is typically only used for named registers such as $msaaccess.
15720b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
createMSACtrlReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15730b57cec5SDimitry Andric   createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15740b57cec5SDimitry Andric                    SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15750b57cec5SDimitry Andric     return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
15760b57cec5SDimitry Andric   }
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E,MipsAsmParser & Parser)15790b57cec5SDimitry Andric   CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15808bcb0991SDimitry Andric     auto Op = std::make_unique<MipsOperand>(k_Immediate, Parser);
15810b57cec5SDimitry Andric     Op->Imm.Val = Val;
15820b57cec5SDimitry Andric     Op->StartLoc = S;
15830b57cec5SDimitry Andric     Op->EndLoc = E;
15840b57cec5SDimitry Andric     return Op;
15850b57cec5SDimitry Andric   }
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base,const MCExpr * Off,SMLoc S,SMLoc E,MipsAsmParser & Parser)15880b57cec5SDimitry Andric   CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
15890b57cec5SDimitry Andric             SMLoc E, MipsAsmParser &Parser) {
15908bcb0991SDimitry Andric     auto Op = std::make_unique<MipsOperand>(k_Memory, Parser);
15910b57cec5SDimitry Andric     Op->Mem.Base = Base.release();
15920b57cec5SDimitry Andric     Op->Mem.Off = Off;
15930b57cec5SDimitry Andric     Op->StartLoc = S;
15940b57cec5SDimitry Andric     Op->EndLoc = E;
15950b57cec5SDimitry Andric     return Op;
15960b57cec5SDimitry Andric   }
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric   static std::unique_ptr<MipsOperand>
CreateRegList(SmallVectorImpl<unsigned> & Regs,SMLoc StartLoc,SMLoc EndLoc,MipsAsmParser & Parser)15990b57cec5SDimitry Andric   CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
16000b57cec5SDimitry Andric                 MipsAsmParser &Parser) {
16010b57cec5SDimitry Andric     assert(Regs.size() > 0 && "Empty list not allowed");
16020b57cec5SDimitry Andric 
16038bcb0991SDimitry Andric     auto Op = std::make_unique<MipsOperand>(k_RegList, Parser);
16040b57cec5SDimitry Andric     Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
16050b57cec5SDimitry Andric     Op->StartLoc = StartLoc;
16060b57cec5SDimitry Andric     Op->EndLoc = EndLoc;
16070b57cec5SDimitry Andric     return Op;
16080b57cec5SDimitry Andric   }
16090b57cec5SDimitry Andric 
isGPRZeroAsmReg() const16100b57cec5SDimitry Andric  bool isGPRZeroAsmReg() const {
16110b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
16120b57cec5SDimitry Andric   }
16130b57cec5SDimitry Andric 
isGPRNonZeroAsmReg() const16140b57cec5SDimitry Andric  bool isGPRNonZeroAsmReg() const {
16150b57cec5SDimitry Andric    return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
16160b57cec5SDimitry Andric           RegIdx.Index <= 31;
16170b57cec5SDimitry Andric   }
16180b57cec5SDimitry Andric 
isGPRAsmReg() const16190b57cec5SDimitry Andric   bool isGPRAsmReg() const {
16200b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
16210b57cec5SDimitry Andric   }
16220b57cec5SDimitry Andric 
isMM16AsmReg() const16230b57cec5SDimitry Andric   bool isMM16AsmReg() const {
16240b57cec5SDimitry Andric     if (!(isRegIdx() && RegIdx.Kind))
16250b57cec5SDimitry Andric       return false;
16260b57cec5SDimitry Andric     return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
16270b57cec5SDimitry Andric             || RegIdx.Index == 16 || RegIdx.Index == 17);
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric   }
isMM16AsmRegZero() const16300b57cec5SDimitry Andric   bool isMM16AsmRegZero() const {
16310b57cec5SDimitry Andric     if (!(isRegIdx() && RegIdx.Kind))
16320b57cec5SDimitry Andric       return false;
16330b57cec5SDimitry Andric     return (RegIdx.Index == 0 ||
16340b57cec5SDimitry Andric             (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
16350b57cec5SDimitry Andric             RegIdx.Index == 17);
16360b57cec5SDimitry Andric   }
16370b57cec5SDimitry Andric 
isMM16AsmRegMoveP() const16380b57cec5SDimitry Andric   bool isMM16AsmRegMoveP() const {
16390b57cec5SDimitry Andric     if (!(isRegIdx() && RegIdx.Kind))
16400b57cec5SDimitry Andric       return false;
16410b57cec5SDimitry Andric     return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
16420b57cec5SDimitry Andric       (RegIdx.Index >= 16 && RegIdx.Index <= 20));
16430b57cec5SDimitry Andric   }
16440b57cec5SDimitry Andric 
isMM16AsmRegMovePPairFirst() const16450b57cec5SDimitry Andric   bool isMM16AsmRegMovePPairFirst() const {
16460b57cec5SDimitry Andric     if (!(isRegIdx() && RegIdx.Kind))
16470b57cec5SDimitry Andric       return false;
16480b57cec5SDimitry Andric     return RegIdx.Index >= 4 && RegIdx.Index <= 6;
16490b57cec5SDimitry Andric   }
16500b57cec5SDimitry Andric 
isMM16AsmRegMovePPairSecond() const16510b57cec5SDimitry Andric   bool isMM16AsmRegMovePPairSecond() const {
16520b57cec5SDimitry Andric     if (!(isRegIdx() && RegIdx.Kind))
16530b57cec5SDimitry Andric       return false;
16540b57cec5SDimitry Andric     return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
16550b57cec5SDimitry Andric       (RegIdx.Index >= 5 && RegIdx.Index <= 7));
16560b57cec5SDimitry Andric   }
16570b57cec5SDimitry Andric 
isFGRAsmReg() const16580b57cec5SDimitry Andric   bool isFGRAsmReg() const {
16590b57cec5SDimitry Andric     // AFGR64 is $0-$15 but we handle this in getAFGR64()
16600b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
16610b57cec5SDimitry Andric   }
16620b57cec5SDimitry Andric 
isStrictlyFGRAsmReg() const16630b57cec5SDimitry Andric   bool isStrictlyFGRAsmReg() const {
16640b57cec5SDimitry Andric     // AFGR64 is $0-$15 but we handle this in getAFGR64()
16650b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
16660b57cec5SDimitry Andric   }
16670b57cec5SDimitry Andric 
isHWRegsAsmReg() const16680b57cec5SDimitry Andric   bool isHWRegsAsmReg() const {
16690b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
16700b57cec5SDimitry Andric   }
16710b57cec5SDimitry Andric 
isCCRAsmReg() const16720b57cec5SDimitry Andric   bool isCCRAsmReg() const {
16730b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
16740b57cec5SDimitry Andric   }
16750b57cec5SDimitry Andric 
isFCCAsmReg() const16760b57cec5SDimitry Andric   bool isFCCAsmReg() const {
16770b57cec5SDimitry Andric     if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
16780b57cec5SDimitry Andric       return false;
16790b57cec5SDimitry Andric     return RegIdx.Index <= 7;
16800b57cec5SDimitry Andric   }
16810b57cec5SDimitry Andric 
isACCAsmReg() const16820b57cec5SDimitry Andric   bool isACCAsmReg() const {
16830b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
16840b57cec5SDimitry Andric   }
16850b57cec5SDimitry Andric 
isCOP0AsmReg() const16860b57cec5SDimitry Andric   bool isCOP0AsmReg() const {
16870b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
16880b57cec5SDimitry Andric   }
16890b57cec5SDimitry Andric 
isCOP2AsmReg() const16900b57cec5SDimitry Andric   bool isCOP2AsmReg() const {
16910b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
16920b57cec5SDimitry Andric   }
16930b57cec5SDimitry Andric 
isCOP3AsmReg() const16940b57cec5SDimitry Andric   bool isCOP3AsmReg() const {
16950b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
16960b57cec5SDimitry Andric   }
16970b57cec5SDimitry Andric 
isMSA128AsmReg() const16980b57cec5SDimitry Andric   bool isMSA128AsmReg() const {
16990b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
17000b57cec5SDimitry Andric   }
17010b57cec5SDimitry Andric 
isMSACtrlAsmReg() const17020b57cec5SDimitry Andric   bool isMSACtrlAsmReg() const {
17030b57cec5SDimitry Andric     return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
17040b57cec5SDimitry Andric   }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const17070b57cec5SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
17080b57cec5SDimitry Andric   /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const17090b57cec5SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
17100b57cec5SDimitry Andric 
print(raw_ostream & OS) const17110b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
17120b57cec5SDimitry Andric     switch (Kind) {
17130b57cec5SDimitry Andric     case k_Immediate:
17140b57cec5SDimitry Andric       OS << "Imm<";
17150b57cec5SDimitry Andric       OS << *Imm.Val;
17160b57cec5SDimitry Andric       OS << ">";
17170b57cec5SDimitry Andric       break;
17180b57cec5SDimitry Andric     case k_Memory:
17190b57cec5SDimitry Andric       OS << "Mem<";
17200b57cec5SDimitry Andric       Mem.Base->print(OS);
17210b57cec5SDimitry Andric       OS << ", ";
17220b57cec5SDimitry Andric       OS << *Mem.Off;
17230b57cec5SDimitry Andric       OS << ">";
17240b57cec5SDimitry Andric       break;
17250b57cec5SDimitry Andric     case k_RegisterIndex:
17260b57cec5SDimitry Andric       OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
17270b57cec5SDimitry Andric          << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
17280b57cec5SDimitry Andric       break;
17290b57cec5SDimitry Andric     case k_Token:
17300b57cec5SDimitry Andric       OS << getToken();
17310b57cec5SDimitry Andric       break;
17320b57cec5SDimitry Andric     case k_RegList:
17330b57cec5SDimitry Andric       OS << "RegList< ";
17340b57cec5SDimitry Andric       for (auto Reg : (*RegList.List))
17350b57cec5SDimitry Andric         OS << Reg << " ";
17360b57cec5SDimitry Andric       OS <<  ">";
17370b57cec5SDimitry Andric       break;
17380b57cec5SDimitry Andric     }
17390b57cec5SDimitry Andric   }
17400b57cec5SDimitry Andric 
isValidForTie(const MipsOperand & Other) const17410b57cec5SDimitry Andric   bool isValidForTie(const MipsOperand &Other) const {
17420b57cec5SDimitry Andric     if (Kind != Other.Kind)
17430b57cec5SDimitry Andric       return false;
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric     switch (Kind) {
17460b57cec5SDimitry Andric     default:
17470b57cec5SDimitry Andric       llvm_unreachable("Unexpected kind");
17480b57cec5SDimitry Andric       return false;
17490b57cec5SDimitry Andric     case k_RegisterIndex: {
17500b57cec5SDimitry Andric       StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
17510b57cec5SDimitry Andric       StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
17520b57cec5SDimitry Andric       return Token == OtherToken;
17530b57cec5SDimitry Andric     }
17540b57cec5SDimitry Andric     }
17550b57cec5SDimitry Andric   }
17560b57cec5SDimitry Andric }; // class MipsOperand
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric } // end anonymous namespace
17590b57cec5SDimitry Andric 
hasShortDelaySlot(MCInst & Inst)17600b57cec5SDimitry Andric static bool hasShortDelaySlot(MCInst &Inst) {
17610b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
17620b57cec5SDimitry Andric     case Mips::BEQ_MM:
17630b57cec5SDimitry Andric     case Mips::BNE_MM:
17640b57cec5SDimitry Andric     case Mips::BLTZ_MM:
17650b57cec5SDimitry Andric     case Mips::BGEZ_MM:
17660b57cec5SDimitry Andric     case Mips::BLEZ_MM:
17670b57cec5SDimitry Andric     case Mips::BGTZ_MM:
17680b57cec5SDimitry Andric     case Mips::JRC16_MM:
17690b57cec5SDimitry Andric     case Mips::JALS_MM:
17700b57cec5SDimitry Andric     case Mips::JALRS_MM:
17710b57cec5SDimitry Andric     case Mips::JALRS16_MM:
17720b57cec5SDimitry Andric     case Mips::BGEZALS_MM:
17730b57cec5SDimitry Andric     case Mips::BLTZALS_MM:
17740b57cec5SDimitry Andric       return true;
17750b57cec5SDimitry Andric     case Mips::J_MM:
17760b57cec5SDimitry Andric       return !Inst.getOperand(0).isReg();
17770b57cec5SDimitry Andric     default:
17780b57cec5SDimitry Andric       return false;
17790b57cec5SDimitry Andric   }
17800b57cec5SDimitry Andric }
17810b57cec5SDimitry Andric 
getSingleMCSymbol(const MCExpr * Expr)17820b57cec5SDimitry Andric static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
17830b57cec5SDimitry Andric   if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
17840b57cec5SDimitry Andric     return &SRExpr->getSymbol();
17850b57cec5SDimitry Andric   }
17860b57cec5SDimitry Andric 
17870b57cec5SDimitry Andric   if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
17880b57cec5SDimitry Andric     const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
17890b57cec5SDimitry Andric     const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric     if (LHSSym)
17920b57cec5SDimitry Andric       return LHSSym;
17930b57cec5SDimitry Andric 
17940b57cec5SDimitry Andric     if (RHSSym)
17950b57cec5SDimitry Andric       return RHSSym;
17960b57cec5SDimitry Andric 
17970b57cec5SDimitry Andric     return nullptr;
17980b57cec5SDimitry Andric   }
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric   if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
18010b57cec5SDimitry Andric     return getSingleMCSymbol(UExpr->getSubExpr());
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric   return nullptr;
18040b57cec5SDimitry Andric }
18050b57cec5SDimitry Andric 
countMCSymbolRefExpr(const MCExpr * Expr)18060b57cec5SDimitry Andric static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
18070b57cec5SDimitry Andric   if (isa<MCSymbolRefExpr>(Expr))
18080b57cec5SDimitry Andric     return 1;
18090b57cec5SDimitry Andric 
18100b57cec5SDimitry Andric   if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
18110b57cec5SDimitry Andric     return countMCSymbolRefExpr(BExpr->getLHS()) +
18120b57cec5SDimitry Andric            countMCSymbolRefExpr(BExpr->getRHS());
18130b57cec5SDimitry Andric 
18140b57cec5SDimitry Andric   if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
18150b57cec5SDimitry Andric     return countMCSymbolRefExpr(UExpr->getSubExpr());
18160b57cec5SDimitry Andric 
18170b57cec5SDimitry Andric   return 0;
18180b57cec5SDimitry Andric }
18190b57cec5SDimitry Andric 
isEvaluated(const MCExpr * Expr)1820480093f4SDimitry Andric static bool isEvaluated(const MCExpr *Expr) {
1821480093f4SDimitry Andric   switch (Expr->getKind()) {
1822480093f4SDimitry Andric   case MCExpr::Constant:
1823480093f4SDimitry Andric     return true;
1824480093f4SDimitry Andric   case MCExpr::SymbolRef:
1825480093f4SDimitry Andric     return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1826480093f4SDimitry Andric   case MCExpr::Binary: {
1827480093f4SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
1828480093f4SDimitry Andric     if (!isEvaluated(BE->getLHS()))
1829480093f4SDimitry Andric       return false;
1830480093f4SDimitry Andric     return isEvaluated(BE->getRHS());
1831480093f4SDimitry Andric   }
1832480093f4SDimitry Andric   case MCExpr::Unary:
1833480093f4SDimitry Andric     return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1834480093f4SDimitry Andric   case MCExpr::Target:
1835480093f4SDimitry Andric     return true;
1836480093f4SDimitry Andric   }
1837480093f4SDimitry Andric   return false;
1838480093f4SDimitry Andric }
1839480093f4SDimitry Andric 
needsExpandMemInst(MCInst & Inst,const MCInstrDesc & MCID)1840bdd1243dSDimitry Andric static bool needsExpandMemInst(MCInst &Inst, const MCInstrDesc &MCID) {
1841480093f4SDimitry Andric   unsigned NumOp = MCID.getNumOperands();
1842480093f4SDimitry Andric   if (NumOp != 3 && NumOp != 4)
1843480093f4SDimitry Andric     return false;
1844480093f4SDimitry Andric 
1845bdd1243dSDimitry Andric   const MCOperandInfo &OpInfo = MCID.operands()[NumOp - 1];
1846480093f4SDimitry Andric   if (OpInfo.OperandType != MCOI::OPERAND_MEMORY &&
1847480093f4SDimitry Andric       OpInfo.OperandType != MCOI::OPERAND_UNKNOWN &&
1848480093f4SDimitry Andric       OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9)
1849480093f4SDimitry Andric     return false;
1850480093f4SDimitry Andric 
1851480093f4SDimitry Andric   MCOperand &Op = Inst.getOperand(NumOp - 1);
1852480093f4SDimitry Andric   if (Op.isImm()) {
1853480093f4SDimitry Andric     if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9)
1854480093f4SDimitry Andric       return !isInt<9>(Op.getImm());
1855480093f4SDimitry Andric     // Offset can't exceed 16bit value.
1856480093f4SDimitry Andric     return !isInt<16>(Op.getImm());
1857480093f4SDimitry Andric   }
1858480093f4SDimitry Andric 
1859480093f4SDimitry Andric   if (Op.isExpr()) {
1860480093f4SDimitry Andric     const MCExpr *Expr = Op.getExpr();
1861480093f4SDimitry Andric     if (Expr->getKind() != MCExpr::SymbolRef)
1862480093f4SDimitry Andric       return !isEvaluated(Expr);
1863480093f4SDimitry Andric 
1864480093f4SDimitry Andric     // Expand symbol.
1865480093f4SDimitry Andric     const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr);
1866480093f4SDimitry Andric     return SR->getKind() == MCSymbolRefExpr::VK_None;
1867480093f4SDimitry Andric   }
1868480093f4SDimitry Andric 
1869480093f4SDimitry Andric   return false;
1870480093f4SDimitry Andric }
1871480093f4SDimitry Andric 
processInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)18720b57cec5SDimitry Andric bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
18730b57cec5SDimitry Andric                                        MCStreamer &Out,
18740b57cec5SDimitry Andric                                        const MCSubtargetInfo *STI) {
18750b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
1876480093f4SDimitry Andric   const unsigned Opcode = Inst.getOpcode();
1877bdd1243dSDimitry Andric   const MCInstrDesc &MCID = MII.get(Opcode);
18780b57cec5SDimitry Andric   bool ExpandedJalSym = false;
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric   Inst.setLoc(IDLoc);
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric   if (MCID.isBranch() || MCID.isCall()) {
18830b57cec5SDimitry Andric     MCOperand Offset;
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric     switch (Opcode) {
18860b57cec5SDimitry Andric     default:
18870b57cec5SDimitry Andric       break;
18880b57cec5SDimitry Andric     case Mips::BBIT0:
18890b57cec5SDimitry Andric     case Mips::BBIT032:
18900b57cec5SDimitry Andric     case Mips::BBIT1:
18910b57cec5SDimitry Andric     case Mips::BBIT132:
18920b57cec5SDimitry Andric       assert(hasCnMips() && "instruction only valid for octeon cpus");
1893bdd1243dSDimitry Andric       [[fallthrough]];
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric     case Mips::BEQ:
18960b57cec5SDimitry Andric     case Mips::BNE:
18970b57cec5SDimitry Andric     case Mips::BEQ_MM:
18980b57cec5SDimitry Andric     case Mips::BNE_MM:
18990b57cec5SDimitry Andric       assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
19000b57cec5SDimitry Andric       Offset = Inst.getOperand(2);
19010b57cec5SDimitry Andric       if (!Offset.isImm())
19020b57cec5SDimitry Andric         break; // We'll deal with this situation later on when applying fixups.
19030b57cec5SDimitry Andric       if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
19040b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
19058bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(),
19068bcb0991SDimitry Andric                             (inMicroMipsMode() ? Align(2) : Align(4))))
19070b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
19080b57cec5SDimitry Andric       break;
19090b57cec5SDimitry Andric     case Mips::BGEZ:
19100b57cec5SDimitry Andric     case Mips::BGTZ:
19110b57cec5SDimitry Andric     case Mips::BLEZ:
19120b57cec5SDimitry Andric     case Mips::BLTZ:
19130b57cec5SDimitry Andric     case Mips::BGEZAL:
19140b57cec5SDimitry Andric     case Mips::BLTZAL:
19150b57cec5SDimitry Andric     case Mips::BC1F:
19160b57cec5SDimitry Andric     case Mips::BC1T:
19170b57cec5SDimitry Andric     case Mips::BGEZ_MM:
19180b57cec5SDimitry Andric     case Mips::BGTZ_MM:
19190b57cec5SDimitry Andric     case Mips::BLEZ_MM:
19200b57cec5SDimitry Andric     case Mips::BLTZ_MM:
19210b57cec5SDimitry Andric     case Mips::BGEZAL_MM:
19220b57cec5SDimitry Andric     case Mips::BLTZAL_MM:
19230b57cec5SDimitry Andric     case Mips::BC1F_MM:
19240b57cec5SDimitry Andric     case Mips::BC1T_MM:
19250b57cec5SDimitry Andric     case Mips::BC1EQZC_MMR6:
19260b57cec5SDimitry Andric     case Mips::BC1NEZC_MMR6:
19270b57cec5SDimitry Andric     case Mips::BC2EQZC_MMR6:
19280b57cec5SDimitry Andric     case Mips::BC2NEZC_MMR6:
19290b57cec5SDimitry Andric       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19300b57cec5SDimitry Andric       Offset = Inst.getOperand(1);
19310b57cec5SDimitry Andric       if (!Offset.isImm())
19320b57cec5SDimitry Andric         break; // We'll deal with this situation later on when applying fixups.
19330b57cec5SDimitry Andric       if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
19340b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
19358bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(),
19368bcb0991SDimitry Andric                             (inMicroMipsMode() ? Align(2) : Align(4))))
19370b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
19380b57cec5SDimitry Andric       break;
19390b57cec5SDimitry Andric     case Mips::BGEC:    case Mips::BGEC_MMR6:
19400b57cec5SDimitry Andric     case Mips::BLTC:    case Mips::BLTC_MMR6:
19410b57cec5SDimitry Andric     case Mips::BGEUC:   case Mips::BGEUC_MMR6:
19420b57cec5SDimitry Andric     case Mips::BLTUC:   case Mips::BLTUC_MMR6:
19430b57cec5SDimitry Andric     case Mips::BEQC:    case Mips::BEQC_MMR6:
19440b57cec5SDimitry Andric     case Mips::BNEC:    case Mips::BNEC_MMR6:
19450b57cec5SDimitry Andric       assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
19460b57cec5SDimitry Andric       Offset = Inst.getOperand(2);
19470b57cec5SDimitry Andric       if (!Offset.isImm())
19480b57cec5SDimitry Andric         break; // We'll deal with this situation later on when applying fixups.
19490b57cec5SDimitry Andric       if (!isIntN(18, Offset.getImm()))
19500b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
19518bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(), Align(4)))
19520b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
19530b57cec5SDimitry Andric       break;
19540b57cec5SDimitry Andric     case Mips::BLEZC:   case Mips::BLEZC_MMR6:
19550b57cec5SDimitry Andric     case Mips::BGEZC:   case Mips::BGEZC_MMR6:
19560b57cec5SDimitry Andric     case Mips::BGTZC:   case Mips::BGTZC_MMR6:
19570b57cec5SDimitry Andric     case Mips::BLTZC:   case Mips::BLTZC_MMR6:
19580b57cec5SDimitry Andric       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19590b57cec5SDimitry Andric       Offset = Inst.getOperand(1);
19600b57cec5SDimitry Andric       if (!Offset.isImm())
19610b57cec5SDimitry Andric         break; // We'll deal with this situation later on when applying fixups.
19620b57cec5SDimitry Andric       if (!isIntN(18, Offset.getImm()))
19630b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
19648bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(), Align(4)))
19650b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
19660b57cec5SDimitry Andric       break;
19670b57cec5SDimitry Andric     case Mips::BEQZC:   case Mips::BEQZC_MMR6:
19680b57cec5SDimitry Andric     case Mips::BNEZC:   case Mips::BNEZC_MMR6:
19690b57cec5SDimitry Andric       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19700b57cec5SDimitry Andric       Offset = Inst.getOperand(1);
19710b57cec5SDimitry Andric       if (!Offset.isImm())
19720b57cec5SDimitry Andric         break; // We'll deal with this situation later on when applying fixups.
19730b57cec5SDimitry Andric       if (!isIntN(23, Offset.getImm()))
19740b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
19758bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(), Align(4)))
19760b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
19770b57cec5SDimitry Andric       break;
19780b57cec5SDimitry Andric     case Mips::BEQZ16_MM:
19790b57cec5SDimitry Andric     case Mips::BEQZC16_MMR6:
19800b57cec5SDimitry Andric     case Mips::BNEZ16_MM:
19810b57cec5SDimitry Andric     case Mips::BNEZC16_MMR6:
19820b57cec5SDimitry Andric       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19830b57cec5SDimitry Andric       Offset = Inst.getOperand(1);
19840b57cec5SDimitry Andric       if (!Offset.isImm())
19850b57cec5SDimitry Andric         break; // We'll deal with this situation later on when applying fixups.
19860b57cec5SDimitry Andric       if (!isInt<8>(Offset.getImm()))
19870b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
19888bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(), Align(2)))
19890b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
19900b57cec5SDimitry Andric       break;
19910b57cec5SDimitry Andric     }
19920b57cec5SDimitry Andric   }
19930b57cec5SDimitry Andric 
19940b57cec5SDimitry Andric   // SSNOP is deprecated on MIPS32r6/MIPS64r6
19950b57cec5SDimitry Andric   // We still accept it but it is a normal nop.
1996480093f4SDimitry Andric   if (hasMips32r6() && Opcode == Mips::SSNOP) {
19970b57cec5SDimitry Andric     std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
19980b57cec5SDimitry Andric     Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
19990b57cec5SDimitry Andric                                                       "nop instruction");
20000b57cec5SDimitry Andric   }
20010b57cec5SDimitry Andric 
20020b57cec5SDimitry Andric   if (hasCnMips()) {
20030b57cec5SDimitry Andric     MCOperand Opnd;
20040b57cec5SDimitry Andric     int Imm;
20050b57cec5SDimitry Andric 
20060b57cec5SDimitry Andric     switch (Opcode) {
20070b57cec5SDimitry Andric       default:
20080b57cec5SDimitry Andric         break;
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric       case Mips::BBIT0:
20110b57cec5SDimitry Andric       case Mips::BBIT032:
20120b57cec5SDimitry Andric       case Mips::BBIT1:
20130b57cec5SDimitry Andric       case Mips::BBIT132:
20140b57cec5SDimitry Andric         assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
20150b57cec5SDimitry Andric         // The offset is handled above
20160b57cec5SDimitry Andric         Opnd = Inst.getOperand(1);
20170b57cec5SDimitry Andric         if (!Opnd.isImm())
20180b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
20190b57cec5SDimitry Andric         Imm = Opnd.getImm();
20200b57cec5SDimitry Andric         if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
20210b57cec5SDimitry Andric                               Opcode == Mips::BBIT1 ? 63 : 31))
20220b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
20230b57cec5SDimitry Andric         if (Imm > 31) {
20240b57cec5SDimitry Andric           Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
20250b57cec5SDimitry Andric                                                : Mips::BBIT132);
20260b57cec5SDimitry Andric           Inst.getOperand(1).setImm(Imm - 32);
20270b57cec5SDimitry Andric         }
20280b57cec5SDimitry Andric         break;
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric       case Mips::SEQi:
20310b57cec5SDimitry Andric       case Mips::SNEi:
20320b57cec5SDimitry Andric         assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
20330b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
20340b57cec5SDimitry Andric         if (!Opnd.isImm())
20350b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
20360b57cec5SDimitry Andric         Imm = Opnd.getImm();
20370b57cec5SDimitry Andric         if (!isInt<10>(Imm))
20380b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
20390b57cec5SDimitry Andric         break;
20400b57cec5SDimitry Andric     }
20410b57cec5SDimitry Andric   }
20420b57cec5SDimitry Andric 
20430b57cec5SDimitry Andric   // Warn on division by zero. We're checking here as all instructions get
20440b57cec5SDimitry Andric   // processed here, not just the macros that need expansion.
20450b57cec5SDimitry Andric   //
20460b57cec5SDimitry Andric   // The MIPS backend models most of the divison instructions and macros as
20470b57cec5SDimitry Andric   // three operand instructions. The pre-R6 divide instructions however have
20480b57cec5SDimitry Andric   // two operands and explicitly define HI/LO as part of the instruction,
20490b57cec5SDimitry Andric   // not in the operands.
20500b57cec5SDimitry Andric   unsigned FirstOp = 1;
20510b57cec5SDimitry Andric   unsigned SecondOp = 2;
2052480093f4SDimitry Andric   switch (Opcode) {
20530b57cec5SDimitry Andric   default:
20540b57cec5SDimitry Andric     break;
20550b57cec5SDimitry Andric   case Mips::SDivIMacro:
20560b57cec5SDimitry Andric   case Mips::UDivIMacro:
20570b57cec5SDimitry Andric   case Mips::DSDivIMacro:
20580b57cec5SDimitry Andric   case Mips::DUDivIMacro:
20590b57cec5SDimitry Andric     if (Inst.getOperand(2).getImm() == 0) {
20600b57cec5SDimitry Andric       if (Inst.getOperand(1).getReg() == Mips::ZERO ||
20610b57cec5SDimitry Andric           Inst.getOperand(1).getReg() == Mips::ZERO_64)
20620b57cec5SDimitry Andric         Warning(IDLoc, "dividing zero by zero");
20630b57cec5SDimitry Andric       else
20640b57cec5SDimitry Andric         Warning(IDLoc, "division by zero");
20650b57cec5SDimitry Andric     }
20660b57cec5SDimitry Andric     break;
20670b57cec5SDimitry Andric   case Mips::DSDIV:
20680b57cec5SDimitry Andric   case Mips::SDIV:
20690b57cec5SDimitry Andric   case Mips::UDIV:
20700b57cec5SDimitry Andric   case Mips::DUDIV:
20710b57cec5SDimitry Andric   case Mips::UDIV_MM:
20720b57cec5SDimitry Andric   case Mips::SDIV_MM:
20730b57cec5SDimitry Andric     FirstOp = 0;
20740b57cec5SDimitry Andric     SecondOp = 1;
2075bdd1243dSDimitry Andric     [[fallthrough]];
20760b57cec5SDimitry Andric   case Mips::SDivMacro:
20770b57cec5SDimitry Andric   case Mips::DSDivMacro:
20780b57cec5SDimitry Andric   case Mips::UDivMacro:
20790b57cec5SDimitry Andric   case Mips::DUDivMacro:
20800b57cec5SDimitry Andric   case Mips::DIV:
20810b57cec5SDimitry Andric   case Mips::DIVU:
20820b57cec5SDimitry Andric   case Mips::DDIV:
20830b57cec5SDimitry Andric   case Mips::DDIVU:
20840b57cec5SDimitry Andric   case Mips::DIVU_MMR6:
20850b57cec5SDimitry Andric   case Mips::DIV_MMR6:
20860b57cec5SDimitry Andric     if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
20870b57cec5SDimitry Andric         Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
20880b57cec5SDimitry Andric       if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
20890b57cec5SDimitry Andric           Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
20900b57cec5SDimitry Andric         Warning(IDLoc, "dividing zero by zero");
20910b57cec5SDimitry Andric       else
20920b57cec5SDimitry Andric         Warning(IDLoc, "division by zero");
20930b57cec5SDimitry Andric     }
20940b57cec5SDimitry Andric     break;
20950b57cec5SDimitry Andric   }
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric   // For PIC code convert unconditional jump to unconditional branch.
2098480093f4SDimitry Andric   if ((Opcode == Mips::J || Opcode == Mips::J_MM) && inPicMode()) {
20990b57cec5SDimitry Andric     MCInst BInst;
21000b57cec5SDimitry Andric     BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
21010b57cec5SDimitry Andric     BInst.addOperand(MCOperand::createReg(Mips::ZERO));
21020b57cec5SDimitry Andric     BInst.addOperand(MCOperand::createReg(Mips::ZERO));
21030b57cec5SDimitry Andric     BInst.addOperand(Inst.getOperand(0));
21040b57cec5SDimitry Andric     Inst = BInst;
21050b57cec5SDimitry Andric   }
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric   // This expansion is not in a function called by tryExpandInstruction()
21080b57cec5SDimitry Andric   // because the pseudo-instruction doesn't have a distinct opcode.
2109480093f4SDimitry Andric   if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) {
21100b57cec5SDimitry Andric     warnIfNoMacro(IDLoc);
21110b57cec5SDimitry Andric 
21120b57cec5SDimitry Andric     const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric     // We can do this expansion if there's only 1 symbol in the argument
21150b57cec5SDimitry Andric     // expression.
21160b57cec5SDimitry Andric     if (countMCSymbolRefExpr(JalExpr) > 1)
21170b57cec5SDimitry Andric       return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
21180b57cec5SDimitry Andric 
21190b57cec5SDimitry Andric     // FIXME: This is checking the expression can be handled by the later stages
21200b57cec5SDimitry Andric     //        of the assembler. We ought to leave it to those later stages.
21210b57cec5SDimitry Andric     const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
21220b57cec5SDimitry Andric 
2123480093f4SDimitry Andric     if (expandLoadAddress(Mips::T9, Mips::NoRegister, Inst.getOperand(0),
2124480093f4SDimitry Andric                           !isGP64bit(), IDLoc, Out, STI))
2125480093f4SDimitry Andric       return true;
21260b57cec5SDimitry Andric 
21270b57cec5SDimitry Andric     MCInst JalrInst;
2128480093f4SDimitry Andric     if (inMicroMipsMode())
2129480093f4SDimitry Andric       JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM);
21300b57cec5SDimitry Andric     else
2131480093f4SDimitry Andric       JalrInst.setOpcode(Mips::JALR);
21320b57cec5SDimitry Andric     JalrInst.addOperand(MCOperand::createReg(Mips::RA));
21330b57cec5SDimitry Andric     JalrInst.addOperand(MCOperand::createReg(Mips::T9));
21340b57cec5SDimitry Andric 
2135480093f4SDimitry Andric     if (isJalrRelocAvailable(JalExpr)) {
21360b57cec5SDimitry Andric       // As an optimization hint for the linker, before the JALR we add:
21370b57cec5SDimitry Andric       // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
21380b57cec5SDimitry Andric       // tmplabel:
21390b57cec5SDimitry Andric       MCSymbol *TmpLabel = getContext().createTempSymbol();
21400b57cec5SDimitry Andric       const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
21410b57cec5SDimitry Andric       const MCExpr *RelocJalrExpr =
21420b57cec5SDimitry Andric           MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
21430b57cec5SDimitry Andric                                   getContext(), IDLoc);
21440b57cec5SDimitry Andric 
21455ffd83dbSDimitry Andric       TOut.getStreamer().emitRelocDirective(
21465ffd83dbSDimitry Andric           *TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
21470b57cec5SDimitry Andric           RelocJalrExpr, IDLoc, *STI);
21485ffd83dbSDimitry Andric       TOut.getStreamer().emitLabel(TmpLabel);
21490b57cec5SDimitry Andric     }
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric     Inst = JalrInst;
21520b57cec5SDimitry Andric     ExpandedJalSym = true;
21530b57cec5SDimitry Andric   }
21540b57cec5SDimitry Andric 
2155480093f4SDimitry Andric   if (MCID.mayLoad() || MCID.mayStore()) {
21560b57cec5SDimitry Andric     // Check the offset of memory operand, if it is a symbol
21570b57cec5SDimitry Andric     // reference or immediate we may have to expand instructions.
2158bdd1243dSDimitry Andric     if (needsExpandMemInst(Inst, MCID)) {
2159bdd1243dSDimitry Andric       switch (MCID.operands()[MCID.getNumOperands() - 1].OperandType) {
2160480093f4SDimitry Andric       case MipsII::OPERAND_MEM_SIMM9:
2161480093f4SDimitry Andric         expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2162480093f4SDimitry Andric         break;
2163480093f4SDimitry Andric       default:
2164480093f4SDimitry Andric         expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2165480093f4SDimitry Andric         break;
21660b57cec5SDimitry Andric       }
21670b57cec5SDimitry Andric       return getParser().hasPendingError();
21680b57cec5SDimitry Andric     }
21690b57cec5SDimitry Andric   }
21700b57cec5SDimitry Andric 
21710b57cec5SDimitry Andric   if (inMicroMipsMode()) {
2172480093f4SDimitry Andric     if (MCID.mayLoad() && Opcode != Mips::LWP_MM) {
21730b57cec5SDimitry Andric       // Try to create 16-bit GP relative load instruction.
21740b57cec5SDimitry Andric       for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2175bdd1243dSDimitry Andric         const MCOperandInfo &OpInfo = MCID.operands()[i];
21760b57cec5SDimitry Andric         if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
21770b57cec5SDimitry Andric             (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
21780b57cec5SDimitry Andric           MCOperand &Op = Inst.getOperand(i);
21790b57cec5SDimitry Andric           if (Op.isImm()) {
21800b57cec5SDimitry Andric             int MemOffset = Op.getImm();
21810b57cec5SDimitry Andric             MCOperand &DstReg = Inst.getOperand(0);
21820b57cec5SDimitry Andric             MCOperand &BaseReg = Inst.getOperand(1);
21830b57cec5SDimitry Andric             if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
21840b57cec5SDimitry Andric                 getContext().getRegisterInfo()->getRegClass(
21850b57cec5SDimitry Andric                   Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
21860b57cec5SDimitry Andric                 (BaseReg.getReg() == Mips::GP ||
21870b57cec5SDimitry Andric                 BaseReg.getReg() == Mips::GP_64)) {
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric               TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
21900b57cec5SDimitry Andric                            IDLoc, STI);
21910b57cec5SDimitry Andric               return false;
21920b57cec5SDimitry Andric             }
21930b57cec5SDimitry Andric           }
21940b57cec5SDimitry Andric         }
21950b57cec5SDimitry Andric       } // for
21960b57cec5SDimitry Andric     }   // if load
21970b57cec5SDimitry Andric 
21980b57cec5SDimitry Andric     // TODO: Handle this with the AsmOperandClass.PredicateMethod.
21990b57cec5SDimitry Andric 
22000b57cec5SDimitry Andric     MCOperand Opnd;
22010b57cec5SDimitry Andric     int Imm;
22020b57cec5SDimitry Andric 
2203480093f4SDimitry Andric     switch (Opcode) {
22040b57cec5SDimitry Andric       default:
22050b57cec5SDimitry Andric         break;
22060b57cec5SDimitry Andric       case Mips::ADDIUSP_MM:
22070b57cec5SDimitry Andric         Opnd = Inst.getOperand(0);
22080b57cec5SDimitry Andric         if (!Opnd.isImm())
22090b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22100b57cec5SDimitry Andric         Imm = Opnd.getImm();
22110b57cec5SDimitry Andric         if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
22120b57cec5SDimitry Andric             Imm % 4 != 0)
22130b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22140b57cec5SDimitry Andric         break;
22150b57cec5SDimitry Andric       case Mips::SLL16_MM:
22160b57cec5SDimitry Andric       case Mips::SRL16_MM:
22170b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22180b57cec5SDimitry Andric         if (!Opnd.isImm())
22190b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22200b57cec5SDimitry Andric         Imm = Opnd.getImm();
22210b57cec5SDimitry Andric         if (Imm < 1 || Imm > 8)
22220b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22230b57cec5SDimitry Andric         break;
22240b57cec5SDimitry Andric       case Mips::LI16_MM:
22250b57cec5SDimitry Andric         Opnd = Inst.getOperand(1);
22260b57cec5SDimitry Andric         if (!Opnd.isImm())
22270b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22280b57cec5SDimitry Andric         Imm = Opnd.getImm();
22290b57cec5SDimitry Andric         if (Imm < -1 || Imm > 126)
22300b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22310b57cec5SDimitry Andric         break;
22320b57cec5SDimitry Andric       case Mips::ADDIUR2_MM:
22330b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22340b57cec5SDimitry Andric         if (!Opnd.isImm())
22350b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22360b57cec5SDimitry Andric         Imm = Opnd.getImm();
22370b57cec5SDimitry Andric         if (!(Imm == 1 || Imm == -1 ||
22380b57cec5SDimitry Andric               ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
22390b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22400b57cec5SDimitry Andric         break;
22410b57cec5SDimitry Andric       case Mips::ANDI16_MM:
22420b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22430b57cec5SDimitry Andric         if (!Opnd.isImm())
22440b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22450b57cec5SDimitry Andric         Imm = Opnd.getImm();
22460b57cec5SDimitry Andric         if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
22470b57cec5SDimitry Andric               Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
22480b57cec5SDimitry Andric               Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
22490b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22500b57cec5SDimitry Andric         break;
22510b57cec5SDimitry Andric       case Mips::LBU16_MM:
22520b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22530b57cec5SDimitry Andric         if (!Opnd.isImm())
22540b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22550b57cec5SDimitry Andric         Imm = Opnd.getImm();
22560b57cec5SDimitry Andric         if (Imm < -1 || Imm > 14)
22570b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22580b57cec5SDimitry Andric         break;
22590b57cec5SDimitry Andric       case Mips::SB16_MM:
22600b57cec5SDimitry Andric       case Mips::SB16_MMR6:
22610b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22620b57cec5SDimitry Andric         if (!Opnd.isImm())
22630b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22640b57cec5SDimitry Andric         Imm = Opnd.getImm();
22650b57cec5SDimitry Andric         if (Imm < 0 || Imm > 15)
22660b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22670b57cec5SDimitry Andric         break;
22680b57cec5SDimitry Andric       case Mips::LHU16_MM:
22690b57cec5SDimitry Andric       case Mips::SH16_MM:
22700b57cec5SDimitry Andric       case Mips::SH16_MMR6:
22710b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22720b57cec5SDimitry Andric         if (!Opnd.isImm())
22730b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22740b57cec5SDimitry Andric         Imm = Opnd.getImm();
22750b57cec5SDimitry Andric         if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
22760b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22770b57cec5SDimitry Andric         break;
22780b57cec5SDimitry Andric       case Mips::LW16_MM:
22790b57cec5SDimitry Andric       case Mips::SW16_MM:
22800b57cec5SDimitry Andric       case Mips::SW16_MMR6:
22810b57cec5SDimitry Andric         Opnd = Inst.getOperand(2);
22820b57cec5SDimitry Andric         if (!Opnd.isImm())
22830b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22840b57cec5SDimitry Andric         Imm = Opnd.getImm();
22850b57cec5SDimitry Andric         if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
22860b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22870b57cec5SDimitry Andric         break;
22880b57cec5SDimitry Andric       case Mips::ADDIUPC_MM:
22890b57cec5SDimitry Andric         Opnd = Inst.getOperand(1);
22900b57cec5SDimitry Andric         if (!Opnd.isImm())
22910b57cec5SDimitry Andric           return Error(IDLoc, "expected immediate operand kind");
22920b57cec5SDimitry Andric         Imm = Opnd.getImm();
22930b57cec5SDimitry Andric         if ((Imm % 4 != 0) || !isInt<25>(Imm))
22940b57cec5SDimitry Andric           return Error(IDLoc, "immediate operand value out of range");
22950b57cec5SDimitry Andric         break;
22960b57cec5SDimitry Andric       case Mips::LWP_MM:
22970b57cec5SDimitry Andric       case Mips::SWP_MM:
22980b57cec5SDimitry Andric         if (Inst.getOperand(0).getReg() == Mips::RA)
22990b57cec5SDimitry Andric           return Error(IDLoc, "invalid operand for instruction");
23000b57cec5SDimitry Andric         break;
23010b57cec5SDimitry Andric       case Mips::MOVEP_MM:
23020b57cec5SDimitry Andric       case Mips::MOVEP_MMR6: {
23030b57cec5SDimitry Andric         unsigned R0 = Inst.getOperand(0).getReg();
23040b57cec5SDimitry Andric         unsigned R1 = Inst.getOperand(1).getReg();
23050b57cec5SDimitry Andric         bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
23060b57cec5SDimitry Andric                         (R0 == Mips::A1 && R1 == Mips::A3) ||
23070b57cec5SDimitry Andric                         (R0 == Mips::A2 && R1 == Mips::A3) ||
23080b57cec5SDimitry Andric                         (R0 == Mips::A0 && R1 == Mips::S5) ||
23090b57cec5SDimitry Andric                         (R0 == Mips::A0 && R1 == Mips::S6) ||
23100b57cec5SDimitry Andric                         (R0 == Mips::A0 && R1 == Mips::A1) ||
23110b57cec5SDimitry Andric                         (R0 == Mips::A0 && R1 == Mips::A2) ||
23120b57cec5SDimitry Andric                         (R0 == Mips::A0 && R1 == Mips::A3));
23130b57cec5SDimitry Andric         if (!RegPair)
23140b57cec5SDimitry Andric           return Error(IDLoc, "invalid operand for instruction");
23150b57cec5SDimitry Andric         break;
23160b57cec5SDimitry Andric       }
23170b57cec5SDimitry Andric     }
23180b57cec5SDimitry Andric   }
23190b57cec5SDimitry Andric 
23200b57cec5SDimitry Andric   bool FillDelaySlot =
23210b57cec5SDimitry Andric       MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
23224c2d3b02SDimitry Andric 
23234c2d3b02SDimitry Andric   // Get previous instruction`s forbidden slot attribute and
23244c2d3b02SDimitry Andric   // whether set reorder.
23254c2d3b02SDimitry Andric   bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
23264c2d3b02SDimitry Andric 
23274c2d3b02SDimitry Andric   // Flag represents we set reorder after nop.
23284c2d3b02SDimitry Andric   bool SetReorderAfterNop = false;
23294c2d3b02SDimitry Andric 
23304c2d3b02SDimitry Andric   // If previous instruction has forbidden slot and .set reorder
23314c2d3b02SDimitry Andric   // is active and current instruction is CTI.
23324c2d3b02SDimitry Andric   // Then emit a NOP after it.
23334c2d3b02SDimitry Andric   if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {
23344c2d3b02SDimitry Andric     TOut.emitEmptyDelaySlot(false, IDLoc, STI);
23354c2d3b02SDimitry Andric     // When 'FillDelaySlot' is true, the existing logic will add
23364c2d3b02SDimitry Andric     // noreorder before instruction and reorder after it. So there
23374c2d3b02SDimitry Andric     // need exclude this case avoiding two '.set reorder'.
23384c2d3b02SDimitry Andric     // The format of the first case is:
23394c2d3b02SDimitry Andric     // .set noreorder
23404c2d3b02SDimitry Andric     // bnezc
23414c2d3b02SDimitry Andric     // nop
23424c2d3b02SDimitry Andric     // .set reorder
23434c2d3b02SDimitry Andric     if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
23444c2d3b02SDimitry Andric       SetReorderAfterNop = true;
23454c2d3b02SDimitry Andric       TOut.emitDirectiveSetReorder();
23464c2d3b02SDimitry Andric     }
23474c2d3b02SDimitry Andric   }
23484c2d3b02SDimitry Andric 
23494c2d3b02SDimitry Andric   // Save current instruction`s forbidden slot and whether set reorder.
23504c2d3b02SDimitry Andric   // This is the judgment condition for whether to add nop.
23514c2d3b02SDimitry Andric   // We would add a couple of '.set noreorder' and '.set reorder' to
23524c2d3b02SDimitry Andric   // wrap the current instruction and the next instruction.
23534c2d3b02SDimitry Andric   CurForbiddenSlotAttr =
23544c2d3b02SDimitry Andric       hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();
23554c2d3b02SDimitry Andric 
23564c2d3b02SDimitry Andric   if (FillDelaySlot || CurForbiddenSlotAttr)
23570b57cec5SDimitry Andric     TOut.emitDirectiveSetNoReorder();
23580b57cec5SDimitry Andric 
23590b57cec5SDimitry Andric   MacroExpanderResultTy ExpandResult =
23600b57cec5SDimitry Andric       tryExpandInstruction(Inst, IDLoc, Out, STI);
23610b57cec5SDimitry Andric   switch (ExpandResult) {
23620b57cec5SDimitry Andric   case MER_NotAMacro:
23635ffd83dbSDimitry Andric     Out.emitInstruction(Inst, *STI);
23640b57cec5SDimitry Andric     break;
23650b57cec5SDimitry Andric   case MER_Success:
23660b57cec5SDimitry Andric     break;
23670b57cec5SDimitry Andric   case MER_Fail:
23680b57cec5SDimitry Andric     return true;
23690b57cec5SDimitry Andric   }
23700b57cec5SDimitry Andric 
23714c2d3b02SDimitry Andric   // When current instruction was not CTI, recover reorder state.
23724c2d3b02SDimitry Andric   // The format of the second case is:
23734c2d3b02SDimitry Andric   // .set noreoder
23744c2d3b02SDimitry Andric   // bnezc
23754c2d3b02SDimitry Andric   // add
23764c2d3b02SDimitry Andric   // .set reorder
23774c2d3b02SDimitry Andric   if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
23784c2d3b02SDimitry Andric       AssemblerOptions.back()->isReorder()) {
23794c2d3b02SDimitry Andric     TOut.emitDirectiveSetReorder();
23804c2d3b02SDimitry Andric   }
23814c2d3b02SDimitry Andric 
23820b57cec5SDimitry Andric   // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
23830b57cec5SDimitry Andric   // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
23840b57cec5SDimitry Andric   if (inMicroMipsMode()) {
23850b57cec5SDimitry Andric     TOut.setUsesMicroMips();
23860b57cec5SDimitry Andric     TOut.updateABIInfo(*this);
23870b57cec5SDimitry Andric   }
23880b57cec5SDimitry Andric 
23890b57cec5SDimitry Andric   // If this instruction has a delay slot and .set reorder is active,
23900b57cec5SDimitry Andric   // emit a NOP after it.
23914c2d3b02SDimitry Andric   // The format of the third case is:
23924c2d3b02SDimitry Andric   // .set noreorder
23934c2d3b02SDimitry Andric   // bnezc
23944c2d3b02SDimitry Andric   // nop
23954c2d3b02SDimitry Andric   // .set noreorder
23964c2d3b02SDimitry Andric   // j
23974c2d3b02SDimitry Andric   // nop
23984c2d3b02SDimitry Andric   // .set reorder
23990b57cec5SDimitry Andric   if (FillDelaySlot) {
24000b57cec5SDimitry Andric     TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
24010b57cec5SDimitry Andric     TOut.emitDirectiveSetReorder();
24020b57cec5SDimitry Andric   }
24030b57cec5SDimitry Andric 
2404480093f4SDimitry Andric   if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg ||
2405480093f4SDimitry Andric        ExpandedJalSym) &&
24060b57cec5SDimitry Andric       isPicAndNotNxxAbi()) {
24070b57cec5SDimitry Andric     if (IsCpRestoreSet) {
24080b57cec5SDimitry Andric       // We need a NOP between the JALR and the LW:
24090b57cec5SDimitry Andric       // If .set reorder has been used, we've already emitted a NOP.
24100b57cec5SDimitry Andric       // If .set noreorder has been used, we need to emit a NOP at this point.
24110b57cec5SDimitry Andric       if (!AssemblerOptions.back()->isReorder())
24120b57cec5SDimitry Andric         TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
24130b57cec5SDimitry Andric                                 STI);
24140b57cec5SDimitry Andric 
24150b57cec5SDimitry Andric       // Load the $gp from the stack.
24160b57cec5SDimitry Andric       TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
24170b57cec5SDimitry Andric     } else
24180b57cec5SDimitry Andric       Warning(IDLoc, "no .cprestore used in PIC mode");
24190b57cec5SDimitry Andric   }
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric   return false;
24220b57cec5SDimitry Andric }
24230b57cec5SDimitry Andric 
onEndOfFile()24244c2d3b02SDimitry Andric void MipsAsmParser::onEndOfFile() {
24254c2d3b02SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
24264c2d3b02SDimitry Andric   SMLoc IDLoc = SMLoc();
24274c2d3b02SDimitry Andric   // If has pending forbidden slot, fill nop and recover reorder.
24284c2d3b02SDimitry Andric   if (CurForbiddenSlotAttr) {
24294c2d3b02SDimitry Andric     TOut.emitEmptyDelaySlot(false, IDLoc, STI);
24304c2d3b02SDimitry Andric     if (AssemblerOptions.back()->isReorder())
24314c2d3b02SDimitry Andric       TOut.emitDirectiveSetReorder();
24324c2d3b02SDimitry Andric   }
24334c2d3b02SDimitry Andric }
24344c2d3b02SDimitry Andric 
24350b57cec5SDimitry Andric MipsAsmParser::MacroExpanderResultTy
tryExpandInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)24360b57cec5SDimitry Andric MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
24370b57cec5SDimitry Andric                                     const MCSubtargetInfo *STI) {
24380b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
24390b57cec5SDimitry Andric   default:
24400b57cec5SDimitry Andric     return MER_NotAMacro;
24410b57cec5SDimitry Andric   case Mips::LoadImm32:
24420b57cec5SDimitry Andric     return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24430b57cec5SDimitry Andric   case Mips::LoadImm64:
24440b57cec5SDimitry Andric     return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24450b57cec5SDimitry Andric   case Mips::LoadAddrImm32:
24460b57cec5SDimitry Andric   case Mips::LoadAddrImm64:
24470b57cec5SDimitry Andric     assert(Inst.getOperand(0).isReg() && "expected register operand kind");
24480b57cec5SDimitry Andric     assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
24490b57cec5SDimitry Andric            "expected immediate operand kind");
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric     return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
24520b57cec5SDimitry Andric                              Inst.getOperand(1),
24530b57cec5SDimitry Andric                              Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
24540b57cec5SDimitry Andric                              Out, STI)
24550b57cec5SDimitry Andric                ? MER_Fail
24560b57cec5SDimitry Andric                : MER_Success;
24570b57cec5SDimitry Andric   case Mips::LoadAddrReg32:
24580b57cec5SDimitry Andric   case Mips::LoadAddrReg64:
24590b57cec5SDimitry Andric     assert(Inst.getOperand(0).isReg() && "expected register operand kind");
24600b57cec5SDimitry Andric     assert(Inst.getOperand(1).isReg() && "expected register operand kind");
24610b57cec5SDimitry Andric     assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
24620b57cec5SDimitry Andric            "expected immediate operand kind");
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric     return expandLoadAddress(Inst.getOperand(0).getReg(),
24650b57cec5SDimitry Andric                              Inst.getOperand(1).getReg(), Inst.getOperand(2),
24660b57cec5SDimitry Andric                              Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
24670b57cec5SDimitry Andric                              Out, STI)
24680b57cec5SDimitry Andric                ? MER_Fail
24690b57cec5SDimitry Andric                : MER_Success;
24700b57cec5SDimitry Andric   case Mips::B_MM_Pseudo:
24710b57cec5SDimitry Andric   case Mips::B_MMR6_Pseudo:
24720b57cec5SDimitry Andric     return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
24730b57cec5SDimitry Andric                                                              : MER_Success;
24740b57cec5SDimitry Andric   case Mips::SWM_MM:
24750b57cec5SDimitry Andric   case Mips::LWM_MM:
24760b57cec5SDimitry Andric     return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
24770b57cec5SDimitry Andric                                                           : MER_Success;
24780b57cec5SDimitry Andric   case Mips::JalOneReg:
24790b57cec5SDimitry Andric   case Mips::JalTwoReg:
24800b57cec5SDimitry Andric     return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24810b57cec5SDimitry Andric   case Mips::BneImm:
24820b57cec5SDimitry Andric   case Mips::BeqImm:
24830b57cec5SDimitry Andric   case Mips::BEQLImmMacro:
24840b57cec5SDimitry Andric   case Mips::BNELImmMacro:
24850b57cec5SDimitry Andric     return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24860b57cec5SDimitry Andric   case Mips::BLT:
24870b57cec5SDimitry Andric   case Mips::BLE:
24880b57cec5SDimitry Andric   case Mips::BGE:
24890b57cec5SDimitry Andric   case Mips::BGT:
24900b57cec5SDimitry Andric   case Mips::BLTU:
24910b57cec5SDimitry Andric   case Mips::BLEU:
24920b57cec5SDimitry Andric   case Mips::BGEU:
24930b57cec5SDimitry Andric   case Mips::BGTU:
24940b57cec5SDimitry Andric   case Mips::BLTL:
24950b57cec5SDimitry Andric   case Mips::BLEL:
24960b57cec5SDimitry Andric   case Mips::BGEL:
24970b57cec5SDimitry Andric   case Mips::BGTL:
24980b57cec5SDimitry Andric   case Mips::BLTUL:
24990b57cec5SDimitry Andric   case Mips::BLEUL:
25000b57cec5SDimitry Andric   case Mips::BGEUL:
25010b57cec5SDimitry Andric   case Mips::BGTUL:
25020b57cec5SDimitry Andric   case Mips::BLTImmMacro:
25030b57cec5SDimitry Andric   case Mips::BLEImmMacro:
25040b57cec5SDimitry Andric   case Mips::BGEImmMacro:
25050b57cec5SDimitry Andric   case Mips::BGTImmMacro:
25060b57cec5SDimitry Andric   case Mips::BLTUImmMacro:
25070b57cec5SDimitry Andric   case Mips::BLEUImmMacro:
25080b57cec5SDimitry Andric   case Mips::BGEUImmMacro:
25090b57cec5SDimitry Andric   case Mips::BGTUImmMacro:
25100b57cec5SDimitry Andric   case Mips::BLTLImmMacro:
25110b57cec5SDimitry Andric   case Mips::BLELImmMacro:
25120b57cec5SDimitry Andric   case Mips::BGELImmMacro:
25130b57cec5SDimitry Andric   case Mips::BGTLImmMacro:
25140b57cec5SDimitry Andric   case Mips::BLTULImmMacro:
25150b57cec5SDimitry Andric   case Mips::BLEULImmMacro:
25160b57cec5SDimitry Andric   case Mips::BGEULImmMacro:
25170b57cec5SDimitry Andric   case Mips::BGTULImmMacro:
25180b57cec5SDimitry Andric     return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25190b57cec5SDimitry Andric   case Mips::SDivMacro:
25200b57cec5SDimitry Andric   case Mips::SDivIMacro:
25210b57cec5SDimitry Andric   case Mips::SRemMacro:
25220b57cec5SDimitry Andric   case Mips::SRemIMacro:
25230b57cec5SDimitry Andric     return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
25240b57cec5SDimitry Andric                                                             : MER_Success;
25250b57cec5SDimitry Andric   case Mips::DSDivMacro:
25260b57cec5SDimitry Andric   case Mips::DSDivIMacro:
25270b57cec5SDimitry Andric   case Mips::DSRemMacro:
25280b57cec5SDimitry Andric   case Mips::DSRemIMacro:
25290b57cec5SDimitry Andric     return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
25300b57cec5SDimitry Andric                                                            : MER_Success;
25310b57cec5SDimitry Andric   case Mips::UDivMacro:
25320b57cec5SDimitry Andric   case Mips::UDivIMacro:
25330b57cec5SDimitry Andric   case Mips::URemMacro:
25340b57cec5SDimitry Andric   case Mips::URemIMacro:
25350b57cec5SDimitry Andric     return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
25360b57cec5SDimitry Andric                                                              : MER_Success;
25370b57cec5SDimitry Andric   case Mips::DUDivMacro:
25380b57cec5SDimitry Andric   case Mips::DUDivIMacro:
25390b57cec5SDimitry Andric   case Mips::DURemMacro:
25400b57cec5SDimitry Andric   case Mips::DURemIMacro:
25410b57cec5SDimitry Andric     return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
25420b57cec5SDimitry Andric                                                             : MER_Success;
25430b57cec5SDimitry Andric   case Mips::PseudoTRUNC_W_S:
25440b57cec5SDimitry Andric     return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
25450b57cec5SDimitry Andric                                                             : MER_Success;
25460b57cec5SDimitry Andric   case Mips::PseudoTRUNC_W_D32:
25470b57cec5SDimitry Andric     return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
25480b57cec5SDimitry Andric                                                            : MER_Success;
25490b57cec5SDimitry Andric   case Mips::PseudoTRUNC_W_D:
25500b57cec5SDimitry Andric     return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
25510b57cec5SDimitry Andric                                                           : MER_Success;
25520b57cec5SDimitry Andric 
25530b57cec5SDimitry Andric   case Mips::LoadImmSingleGPR:
2554c14a5a88SDimitry Andric     return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
25550b57cec5SDimitry Andric                                                            : MER_Success;
25560b57cec5SDimitry Andric   case Mips::LoadImmSingleFGR:
2557c14a5a88SDimitry Andric     return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail
25580b57cec5SDimitry Andric                                                            : MER_Success;
25590b57cec5SDimitry Andric   case Mips::LoadImmDoubleGPR:
2560c14a5a88SDimitry Andric     return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
25610b57cec5SDimitry Andric                                                            : MER_Success;
25620b57cec5SDimitry Andric   case Mips::LoadImmDoubleFGR:
2563c14a5a88SDimitry Andric     return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail
25640b57cec5SDimitry Andric                                                                  : MER_Success;
25650b57cec5SDimitry Andric   case Mips::LoadImmDoubleFGR_32:
2566c14a5a88SDimitry Andric     return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail
25670b57cec5SDimitry Andric                                                                   : MER_Success;
2568c14a5a88SDimitry Andric 
25690b57cec5SDimitry Andric   case Mips::Ulh:
25700b57cec5SDimitry Andric     return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25710b57cec5SDimitry Andric   case Mips::Ulhu:
25720b57cec5SDimitry Andric     return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25730b57cec5SDimitry Andric   case Mips::Ush:
25740b57cec5SDimitry Andric     return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25750b57cec5SDimitry Andric   case Mips::Ulw:
25760b57cec5SDimitry Andric   case Mips::Usw:
25770b57cec5SDimitry Andric     return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25780b57cec5SDimitry Andric   case Mips::NORImm:
25790b57cec5SDimitry Andric   case Mips::NORImm64:
25800b57cec5SDimitry Andric     return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25810b57cec5SDimitry Andric   case Mips::SGE:
25820b57cec5SDimitry Andric   case Mips::SGEU:
25830b57cec5SDimitry Andric     return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25840b57cec5SDimitry Andric   case Mips::SGEImm:
25850b57cec5SDimitry Andric   case Mips::SGEUImm:
25860b57cec5SDimitry Andric   case Mips::SGEImm64:
25870b57cec5SDimitry Andric   case Mips::SGEUImm64:
25880b57cec5SDimitry Andric     return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25890b57cec5SDimitry Andric   case Mips::SGTImm:
25900b57cec5SDimitry Andric   case Mips::SGTUImm:
25910b57cec5SDimitry Andric   case Mips::SGTImm64:
25920b57cec5SDimitry Andric   case Mips::SGTUImm64:
25930b57cec5SDimitry Andric     return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25945ffd83dbSDimitry Andric   case Mips::SLE:
25955ffd83dbSDimitry Andric   case Mips::SLEU:
25965ffd83dbSDimitry Andric     return expandSle(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25975ffd83dbSDimitry Andric   case Mips::SLEImm:
25985ffd83dbSDimitry Andric   case Mips::SLEUImm:
25995ffd83dbSDimitry Andric   case Mips::SLEImm64:
26005ffd83dbSDimitry Andric   case Mips::SLEUImm64:
26015ffd83dbSDimitry Andric     return expandSleImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26020b57cec5SDimitry Andric   case Mips::SLTImm64:
26030b57cec5SDimitry Andric     if (isInt<16>(Inst.getOperand(2).getImm())) {
26040b57cec5SDimitry Andric       Inst.setOpcode(Mips::SLTi64);
26050b57cec5SDimitry Andric       return MER_NotAMacro;
26060b57cec5SDimitry Andric     }
26070b57cec5SDimitry Andric     return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26080b57cec5SDimitry Andric   case Mips::SLTUImm64:
26090b57cec5SDimitry Andric     if (isInt<16>(Inst.getOperand(2).getImm())) {
26100b57cec5SDimitry Andric       Inst.setOpcode(Mips::SLTiu64);
26110b57cec5SDimitry Andric       return MER_NotAMacro;
26120b57cec5SDimitry Andric     }
26130b57cec5SDimitry Andric     return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26140b57cec5SDimitry Andric   case Mips::ADDi:   case Mips::ADDi_MM:
26150b57cec5SDimitry Andric   case Mips::ADDiu:  case Mips::ADDiu_MM:
26160b57cec5SDimitry Andric   case Mips::SLTi:   case Mips::SLTi_MM:
26170b57cec5SDimitry Andric   case Mips::SLTiu:  case Mips::SLTiu_MM:
26180b57cec5SDimitry Andric     if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
26190b57cec5SDimitry Andric         Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
26200b57cec5SDimitry Andric       int64_t ImmValue = Inst.getOperand(2).getImm();
26210b57cec5SDimitry Andric       if (isInt<16>(ImmValue))
26220b57cec5SDimitry Andric         return MER_NotAMacro;
26230b57cec5SDimitry Andric       return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
26240b57cec5SDimitry Andric                                                          : MER_Success;
26250b57cec5SDimitry Andric     }
26260b57cec5SDimitry Andric     return MER_NotAMacro;
26270b57cec5SDimitry Andric   case Mips::ANDi:  case Mips::ANDi_MM:  case Mips::ANDi64:
26280b57cec5SDimitry Andric   case Mips::ORi:   case Mips::ORi_MM:   case Mips::ORi64:
26290b57cec5SDimitry Andric   case Mips::XORi:  case Mips::XORi_MM:  case Mips::XORi64:
26300b57cec5SDimitry Andric     if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
26310b57cec5SDimitry Andric         Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
26320b57cec5SDimitry Andric       int64_t ImmValue = Inst.getOperand(2).getImm();
26330b57cec5SDimitry Andric       if (isUInt<16>(ImmValue))
26340b57cec5SDimitry Andric         return MER_NotAMacro;
26350b57cec5SDimitry Andric       return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
26360b57cec5SDimitry Andric                                                          : MER_Success;
26370b57cec5SDimitry Andric     }
26380b57cec5SDimitry Andric     return MER_NotAMacro;
26390b57cec5SDimitry Andric   case Mips::ROL:
26400b57cec5SDimitry Andric   case Mips::ROR:
26410b57cec5SDimitry Andric     return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26420b57cec5SDimitry Andric   case Mips::ROLImm:
26430b57cec5SDimitry Andric   case Mips::RORImm:
26440b57cec5SDimitry Andric     return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26450b57cec5SDimitry Andric   case Mips::DROL:
26460b57cec5SDimitry Andric   case Mips::DROR:
26470b57cec5SDimitry Andric     return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26480b57cec5SDimitry Andric   case Mips::DROLImm:
26490b57cec5SDimitry Andric   case Mips::DRORImm:
26500b57cec5SDimitry Andric     return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26510b57cec5SDimitry Andric   case Mips::ABSMacro:
26520b57cec5SDimitry Andric     return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26530b57cec5SDimitry Andric   case Mips::MULImmMacro:
26540b57cec5SDimitry Andric   case Mips::DMULImmMacro:
26550b57cec5SDimitry Andric     return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26560b57cec5SDimitry Andric   case Mips::MULOMacro:
26570b57cec5SDimitry Andric   case Mips::DMULOMacro:
26580b57cec5SDimitry Andric     return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26590b57cec5SDimitry Andric   case Mips::MULOUMacro:
26600b57cec5SDimitry Andric   case Mips::DMULOUMacro:
26610b57cec5SDimitry Andric     return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26620b57cec5SDimitry Andric   case Mips::DMULMacro:
26630b57cec5SDimitry Andric     return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26640b57cec5SDimitry Andric   case Mips::LDMacro:
26650b57cec5SDimitry Andric   case Mips::SDMacro:
26660b57cec5SDimitry Andric     return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
26670b57cec5SDimitry Andric                                  Inst.getOpcode() == Mips::LDMacro)
26680b57cec5SDimitry Andric                ? MER_Fail
26690b57cec5SDimitry Andric                : MER_Success;
26700b57cec5SDimitry Andric   case Mips::SDC1_M1:
26710b57cec5SDimitry Andric     return expandStoreDM1Macro(Inst, IDLoc, Out, STI)
26720b57cec5SDimitry Andric                ? MER_Fail
26730b57cec5SDimitry Andric                : MER_Success;
26740b57cec5SDimitry Andric   case Mips::SEQMacro:
26750b57cec5SDimitry Andric     return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26760b57cec5SDimitry Andric   case Mips::SEQIMacro:
26770b57cec5SDimitry Andric     return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26785ffd83dbSDimitry Andric   case Mips::SNEMacro:
26795ffd83dbSDimitry Andric     return expandSne(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26805ffd83dbSDimitry Andric   case Mips::SNEIMacro:
26815ffd83dbSDimitry Andric     return expandSneI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26820b57cec5SDimitry Andric   case Mips::MFTC0:   case Mips::MTTC0:
26830b57cec5SDimitry Andric   case Mips::MFTGPR:  case Mips::MTTGPR:
26840b57cec5SDimitry Andric   case Mips::MFTLO:   case Mips::MTTLO:
26850b57cec5SDimitry Andric   case Mips::MFTHI:   case Mips::MTTHI:
26860b57cec5SDimitry Andric   case Mips::MFTACX:  case Mips::MTTACX:
26870b57cec5SDimitry Andric   case Mips::MFTDSP:  case Mips::MTTDSP:
26880b57cec5SDimitry Andric   case Mips::MFTC1:   case Mips::MTTC1:
26890b57cec5SDimitry Andric   case Mips::MFTHC1:  case Mips::MTTHC1:
26900b57cec5SDimitry Andric   case Mips::CFTC1:   case Mips::CTTC1:
26910b57cec5SDimitry Andric     return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26920b57cec5SDimitry Andric   case Mips::SaaAddr:
26930b57cec5SDimitry Andric   case Mips::SaadAddr:
26940b57cec5SDimitry Andric     return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26950b57cec5SDimitry Andric   }
26960b57cec5SDimitry Andric }
26970b57cec5SDimitry Andric 
expandJalWithRegs(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)26980b57cec5SDimitry Andric bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
26990b57cec5SDimitry Andric                                       MCStreamer &Out,
27000b57cec5SDimitry Andric                                       const MCSubtargetInfo *STI) {
27010b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric   // Create a JALR instruction which is going to replace the pseudo-JAL.
27040b57cec5SDimitry Andric   MCInst JalrInst;
27050b57cec5SDimitry Andric   JalrInst.setLoc(IDLoc);
27060b57cec5SDimitry Andric   const MCOperand FirstRegOp = Inst.getOperand(0);
27070b57cec5SDimitry Andric   const unsigned Opcode = Inst.getOpcode();
27080b57cec5SDimitry Andric 
27090b57cec5SDimitry Andric   if (Opcode == Mips::JalOneReg) {
27100b57cec5SDimitry Andric     // jal $rs => jalr $rs
27110b57cec5SDimitry Andric     if (IsCpRestoreSet && inMicroMipsMode()) {
27120b57cec5SDimitry Andric       JalrInst.setOpcode(Mips::JALRS16_MM);
27130b57cec5SDimitry Andric       JalrInst.addOperand(FirstRegOp);
27140b57cec5SDimitry Andric     } else if (inMicroMipsMode()) {
27150b57cec5SDimitry Andric       JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
27160b57cec5SDimitry Andric       JalrInst.addOperand(FirstRegOp);
27170b57cec5SDimitry Andric     } else {
27180b57cec5SDimitry Andric       JalrInst.setOpcode(Mips::JALR);
27190b57cec5SDimitry Andric       JalrInst.addOperand(MCOperand::createReg(Mips::RA));
27200b57cec5SDimitry Andric       JalrInst.addOperand(FirstRegOp);
27210b57cec5SDimitry Andric     }
27220b57cec5SDimitry Andric   } else if (Opcode == Mips::JalTwoReg) {
27230b57cec5SDimitry Andric     // jal $rd, $rs => jalr $rd, $rs
27240b57cec5SDimitry Andric     if (IsCpRestoreSet && inMicroMipsMode())
27250b57cec5SDimitry Andric       JalrInst.setOpcode(Mips::JALRS_MM);
27260b57cec5SDimitry Andric     else
27270b57cec5SDimitry Andric       JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
27280b57cec5SDimitry Andric     JalrInst.addOperand(FirstRegOp);
27290b57cec5SDimitry Andric     const MCOperand SecondRegOp = Inst.getOperand(1);
27300b57cec5SDimitry Andric     JalrInst.addOperand(SecondRegOp);
27310b57cec5SDimitry Andric   }
27325ffd83dbSDimitry Andric   Out.emitInstruction(JalrInst, *STI);
27330b57cec5SDimitry Andric 
27340b57cec5SDimitry Andric   // If .set reorder is active and branch instruction has a delay slot,
27350b57cec5SDimitry Andric   // emit a NOP after it.
2736bdd1243dSDimitry Andric   const MCInstrDesc &MCID = MII.get(JalrInst.getOpcode());
27370b57cec5SDimitry Andric   if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
27380b57cec5SDimitry Andric     TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
27390b57cec5SDimitry Andric                             STI);
27400b57cec5SDimitry Andric 
27410b57cec5SDimitry Andric   return false;
27420b57cec5SDimitry Andric }
27430b57cec5SDimitry Andric 
27440b57cec5SDimitry Andric /// Can the value be represented by a unsigned N-bit value and a shift left?
isShiftedUIntAtAnyPosition(uint64_t x)27450b57cec5SDimitry Andric template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
274606c3fb27SDimitry Andric   return x && isUInt<N>(x >> llvm::countr_zero(x));
27470b57cec5SDimitry Andric }
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric /// Load (or add) an immediate into a register.
27500b57cec5SDimitry Andric ///
27510b57cec5SDimitry Andric /// @param ImmValue     The immediate to load.
27520b57cec5SDimitry Andric /// @param DstReg       The register that will hold the immediate.
27530b57cec5SDimitry Andric /// @param SrcReg       A register to add to the immediate or Mips::NoRegister
27540b57cec5SDimitry Andric ///                     for a simple initialization.
27550b57cec5SDimitry Andric /// @param Is32BitImm   Is ImmValue 32-bit or 64-bit?
27560b57cec5SDimitry Andric /// @param IsAddress    True if the immediate represents an address. False if it
27570b57cec5SDimitry Andric ///                     is an integer.
27580b57cec5SDimitry Andric /// @param IDLoc        Location of the immediate in the source file.
loadImmediate(int64_t ImmValue,unsigned DstReg,unsigned SrcReg,bool Is32BitImm,bool IsAddress,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)27590b57cec5SDimitry Andric bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
27600b57cec5SDimitry Andric                                   unsigned SrcReg, bool Is32BitImm,
27610b57cec5SDimitry Andric                                   bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
27620b57cec5SDimitry Andric                                   const MCSubtargetInfo *STI) {
27630b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric   if (!Is32BitImm && !isGP64bit()) {
27660b57cec5SDimitry Andric     Error(IDLoc, "instruction requires a 64-bit architecture");
27670b57cec5SDimitry Andric     return true;
27680b57cec5SDimitry Andric   }
27690b57cec5SDimitry Andric 
27700b57cec5SDimitry Andric   if (Is32BitImm) {
27710b57cec5SDimitry Andric     if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
27720b57cec5SDimitry Andric       // Sign extend up to 64-bit so that the predicates match the hardware
27730b57cec5SDimitry Andric       // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
27740b57cec5SDimitry Andric       // true.
27750b57cec5SDimitry Andric       ImmValue = SignExtend64<32>(ImmValue);
27760b57cec5SDimitry Andric     } else {
27770b57cec5SDimitry Andric       Error(IDLoc, "instruction requires a 32-bit immediate");
27780b57cec5SDimitry Andric       return true;
27790b57cec5SDimitry Andric     }
27800b57cec5SDimitry Andric   }
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric   unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
27830b57cec5SDimitry Andric   unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
27840b57cec5SDimitry Andric 
27850b57cec5SDimitry Andric   bool UseSrcReg = false;
27860b57cec5SDimitry Andric   if (SrcReg != Mips::NoRegister)
27870b57cec5SDimitry Andric     UseSrcReg = true;
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric   unsigned TmpReg = DstReg;
27900b57cec5SDimitry Andric   if (UseSrcReg &&
27910b57cec5SDimitry Andric       getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
27920b57cec5SDimitry Andric     // At this point we need AT to perform the expansions and we exit if it is
27930b57cec5SDimitry Andric     // not available.
27940b57cec5SDimitry Andric     unsigned ATReg = getATReg(IDLoc);
27950b57cec5SDimitry Andric     if (!ATReg)
27960b57cec5SDimitry Andric       return true;
27970b57cec5SDimitry Andric     TmpReg = ATReg;
27980b57cec5SDimitry Andric   }
27990b57cec5SDimitry Andric 
28000b57cec5SDimitry Andric   if (isInt<16>(ImmValue)) {
28010b57cec5SDimitry Andric     if (!UseSrcReg)
28020b57cec5SDimitry Andric       SrcReg = ZeroReg;
28030b57cec5SDimitry Andric 
28040b57cec5SDimitry Andric     // This doesn't quite follow the usual ABI expectations for N32 but matches
28050b57cec5SDimitry Andric     // traditional assembler behaviour. N32 would normally use addiu for both
28060b57cec5SDimitry Andric     // integers and addresses.
28070b57cec5SDimitry Andric     if (IsAddress && !Is32BitImm) {
28080b57cec5SDimitry Andric       TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
28090b57cec5SDimitry Andric       return false;
28100b57cec5SDimitry Andric     }
28110b57cec5SDimitry Andric 
28120b57cec5SDimitry Andric     TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
28130b57cec5SDimitry Andric     return false;
28140b57cec5SDimitry Andric   }
28150b57cec5SDimitry Andric 
28160b57cec5SDimitry Andric   if (isUInt<16>(ImmValue)) {
28170b57cec5SDimitry Andric     unsigned TmpReg = DstReg;
28180b57cec5SDimitry Andric     if (SrcReg == DstReg) {
28190b57cec5SDimitry Andric       TmpReg = getATReg(IDLoc);
28200b57cec5SDimitry Andric       if (!TmpReg)
28210b57cec5SDimitry Andric         return true;
28220b57cec5SDimitry Andric     }
28230b57cec5SDimitry Andric 
28240b57cec5SDimitry Andric     TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
28250b57cec5SDimitry Andric     if (UseSrcReg)
28260b57cec5SDimitry Andric       TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
28270b57cec5SDimitry Andric     return false;
28280b57cec5SDimitry Andric   }
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric   if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
28310b57cec5SDimitry Andric     warnIfNoMacro(IDLoc);
28320b57cec5SDimitry Andric 
28330b57cec5SDimitry Andric     uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
28340b57cec5SDimitry Andric     uint16_t Bits15To0 = ImmValue & 0xffff;
28350b57cec5SDimitry Andric     if (!Is32BitImm && !isInt<32>(ImmValue)) {
28360b57cec5SDimitry Andric       // Traditional behaviour seems to special case this particular value. It's
28370b57cec5SDimitry Andric       // not clear why other masks are handled differently.
28380b57cec5SDimitry Andric       if (ImmValue == 0xffffffff) {
28390b57cec5SDimitry Andric         TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
28400b57cec5SDimitry Andric         TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
28410b57cec5SDimitry Andric         if (UseSrcReg)
28420b57cec5SDimitry Andric           TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28430b57cec5SDimitry Andric         return false;
28440b57cec5SDimitry Andric       }
28450b57cec5SDimitry Andric 
28460b57cec5SDimitry Andric       // Expand to an ORi instead of a LUi to avoid sign-extending into the
28470b57cec5SDimitry Andric       // upper 32 bits.
28480b57cec5SDimitry Andric       TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
28490b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
28500b57cec5SDimitry Andric       if (Bits15To0)
28510b57cec5SDimitry Andric         TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
28520b57cec5SDimitry Andric       if (UseSrcReg)
28530b57cec5SDimitry Andric         TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28540b57cec5SDimitry Andric       return false;
28550b57cec5SDimitry Andric     }
28560b57cec5SDimitry Andric 
28570b57cec5SDimitry Andric     TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
28580b57cec5SDimitry Andric     if (Bits15To0)
28590b57cec5SDimitry Andric       TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
28600b57cec5SDimitry Andric     if (UseSrcReg)
28610b57cec5SDimitry Andric       TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28620b57cec5SDimitry Andric     return false;
28630b57cec5SDimitry Andric   }
28640b57cec5SDimitry Andric 
28650b57cec5SDimitry Andric   if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
28660b57cec5SDimitry Andric     if (Is32BitImm) {
28670b57cec5SDimitry Andric       Error(IDLoc, "instruction requires a 32-bit immediate");
28680b57cec5SDimitry Andric       return true;
28690b57cec5SDimitry Andric     }
28700b57cec5SDimitry Andric 
287106c3fb27SDimitry Andric     // We've processed ImmValue satisfying isUInt<16> above, so ImmValue must be
287206c3fb27SDimitry Andric     // at least 17-bit wide here.
287306c3fb27SDimitry Andric     unsigned BitWidth = llvm::bit_width((uint64_t)ImmValue);
287406c3fb27SDimitry Andric     assert(BitWidth >= 17 && "ImmValue must be at least 17-bit wide");
287506c3fb27SDimitry Andric 
28760b57cec5SDimitry Andric     // Traditionally, these immediates are shifted as little as possible and as
28770b57cec5SDimitry Andric     // such we align the most significant bit to bit 15 of our temporary.
287806c3fb27SDimitry Andric     unsigned ShiftAmount = BitWidth - 16;
28790b57cec5SDimitry Andric     uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
28800b57cec5SDimitry Andric     TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
28810b57cec5SDimitry Andric     TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
28820b57cec5SDimitry Andric 
28830b57cec5SDimitry Andric     if (UseSrcReg)
28840b57cec5SDimitry Andric       TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28850b57cec5SDimitry Andric 
28860b57cec5SDimitry Andric     return false;
28870b57cec5SDimitry Andric   }
28880b57cec5SDimitry Andric 
28890b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
28900b57cec5SDimitry Andric 
28910b57cec5SDimitry Andric   // The remaining case is packed with a sequence of dsll and ori with zeros
28920b57cec5SDimitry Andric   // being omitted and any neighbouring dsll's being coalesced.
28930b57cec5SDimitry Andric   // The highest 32-bit's are equivalent to a 32-bit immediate load.
28940b57cec5SDimitry Andric 
28950b57cec5SDimitry Andric   // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
28960b57cec5SDimitry Andric   if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
28970b57cec5SDimitry Andric                     IDLoc, Out, STI))
28980b57cec5SDimitry Andric     return false;
28990b57cec5SDimitry Andric 
29000b57cec5SDimitry Andric   // Shift and accumulate into the register. If a 16-bit chunk is zero, then
29010b57cec5SDimitry Andric   // skip it and defer the shift to the next chunk.
29020b57cec5SDimitry Andric   unsigned ShiftCarriedForwards = 16;
29030b57cec5SDimitry Andric   for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
29040b57cec5SDimitry Andric     uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric     if (ImmChunk != 0) {
29070b57cec5SDimitry Andric       TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
29080b57cec5SDimitry Andric       TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
29090b57cec5SDimitry Andric       ShiftCarriedForwards = 0;
29100b57cec5SDimitry Andric     }
29110b57cec5SDimitry Andric 
29120b57cec5SDimitry Andric     ShiftCarriedForwards += 16;
29130b57cec5SDimitry Andric   }
29140b57cec5SDimitry Andric   ShiftCarriedForwards -= 16;
29150b57cec5SDimitry Andric 
29160b57cec5SDimitry Andric   // Finish any remaining shifts left by trailing zeros.
29170b57cec5SDimitry Andric   if (ShiftCarriedForwards)
29180b57cec5SDimitry Andric     TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
29190b57cec5SDimitry Andric 
29200b57cec5SDimitry Andric   if (UseSrcReg)
29210b57cec5SDimitry Andric     TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric   return false;
29240b57cec5SDimitry Andric }
29250b57cec5SDimitry Andric 
expandLoadImm(MCInst & Inst,bool Is32BitImm,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)29260b57cec5SDimitry Andric bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
29270b57cec5SDimitry Andric                                   MCStreamer &Out, const MCSubtargetInfo *STI) {
29280b57cec5SDimitry Andric   const MCOperand &ImmOp = Inst.getOperand(1);
29290b57cec5SDimitry Andric   assert(ImmOp.isImm() && "expected immediate operand kind");
29300b57cec5SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(0);
29310b57cec5SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
29320b57cec5SDimitry Andric 
29330b57cec5SDimitry Andric   if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
29340b57cec5SDimitry Andric                     Is32BitImm, false, IDLoc, Out, STI))
29350b57cec5SDimitry Andric     return true;
29360b57cec5SDimitry Andric 
29370b57cec5SDimitry Andric   return false;
29380b57cec5SDimitry Andric }
29390b57cec5SDimitry Andric 
expandLoadAddress(unsigned DstReg,unsigned BaseReg,const MCOperand & Offset,bool Is32BitAddress,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)29400b57cec5SDimitry Andric bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
29410b57cec5SDimitry Andric                                       const MCOperand &Offset,
29420b57cec5SDimitry Andric                                       bool Is32BitAddress, SMLoc IDLoc,
29430b57cec5SDimitry Andric                                       MCStreamer &Out,
29440b57cec5SDimitry Andric                                       const MCSubtargetInfo *STI) {
29450b57cec5SDimitry Andric   // la can't produce a usable address when addresses are 64-bit.
29460b57cec5SDimitry Andric   if (Is32BitAddress && ABI.ArePtrs64bit()) {
2947480093f4SDimitry Andric     Warning(IDLoc, "la used to load 64-bit address");
29480b57cec5SDimitry Andric     // Continue as if we had 'dla' instead.
29490b57cec5SDimitry Andric     Is32BitAddress = false;
29500b57cec5SDimitry Andric   }
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   // dla requires 64-bit addresses.
29530b57cec5SDimitry Andric   if (!Is32BitAddress && !hasMips3()) {
29540b57cec5SDimitry Andric     Error(IDLoc, "instruction requires a 64-bit architecture");
29550b57cec5SDimitry Andric     return true;
29560b57cec5SDimitry Andric   }
29570b57cec5SDimitry Andric 
29580b57cec5SDimitry Andric   if (!Offset.isImm())
29590b57cec5SDimitry Andric     return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
29600b57cec5SDimitry Andric                                    Is32BitAddress, IDLoc, Out, STI);
29610b57cec5SDimitry Andric 
29620b57cec5SDimitry Andric   if (!ABI.ArePtrs64bit()) {
29630b57cec5SDimitry Andric     // Continue as if we had 'la' whether we had 'la' or 'dla'.
29640b57cec5SDimitry Andric     Is32BitAddress = true;
29650b57cec5SDimitry Andric   }
29660b57cec5SDimitry Andric 
29670b57cec5SDimitry Andric   return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
29680b57cec5SDimitry Andric                        IDLoc, Out, STI);
29690b57cec5SDimitry Andric }
29700b57cec5SDimitry Andric 
loadAndAddSymbolAddress(const MCExpr * SymExpr,unsigned DstReg,unsigned SrcReg,bool Is32BitSym,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)29710b57cec5SDimitry Andric bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
29720b57cec5SDimitry Andric                                             unsigned DstReg, unsigned SrcReg,
29730b57cec5SDimitry Andric                                             bool Is32BitSym, SMLoc IDLoc,
29740b57cec5SDimitry Andric                                             MCStreamer &Out,
29750b57cec5SDimitry Andric                                             const MCSubtargetInfo *STI) {
29760b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
29778bcb0991SDimitry Andric   bool UseSrcReg = SrcReg != Mips::NoRegister && SrcReg != Mips::ZERO &&
29788bcb0991SDimitry Andric                    SrcReg != Mips::ZERO_64;
29790b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
29800b57cec5SDimitry Andric 
29818bcb0991SDimitry Andric   if (inPicMode()) {
29820b57cec5SDimitry Andric     MCValue Res;
29830b57cec5SDimitry Andric     if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
29840b57cec5SDimitry Andric       Error(IDLoc, "expected relocatable expression");
29850b57cec5SDimitry Andric       return true;
29860b57cec5SDimitry Andric     }
29870b57cec5SDimitry Andric     if (Res.getSymB() != nullptr) {
29880b57cec5SDimitry Andric       Error(IDLoc, "expected relocatable expression with only one symbol");
29890b57cec5SDimitry Andric       return true;
29900b57cec5SDimitry Andric     }
29910b57cec5SDimitry Andric 
29928bcb0991SDimitry Andric     bool IsPtr64 = ABI.ArePtrs64bit();
29938bcb0991SDimitry Andric     bool IsLocalSym =
29948bcb0991SDimitry Andric         Res.getSymA()->getSymbol().isInSection() ||
29950b57cec5SDimitry Andric         Res.getSymA()->getSymbol().isTemporary() ||
29960b57cec5SDimitry Andric         (Res.getSymA()->getSymbol().isELF() &&
29970b57cec5SDimitry Andric          cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
29988bcb0991SDimitry Andric              ELF::STB_LOCAL);
299974626c16SDimitry Andric     // For O32, "$"-prefixed symbols are recognized as temporary while
300074626c16SDimitry Andric     // .L-prefixed symbols are not (PrivateGlobalPrefix is "$"). Recognize ".L"
300174626c16SDimitry Andric     // manually.
300274626c16SDimitry Andric     if (ABI.IsO32() && Res.getSymA()->getSymbol().getName().starts_with(".L"))
300374626c16SDimitry Andric       IsLocalSym = true;
300406c3fb27SDimitry Andric     bool UseXGOT = STI->hasFeature(Mips::FeatureXGOT) && !IsLocalSym;
30058bcb0991SDimitry Andric 
30068bcb0991SDimitry Andric     // The case where the result register is $25 is somewhat special. If the
30078bcb0991SDimitry Andric     // symbol in the final relocation is external and not modified with a
30088bcb0991SDimitry Andric     // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
30098bcb0991SDimitry Andric     // or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
30108bcb0991SDimitry Andric     if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
30118bcb0991SDimitry Andric         Res.getConstant() == 0 && !IsLocalSym) {
30128bcb0991SDimitry Andric       if (UseXGOT) {
30138bcb0991SDimitry Andric         const MCExpr *CallHiExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16,
30148bcb0991SDimitry Andric                                                       SymExpr, getContext());
30158bcb0991SDimitry Andric         const MCExpr *CallLoExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16,
30168bcb0991SDimitry Andric                                                       SymExpr, getContext());
30178bcb0991SDimitry Andric         TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(CallHiExpr), IDLoc,
30188bcb0991SDimitry Andric                     STI);
30198bcb0991SDimitry Andric         TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, DstReg, GPReg,
30208bcb0991SDimitry Andric                      IDLoc, STI);
30218bcb0991SDimitry Andric         TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, DstReg,
30228bcb0991SDimitry Andric                      MCOperand::createExpr(CallLoExpr), IDLoc, STI);
30238bcb0991SDimitry Andric       } else {
30240b57cec5SDimitry Andric         const MCExpr *CallExpr =
30250b57cec5SDimitry Andric             MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
30268bcb0991SDimitry Andric         TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
30278bcb0991SDimitry Andric                      MCOperand::createExpr(CallExpr), IDLoc, STI);
30280b57cec5SDimitry Andric       }
30298bcb0991SDimitry Andric       return false;
30300b57cec5SDimitry Andric     }
30310b57cec5SDimitry Andric 
30320b57cec5SDimitry Andric     unsigned TmpReg = DstReg;
30330b57cec5SDimitry Andric     if (UseSrcReg &&
30340b57cec5SDimitry Andric         getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
30350b57cec5SDimitry Andric                                                                SrcReg)) {
30360b57cec5SDimitry Andric       // If $rs is the same as $rd, we need to use AT.
30370b57cec5SDimitry Andric       // If it is not available we exit.
30380b57cec5SDimitry Andric       unsigned ATReg = getATReg(IDLoc);
30390b57cec5SDimitry Andric       if (!ATReg)
30400b57cec5SDimitry Andric         return true;
30410b57cec5SDimitry Andric       TmpReg = ATReg;
30420b57cec5SDimitry Andric     }
30430b57cec5SDimitry Andric 
3044480093f4SDimitry Andric     // FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses
3045480093f4SDimitry Andric     // loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations.
3046480093f4SDimitry Andric     // FIXME: Implement XGOT for microMIPS.
30478bcb0991SDimitry Andric     if (UseXGOT) {
30488bcb0991SDimitry Andric       // Loading address from XGOT
30498bcb0991SDimitry Andric       //   External GOT: lui $tmp, %got_hi(symbol)($gp)
30508bcb0991SDimitry Andric       //                 addu $tmp, $tmp, $gp
30518bcb0991SDimitry Andric       //                 lw $tmp, %got_lo(symbol)($tmp)
30528bcb0991SDimitry Andric       //                >addiu $tmp, $tmp, offset
30538bcb0991SDimitry Andric       //                >addiu $rd, $tmp, $rs
30548bcb0991SDimitry Andric       // The addiu's marked with a '>' may be omitted if they are redundant. If
30558bcb0991SDimitry Andric       // this happens then the last instruction must use $rd as the result
30568bcb0991SDimitry Andric       // register.
30578bcb0991SDimitry Andric       const MCExpr *CallHiExpr =
30588bcb0991SDimitry Andric           MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, SymExpr, getContext());
30598bcb0991SDimitry Andric       const MCExpr *CallLoExpr = MipsMCExpr::create(
30608bcb0991SDimitry Andric           MipsMCExpr::MEK_GOT_LO16, Res.getSymA(), getContext());
30610b57cec5SDimitry Andric 
30628bcb0991SDimitry Andric       TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(CallHiExpr), IDLoc,
30638bcb0991SDimitry Andric                   STI);
30648bcb0991SDimitry Andric       TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, GPReg,
30658bcb0991SDimitry Andric                    IDLoc, STI);
30668bcb0991SDimitry Andric       TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, TmpReg,
30678bcb0991SDimitry Andric                    MCOperand::createExpr(CallLoExpr), IDLoc, STI);
30688bcb0991SDimitry Andric 
30698bcb0991SDimitry Andric       if (Res.getConstant() != 0)
30708bcb0991SDimitry Andric         TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
30718bcb0991SDimitry Andric                      MCOperand::createExpr(MCConstantExpr::create(
30728bcb0991SDimitry Andric                          Res.getConstant(), getContext())),
30730b57cec5SDimitry Andric                      IDLoc, STI);
30740b57cec5SDimitry Andric 
30750b57cec5SDimitry Andric       if (UseSrcReg)
30768bcb0991SDimitry Andric         TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
30770b57cec5SDimitry Andric                      IDLoc, STI);
30780b57cec5SDimitry Andric       return false;
30790b57cec5SDimitry Andric     }
30800b57cec5SDimitry Andric 
30818bcb0991SDimitry Andric     const MipsMCExpr *GotExpr = nullptr;
30828bcb0991SDimitry Andric     const MCExpr *LoExpr = nullptr;
3083480093f4SDimitry Andric     if (ABI.IsN32() || ABI.IsN64()) {
30840b57cec5SDimitry Andric       // The remaining cases are:
30850b57cec5SDimitry Andric       //   Small offset: ld $tmp, %got_disp(symbol)($gp)
30860b57cec5SDimitry Andric       //                >daddiu $tmp, $tmp, offset
30870b57cec5SDimitry Andric       //                >daddu $rd, $tmp, $rs
30880b57cec5SDimitry Andric       // The daddiu's marked with a '>' may be omitted if they are redundant. If
30890b57cec5SDimitry Andric       // this happens then the last instruction must use $rd as the result
30900b57cec5SDimitry Andric       // register.
30918bcb0991SDimitry Andric       GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),
30920b57cec5SDimitry Andric                                    getContext());
30930b57cec5SDimitry Andric       if (Res.getConstant() != 0) {
30940b57cec5SDimitry Andric         // Symbols fully resolve with just the %got_disp(symbol) but we
30950b57cec5SDimitry Andric         // must still account for any offset to the symbol for
30960b57cec5SDimitry Andric         // expressions like symbol+8.
30970b57cec5SDimitry Andric         LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
30980b57cec5SDimitry Andric 
30990b57cec5SDimitry Andric         // FIXME: Offsets greater than 16 bits are not yet implemented.
31000b57cec5SDimitry Andric         // FIXME: The correct range is a 32-bit sign-extended number.
31010b57cec5SDimitry Andric         if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
31020b57cec5SDimitry Andric           Error(IDLoc, "macro instruction uses large offset, which is not "
31030b57cec5SDimitry Andric                        "currently supported");
31040b57cec5SDimitry Andric           return true;
31050b57cec5SDimitry Andric         }
31060b57cec5SDimitry Andric       }
31078bcb0991SDimitry Andric     } else {
31088bcb0991SDimitry Andric       // The remaining cases are:
31098bcb0991SDimitry Andric       //   External GOT: lw $tmp, %got(symbol)($gp)
31108bcb0991SDimitry Andric       //                >addiu $tmp, $tmp, offset
31118bcb0991SDimitry Andric       //                >addiu $rd, $tmp, $rs
31128bcb0991SDimitry Andric       //   Local GOT:    lw $tmp, %got(symbol+offset)($gp)
31138bcb0991SDimitry Andric       //                 addiu $tmp, $tmp, %lo(symbol+offset)($gp)
31148bcb0991SDimitry Andric       //                >addiu $rd, $tmp, $rs
31158bcb0991SDimitry Andric       // The addiu's marked with a '>' may be omitted if they are redundant. If
31168bcb0991SDimitry Andric       // this happens then the last instruction must use $rd as the result
31178bcb0991SDimitry Andric       // register.
31188bcb0991SDimitry Andric       if (IsLocalSym) {
31198bcb0991SDimitry Andric         GotExpr =
31208bcb0991SDimitry Andric             MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
31218bcb0991SDimitry Andric         LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
31228bcb0991SDimitry Andric       } else {
31238bcb0991SDimitry Andric         // External symbols fully resolve the symbol with just the %got(symbol)
31248bcb0991SDimitry Andric         // but we must still account for any offset to the symbol for
31258bcb0991SDimitry Andric         // expressions like symbol+8.
31268bcb0991SDimitry Andric         GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),
31278bcb0991SDimitry Andric                                      getContext());
31288bcb0991SDimitry Andric         if (Res.getConstant() != 0)
31298bcb0991SDimitry Andric           LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
31308bcb0991SDimitry Andric       }
31310b57cec5SDimitry Andric     }
31320b57cec5SDimitry Andric 
31338bcb0991SDimitry Andric     TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
31348bcb0991SDimitry Andric                  MCOperand::createExpr(GotExpr), IDLoc, STI);
31350b57cec5SDimitry Andric 
31360b57cec5SDimitry Andric     if (LoExpr)
31378bcb0991SDimitry Andric       TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
31388bcb0991SDimitry Andric                    MCOperand::createExpr(LoExpr), IDLoc, STI);
31390b57cec5SDimitry Andric 
31400b57cec5SDimitry Andric     if (UseSrcReg)
31418bcb0991SDimitry Andric       TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
31428bcb0991SDimitry Andric                    IDLoc, STI);
31430b57cec5SDimitry Andric 
31440b57cec5SDimitry Andric     return false;
31450b57cec5SDimitry Andric   }
31460b57cec5SDimitry Andric 
31470b57cec5SDimitry Andric   const MipsMCExpr *HiExpr =
31480b57cec5SDimitry Andric       MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
31490b57cec5SDimitry Andric   const MipsMCExpr *LoExpr =
31500b57cec5SDimitry Andric       MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
31510b57cec5SDimitry Andric 
31520b57cec5SDimitry Andric   // This is the 64-bit symbol address expansion.
31530b57cec5SDimitry Andric   if (ABI.ArePtrs64bit() && isGP64bit()) {
31540b57cec5SDimitry Andric     // We need AT for the 64-bit expansion in the cases where the optional
31550b57cec5SDimitry Andric     // source register is the destination register and for the superscalar
31560b57cec5SDimitry Andric     // scheduled form.
31570b57cec5SDimitry Andric     //
31580b57cec5SDimitry Andric     // If it is not available we exit if the destination is the same as the
31590b57cec5SDimitry Andric     // source register.
31600b57cec5SDimitry Andric 
31610b57cec5SDimitry Andric     const MipsMCExpr *HighestExpr =
31620b57cec5SDimitry Andric         MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
31630b57cec5SDimitry Andric     const MipsMCExpr *HigherExpr =
31640b57cec5SDimitry Andric         MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
31650b57cec5SDimitry Andric 
31660b57cec5SDimitry Andric     bool RdRegIsRsReg =
316706c3fb27SDimitry Andric         UseSrcReg &&
31680b57cec5SDimitry Andric         getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
31690b57cec5SDimitry Andric 
31700b57cec5SDimitry Andric     if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
31710b57cec5SDimitry Andric       unsigned ATReg = getATReg(IDLoc);
31720b57cec5SDimitry Andric 
31730b57cec5SDimitry Andric       // If $rs is the same as $rd:
31740b57cec5SDimitry Andric       // (d)la $rd, sym($rd) => lui    $at, %highest(sym)
31750b57cec5SDimitry Andric       //                        daddiu $at, $at, %higher(sym)
31760b57cec5SDimitry Andric       //                        dsll   $at, $at, 16
31770b57cec5SDimitry Andric       //                        daddiu $at, $at, %hi(sym)
31780b57cec5SDimitry Andric       //                        dsll   $at, $at, 16
31790b57cec5SDimitry Andric       //                        daddiu $at, $at, %lo(sym)
31800b57cec5SDimitry Andric       //                        daddu  $rd, $at, $rd
31810b57cec5SDimitry Andric       TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
31820b57cec5SDimitry Andric                   STI);
31830b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
31840b57cec5SDimitry Andric                    MCOperand::createExpr(HigherExpr), IDLoc, STI);
31850b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
31860b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
31870b57cec5SDimitry Andric                    IDLoc, STI);
31880b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
31890b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
31900b57cec5SDimitry Andric                    IDLoc, STI);
31910b57cec5SDimitry Andric       TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
31920b57cec5SDimitry Andric 
31930b57cec5SDimitry Andric       return false;
31940b57cec5SDimitry Andric     } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {
31950b57cec5SDimitry Andric       unsigned ATReg = getATReg(IDLoc);
31960b57cec5SDimitry Andric 
31970b57cec5SDimitry Andric       // If the $rs is different from $rd or if $rs isn't specified and we
31980b57cec5SDimitry Andric       // have $at available:
31990b57cec5SDimitry Andric       // (d)la $rd, sym/sym($rs) => lui    $rd, %highest(sym)
32000b57cec5SDimitry Andric       //                            lui    $at, %hi(sym)
32010b57cec5SDimitry Andric       //                            daddiu $rd, $rd, %higher(sym)
32020b57cec5SDimitry Andric       //                            daddiu $at, $at, %lo(sym)
32030b57cec5SDimitry Andric       //                            dsll32 $rd, $rd, 0
32040b57cec5SDimitry Andric       //                            daddu  $rd, $rd, $at
32050b57cec5SDimitry Andric       //                            (daddu  $rd, $rd, $rs)
32060b57cec5SDimitry Andric       //
32070b57cec5SDimitry Andric       // Which is preferred for superscalar issue.
32080b57cec5SDimitry Andric       TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
32090b57cec5SDimitry Andric                   STI);
32100b57cec5SDimitry Andric       TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
32110b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32120b57cec5SDimitry Andric                    MCOperand::createExpr(HigherExpr), IDLoc, STI);
32130b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
32140b57cec5SDimitry Andric                    IDLoc, STI);
32150b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
32160b57cec5SDimitry Andric       TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
32170b57cec5SDimitry Andric       if (UseSrcReg)
32180b57cec5SDimitry Andric         TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric       return false;
32210b57cec5SDimitry Andric     } else if ((!canUseATReg() && !RdRegIsRsReg) ||
32220b57cec5SDimitry Andric                (canUseATReg() && DstReg == getATReg(IDLoc))) {
32230b57cec5SDimitry Andric       // Otherwise, synthesize the address in the destination register
32240b57cec5SDimitry Andric       // serially:
32250b57cec5SDimitry Andric       // (d)la $rd, sym/sym($rs) => lui    $rd, %highest(sym)
32260b57cec5SDimitry Andric       //                            daddiu $rd, $rd, %higher(sym)
32270b57cec5SDimitry Andric       //                            dsll   $rd, $rd, 16
32280b57cec5SDimitry Andric       //                            daddiu $rd, $rd, %hi(sym)
32290b57cec5SDimitry Andric       //                            dsll   $rd, $rd, 16
32300b57cec5SDimitry Andric       //                            daddiu $rd, $rd, %lo(sym)
32310b57cec5SDimitry Andric       TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
32320b57cec5SDimitry Andric                   STI);
32330b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32340b57cec5SDimitry Andric                    MCOperand::createExpr(HigherExpr), IDLoc, STI);
32350b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
32360b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32370b57cec5SDimitry Andric                    MCOperand::createExpr(HiExpr), IDLoc, STI);
32380b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
32390b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32400b57cec5SDimitry Andric                    MCOperand::createExpr(LoExpr), IDLoc, STI);
32410b57cec5SDimitry Andric       if (UseSrcReg)
32420b57cec5SDimitry Andric         TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
32430b57cec5SDimitry Andric 
32440b57cec5SDimitry Andric       return false;
32450b57cec5SDimitry Andric     } else {
32460b57cec5SDimitry Andric       // We have a case where SrcReg == DstReg and we don't have $at
32470b57cec5SDimitry Andric       // available. We can't expand this case, so error out appropriately.
32480b57cec5SDimitry Andric       assert(SrcReg == DstReg && !canUseATReg() &&
32490b57cec5SDimitry Andric              "Could have expanded dla but didn't?");
32500b57cec5SDimitry Andric       reportParseError(IDLoc,
32510b57cec5SDimitry Andric                      "pseudo-instruction requires $at, which is not available");
32520b57cec5SDimitry Andric       return true;
32530b57cec5SDimitry Andric     }
32540b57cec5SDimitry Andric   }
32550b57cec5SDimitry Andric 
32560b57cec5SDimitry Andric   // And now, the 32-bit symbol address expansion:
32570b57cec5SDimitry Andric   // If $rs is the same as $rd:
32580b57cec5SDimitry Andric   // (d)la $rd, sym($rd)     => lui   $at, %hi(sym)
32590b57cec5SDimitry Andric   //                            ori   $at, $at, %lo(sym)
32600b57cec5SDimitry Andric   //                            addu  $rd, $at, $rd
32610b57cec5SDimitry Andric   // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
32620b57cec5SDimitry Andric   // (d)la $rd, sym/sym($rs) => lui   $rd, %hi(sym)
32630b57cec5SDimitry Andric   //                            ori   $rd, $rd, %lo(sym)
32640b57cec5SDimitry Andric   //                            (addu $rd, $rd, $rs)
32650b57cec5SDimitry Andric   unsigned TmpReg = DstReg;
32660b57cec5SDimitry Andric   if (UseSrcReg &&
32670b57cec5SDimitry Andric       getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
32680b57cec5SDimitry Andric     // If $rs is the same as $rd, we need to use AT.
32690b57cec5SDimitry Andric     // If it is not available we exit.
32700b57cec5SDimitry Andric     unsigned ATReg = getATReg(IDLoc);
32710b57cec5SDimitry Andric     if (!ATReg)
32720b57cec5SDimitry Andric       return true;
32730b57cec5SDimitry Andric     TmpReg = ATReg;
32740b57cec5SDimitry Andric   }
32750b57cec5SDimitry Andric 
32760b57cec5SDimitry Andric   TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
32770b57cec5SDimitry Andric   TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
32780b57cec5SDimitry Andric                IDLoc, STI);
32790b57cec5SDimitry Andric 
32800b57cec5SDimitry Andric   if (UseSrcReg)
32810b57cec5SDimitry Andric     TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
32820b57cec5SDimitry Andric   else
32830b57cec5SDimitry Andric     assert(
32840b57cec5SDimitry Andric         getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
32850b57cec5SDimitry Andric 
32860b57cec5SDimitry Andric   return false;
32870b57cec5SDimitry Andric }
32880b57cec5SDimitry Andric 
32890b57cec5SDimitry Andric // Each double-precision register DO-D15 overlaps with two of the single
32900b57cec5SDimitry Andric // precision registers F0-F31. As an example, all of the following hold true:
32910b57cec5SDimitry Andric // D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
nextReg(unsigned Reg)32920b57cec5SDimitry Andric static unsigned nextReg(unsigned Reg) {
32930b57cec5SDimitry Andric   if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
32940b57cec5SDimitry Andric     return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
32950b57cec5SDimitry Andric   switch (Reg) {
32960b57cec5SDimitry Andric   default: llvm_unreachable("Unknown register in assembly macro expansion!");
32970b57cec5SDimitry Andric   case Mips::ZERO: return Mips::AT;
32980b57cec5SDimitry Andric   case Mips::AT:   return Mips::V0;
32990b57cec5SDimitry Andric   case Mips::V0:   return Mips::V1;
33000b57cec5SDimitry Andric   case Mips::V1:   return Mips::A0;
33010b57cec5SDimitry Andric   case Mips::A0:   return Mips::A1;
33020b57cec5SDimitry Andric   case Mips::A1:   return Mips::A2;
33030b57cec5SDimitry Andric   case Mips::A2:   return Mips::A3;
33040b57cec5SDimitry Andric   case Mips::A3:   return Mips::T0;
33050b57cec5SDimitry Andric   case Mips::T0:   return Mips::T1;
33060b57cec5SDimitry Andric   case Mips::T1:   return Mips::T2;
33070b57cec5SDimitry Andric   case Mips::T2:   return Mips::T3;
33080b57cec5SDimitry Andric   case Mips::T3:   return Mips::T4;
33090b57cec5SDimitry Andric   case Mips::T4:   return Mips::T5;
33100b57cec5SDimitry Andric   case Mips::T5:   return Mips::T6;
33110b57cec5SDimitry Andric   case Mips::T6:   return Mips::T7;
33120b57cec5SDimitry Andric   case Mips::T7:   return Mips::S0;
33130b57cec5SDimitry Andric   case Mips::S0:   return Mips::S1;
33140b57cec5SDimitry Andric   case Mips::S1:   return Mips::S2;
33150b57cec5SDimitry Andric   case Mips::S2:   return Mips::S3;
33160b57cec5SDimitry Andric   case Mips::S3:   return Mips::S4;
33170b57cec5SDimitry Andric   case Mips::S4:   return Mips::S5;
33180b57cec5SDimitry Andric   case Mips::S5:   return Mips::S6;
33190b57cec5SDimitry Andric   case Mips::S6:   return Mips::S7;
33200b57cec5SDimitry Andric   case Mips::S7:   return Mips::T8;
33210b57cec5SDimitry Andric   case Mips::T8:   return Mips::T9;
33220b57cec5SDimitry Andric   case Mips::T9:   return Mips::K0;
33230b57cec5SDimitry Andric   case Mips::K0:   return Mips::K1;
33240b57cec5SDimitry Andric   case Mips::K1:   return Mips::GP;
33250b57cec5SDimitry Andric   case Mips::GP:   return Mips::SP;
33260b57cec5SDimitry Andric   case Mips::SP:   return Mips::FP;
33270b57cec5SDimitry Andric   case Mips::FP:   return Mips::RA;
33280b57cec5SDimitry Andric   case Mips::RA:   return Mips::ZERO;
33290b57cec5SDimitry Andric   case Mips::D0:   return Mips::F1;
33300b57cec5SDimitry Andric   case Mips::D1:   return Mips::F3;
33310b57cec5SDimitry Andric   case Mips::D2:   return Mips::F5;
33320b57cec5SDimitry Andric   case Mips::D3:   return Mips::F7;
33330b57cec5SDimitry Andric   case Mips::D4:   return Mips::F9;
33340b57cec5SDimitry Andric   case Mips::D5:   return Mips::F11;
33350b57cec5SDimitry Andric   case Mips::D6:   return Mips::F13;
33360b57cec5SDimitry Andric   case Mips::D7:   return Mips::F15;
33370b57cec5SDimitry Andric   case Mips::D8:   return Mips::F17;
33380b57cec5SDimitry Andric   case Mips::D9:   return Mips::F19;
33390b57cec5SDimitry Andric   case Mips::D10:   return Mips::F21;
33400b57cec5SDimitry Andric   case Mips::D11:   return Mips::F23;
33410b57cec5SDimitry Andric   case Mips::D12:   return Mips::F25;
33420b57cec5SDimitry Andric   case Mips::D13:   return Mips::F27;
33430b57cec5SDimitry Andric   case Mips::D14:   return Mips::F29;
33440b57cec5SDimitry Andric   case Mips::D15:   return Mips::F31;
33450b57cec5SDimitry Andric   }
33460b57cec5SDimitry Andric }
33470b57cec5SDimitry Andric 
33480b57cec5SDimitry Andric // FIXME: This method is too general. In principle we should compute the number
33490b57cec5SDimitry Andric // of instructions required to synthesize the immediate inline compared to
33500b57cec5SDimitry Andric // synthesizing the address inline and relying on non .text sections.
33510b57cec5SDimitry Andric // For static O32 and N32 this may yield a small benefit, for static N64 this is
33520b57cec5SDimitry Andric // likely to yield a much larger benefit as we have to synthesize a 64bit
33530b57cec5SDimitry Andric // address to load a 64 bit value.
emitPartialAddress(MipsTargetStreamer & TOut,SMLoc IDLoc,MCSymbol * Sym)33540b57cec5SDimitry Andric bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
33550b57cec5SDimitry Andric                                        MCSymbol *Sym) {
33560b57cec5SDimitry Andric   unsigned ATReg = getATReg(IDLoc);
33570b57cec5SDimitry Andric   if (!ATReg)
33580b57cec5SDimitry Andric     return true;
33590b57cec5SDimitry Andric 
33600b57cec5SDimitry Andric   if(IsPicEnabled) {
33610b57cec5SDimitry Andric     const MCExpr *GotSym =
33620b57cec5SDimitry Andric         MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33630b57cec5SDimitry Andric     const MipsMCExpr *GotExpr =
33640b57cec5SDimitry Andric         MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
33650b57cec5SDimitry Andric 
33660b57cec5SDimitry Andric     if(isABI_O32() || isABI_N32()) {
33670b57cec5SDimitry Andric       TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),
33680b57cec5SDimitry Andric                    IDLoc, STI);
33690b57cec5SDimitry Andric     } else { //isABI_N64()
33700b57cec5SDimitry Andric       TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),
33710b57cec5SDimitry Andric                    IDLoc, STI);
33720b57cec5SDimitry Andric     }
33730b57cec5SDimitry Andric   } else { //!IsPicEnabled
33740b57cec5SDimitry Andric     const MCExpr *HiSym =
33750b57cec5SDimitry Andric         MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33760b57cec5SDimitry Andric     const MipsMCExpr *HiExpr =
33770b57cec5SDimitry Andric         MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
33780b57cec5SDimitry Andric 
33790b57cec5SDimitry Andric     // FIXME: This is technically correct but gives a different result to gas,
33800b57cec5SDimitry Andric     // but gas is incomplete there (it has a fixme noting it doesn't work with
33810b57cec5SDimitry Andric     // 64-bit addresses).
33820b57cec5SDimitry Andric     // FIXME: With -msym32 option, the address expansion for N64 should probably
33830b57cec5SDimitry Andric     // use the O32 / N32 case. It's safe to use the 64 address expansion as the
33840b57cec5SDimitry Andric     // symbol's value is considered sign extended.
33850b57cec5SDimitry Andric     if(isABI_O32() || isABI_N32()) {
33860b57cec5SDimitry Andric       TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
33870b57cec5SDimitry Andric     } else { //isABI_N64()
33880b57cec5SDimitry Andric       const MCExpr *HighestSym =
33890b57cec5SDimitry Andric           MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33900b57cec5SDimitry Andric       const MipsMCExpr *HighestExpr =
33910b57cec5SDimitry Andric           MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
33920b57cec5SDimitry Andric       const MCExpr *HigherSym =
33930b57cec5SDimitry Andric           MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33940b57cec5SDimitry Andric       const MipsMCExpr *HigherExpr =
33950b57cec5SDimitry Andric           MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric       TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
33980b57cec5SDimitry Andric                   STI);
33990b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
34000b57cec5SDimitry Andric                    MCOperand::createExpr(HigherExpr), IDLoc, STI);
34010b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
34020b57cec5SDimitry Andric       TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
34030b57cec5SDimitry Andric                    IDLoc, STI);
34040b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
34050b57cec5SDimitry Andric     }
34060b57cec5SDimitry Andric   }
34070b57cec5SDimitry Andric   return false;
34080b57cec5SDimitry Andric }
34090b57cec5SDimitry Andric 
convertIntToDoubleImm(uint64_t ImmOp64)3410c14a5a88SDimitry Andric static uint64_t convertIntToDoubleImm(uint64_t ImmOp64) {
3411c14a5a88SDimitry Andric   // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3412c14a5a88SDimitry Andric   // exponent field), convert it to double (e.g. 1 to 1.0)
3413c14a5a88SDimitry Andric   if ((Hi_32(ImmOp64) & 0x7ff00000) == 0) {
3414c14a5a88SDimitry Andric     APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3415c14a5a88SDimitry Andric     ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3416c14a5a88SDimitry Andric   }
3417c14a5a88SDimitry Andric   return ImmOp64;
3418c14a5a88SDimitry Andric }
3419c14a5a88SDimitry Andric 
covertDoubleImmToSingleImm(uint64_t ImmOp64)3420c14a5a88SDimitry Andric static uint32_t covertDoubleImmToSingleImm(uint64_t ImmOp64) {
3421c14a5a88SDimitry Andric   // Conversion of a double in an uint64_t to a float in a uint32_t,
3422c14a5a88SDimitry Andric   // retaining the bit pattern of a float.
342306c3fb27SDimitry Andric   double DoubleImm = llvm::bit_cast<double>(ImmOp64);
3424c14a5a88SDimitry Andric   float TmpFloat = static_cast<float>(DoubleImm);
342506c3fb27SDimitry Andric   return llvm::bit_cast<uint32_t>(TmpFloat);
3426c14a5a88SDimitry Andric }
3427c14a5a88SDimitry Andric 
expandLoadSingleImmToGPR(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3428c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3429c14a5a88SDimitry Andric                                              MCStreamer &Out,
3430c14a5a88SDimitry Andric                                              const MCSubtargetInfo *STI) {
3431c14a5a88SDimitry Andric   assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3432c14a5a88SDimitry Andric   assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3433c14a5a88SDimitry Andric          "Invalid instruction operand.");
3434c14a5a88SDimitry Andric 
3435c14a5a88SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
3436c14a5a88SDimitry Andric   uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3437c14a5a88SDimitry Andric 
34388bcb0991SDimitry Andric   uint32_t ImmOp32 = covertDoubleImmToSingleImm(convertIntToDoubleImm(ImmOp64));
3439c14a5a88SDimitry Andric 
34408bcb0991SDimitry Andric   return loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, false, IDLoc,
3441c14a5a88SDimitry Andric                        Out, STI);
3442c14a5a88SDimitry Andric }
3443c14a5a88SDimitry Andric 
expandLoadSingleImmToFPR(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3444c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc,
34450b57cec5SDimitry Andric                                              MCStreamer &Out,
34460b57cec5SDimitry Andric                                              const MCSubtargetInfo *STI) {
34470b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
34480b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 2 && "Invalid operand count");
34490b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
34500b57cec5SDimitry Andric          "Invalid instruction operand.");
34510b57cec5SDimitry Andric 
34520b57cec5SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
34530b57cec5SDimitry Andric   uint64_t ImmOp64 = Inst.getOperand(1).getImm();
34540b57cec5SDimitry Andric 
3455c14a5a88SDimitry Andric   ImmOp64 = convertIntToDoubleImm(ImmOp64);
34560b57cec5SDimitry Andric 
3457c14a5a88SDimitry Andric   uint32_t ImmOp32 = covertDoubleImmToSingleImm(ImmOp64);
34580b57cec5SDimitry Andric 
34598bcb0991SDimitry Andric   unsigned TmpReg = Mips::ZERO;
34608bcb0991SDimitry Andric   if (ImmOp32 != 0) {
34618bcb0991SDimitry Andric     TmpReg = getATReg(IDLoc);
3462c14a5a88SDimitry Andric     if (!TmpReg)
3463c14a5a88SDimitry Andric       return true;
34648bcb0991SDimitry Andric   }
34650b57cec5SDimitry Andric 
3466c14a5a88SDimitry Andric   if (Lo_32(ImmOp64) == 0) {
34678bcb0991SDimitry Andric     if (TmpReg != Mips::ZERO && loadImmediate(ImmOp32, TmpReg, Mips::NoRegister,
34688bcb0991SDimitry Andric                                               true, false, IDLoc, Out, STI))
34690b57cec5SDimitry Andric       return true;
3470c14a5a88SDimitry Andric     TOut.emitRR(Mips::MTC1, FirstReg, TmpReg, IDLoc, STI);
34710b57cec5SDimitry Andric     return false;
34720b57cec5SDimitry Andric   }
34730b57cec5SDimitry Andric 
34740b57cec5SDimitry Andric   MCSection *CS = getStreamer().getCurrentSectionOnly();
34750b57cec5SDimitry Andric   // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
34760b57cec5SDimitry Andric   // where appropriate.
3477c14a5a88SDimitry Andric   MCSection *ReadOnlySection =
3478c14a5a88SDimitry Andric       getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
34790b57cec5SDimitry Andric 
34800b57cec5SDimitry Andric   MCSymbol *Sym = getContext().createTempSymbol();
34810b57cec5SDimitry Andric   const MCExpr *LoSym =
34820b57cec5SDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
34830b57cec5SDimitry Andric   const MipsMCExpr *LoExpr =
34840b57cec5SDimitry Andric       MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
34850b57cec5SDimitry Andric 
348681ad6265SDimitry Andric   getStreamer().switchSection(ReadOnlySection);
34875ffd83dbSDimitry Andric   getStreamer().emitLabel(Sym, IDLoc);
34885ffd83dbSDimitry Andric   getStreamer().emitInt32(ImmOp32);
348981ad6265SDimitry Andric   getStreamer().switchSection(CS);
34900b57cec5SDimitry Andric 
34910b57cec5SDimitry Andric   if (emitPartialAddress(TOut, IDLoc, Sym))
34920b57cec5SDimitry Andric     return true;
3493c14a5a88SDimitry Andric   TOut.emitRRX(Mips::LWC1, FirstReg, TmpReg, MCOperand::createExpr(LoExpr),
3494c14a5a88SDimitry Andric                IDLoc, STI);
34950b57cec5SDimitry Andric   return false;
34960b57cec5SDimitry Andric }
34970b57cec5SDimitry Andric 
expandLoadDoubleImmToGPR(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3498c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3499c14a5a88SDimitry Andric                                              MCStreamer &Out,
3500c14a5a88SDimitry Andric                                              const MCSubtargetInfo *STI) {
3501c14a5a88SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
3502c14a5a88SDimitry Andric   assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3503c14a5a88SDimitry Andric   assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3504c14a5a88SDimitry Andric          "Invalid instruction operand.");
3505c14a5a88SDimitry Andric 
3506c14a5a88SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
3507c14a5a88SDimitry Andric   uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3508c14a5a88SDimitry Andric 
3509c14a5a88SDimitry Andric   ImmOp64 = convertIntToDoubleImm(ImmOp64);
3510c14a5a88SDimitry Andric 
35118bcb0991SDimitry Andric   if (Lo_32(ImmOp64) == 0) {
35128bcb0991SDimitry Andric     if (isGP64bit()) {
35138bcb0991SDimitry Andric       if (loadImmediate(ImmOp64, FirstReg, Mips::NoRegister, false, false,
35148bcb0991SDimitry Andric                         IDLoc, Out, STI))
35150b57cec5SDimitry Andric         return true;
35160b57cec5SDimitry Andric     } else {
35178bcb0991SDimitry Andric       if (loadImmediate(Hi_32(ImmOp64), FirstReg, Mips::NoRegister, true, false,
35180b57cec5SDimitry Andric                         IDLoc, Out, STI))
35190b57cec5SDimitry Andric         return true;
35200b57cec5SDimitry Andric 
35218bcb0991SDimitry Andric       if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, false,
35220b57cec5SDimitry Andric                         IDLoc, Out, STI))
35230b57cec5SDimitry Andric         return true;
35240b57cec5SDimitry Andric     }
3525c14a5a88SDimitry Andric     return false;
35260b57cec5SDimitry Andric   }
35270b57cec5SDimitry Andric 
35280b57cec5SDimitry Andric   MCSection *CS = getStreamer().getCurrentSectionOnly();
3529c14a5a88SDimitry Andric   MCSection *ReadOnlySection =
3530c14a5a88SDimitry Andric       getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
35310b57cec5SDimitry Andric 
35320b57cec5SDimitry Andric   MCSymbol *Sym = getContext().createTempSymbol();
35330b57cec5SDimitry Andric   const MCExpr *LoSym =
35340b57cec5SDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
35350b57cec5SDimitry Andric   const MipsMCExpr *LoExpr =
35360b57cec5SDimitry Andric       MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
35370b57cec5SDimitry Andric 
353881ad6265SDimitry Andric   getStreamer().switchSection(ReadOnlySection);
35395ffd83dbSDimitry Andric   getStreamer().emitLabel(Sym, IDLoc);
3540bdd1243dSDimitry Andric   getStreamer().emitValueToAlignment(Align(8));
35415ffd83dbSDimitry Andric   getStreamer().emitIntValue(ImmOp64, 8);
354281ad6265SDimitry Andric   getStreamer().switchSection(CS);
35430b57cec5SDimitry Andric 
35448bcb0991SDimitry Andric   unsigned TmpReg = getATReg(IDLoc);
35458bcb0991SDimitry Andric   if (!TmpReg)
35468bcb0991SDimitry Andric     return true;
35478bcb0991SDimitry Andric 
35480b57cec5SDimitry Andric   if (emitPartialAddress(TOut, IDLoc, Sym))
35490b57cec5SDimitry Andric     return true;
3550c14a5a88SDimitry Andric 
35518bcb0991SDimitry Andric   TOut.emitRRX(isABI_N64() ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
35528bcb0991SDimitry Andric                MCOperand::createExpr(LoExpr), IDLoc, STI);
35530b57cec5SDimitry Andric 
35548bcb0991SDimitry Andric   if (isGP64bit())
3555c14a5a88SDimitry Andric     TOut.emitRRI(Mips::LD, FirstReg, TmpReg, 0, IDLoc, STI);
35560b57cec5SDimitry Andric   else {
3557c14a5a88SDimitry Andric     TOut.emitRRI(Mips::LW, FirstReg, TmpReg, 0, IDLoc, STI);
3558c14a5a88SDimitry Andric     TOut.emitRRI(Mips::LW, nextReg(FirstReg), TmpReg, 4, IDLoc, STI);
35590b57cec5SDimitry Andric   }
35600b57cec5SDimitry Andric   return false;
3561c14a5a88SDimitry Andric }
3562c14a5a88SDimitry Andric 
expandLoadDoubleImmToFPR(MCInst & Inst,bool Is64FPU,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3563c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU,
3564c14a5a88SDimitry Andric                                              SMLoc IDLoc, MCStreamer &Out,
3565c14a5a88SDimitry Andric                                              const MCSubtargetInfo *STI) {
3566c14a5a88SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
3567c14a5a88SDimitry Andric   assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3568c14a5a88SDimitry Andric   assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3569c14a5a88SDimitry Andric          "Invalid instruction operand.");
3570c14a5a88SDimitry Andric 
3571c14a5a88SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
3572c14a5a88SDimitry Andric   uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3573c14a5a88SDimitry Andric 
3574c14a5a88SDimitry Andric   ImmOp64 = convertIntToDoubleImm(ImmOp64);
3575c14a5a88SDimitry Andric 
35768bcb0991SDimitry Andric   unsigned TmpReg = Mips::ZERO;
35778bcb0991SDimitry Andric   if (ImmOp64 != 0) {
35788bcb0991SDimitry Andric     TmpReg = getATReg(IDLoc);
3579c14a5a88SDimitry Andric     if (!TmpReg)
3580c14a5a88SDimitry Andric       return true;
35818bcb0991SDimitry Andric   }
3582c14a5a88SDimitry Andric 
35838bcb0991SDimitry Andric   if ((Lo_32(ImmOp64) == 0) &&
35848bcb0991SDimitry Andric       !((Hi_32(ImmOp64) & 0xffff0000) && (Hi_32(ImmOp64) & 0x0000ffff))) {
35858bcb0991SDimitry Andric     if (isGP64bit()) {
35868bcb0991SDimitry Andric       if (TmpReg != Mips::ZERO &&
35878bcb0991SDimitry Andric           loadImmediate(ImmOp64, TmpReg, Mips::NoRegister, false, false, IDLoc,
35880b57cec5SDimitry Andric                         Out, STI))
35890b57cec5SDimitry Andric         return true;
3590c14a5a88SDimitry Andric       TOut.emitRR(Mips::DMTC1, FirstReg, TmpReg, IDLoc, STI);
3591c14a5a88SDimitry Andric       return false;
3592c14a5a88SDimitry Andric     }
3593c14a5a88SDimitry Andric 
35948bcb0991SDimitry Andric     if (TmpReg != Mips::ZERO &&
35958bcb0991SDimitry Andric         loadImmediate(Hi_32(ImmOp64), TmpReg, Mips::NoRegister, true, false,
35968bcb0991SDimitry Andric                       IDLoc, Out, STI))
3597c14a5a88SDimitry Andric       return true;
3598c14a5a88SDimitry Andric 
3599c14a5a88SDimitry Andric     if (hasMips32r2()) {
36000b57cec5SDimitry Andric       TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3601c14a5a88SDimitry Andric       TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, TmpReg, IDLoc, STI);
36020b57cec5SDimitry Andric     } else {
3603c14a5a88SDimitry Andric       TOut.emitRR(Mips::MTC1, nextReg(FirstReg), TmpReg, IDLoc, STI);
36040b57cec5SDimitry Andric       TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
36050b57cec5SDimitry Andric     }
36060b57cec5SDimitry Andric     return false;
36070b57cec5SDimitry Andric   }
36080b57cec5SDimitry Andric 
36090b57cec5SDimitry Andric   MCSection *CS = getStreamer().getCurrentSectionOnly();
36100b57cec5SDimitry Andric   // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
36110b57cec5SDimitry Andric   // where appropriate.
3612c14a5a88SDimitry Andric   MCSection *ReadOnlySection =
3613c14a5a88SDimitry Andric       getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
36140b57cec5SDimitry Andric 
36150b57cec5SDimitry Andric   MCSymbol *Sym = getContext().createTempSymbol();
36160b57cec5SDimitry Andric   const MCExpr *LoSym =
36170b57cec5SDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
36180b57cec5SDimitry Andric   const MipsMCExpr *LoExpr =
36190b57cec5SDimitry Andric       MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
36200b57cec5SDimitry Andric 
362181ad6265SDimitry Andric   getStreamer().switchSection(ReadOnlySection);
36225ffd83dbSDimitry Andric   getStreamer().emitLabel(Sym, IDLoc);
3623bdd1243dSDimitry Andric   getStreamer().emitValueToAlignment(Align(8));
36245ffd83dbSDimitry Andric   getStreamer().emitIntValue(ImmOp64, 8);
362581ad6265SDimitry Andric   getStreamer().switchSection(CS);
36260b57cec5SDimitry Andric 
36270b57cec5SDimitry Andric   if (emitPartialAddress(TOut, IDLoc, Sym))
36280b57cec5SDimitry Andric     return true;
3629c14a5a88SDimitry Andric 
3630c14a5a88SDimitry Andric   TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, TmpReg,
36310b57cec5SDimitry Andric                MCOperand::createExpr(LoExpr), IDLoc, STI);
3632c14a5a88SDimitry Andric 
36330b57cec5SDimitry Andric   return false;
36340b57cec5SDimitry Andric }
36350b57cec5SDimitry Andric 
expandUncondBranchMMPseudo(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)36360b57cec5SDimitry Andric bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
36370b57cec5SDimitry Andric                                                MCStreamer &Out,
36380b57cec5SDimitry Andric                                                const MCSubtargetInfo *STI) {
36390b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
36400b57cec5SDimitry Andric 
3641bdd1243dSDimitry Andric   assert(MII.get(Inst.getOpcode()).getNumOperands() == 1 &&
36420b57cec5SDimitry Andric          "unexpected number of operands");
36430b57cec5SDimitry Andric 
36440b57cec5SDimitry Andric   MCOperand Offset = Inst.getOperand(0);
36450b57cec5SDimitry Andric   if (Offset.isExpr()) {
36460b57cec5SDimitry Andric     Inst.clear();
36470b57cec5SDimitry Andric     Inst.setOpcode(Mips::BEQ_MM);
36480b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36490b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36500b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
36510b57cec5SDimitry Andric   } else {
36520b57cec5SDimitry Andric     assert(Offset.isImm() && "expected immediate operand kind");
36530b57cec5SDimitry Andric     if (isInt<11>(Offset.getImm())) {
36540b57cec5SDimitry Andric       // If offset fits into 11 bits then this instruction becomes microMIPS
36550b57cec5SDimitry Andric       // 16-bit unconditional branch instruction.
36560b57cec5SDimitry Andric       if (inMicroMipsMode())
36570b57cec5SDimitry Andric         Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
36580b57cec5SDimitry Andric     } else {
36590b57cec5SDimitry Andric       if (!isInt<17>(Offset.getImm()))
36600b57cec5SDimitry Andric         return Error(IDLoc, "branch target out of range");
36618bcb0991SDimitry Andric       if (offsetToAlignment(Offset.getImm(), Align(2)))
36620b57cec5SDimitry Andric         return Error(IDLoc, "branch to misaligned address");
36630b57cec5SDimitry Andric       Inst.clear();
36640b57cec5SDimitry Andric       Inst.setOpcode(Mips::BEQ_MM);
36650b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36660b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36670b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(Offset.getImm()));
36680b57cec5SDimitry Andric     }
36690b57cec5SDimitry Andric   }
36705ffd83dbSDimitry Andric   Out.emitInstruction(Inst, *STI);
36710b57cec5SDimitry Andric 
36720b57cec5SDimitry Andric   // If .set reorder is active and branch instruction has a delay slot,
36730b57cec5SDimitry Andric   // emit a NOP after it.
3674bdd1243dSDimitry Andric   const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
36750b57cec5SDimitry Andric   if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
36760b57cec5SDimitry Andric     TOut.emitEmptyDelaySlot(true, IDLoc, STI);
36770b57cec5SDimitry Andric 
36780b57cec5SDimitry Andric   return false;
36790b57cec5SDimitry Andric }
36800b57cec5SDimitry Andric 
expandBranchImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)36810b57cec5SDimitry Andric bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
36820b57cec5SDimitry Andric                                     const MCSubtargetInfo *STI) {
36830b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
36840b57cec5SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(0);
36850b57cec5SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
36860b57cec5SDimitry Andric 
36870b57cec5SDimitry Andric   const MCOperand &ImmOp = Inst.getOperand(1);
36880b57cec5SDimitry Andric   assert(ImmOp.isImm() && "expected immediate operand kind");
36890b57cec5SDimitry Andric 
36900b57cec5SDimitry Andric   const MCOperand &MemOffsetOp = Inst.getOperand(2);
36910b57cec5SDimitry Andric   assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
36920b57cec5SDimitry Andric          "expected immediate or expression operand");
36930b57cec5SDimitry Andric 
36940b57cec5SDimitry Andric   bool IsLikely = false;
36950b57cec5SDimitry Andric 
36960b57cec5SDimitry Andric   unsigned OpCode = 0;
36970b57cec5SDimitry Andric   switch(Inst.getOpcode()) {
36980b57cec5SDimitry Andric     case Mips::BneImm:
36990b57cec5SDimitry Andric       OpCode = Mips::BNE;
37000b57cec5SDimitry Andric       break;
37010b57cec5SDimitry Andric     case Mips::BeqImm:
37020b57cec5SDimitry Andric       OpCode = Mips::BEQ;
37030b57cec5SDimitry Andric       break;
37040b57cec5SDimitry Andric     case Mips::BEQLImmMacro:
37050b57cec5SDimitry Andric       OpCode = Mips::BEQL;
37060b57cec5SDimitry Andric       IsLikely = true;
37070b57cec5SDimitry Andric       break;
37080b57cec5SDimitry Andric     case Mips::BNELImmMacro:
37090b57cec5SDimitry Andric       OpCode = Mips::BNEL;
37100b57cec5SDimitry Andric       IsLikely = true;
37110b57cec5SDimitry Andric       break;
37120b57cec5SDimitry Andric     default:
37130b57cec5SDimitry Andric       llvm_unreachable("Unknown immediate branch pseudo-instruction.");
37140b57cec5SDimitry Andric       break;
37150b57cec5SDimitry Andric   }
37160b57cec5SDimitry Andric 
37170b57cec5SDimitry Andric   int64_t ImmValue = ImmOp.getImm();
37180b57cec5SDimitry Andric   if (ImmValue == 0) {
37190b57cec5SDimitry Andric     if (IsLikely) {
37200b57cec5SDimitry Andric       TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
37210b57cec5SDimitry Andric                    MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
37220b57cec5SDimitry Andric       TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
37230b57cec5SDimitry Andric     } else
37240b57cec5SDimitry Andric       TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
37250b57cec5SDimitry Andric               STI);
37260b57cec5SDimitry Andric   } else {
37270b57cec5SDimitry Andric     warnIfNoMacro(IDLoc);
37280b57cec5SDimitry Andric 
37290b57cec5SDimitry Andric     unsigned ATReg = getATReg(IDLoc);
37300b57cec5SDimitry Andric     if (!ATReg)
37310b57cec5SDimitry Andric       return true;
37320b57cec5SDimitry Andric 
37330b57cec5SDimitry Andric     if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
37340b57cec5SDimitry Andric                       IDLoc, Out, STI))
37350b57cec5SDimitry Andric       return true;
37360b57cec5SDimitry Andric 
37370b57cec5SDimitry Andric     if (IsLikely) {
37380b57cec5SDimitry Andric       TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
37390b57cec5SDimitry Andric               MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
37400b57cec5SDimitry Andric       TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
37410b57cec5SDimitry Andric     } else
37420b57cec5SDimitry Andric       TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
37430b57cec5SDimitry Andric   }
37440b57cec5SDimitry Andric   return false;
37450b57cec5SDimitry Andric }
37460b57cec5SDimitry Andric 
expandMem16Inst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad)3747480093f4SDimitry Andric void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
37480b57cec5SDimitry Andric                                     const MCSubtargetInfo *STI, bool IsLoad) {
3749480093f4SDimitry Andric   unsigned NumOp = Inst.getNumOperands();
3750480093f4SDimitry Andric   assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");
3751480093f4SDimitry Andric   unsigned StartOp = NumOp == 3 ? 0 : 1;
3752480093f4SDimitry Andric 
3753480093f4SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(StartOp);
37540b57cec5SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
3755480093f4SDimitry Andric   const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
37560b57cec5SDimitry Andric   assert(BaseRegOp.isReg() && "expected register operand kind");
3757480093f4SDimitry Andric   const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
37580b57cec5SDimitry Andric 
37590b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
3760480093f4SDimitry Andric   unsigned OpCode = Inst.getOpcode();
37610b57cec5SDimitry Andric   unsigned DstReg = DstRegOp.getReg();
37620b57cec5SDimitry Andric   unsigned BaseReg = BaseRegOp.getReg();
37630b57cec5SDimitry Andric   unsigned TmpReg = DstReg;
37640b57cec5SDimitry Andric 
3765bdd1243dSDimitry Andric   const MCInstrDesc &Desc = MII.get(OpCode);
3766bdd1243dSDimitry Andric   int16_t DstRegClass = Desc.operands()[StartOp].RegClass;
37670b57cec5SDimitry Andric   unsigned DstRegClassID =
37680b57cec5SDimitry Andric       getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
37690b57cec5SDimitry Andric   bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
37700b57cec5SDimitry Andric                (DstRegClassID == Mips::GPR64RegClassID);
37710b57cec5SDimitry Andric 
37720b57cec5SDimitry Andric   if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
37730b57cec5SDimitry Andric     // At this point we need AT to perform the expansions
37740b57cec5SDimitry Andric     // and we exit if it is not available.
37750b57cec5SDimitry Andric     TmpReg = getATReg(IDLoc);
37760b57cec5SDimitry Andric     if (!TmpReg)
37770b57cec5SDimitry Andric       return;
37780b57cec5SDimitry Andric   }
37790b57cec5SDimitry Andric 
3780480093f4SDimitry Andric   auto emitInstWithOffset = [&](const MCOperand &Off) {
3781480093f4SDimitry Andric     if (NumOp == 3)
3782480093f4SDimitry Andric       TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI);
3783480093f4SDimitry Andric     else
3784480093f4SDimitry Andric       TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI);
3785480093f4SDimitry Andric   };
37868bcb0991SDimitry Andric 
37870b57cec5SDimitry Andric   if (OffsetOp.isImm()) {
37880b57cec5SDimitry Andric     int64_t LoOffset = OffsetOp.getImm() & 0xffff;
37890b57cec5SDimitry Andric     int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
37900b57cec5SDimitry Andric 
37910b57cec5SDimitry Andric     // If msb of LoOffset is 1(negative number) we must increment
37920b57cec5SDimitry Andric     // HiOffset to account for the sign-extension of the low part.
37930b57cec5SDimitry Andric     if (LoOffset & 0x8000)
37940b57cec5SDimitry Andric       HiOffset += 0x10000;
37950b57cec5SDimitry Andric 
37960b57cec5SDimitry Andric     bool IsLargeOffset = HiOffset != 0;
37970b57cec5SDimitry Andric 
37980b57cec5SDimitry Andric     if (IsLargeOffset) {
3799480093f4SDimitry Andric       bool Is32BitImm = isInt<32>(OffsetOp.getImm());
38000b57cec5SDimitry Andric       if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
38010b57cec5SDimitry Andric                         IDLoc, Out, STI))
38020b57cec5SDimitry Andric         return;
38030b57cec5SDimitry Andric     }
38040b57cec5SDimitry Andric 
38050b57cec5SDimitry Andric     if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3806480093f4SDimitry Andric       TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg,
3807480093f4SDimitry Andric                    TmpReg, BaseReg, IDLoc, STI);
3808480093f4SDimitry Andric     emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset)));
38090b57cec5SDimitry Andric     return;
38100b57cec5SDimitry Andric   }
38110b57cec5SDimitry Andric 
38128bcb0991SDimitry Andric   if (OffsetOp.isExpr()) {
38130b57cec5SDimitry Andric     if (inPicMode()) {
38140b57cec5SDimitry Andric       // FIXME:
38150b57cec5SDimitry Andric       // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
38160b57cec5SDimitry Andric       //    do not exceed 16-bit.
38170b57cec5SDimitry Andric       // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
38180b57cec5SDimitry Andric       //    of R_MIPS_GOT_DISP in appropriate cases to reduce number
38190b57cec5SDimitry Andric       //    of GOT entries.
38208bcb0991SDimitry Andric       MCValue Res;
38218bcb0991SDimitry Andric       if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) {
38228bcb0991SDimitry Andric         Error(IDLoc, "expected relocatable expression");
38238bcb0991SDimitry Andric         return;
38248bcb0991SDimitry Andric       }
38258bcb0991SDimitry Andric       if (Res.getSymB() != nullptr) {
38268bcb0991SDimitry Andric         Error(IDLoc, "expected relocatable expression with only one symbol");
38278bcb0991SDimitry Andric         return;
38288bcb0991SDimitry Andric       }
38298bcb0991SDimitry Andric 
38308bcb0991SDimitry Andric       loadAndAddSymbolAddress(Res.getSymA(), TmpReg, BaseReg,
38318bcb0991SDimitry Andric                               !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3832480093f4SDimitry Andric       emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant())));
38330b57cec5SDimitry Andric     } else {
38348bcb0991SDimitry Andric       // FIXME: Implement 64-bit case.
38358bcb0991SDimitry Andric       // 1) lw $8, sym => lui $8,  %hi(sym)
38368bcb0991SDimitry Andric       //                  lw  $8,  %lo(sym)($8)
38378bcb0991SDimitry Andric       // 2) sw $8, sym => lui $at, %hi(sym)
38388bcb0991SDimitry Andric       //                  sw  $8,  %lo(sym)($at)
3839480093f4SDimitry Andric       const MCExpr *OffExpr = OffsetOp.getExpr();
38400b57cec5SDimitry Andric       MCOperand LoOperand = MCOperand::createExpr(
3841480093f4SDimitry Andric           MipsMCExpr::create(MipsMCExpr::MEK_LO, OffExpr, getContext()));
38420b57cec5SDimitry Andric       MCOperand HiOperand = MCOperand::createExpr(
3843480093f4SDimitry Andric           MipsMCExpr::create(MipsMCExpr::MEK_HI, OffExpr, getContext()));
38440b57cec5SDimitry Andric 
3845480093f4SDimitry Andric       if (ABI.IsN64()) {
3846480093f4SDimitry Andric         MCOperand HighestOperand = MCOperand::createExpr(
3847480093f4SDimitry Andric             MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, OffExpr, getContext()));
3848480093f4SDimitry Andric         MCOperand HigherOperand = MCOperand::createExpr(
3849480093f4SDimitry Andric             MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, OffExpr, getContext()));
3850480093f4SDimitry Andric 
3851480093f4SDimitry Andric         TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI);
3852480093f4SDimitry Andric         TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI);
3853480093f4SDimitry Andric         TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3854480093f4SDimitry Andric         TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI);
3855480093f4SDimitry Andric         TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3856480093f4SDimitry Andric         if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3857480093f4SDimitry Andric           TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
3858480093f4SDimitry Andric         emitInstWithOffset(LoOperand);
3859480093f4SDimitry Andric       } else {
38608bcb0991SDimitry Andric         // Generate the base address in TmpReg.
38618bcb0991SDimitry Andric         TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
38628bcb0991SDimitry Andric         if (BaseReg != Mips::ZERO)
38638bcb0991SDimitry Andric           TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
38648bcb0991SDimitry Andric         // Emit the load or store with the adjusted base and offset.
3865480093f4SDimitry Andric         emitInstWithOffset(LoOperand);
38660b57cec5SDimitry Andric       }
3867480093f4SDimitry Andric     }
3868480093f4SDimitry Andric     return;
3869480093f4SDimitry Andric   }
3870480093f4SDimitry Andric 
3871480093f4SDimitry Andric   llvm_unreachable("unexpected operand type");
3872480093f4SDimitry Andric }
3873480093f4SDimitry Andric 
expandMem9Inst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad)3874480093f4SDimitry Andric void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3875480093f4SDimitry Andric                                    const MCSubtargetInfo *STI, bool IsLoad) {
3876480093f4SDimitry Andric   unsigned NumOp = Inst.getNumOperands();
3877480093f4SDimitry Andric   assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");
3878480093f4SDimitry Andric   unsigned StartOp = NumOp == 3 ? 0 : 1;
3879480093f4SDimitry Andric 
3880480093f4SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(StartOp);
3881480093f4SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
3882480093f4SDimitry Andric   const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
3883480093f4SDimitry Andric   assert(BaseRegOp.isReg() && "expected register operand kind");
3884480093f4SDimitry Andric   const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
3885480093f4SDimitry Andric 
3886480093f4SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
3887480093f4SDimitry Andric   unsigned OpCode = Inst.getOpcode();
3888480093f4SDimitry Andric   unsigned DstReg = DstRegOp.getReg();
3889480093f4SDimitry Andric   unsigned BaseReg = BaseRegOp.getReg();
3890480093f4SDimitry Andric   unsigned TmpReg = DstReg;
3891480093f4SDimitry Andric 
3892bdd1243dSDimitry Andric   const MCInstrDesc &Desc = MII.get(OpCode);
3893bdd1243dSDimitry Andric   int16_t DstRegClass = Desc.operands()[StartOp].RegClass;
3894480093f4SDimitry Andric   unsigned DstRegClassID =
3895480093f4SDimitry Andric       getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3896480093f4SDimitry Andric   bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3897480093f4SDimitry Andric                (DstRegClassID == Mips::GPR64RegClassID);
3898480093f4SDimitry Andric 
3899480093f4SDimitry Andric   if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
3900480093f4SDimitry Andric     // At this point we need AT to perform the expansions
3901480093f4SDimitry Andric     // and we exit if it is not available.
3902480093f4SDimitry Andric     TmpReg = getATReg(IDLoc);
3903480093f4SDimitry Andric     if (!TmpReg)
3904480093f4SDimitry Andric       return;
3905480093f4SDimitry Andric   }
3906480093f4SDimitry Andric 
3907480093f4SDimitry Andric   auto emitInst = [&]() {
3908480093f4SDimitry Andric     if (NumOp == 3)
3909480093f4SDimitry Andric       TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI);
3910480093f4SDimitry Andric     else
3911480093f4SDimitry Andric       TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0),
3912480093f4SDimitry Andric                     IDLoc, STI);
3913480093f4SDimitry Andric   };
3914480093f4SDimitry Andric 
3915480093f4SDimitry Andric   if (OffsetOp.isImm()) {
3916480093f4SDimitry Andric     loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true,
3917480093f4SDimitry Andric                   IDLoc, Out, STI);
3918480093f4SDimitry Andric     emitInst();
3919480093f4SDimitry Andric     return;
3920480093f4SDimitry Andric   }
3921480093f4SDimitry Andric 
3922480093f4SDimitry Andric   if (OffsetOp.isExpr()) {
3923480093f4SDimitry Andric     loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg,
3924480093f4SDimitry Andric                             !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3925480093f4SDimitry Andric     emitInst();
39268bcb0991SDimitry Andric     return;
39278bcb0991SDimitry Andric   }
39288bcb0991SDimitry Andric 
39298bcb0991SDimitry Andric   llvm_unreachable("unexpected operand type");
39300b57cec5SDimitry Andric }
39310b57cec5SDimitry Andric 
expandLoadStoreMultiple(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)39320b57cec5SDimitry Andric bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
39330b57cec5SDimitry Andric                                             MCStreamer &Out,
39340b57cec5SDimitry Andric                                             const MCSubtargetInfo *STI) {
39350b57cec5SDimitry Andric   unsigned OpNum = Inst.getNumOperands();
39360b57cec5SDimitry Andric   unsigned Opcode = Inst.getOpcode();
39370b57cec5SDimitry Andric   unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
39380b57cec5SDimitry Andric 
39390b57cec5SDimitry Andric   assert(Inst.getOperand(OpNum - 1).isImm() &&
39400b57cec5SDimitry Andric          Inst.getOperand(OpNum - 2).isReg() &&
39410b57cec5SDimitry Andric          Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
39420b57cec5SDimitry Andric 
39430b57cec5SDimitry Andric   if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
39440b57cec5SDimitry Andric       Inst.getOperand(OpNum - 1).getImm() >= 0 &&
39450b57cec5SDimitry Andric       (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
39460b57cec5SDimitry Andric        Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
39470b57cec5SDimitry Andric       (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
39480b57cec5SDimitry Andric        Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
39490b57cec5SDimitry Andric     // It can be implemented as SWM16 or LWM16 instruction.
39500b57cec5SDimitry Andric     if (inMicroMipsMode() && hasMips32r6())
39510b57cec5SDimitry Andric       NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
39520b57cec5SDimitry Andric     else
39530b57cec5SDimitry Andric       NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
39540b57cec5SDimitry Andric   }
39550b57cec5SDimitry Andric 
39560b57cec5SDimitry Andric   Inst.setOpcode(NewOpcode);
39575ffd83dbSDimitry Andric   Out.emitInstruction(Inst, *STI);
39580b57cec5SDimitry Andric   return false;
39590b57cec5SDimitry Andric }
39600b57cec5SDimitry Andric 
expandCondBranches(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)39610b57cec5SDimitry Andric bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
39620b57cec5SDimitry Andric                                        MCStreamer &Out,
39630b57cec5SDimitry Andric                                        const MCSubtargetInfo *STI) {
39640b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
39650b57cec5SDimitry Andric   bool EmittedNoMacroWarning = false;
39660b57cec5SDimitry Andric   unsigned PseudoOpcode = Inst.getOpcode();
39670b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(0).getReg();
39680b57cec5SDimitry Andric   const MCOperand &TrgOp = Inst.getOperand(1);
39690b57cec5SDimitry Andric   const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
39700b57cec5SDimitry Andric 
39710b57cec5SDimitry Andric   unsigned ZeroSrcOpcode, ZeroTrgOpcode;
39720b57cec5SDimitry Andric   bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
39730b57cec5SDimitry Andric 
39740b57cec5SDimitry Andric   unsigned TrgReg;
39750b57cec5SDimitry Andric   if (TrgOp.isReg())
39760b57cec5SDimitry Andric     TrgReg = TrgOp.getReg();
39770b57cec5SDimitry Andric   else if (TrgOp.isImm()) {
39780b57cec5SDimitry Andric     warnIfNoMacro(IDLoc);
39790b57cec5SDimitry Andric     EmittedNoMacroWarning = true;
39800b57cec5SDimitry Andric 
39810b57cec5SDimitry Andric     TrgReg = getATReg(IDLoc);
39820b57cec5SDimitry Andric     if (!TrgReg)
39830b57cec5SDimitry Andric       return true;
39840b57cec5SDimitry Andric 
39850b57cec5SDimitry Andric     switch(PseudoOpcode) {
39860b57cec5SDimitry Andric     default:
39870b57cec5SDimitry Andric       llvm_unreachable("unknown opcode for branch pseudo-instruction");
39880b57cec5SDimitry Andric     case Mips::BLTImmMacro:
39890b57cec5SDimitry Andric       PseudoOpcode = Mips::BLT;
39900b57cec5SDimitry Andric       break;
39910b57cec5SDimitry Andric     case Mips::BLEImmMacro:
39920b57cec5SDimitry Andric       PseudoOpcode = Mips::BLE;
39930b57cec5SDimitry Andric       break;
39940b57cec5SDimitry Andric     case Mips::BGEImmMacro:
39950b57cec5SDimitry Andric       PseudoOpcode = Mips::BGE;
39960b57cec5SDimitry Andric       break;
39970b57cec5SDimitry Andric     case Mips::BGTImmMacro:
39980b57cec5SDimitry Andric       PseudoOpcode = Mips::BGT;
39990b57cec5SDimitry Andric       break;
40000b57cec5SDimitry Andric     case Mips::BLTUImmMacro:
40010b57cec5SDimitry Andric       PseudoOpcode = Mips::BLTU;
40020b57cec5SDimitry Andric       break;
40030b57cec5SDimitry Andric     case Mips::BLEUImmMacro:
40040b57cec5SDimitry Andric       PseudoOpcode = Mips::BLEU;
40050b57cec5SDimitry Andric       break;
40060b57cec5SDimitry Andric     case Mips::BGEUImmMacro:
40070b57cec5SDimitry Andric       PseudoOpcode = Mips::BGEU;
40080b57cec5SDimitry Andric       break;
40090b57cec5SDimitry Andric     case Mips::BGTUImmMacro:
40100b57cec5SDimitry Andric       PseudoOpcode = Mips::BGTU;
40110b57cec5SDimitry Andric       break;
40120b57cec5SDimitry Andric     case Mips::BLTLImmMacro:
40130b57cec5SDimitry Andric       PseudoOpcode = Mips::BLTL;
40140b57cec5SDimitry Andric       break;
40150b57cec5SDimitry Andric     case Mips::BLELImmMacro:
40160b57cec5SDimitry Andric       PseudoOpcode = Mips::BLEL;
40170b57cec5SDimitry Andric       break;
40180b57cec5SDimitry Andric     case Mips::BGELImmMacro:
40190b57cec5SDimitry Andric       PseudoOpcode = Mips::BGEL;
40200b57cec5SDimitry Andric       break;
40210b57cec5SDimitry Andric     case Mips::BGTLImmMacro:
40220b57cec5SDimitry Andric       PseudoOpcode = Mips::BGTL;
40230b57cec5SDimitry Andric       break;
40240b57cec5SDimitry Andric     case Mips::BLTULImmMacro:
40250b57cec5SDimitry Andric       PseudoOpcode = Mips::BLTUL;
40260b57cec5SDimitry Andric       break;
40270b57cec5SDimitry Andric     case Mips::BLEULImmMacro:
40280b57cec5SDimitry Andric       PseudoOpcode = Mips::BLEUL;
40290b57cec5SDimitry Andric       break;
40300b57cec5SDimitry Andric     case Mips::BGEULImmMacro:
40310b57cec5SDimitry Andric       PseudoOpcode = Mips::BGEUL;
40320b57cec5SDimitry Andric       break;
40330b57cec5SDimitry Andric     case Mips::BGTULImmMacro:
40340b57cec5SDimitry Andric       PseudoOpcode = Mips::BGTUL;
40350b57cec5SDimitry Andric       break;
40360b57cec5SDimitry Andric     }
40370b57cec5SDimitry Andric 
40380b57cec5SDimitry Andric     if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
40390b57cec5SDimitry Andric                       false, IDLoc, Out, STI))
40400b57cec5SDimitry Andric       return true;
40410b57cec5SDimitry Andric   }
40420b57cec5SDimitry Andric 
40430b57cec5SDimitry Andric   switch (PseudoOpcode) {
40440b57cec5SDimitry Andric   case Mips::BLT:
40450b57cec5SDimitry Andric   case Mips::BLTU:
40460b57cec5SDimitry Andric   case Mips::BLTL:
40470b57cec5SDimitry Andric   case Mips::BLTUL:
40480b57cec5SDimitry Andric     AcceptsEquality = false;
40490b57cec5SDimitry Andric     ReverseOrderSLT = false;
40500b57cec5SDimitry Andric     IsUnsigned =
40510b57cec5SDimitry Andric         ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
40520b57cec5SDimitry Andric     IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
40530b57cec5SDimitry Andric     ZeroSrcOpcode = Mips::BGTZ;
40540b57cec5SDimitry Andric     ZeroTrgOpcode = Mips::BLTZ;
40550b57cec5SDimitry Andric     break;
40560b57cec5SDimitry Andric   case Mips::BLE:
40570b57cec5SDimitry Andric   case Mips::BLEU:
40580b57cec5SDimitry Andric   case Mips::BLEL:
40590b57cec5SDimitry Andric   case Mips::BLEUL:
40600b57cec5SDimitry Andric     AcceptsEquality = true;
40610b57cec5SDimitry Andric     ReverseOrderSLT = true;
40620b57cec5SDimitry Andric     IsUnsigned =
40630b57cec5SDimitry Andric         ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
40640b57cec5SDimitry Andric     IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
40650b57cec5SDimitry Andric     ZeroSrcOpcode = Mips::BGEZ;
40660b57cec5SDimitry Andric     ZeroTrgOpcode = Mips::BLEZ;
40670b57cec5SDimitry Andric     break;
40680b57cec5SDimitry Andric   case Mips::BGE:
40690b57cec5SDimitry Andric   case Mips::BGEU:
40700b57cec5SDimitry Andric   case Mips::BGEL:
40710b57cec5SDimitry Andric   case Mips::BGEUL:
40720b57cec5SDimitry Andric     AcceptsEquality = true;
40730b57cec5SDimitry Andric     ReverseOrderSLT = false;
40740b57cec5SDimitry Andric     IsUnsigned =
40750b57cec5SDimitry Andric         ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
40760b57cec5SDimitry Andric     IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
40770b57cec5SDimitry Andric     ZeroSrcOpcode = Mips::BLEZ;
40780b57cec5SDimitry Andric     ZeroTrgOpcode = Mips::BGEZ;
40790b57cec5SDimitry Andric     break;
40800b57cec5SDimitry Andric   case Mips::BGT:
40810b57cec5SDimitry Andric   case Mips::BGTU:
40820b57cec5SDimitry Andric   case Mips::BGTL:
40830b57cec5SDimitry Andric   case Mips::BGTUL:
40840b57cec5SDimitry Andric     AcceptsEquality = false;
40850b57cec5SDimitry Andric     ReverseOrderSLT = true;
40860b57cec5SDimitry Andric     IsUnsigned =
40870b57cec5SDimitry Andric         ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
40880b57cec5SDimitry Andric     IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
40890b57cec5SDimitry Andric     ZeroSrcOpcode = Mips::BLTZ;
40900b57cec5SDimitry Andric     ZeroTrgOpcode = Mips::BGTZ;
40910b57cec5SDimitry Andric     break;
40920b57cec5SDimitry Andric   default:
40930b57cec5SDimitry Andric     llvm_unreachable("unknown opcode for branch pseudo-instruction");
40940b57cec5SDimitry Andric   }
40950b57cec5SDimitry Andric 
40960b57cec5SDimitry Andric   bool IsTrgRegZero = (TrgReg == Mips::ZERO);
40970b57cec5SDimitry Andric   bool IsSrcRegZero = (SrcReg == Mips::ZERO);
40980b57cec5SDimitry Andric   if (IsSrcRegZero && IsTrgRegZero) {
40990b57cec5SDimitry Andric     // FIXME: All of these Opcode-specific if's are needed for compatibility
41000b57cec5SDimitry Andric     // with GAS' behaviour. However, they may not generate the most efficient
41010b57cec5SDimitry Andric     // code in some circumstances.
41020b57cec5SDimitry Andric     if (PseudoOpcode == Mips::BLT) {
41030b57cec5SDimitry Andric       TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41040b57cec5SDimitry Andric                   IDLoc, STI);
41050b57cec5SDimitry Andric       return false;
41060b57cec5SDimitry Andric     }
41070b57cec5SDimitry Andric     if (PseudoOpcode == Mips::BLE) {
41080b57cec5SDimitry Andric       TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41090b57cec5SDimitry Andric                   IDLoc, STI);
41100b57cec5SDimitry Andric       Warning(IDLoc, "branch is always taken");
41110b57cec5SDimitry Andric       return false;
41120b57cec5SDimitry Andric     }
41130b57cec5SDimitry Andric     if (PseudoOpcode == Mips::BGE) {
41140b57cec5SDimitry Andric       TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41150b57cec5SDimitry Andric                   IDLoc, STI);
41160b57cec5SDimitry Andric       Warning(IDLoc, "branch is always taken");
41170b57cec5SDimitry Andric       return false;
41180b57cec5SDimitry Andric     }
41190b57cec5SDimitry Andric     if (PseudoOpcode == Mips::BGT) {
41200b57cec5SDimitry Andric       TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41210b57cec5SDimitry Andric                   IDLoc, STI);
41220b57cec5SDimitry Andric       return false;
41230b57cec5SDimitry Andric     }
41240b57cec5SDimitry Andric     if (PseudoOpcode == Mips::BGTU) {
41250b57cec5SDimitry Andric       TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
41260b57cec5SDimitry Andric                    MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41270b57cec5SDimitry Andric       return false;
41280b57cec5SDimitry Andric     }
41290b57cec5SDimitry Andric     if (AcceptsEquality) {
41300b57cec5SDimitry Andric       // If both registers are $0 and the pseudo-branch accepts equality, it
41310b57cec5SDimitry Andric       // will always be taken, so we emit an unconditional branch.
41320b57cec5SDimitry Andric       TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
41330b57cec5SDimitry Andric                    MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41340b57cec5SDimitry Andric       Warning(IDLoc, "branch is always taken");
41350b57cec5SDimitry Andric       return false;
41360b57cec5SDimitry Andric     }
41370b57cec5SDimitry Andric     // If both registers are $0 and the pseudo-branch does not accept
41380b57cec5SDimitry Andric     // equality, it will never be taken, so we don't have to emit anything.
41390b57cec5SDimitry Andric     return false;
41400b57cec5SDimitry Andric   }
41410b57cec5SDimitry Andric   if (IsSrcRegZero || IsTrgRegZero) {
41420b57cec5SDimitry Andric     if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
41430b57cec5SDimitry Andric         (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
41440b57cec5SDimitry Andric       // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
41450b57cec5SDimitry Andric       // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
41460b57cec5SDimitry Andric       // the pseudo-branch will never be taken, so we don't emit anything.
41470b57cec5SDimitry Andric       // This only applies to unsigned pseudo-branches.
41480b57cec5SDimitry Andric       return false;
41490b57cec5SDimitry Andric     }
41500b57cec5SDimitry Andric     if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
41510b57cec5SDimitry Andric         (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
41520b57cec5SDimitry Andric       // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
41530b57cec5SDimitry Andric       // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
41540b57cec5SDimitry Andric       // the pseudo-branch will always be taken, so we emit an unconditional
41550b57cec5SDimitry Andric       // branch.
41560b57cec5SDimitry Andric       // This only applies to unsigned pseudo-branches.
41570b57cec5SDimitry Andric       TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
41580b57cec5SDimitry Andric                    MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41590b57cec5SDimitry Andric       Warning(IDLoc, "branch is always taken");
41600b57cec5SDimitry Andric       return false;
41610b57cec5SDimitry Andric     }
41620b57cec5SDimitry Andric     if (IsUnsigned) {
41630b57cec5SDimitry Andric       // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
41640b57cec5SDimitry Andric       // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
41650b57cec5SDimitry Andric       // the pseudo-branch will be taken only when the non-zero register is
41660b57cec5SDimitry Andric       // different from 0, so we emit a BNEZ.
41670b57cec5SDimitry Andric       //
41680b57cec5SDimitry Andric       // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
41690b57cec5SDimitry Andric       // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
41700b57cec5SDimitry Andric       // the pseudo-branch will be taken only when the non-zero register is
41710b57cec5SDimitry Andric       // equal to 0, so we emit a BEQZ.
41720b57cec5SDimitry Andric       //
41730b57cec5SDimitry Andric       // Because only BLEU and BGEU branch on equality, we can use the
41740b57cec5SDimitry Andric       // AcceptsEquality variable to decide when to emit the BEQZ.
41750b57cec5SDimitry Andric       TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
41760b57cec5SDimitry Andric                    IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
41770b57cec5SDimitry Andric                    MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41780b57cec5SDimitry Andric       return false;
41790b57cec5SDimitry Andric     }
41800b57cec5SDimitry Andric     // If we have a signed pseudo-branch and one of the registers is $0,
41810b57cec5SDimitry Andric     // we can use an appropriate compare-to-zero branch. We select which one
41820b57cec5SDimitry Andric     // to use in the switch statement above.
41830b57cec5SDimitry Andric     TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
41840b57cec5SDimitry Andric                 IsSrcRegZero ? TrgReg : SrcReg,
41850b57cec5SDimitry Andric                 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41860b57cec5SDimitry Andric     return false;
41870b57cec5SDimitry Andric   }
41880b57cec5SDimitry Andric 
41890b57cec5SDimitry Andric   // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
41900b57cec5SDimitry Andric   // expansions. If it is not available, we return.
41910b57cec5SDimitry Andric   unsigned ATRegNum = getATReg(IDLoc);
41920b57cec5SDimitry Andric   if (!ATRegNum)
41930b57cec5SDimitry Andric     return true;
41940b57cec5SDimitry Andric 
41950b57cec5SDimitry Andric   if (!EmittedNoMacroWarning)
41960b57cec5SDimitry Andric     warnIfNoMacro(IDLoc);
41970b57cec5SDimitry Andric 
41980b57cec5SDimitry Andric   // SLT fits well with 2 of our 4 pseudo-branches:
41990b57cec5SDimitry Andric   //   BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
42000b57cec5SDimitry Andric   //   BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
42010b57cec5SDimitry Andric   // If the result of the SLT is 1, we branch, and if it's 0, we don't.
42020b57cec5SDimitry Andric   // This is accomplished by using a BNEZ with the result of the SLT.
42030b57cec5SDimitry Andric   //
42040b57cec5SDimitry Andric   // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
42050b57cec5SDimitry Andric   // and BLE with BGT), so we change the BNEZ into a BEQZ.
42060b57cec5SDimitry Andric   // Because only BGE and BLE branch on equality, we can use the
42070b57cec5SDimitry Andric   // AcceptsEquality variable to decide when to emit the BEQZ.
42080b57cec5SDimitry Andric   // Note that the order of the SLT arguments doesn't change between
42090b57cec5SDimitry Andric   // opposites.
42100b57cec5SDimitry Andric   //
42110b57cec5SDimitry Andric   // The same applies to the unsigned variants, except that SLTu is used
42120b57cec5SDimitry Andric   // instead of SLT.
42130b57cec5SDimitry Andric   TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
42140b57cec5SDimitry Andric                ReverseOrderSLT ? TrgReg : SrcReg,
42150b57cec5SDimitry Andric                ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
42160b57cec5SDimitry Andric 
42170b57cec5SDimitry Andric   TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
42180b57cec5SDimitry Andric                         : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
42190b57cec5SDimitry Andric                ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
42200b57cec5SDimitry Andric                STI);
42210b57cec5SDimitry Andric   return false;
42220b57cec5SDimitry Andric }
42230b57cec5SDimitry Andric 
42240b57cec5SDimitry Andric // Expand a integer division macro.
42250b57cec5SDimitry Andric //
42260b57cec5SDimitry Andric // Notably we don't have to emit a warning when encountering $rt as the $zero
42270b57cec5SDimitry Andric // register, or 0 as an immediate. processInstruction() has already done that.
42280b57cec5SDimitry Andric //
42290b57cec5SDimitry Andric // The destination register can only be $zero when expanding (S)DivIMacro or
42300b57cec5SDimitry Andric // D(S)DivMacro.
42310b57cec5SDimitry Andric 
expandDivRem(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,const bool IsMips64,const bool Signed)42320b57cec5SDimitry Andric bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4233480093f4SDimitry Andric                                  const MCSubtargetInfo *STI,
4234480093f4SDimitry Andric                                  const bool IsMips64, const bool Signed) {
42350b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
42360b57cec5SDimitry Andric 
42370b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
42380b57cec5SDimitry Andric 
42390b57cec5SDimitry Andric   const MCOperand &RdRegOp = Inst.getOperand(0);
42400b57cec5SDimitry Andric   assert(RdRegOp.isReg() && "expected register operand kind");
42410b57cec5SDimitry Andric   unsigned RdReg = RdRegOp.getReg();
42420b57cec5SDimitry Andric 
42430b57cec5SDimitry Andric   const MCOperand &RsRegOp = Inst.getOperand(1);
42440b57cec5SDimitry Andric   assert(RsRegOp.isReg() && "expected register operand kind");
42450b57cec5SDimitry Andric   unsigned RsReg = RsRegOp.getReg();
42460b57cec5SDimitry Andric 
42470b57cec5SDimitry Andric   unsigned RtReg;
42480b57cec5SDimitry Andric   int64_t ImmValue;
42490b57cec5SDimitry Andric 
42500b57cec5SDimitry Andric   const MCOperand &RtOp = Inst.getOperand(2);
42510b57cec5SDimitry Andric   assert((RtOp.isReg() || RtOp.isImm()) &&
42520b57cec5SDimitry Andric          "expected register or immediate operand kind");
42530b57cec5SDimitry Andric   if (RtOp.isReg())
42540b57cec5SDimitry Andric     RtReg = RtOp.getReg();
42550b57cec5SDimitry Andric   else
42560b57cec5SDimitry Andric     ImmValue = RtOp.getImm();
42570b57cec5SDimitry Andric 
42580b57cec5SDimitry Andric   unsigned DivOp;
42590b57cec5SDimitry Andric   unsigned ZeroReg;
42600b57cec5SDimitry Andric   unsigned SubOp;
42610b57cec5SDimitry Andric 
42620b57cec5SDimitry Andric   if (IsMips64) {
42630b57cec5SDimitry Andric     DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
42640b57cec5SDimitry Andric     ZeroReg = Mips::ZERO_64;
42650b57cec5SDimitry Andric     SubOp = Mips::DSUB;
42660b57cec5SDimitry Andric   } else {
42670b57cec5SDimitry Andric     DivOp = Signed ? Mips::SDIV : Mips::UDIV;
42680b57cec5SDimitry Andric     ZeroReg = Mips::ZERO;
42690b57cec5SDimitry Andric     SubOp = Mips::SUB;
42700b57cec5SDimitry Andric   }
42710b57cec5SDimitry Andric 
42720b57cec5SDimitry Andric   bool UseTraps = useTraps();
42730b57cec5SDimitry Andric 
42740b57cec5SDimitry Andric   unsigned Opcode = Inst.getOpcode();
42750b57cec5SDimitry Andric   bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
42760b57cec5SDimitry Andric                Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
42770b57cec5SDimitry Andric                Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
42780b57cec5SDimitry Andric                Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
42790b57cec5SDimitry Andric 
42800b57cec5SDimitry Andric   bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
42810b57cec5SDimitry Andric                Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
42820b57cec5SDimitry Andric                Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
42830b57cec5SDimitry Andric                Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
42840b57cec5SDimitry Andric 
42850b57cec5SDimitry Andric   if (RtOp.isImm()) {
42860b57cec5SDimitry Andric     unsigned ATReg = getATReg(IDLoc);
42870b57cec5SDimitry Andric     if (!ATReg)
42880b57cec5SDimitry Andric       return true;
42890b57cec5SDimitry Andric 
42900b57cec5SDimitry Andric     if (ImmValue == 0) {
42910b57cec5SDimitry Andric       if (UseTraps)
42920b57cec5SDimitry Andric         TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
42930b57cec5SDimitry Andric       else
42940b57cec5SDimitry Andric         TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
42950b57cec5SDimitry Andric       return false;
42960b57cec5SDimitry Andric     }
42970b57cec5SDimitry Andric 
42980b57cec5SDimitry Andric     if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
42990b57cec5SDimitry Andric       TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
43000b57cec5SDimitry Andric       return false;
43010b57cec5SDimitry Andric     } else if (isDiv && ImmValue == 1) {
43020b57cec5SDimitry Andric       TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
43030b57cec5SDimitry Andric       return false;
43040b57cec5SDimitry Andric     } else if (isDiv && Signed && ImmValue == -1) {
43050b57cec5SDimitry Andric       TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
43060b57cec5SDimitry Andric       return false;
43070b57cec5SDimitry Andric     } else {
43080b57cec5SDimitry Andric       if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
43090b57cec5SDimitry Andric                         false, Inst.getLoc(), Out, STI))
43100b57cec5SDimitry Andric         return true;
43110b57cec5SDimitry Andric       TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
43120b57cec5SDimitry Andric       TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
43130b57cec5SDimitry Andric       return false;
43140b57cec5SDimitry Andric     }
43150b57cec5SDimitry Andric     return true;
43160b57cec5SDimitry Andric   }
43170b57cec5SDimitry Andric 
43180b57cec5SDimitry Andric   // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
43190b57cec5SDimitry Andric   // break, insert the trap/break and exit. This gives a different result to
43200b57cec5SDimitry Andric   // GAS. GAS has an inconsistency/missed optimization in that not all cases
43210b57cec5SDimitry Andric   // are handled equivalently. As the observed behaviour is the same, we're ok.
43220b57cec5SDimitry Andric   if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
43230b57cec5SDimitry Andric     if (UseTraps) {
43240b57cec5SDimitry Andric       TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
43250b57cec5SDimitry Andric       return false;
43260b57cec5SDimitry Andric     }
43270b57cec5SDimitry Andric     TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
43280b57cec5SDimitry Andric     return false;
43290b57cec5SDimitry Andric   }
43300b57cec5SDimitry Andric 
43310b57cec5SDimitry Andric   // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
43320b57cec5SDimitry Andric   // not expand to macro sequence.
43330b57cec5SDimitry Andric   if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
43340b57cec5SDimitry Andric     TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
43350b57cec5SDimitry Andric     return false;
43360b57cec5SDimitry Andric   }
43370b57cec5SDimitry Andric 
43380b57cec5SDimitry Andric   // Temporary label for first branch traget
43390b57cec5SDimitry Andric   MCContext &Context = TOut.getStreamer().getContext();
43400b57cec5SDimitry Andric   MCSymbol *BrTarget;
43410b57cec5SDimitry Andric   MCOperand LabelOp;
43420b57cec5SDimitry Andric 
43430b57cec5SDimitry Andric   if (UseTraps) {
43440b57cec5SDimitry Andric     TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
43450b57cec5SDimitry Andric   } else {
43460b57cec5SDimitry Andric     // Branch to the li instruction.
43470b57cec5SDimitry Andric     BrTarget = Context.createTempSymbol();
43480b57cec5SDimitry Andric     LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
43490b57cec5SDimitry Andric     TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
43500b57cec5SDimitry Andric   }
43510b57cec5SDimitry Andric 
43520b57cec5SDimitry Andric   TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
43530b57cec5SDimitry Andric 
43540b57cec5SDimitry Andric   if (!UseTraps)
43550b57cec5SDimitry Andric     TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
43560b57cec5SDimitry Andric 
43570b57cec5SDimitry Andric   if (!Signed) {
43580b57cec5SDimitry Andric     if (!UseTraps)
43595ffd83dbSDimitry Andric       TOut.getStreamer().emitLabel(BrTarget);
43600b57cec5SDimitry Andric 
43610b57cec5SDimitry Andric     TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
43620b57cec5SDimitry Andric     return false;
43630b57cec5SDimitry Andric   }
43640b57cec5SDimitry Andric 
43650b57cec5SDimitry Andric   unsigned ATReg = getATReg(IDLoc);
43660b57cec5SDimitry Andric   if (!ATReg)
43670b57cec5SDimitry Andric     return true;
43680b57cec5SDimitry Andric 
43690b57cec5SDimitry Andric   if (!UseTraps)
43705ffd83dbSDimitry Andric     TOut.getStreamer().emitLabel(BrTarget);
43710b57cec5SDimitry Andric 
43720b57cec5SDimitry Andric   TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
43730b57cec5SDimitry Andric 
43740b57cec5SDimitry Andric   // Temporary label for the second branch target.
43750b57cec5SDimitry Andric   MCSymbol *BrTargetEnd = Context.createTempSymbol();
43760b57cec5SDimitry Andric   MCOperand LabelOpEnd =
43770b57cec5SDimitry Andric       MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
43780b57cec5SDimitry Andric 
43790b57cec5SDimitry Andric   // Branch to the mflo instruction.
43800b57cec5SDimitry Andric   TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
43810b57cec5SDimitry Andric 
43820b57cec5SDimitry Andric   if (IsMips64) {
43830b57cec5SDimitry Andric     TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
43840b57cec5SDimitry Andric     TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
43850b57cec5SDimitry Andric   } else {
43860b57cec5SDimitry Andric     TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
43870b57cec5SDimitry Andric   }
43880b57cec5SDimitry Andric 
43890b57cec5SDimitry Andric   if (UseTraps)
43900b57cec5SDimitry Andric     TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
43910b57cec5SDimitry Andric   else {
43920b57cec5SDimitry Andric     // Branch to the mflo instruction.
43930b57cec5SDimitry Andric     TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
43940b57cec5SDimitry Andric     TOut.emitNop(IDLoc, STI);
43950b57cec5SDimitry Andric     TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
43960b57cec5SDimitry Andric   }
43970b57cec5SDimitry Andric 
43985ffd83dbSDimitry Andric   TOut.getStreamer().emitLabel(BrTargetEnd);
43990b57cec5SDimitry Andric   TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
44000b57cec5SDimitry Andric   return false;
44010b57cec5SDimitry Andric }
44020b57cec5SDimitry Andric 
expandTrunc(MCInst & Inst,bool IsDouble,bool Is64FPU,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)44030b57cec5SDimitry Andric bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
44040b57cec5SDimitry Andric                                 SMLoc IDLoc, MCStreamer &Out,
44050b57cec5SDimitry Andric                                 const MCSubtargetInfo *STI) {
44060b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
44070b57cec5SDimitry Andric 
44080b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
44090b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
44100b57cec5SDimitry Andric          Inst.getOperand(2).isReg() && "Invalid instruction operand.");
44110b57cec5SDimitry Andric 
44120b57cec5SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
44130b57cec5SDimitry Andric   unsigned SecondReg = Inst.getOperand(1).getReg();
44140b57cec5SDimitry Andric   unsigned ThirdReg = Inst.getOperand(2).getReg();
44150b57cec5SDimitry Andric 
44160b57cec5SDimitry Andric   if (hasMips1() && !hasMips2()) {
44170b57cec5SDimitry Andric     unsigned ATReg = getATReg(IDLoc);
44180b57cec5SDimitry Andric     if (!ATReg)
44190b57cec5SDimitry Andric       return true;
44200b57cec5SDimitry Andric     TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
44210b57cec5SDimitry Andric     TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
44220b57cec5SDimitry Andric     TOut.emitNop(IDLoc, STI);
44230b57cec5SDimitry Andric     TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
44240b57cec5SDimitry Andric     TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
44250b57cec5SDimitry Andric     TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
44260b57cec5SDimitry Andric     TOut.emitNop(IDLoc, STI);
44270b57cec5SDimitry Andric     TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
44280b57cec5SDimitry Andric                          : Mips::CVT_W_S,
44290b57cec5SDimitry Andric                 FirstReg, SecondReg, IDLoc, STI);
44300b57cec5SDimitry Andric     TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
44310b57cec5SDimitry Andric     TOut.emitNop(IDLoc, STI);
44320b57cec5SDimitry Andric     return false;
44330b57cec5SDimitry Andric   }
44340b57cec5SDimitry Andric 
44350b57cec5SDimitry Andric   TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
44360b57cec5SDimitry Andric                        : Mips::TRUNC_W_S,
44370b57cec5SDimitry Andric               FirstReg, SecondReg, IDLoc, STI);
44380b57cec5SDimitry Andric 
44390b57cec5SDimitry Andric   return false;
44400b57cec5SDimitry Andric }
44410b57cec5SDimitry Andric 
expandUlh(MCInst & Inst,bool Signed,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)44420b57cec5SDimitry Andric bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
44430b57cec5SDimitry Andric                               MCStreamer &Out, const MCSubtargetInfo *STI) {
44440b57cec5SDimitry Andric   if (hasMips32r6() || hasMips64r6()) {
44450b57cec5SDimitry Andric     return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
44460b57cec5SDimitry Andric   }
44470b57cec5SDimitry Andric 
44480b57cec5SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(0);
44490b57cec5SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
44500b57cec5SDimitry Andric   const MCOperand &SrcRegOp = Inst.getOperand(1);
44510b57cec5SDimitry Andric   assert(SrcRegOp.isReg() && "expected register operand kind");
44520b57cec5SDimitry Andric   const MCOperand &OffsetImmOp = Inst.getOperand(2);
44530b57cec5SDimitry Andric   assert(OffsetImmOp.isImm() && "expected immediate operand kind");
44540b57cec5SDimitry Andric 
44550b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
44560b57cec5SDimitry Andric   unsigned DstReg = DstRegOp.getReg();
44570b57cec5SDimitry Andric   unsigned SrcReg = SrcRegOp.getReg();
44580b57cec5SDimitry Andric   int64_t OffsetValue = OffsetImmOp.getImm();
44590b57cec5SDimitry Andric 
44600b57cec5SDimitry Andric   // NOTE: We always need AT for ULHU, as it is always used as the source
44610b57cec5SDimitry Andric   // register for one of the LBu's.
44620b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
44630b57cec5SDimitry Andric   unsigned ATReg = getATReg(IDLoc);
44640b57cec5SDimitry Andric   if (!ATReg)
44650b57cec5SDimitry Andric     return true;
44660b57cec5SDimitry Andric 
44670b57cec5SDimitry Andric   bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
44680b57cec5SDimitry Andric   if (IsLargeOffset) {
44690b57cec5SDimitry Andric     if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
44700b57cec5SDimitry Andric                       IDLoc, Out, STI))
44710b57cec5SDimitry Andric       return true;
44720b57cec5SDimitry Andric   }
44730b57cec5SDimitry Andric 
44740b57cec5SDimitry Andric   int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
44750b57cec5SDimitry Andric   int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
44760b57cec5SDimitry Andric   if (isLittle())
44770b57cec5SDimitry Andric     std::swap(FirstOffset, SecondOffset);
44780b57cec5SDimitry Andric 
44790b57cec5SDimitry Andric   unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
44800b57cec5SDimitry Andric   unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
44810b57cec5SDimitry Andric 
44820b57cec5SDimitry Andric   unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
44830b57cec5SDimitry Andric   unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
44840b57cec5SDimitry Andric 
44850b57cec5SDimitry Andric   TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
44860b57cec5SDimitry Andric                FirstOffset, IDLoc, STI);
44870b57cec5SDimitry Andric   TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
44880b57cec5SDimitry Andric   TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
44890b57cec5SDimitry Andric   TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
44900b57cec5SDimitry Andric 
44910b57cec5SDimitry Andric   return false;
44920b57cec5SDimitry Andric }
44930b57cec5SDimitry Andric 
expandUsh(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)44940b57cec5SDimitry Andric bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
44950b57cec5SDimitry Andric                               const MCSubtargetInfo *STI) {
44960b57cec5SDimitry Andric   if (hasMips32r6() || hasMips64r6()) {
44970b57cec5SDimitry Andric     return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
44980b57cec5SDimitry Andric   }
44990b57cec5SDimitry Andric 
45000b57cec5SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(0);
45010b57cec5SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
45020b57cec5SDimitry Andric   const MCOperand &SrcRegOp = Inst.getOperand(1);
45030b57cec5SDimitry Andric   assert(SrcRegOp.isReg() && "expected register operand kind");
45040b57cec5SDimitry Andric   const MCOperand &OffsetImmOp = Inst.getOperand(2);
45050b57cec5SDimitry Andric   assert(OffsetImmOp.isImm() && "expected immediate operand kind");
45060b57cec5SDimitry Andric 
45070b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
45080b57cec5SDimitry Andric   unsigned DstReg = DstRegOp.getReg();
45090b57cec5SDimitry Andric   unsigned SrcReg = SrcRegOp.getReg();
45100b57cec5SDimitry Andric   int64_t OffsetValue = OffsetImmOp.getImm();
45110b57cec5SDimitry Andric 
45120b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
45130b57cec5SDimitry Andric   unsigned ATReg = getATReg(IDLoc);
45140b57cec5SDimitry Andric   if (!ATReg)
45150b57cec5SDimitry Andric     return true;
45160b57cec5SDimitry Andric 
45170b57cec5SDimitry Andric   bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
45180b57cec5SDimitry Andric   if (IsLargeOffset) {
45190b57cec5SDimitry Andric     if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
45200b57cec5SDimitry Andric                       IDLoc, Out, STI))
45210b57cec5SDimitry Andric       return true;
45220b57cec5SDimitry Andric   }
45230b57cec5SDimitry Andric 
45240b57cec5SDimitry Andric   int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
45250b57cec5SDimitry Andric   int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
45260b57cec5SDimitry Andric   if (isLittle())
45270b57cec5SDimitry Andric     std::swap(FirstOffset, SecondOffset);
45280b57cec5SDimitry Andric 
45290b57cec5SDimitry Andric   if (IsLargeOffset) {
45300b57cec5SDimitry Andric     TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
45310b57cec5SDimitry Andric     TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
45320b57cec5SDimitry Andric     TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
45330b57cec5SDimitry Andric     TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
45340b57cec5SDimitry Andric     TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
45350b57cec5SDimitry Andric     TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
45360b57cec5SDimitry Andric   } else {
45370b57cec5SDimitry Andric     TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
45380b57cec5SDimitry Andric     TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
45390b57cec5SDimitry Andric     TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
45400b57cec5SDimitry Andric   }
45410b57cec5SDimitry Andric 
45420b57cec5SDimitry Andric   return false;
45430b57cec5SDimitry Andric }
45440b57cec5SDimitry Andric 
expandUxw(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)45450b57cec5SDimitry Andric bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
45460b57cec5SDimitry Andric                               const MCSubtargetInfo *STI) {
45470b57cec5SDimitry Andric   if (hasMips32r6() || hasMips64r6()) {
45480b57cec5SDimitry Andric     return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
45490b57cec5SDimitry Andric   }
45500b57cec5SDimitry Andric 
45510b57cec5SDimitry Andric   const MCOperand &DstRegOp = Inst.getOperand(0);
45520b57cec5SDimitry Andric   assert(DstRegOp.isReg() && "expected register operand kind");
45530b57cec5SDimitry Andric   const MCOperand &SrcRegOp = Inst.getOperand(1);
45540b57cec5SDimitry Andric   assert(SrcRegOp.isReg() && "expected register operand kind");
45550b57cec5SDimitry Andric   const MCOperand &OffsetImmOp = Inst.getOperand(2);
45560b57cec5SDimitry Andric   assert(OffsetImmOp.isImm() && "expected immediate operand kind");
45570b57cec5SDimitry Andric 
45580b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
45590b57cec5SDimitry Andric   unsigned DstReg = DstRegOp.getReg();
45600b57cec5SDimitry Andric   unsigned SrcReg = SrcRegOp.getReg();
45610b57cec5SDimitry Andric   int64_t OffsetValue = OffsetImmOp.getImm();
45620b57cec5SDimitry Andric 
45630b57cec5SDimitry Andric   // Compute left/right load/store offsets.
45640b57cec5SDimitry Andric   bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
45650b57cec5SDimitry Andric   int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
45660b57cec5SDimitry Andric   int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
45670b57cec5SDimitry Andric   if (isLittle())
45680b57cec5SDimitry Andric     std::swap(LxlOffset, LxrOffset);
45690b57cec5SDimitry Andric 
45700b57cec5SDimitry Andric   bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
45710b57cec5SDimitry Andric   bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
45720b57cec5SDimitry Andric   unsigned TmpReg = SrcReg;
45730b57cec5SDimitry Andric   if (IsLargeOffset || DoMove) {
45740b57cec5SDimitry Andric     warnIfNoMacro(IDLoc);
45750b57cec5SDimitry Andric     TmpReg = getATReg(IDLoc);
45760b57cec5SDimitry Andric     if (!TmpReg)
45770b57cec5SDimitry Andric       return true;
45780b57cec5SDimitry Andric   }
45790b57cec5SDimitry Andric 
45800b57cec5SDimitry Andric   if (IsLargeOffset) {
45810b57cec5SDimitry Andric     if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
45820b57cec5SDimitry Andric                       IDLoc, Out, STI))
45830b57cec5SDimitry Andric       return true;
45840b57cec5SDimitry Andric   }
45850b57cec5SDimitry Andric 
45860b57cec5SDimitry Andric   if (DoMove)
45870b57cec5SDimitry Andric     std::swap(DstReg, TmpReg);
45880b57cec5SDimitry Andric 
45890b57cec5SDimitry Andric   unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
45900b57cec5SDimitry Andric   unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
45910b57cec5SDimitry Andric   TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
45920b57cec5SDimitry Andric   TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
45930b57cec5SDimitry Andric 
45940b57cec5SDimitry Andric   if (DoMove)
45950b57cec5SDimitry Andric     TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
45960b57cec5SDimitry Andric 
45970b57cec5SDimitry Andric   return false;
45980b57cec5SDimitry Andric }
45990b57cec5SDimitry Andric 
expandSge(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)46000b57cec5SDimitry Andric bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
46010b57cec5SDimitry Andric                               const MCSubtargetInfo *STI) {
46020b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
46030b57cec5SDimitry Andric 
46040b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
46050b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() &&
46060b57cec5SDimitry Andric          Inst.getOperand(1).isReg() &&
46070b57cec5SDimitry Andric          Inst.getOperand(2).isReg() && "Invalid instruction operand.");
46080b57cec5SDimitry Andric 
46090b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
46100b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
46110b57cec5SDimitry Andric   unsigned OpReg = Inst.getOperand(2).getReg();
46120b57cec5SDimitry Andric   unsigned OpCode;
46130b57cec5SDimitry Andric 
46140b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
46150b57cec5SDimitry Andric 
46160b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
46170b57cec5SDimitry Andric   case Mips::SGE:
46180b57cec5SDimitry Andric     OpCode = Mips::SLT;
46190b57cec5SDimitry Andric     break;
46200b57cec5SDimitry Andric   case Mips::SGEU:
46210b57cec5SDimitry Andric     OpCode = Mips::SLTu;
46220b57cec5SDimitry Andric     break;
46230b57cec5SDimitry Andric   default:
46240b57cec5SDimitry Andric     llvm_unreachable("unexpected 'sge' opcode");
46250b57cec5SDimitry Andric   }
46260b57cec5SDimitry Andric 
46270b57cec5SDimitry Andric   // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg))
46280b57cec5SDimitry Andric   TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI);
46290b57cec5SDimitry Andric   TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
46300b57cec5SDimitry Andric 
46310b57cec5SDimitry Andric   return false;
46320b57cec5SDimitry Andric }
46330b57cec5SDimitry Andric 
expandSgeImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)46340b57cec5SDimitry Andric bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
46350b57cec5SDimitry Andric                                  const MCSubtargetInfo *STI) {
46360b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
46370b57cec5SDimitry Andric 
46380b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
46390b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() &&
46400b57cec5SDimitry Andric          Inst.getOperand(1).isReg() &&
46410b57cec5SDimitry Andric          Inst.getOperand(2).isImm() && "Invalid instruction operand.");
46420b57cec5SDimitry Andric 
46430b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
46440b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
46450b57cec5SDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm();
46460b57cec5SDimitry Andric   unsigned OpRegCode, OpImmCode;
46470b57cec5SDimitry Andric 
46480b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
46490b57cec5SDimitry Andric 
46500b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
46510b57cec5SDimitry Andric   case Mips::SGEImm:
46520b57cec5SDimitry Andric   case Mips::SGEImm64:
46530b57cec5SDimitry Andric     OpRegCode = Mips::SLT;
46540b57cec5SDimitry Andric     OpImmCode = Mips::SLTi;
46550b57cec5SDimitry Andric     break;
46560b57cec5SDimitry Andric   case Mips::SGEUImm:
46570b57cec5SDimitry Andric   case Mips::SGEUImm64:
46580b57cec5SDimitry Andric     OpRegCode = Mips::SLTu;
46590b57cec5SDimitry Andric     OpImmCode = Mips::SLTiu;
46600b57cec5SDimitry Andric     break;
46610b57cec5SDimitry Andric   default:
46620b57cec5SDimitry Andric     llvm_unreachable("unexpected 'sge' opcode with immediate");
46630b57cec5SDimitry Andric   }
46640b57cec5SDimitry Andric 
46650b57cec5SDimitry Andric   // $SrcReg >= Imm is equal to (not ($SrcReg < Imm))
46660b57cec5SDimitry Andric   if (isInt<16>(ImmValue)) {
46670b57cec5SDimitry Andric     // Use immediate version of STL.
46680b57cec5SDimitry Andric     TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI);
46690b57cec5SDimitry Andric     TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
46700b57cec5SDimitry Andric   } else {
46710b57cec5SDimitry Andric     unsigned ImmReg = DstReg;
46720b57cec5SDimitry Andric     if (DstReg == SrcReg) {
46730b57cec5SDimitry Andric       unsigned ATReg = getATReg(Inst.getLoc());
46740b57cec5SDimitry Andric       if (!ATReg)
46750b57cec5SDimitry Andric         return true;
46760b57cec5SDimitry Andric       ImmReg = ATReg;
46770b57cec5SDimitry Andric     }
46780b57cec5SDimitry Andric 
46790b57cec5SDimitry Andric     if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
46800b57cec5SDimitry Andric                       false, IDLoc, Out, STI))
46810b57cec5SDimitry Andric       return true;
46820b57cec5SDimitry Andric 
46830b57cec5SDimitry Andric     TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI);
46840b57cec5SDimitry Andric     TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
46850b57cec5SDimitry Andric   }
46860b57cec5SDimitry Andric 
46870b57cec5SDimitry Andric   return false;
46880b57cec5SDimitry Andric }
46890b57cec5SDimitry Andric 
expandSgtImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)46900b57cec5SDimitry Andric bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
46910b57cec5SDimitry Andric                                  const MCSubtargetInfo *STI) {
46920b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
46930b57cec5SDimitry Andric 
46940b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
46950b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() &&
46960b57cec5SDimitry Andric          Inst.getOperand(1).isReg() &&
46970b57cec5SDimitry Andric          Inst.getOperand(2).isImm() && "Invalid instruction operand.");
46980b57cec5SDimitry Andric 
46990b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
47000b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
47010b57cec5SDimitry Andric   unsigned ImmReg = DstReg;
47020b57cec5SDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm();
47030b57cec5SDimitry Andric   unsigned OpCode;
47040b57cec5SDimitry Andric 
47050b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
47060b57cec5SDimitry Andric 
47070b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
47080b57cec5SDimitry Andric   case Mips::SGTImm:
47090b57cec5SDimitry Andric   case Mips::SGTImm64:
47100b57cec5SDimitry Andric     OpCode = Mips::SLT;
47110b57cec5SDimitry Andric     break;
47120b57cec5SDimitry Andric   case Mips::SGTUImm:
47130b57cec5SDimitry Andric   case Mips::SGTUImm64:
47140b57cec5SDimitry Andric     OpCode = Mips::SLTu;
47150b57cec5SDimitry Andric     break;
47160b57cec5SDimitry Andric   default:
47170b57cec5SDimitry Andric     llvm_unreachable("unexpected 'sgt' opcode with immediate");
47180b57cec5SDimitry Andric   }
47190b57cec5SDimitry Andric 
47200b57cec5SDimitry Andric   if (DstReg == SrcReg) {
47210b57cec5SDimitry Andric     unsigned ATReg = getATReg(Inst.getLoc());
47220b57cec5SDimitry Andric     if (!ATReg)
47230b57cec5SDimitry Andric       return true;
47240b57cec5SDimitry Andric     ImmReg = ATReg;
47250b57cec5SDimitry Andric   }
47260b57cec5SDimitry Andric 
47270b57cec5SDimitry Andric   if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
47280b57cec5SDimitry Andric                     false, IDLoc, Out, STI))
47290b57cec5SDimitry Andric     return true;
47300b57cec5SDimitry Andric 
47310b57cec5SDimitry Andric   // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg
47320b57cec5SDimitry Andric   TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
47330b57cec5SDimitry Andric 
47340b57cec5SDimitry Andric   return false;
47350b57cec5SDimitry Andric }
47360b57cec5SDimitry Andric 
expandSle(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)47375ffd83dbSDimitry Andric bool MipsAsmParser::expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
47385ffd83dbSDimitry Andric                               const MCSubtargetInfo *STI) {
47395ffd83dbSDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
47405ffd83dbSDimitry Andric 
47415ffd83dbSDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
47425ffd83dbSDimitry Andric   assert(Inst.getOperand(0).isReg() &&
47435ffd83dbSDimitry Andric          Inst.getOperand(1).isReg() &&
47445ffd83dbSDimitry Andric          Inst.getOperand(2).isReg() && "Invalid instruction operand.");
47455ffd83dbSDimitry Andric 
47465ffd83dbSDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
47475ffd83dbSDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
47485ffd83dbSDimitry Andric   unsigned OpReg = Inst.getOperand(2).getReg();
47495ffd83dbSDimitry Andric   unsigned OpCode;
47505ffd83dbSDimitry Andric 
47515ffd83dbSDimitry Andric   warnIfNoMacro(IDLoc);
47525ffd83dbSDimitry Andric 
47535ffd83dbSDimitry Andric   switch (Inst.getOpcode()) {
47545ffd83dbSDimitry Andric   case Mips::SLE:
47555ffd83dbSDimitry Andric     OpCode = Mips::SLT;
47565ffd83dbSDimitry Andric     break;
47575ffd83dbSDimitry Andric   case Mips::SLEU:
47585ffd83dbSDimitry Andric     OpCode = Mips::SLTu;
47595ffd83dbSDimitry Andric     break;
47605ffd83dbSDimitry Andric   default:
47615ffd83dbSDimitry Andric     llvm_unreachable("unexpected 'sge' opcode");
47625ffd83dbSDimitry Andric   }
47635ffd83dbSDimitry Andric 
47645ffd83dbSDimitry Andric   // $SrcReg <= $OpReg is equal to (not ($OpReg < $SrcReg))
47655ffd83dbSDimitry Andric   TOut.emitRRR(OpCode, DstReg, OpReg, SrcReg, IDLoc, STI);
47665ffd83dbSDimitry Andric   TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
47675ffd83dbSDimitry Andric 
47685ffd83dbSDimitry Andric   return false;
47695ffd83dbSDimitry Andric }
47705ffd83dbSDimitry Andric 
expandSleImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)47715ffd83dbSDimitry Andric bool MipsAsmParser::expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
47725ffd83dbSDimitry Andric                                  const MCSubtargetInfo *STI) {
47735ffd83dbSDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
47745ffd83dbSDimitry Andric 
47755ffd83dbSDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
47765ffd83dbSDimitry Andric   assert(Inst.getOperand(0).isReg() &&
47775ffd83dbSDimitry Andric          Inst.getOperand(1).isReg() &&
47785ffd83dbSDimitry Andric          Inst.getOperand(2).isImm() && "Invalid instruction operand.");
47795ffd83dbSDimitry Andric 
47805ffd83dbSDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
47815ffd83dbSDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
47825ffd83dbSDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm();
47835ffd83dbSDimitry Andric   unsigned OpRegCode;
47845ffd83dbSDimitry Andric 
47855ffd83dbSDimitry Andric   warnIfNoMacro(IDLoc);
47865ffd83dbSDimitry Andric 
47875ffd83dbSDimitry Andric   switch (Inst.getOpcode()) {
47885ffd83dbSDimitry Andric   case Mips::SLEImm:
47895ffd83dbSDimitry Andric   case Mips::SLEImm64:
47905ffd83dbSDimitry Andric     OpRegCode = Mips::SLT;
47915ffd83dbSDimitry Andric     break;
47925ffd83dbSDimitry Andric   case Mips::SLEUImm:
47935ffd83dbSDimitry Andric   case Mips::SLEUImm64:
47945ffd83dbSDimitry Andric     OpRegCode = Mips::SLTu;
47955ffd83dbSDimitry Andric     break;
47965ffd83dbSDimitry Andric   default:
47975ffd83dbSDimitry Andric     llvm_unreachable("unexpected 'sge' opcode with immediate");
47985ffd83dbSDimitry Andric   }
47995ffd83dbSDimitry Andric 
48005ffd83dbSDimitry Andric   // $SrcReg <= Imm is equal to (not (Imm < $SrcReg))
48015ffd83dbSDimitry Andric   unsigned ImmReg = DstReg;
48025ffd83dbSDimitry Andric   if (DstReg == SrcReg) {
48035ffd83dbSDimitry Andric     unsigned ATReg = getATReg(Inst.getLoc());
48045ffd83dbSDimitry Andric     if (!ATReg)
48055ffd83dbSDimitry Andric       return true;
48065ffd83dbSDimitry Andric     ImmReg = ATReg;
48075ffd83dbSDimitry Andric   }
48085ffd83dbSDimitry Andric 
48095ffd83dbSDimitry Andric   if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
48105ffd83dbSDimitry Andric                     false, IDLoc, Out, STI))
48115ffd83dbSDimitry Andric     return true;
48125ffd83dbSDimitry Andric 
48135ffd83dbSDimitry Andric   TOut.emitRRR(OpRegCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
48145ffd83dbSDimitry Andric   TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
48155ffd83dbSDimitry Andric 
48165ffd83dbSDimitry Andric   return false;
48175ffd83dbSDimitry Andric }
48185ffd83dbSDimitry Andric 
expandAliasImmediate(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)48190b57cec5SDimitry Andric bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
48200b57cec5SDimitry Andric                                          MCStreamer &Out,
48210b57cec5SDimitry Andric                                          const MCSubtargetInfo *STI) {
48220b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
48230b57cec5SDimitry Andric 
48240b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
48250b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() &&
48260b57cec5SDimitry Andric          Inst.getOperand(1).isReg() &&
48270b57cec5SDimitry Andric          Inst.getOperand(2).isImm() && "Invalid instruction operand.");
48280b57cec5SDimitry Andric 
48290b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
48300b57cec5SDimitry Andric   unsigned FinalDstReg = Mips::NoRegister;
48310b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
48320b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
48330b57cec5SDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm();
48340b57cec5SDimitry Andric 
48350b57cec5SDimitry Andric   bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
48360b57cec5SDimitry Andric 
48370b57cec5SDimitry Andric   unsigned FinalOpcode = Inst.getOpcode();
48380b57cec5SDimitry Andric 
48390b57cec5SDimitry Andric   if (DstReg == SrcReg) {
48400b57cec5SDimitry Andric     ATReg = getATReg(Inst.getLoc());
48410b57cec5SDimitry Andric     if (!ATReg)
48420b57cec5SDimitry Andric       return true;
48430b57cec5SDimitry Andric     FinalDstReg = DstReg;
48440b57cec5SDimitry Andric     DstReg = ATReg;
48450b57cec5SDimitry Andric   }
48460b57cec5SDimitry Andric 
48470b57cec5SDimitry Andric   if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
48480b57cec5SDimitry Andric                      Inst.getLoc(), Out, STI)) {
48490b57cec5SDimitry Andric     switch (FinalOpcode) {
48500b57cec5SDimitry Andric     default:
48510b57cec5SDimitry Andric       llvm_unreachable("unimplemented expansion");
48520b57cec5SDimitry Andric     case Mips::ADDi:
48530b57cec5SDimitry Andric       FinalOpcode = Mips::ADD;
48540b57cec5SDimitry Andric       break;
48550b57cec5SDimitry Andric     case Mips::ADDiu:
48560b57cec5SDimitry Andric       FinalOpcode = Mips::ADDu;
48570b57cec5SDimitry Andric       break;
48580b57cec5SDimitry Andric     case Mips::ANDi:
48590b57cec5SDimitry Andric       FinalOpcode = Mips::AND;
48600b57cec5SDimitry Andric       break;
48610b57cec5SDimitry Andric     case Mips::NORImm:
48620b57cec5SDimitry Andric       FinalOpcode = Mips::NOR;
48630b57cec5SDimitry Andric       break;
48640b57cec5SDimitry Andric     case Mips::ORi:
48650b57cec5SDimitry Andric       FinalOpcode = Mips::OR;
48660b57cec5SDimitry Andric       break;
48670b57cec5SDimitry Andric     case Mips::SLTi:
48680b57cec5SDimitry Andric       FinalOpcode = Mips::SLT;
48690b57cec5SDimitry Andric       break;
48700b57cec5SDimitry Andric     case Mips::SLTiu:
48710b57cec5SDimitry Andric       FinalOpcode = Mips::SLTu;
48720b57cec5SDimitry Andric       break;
48730b57cec5SDimitry Andric     case Mips::XORi:
48740b57cec5SDimitry Andric       FinalOpcode = Mips::XOR;
48750b57cec5SDimitry Andric       break;
48760b57cec5SDimitry Andric     case Mips::ADDi_MM:
48770b57cec5SDimitry Andric       FinalOpcode = Mips::ADD_MM;
48780b57cec5SDimitry Andric       break;
48790b57cec5SDimitry Andric     case Mips::ADDiu_MM:
48800b57cec5SDimitry Andric       FinalOpcode = Mips::ADDu_MM;
48810b57cec5SDimitry Andric       break;
48820b57cec5SDimitry Andric     case Mips::ANDi_MM:
48830b57cec5SDimitry Andric       FinalOpcode = Mips::AND_MM;
48840b57cec5SDimitry Andric       break;
48850b57cec5SDimitry Andric     case Mips::ORi_MM:
48860b57cec5SDimitry Andric       FinalOpcode = Mips::OR_MM;
48870b57cec5SDimitry Andric       break;
48880b57cec5SDimitry Andric     case Mips::SLTi_MM:
48890b57cec5SDimitry Andric       FinalOpcode = Mips::SLT_MM;
48900b57cec5SDimitry Andric       break;
48910b57cec5SDimitry Andric     case Mips::SLTiu_MM:
48920b57cec5SDimitry Andric       FinalOpcode = Mips::SLTu_MM;
48930b57cec5SDimitry Andric       break;
48940b57cec5SDimitry Andric     case Mips::XORi_MM:
48950b57cec5SDimitry Andric       FinalOpcode = Mips::XOR_MM;
48960b57cec5SDimitry Andric       break;
48970b57cec5SDimitry Andric     case Mips::ANDi64:
48980b57cec5SDimitry Andric       FinalOpcode = Mips::AND64;
48990b57cec5SDimitry Andric       break;
49000b57cec5SDimitry Andric     case Mips::NORImm64:
49010b57cec5SDimitry Andric       FinalOpcode = Mips::NOR64;
49020b57cec5SDimitry Andric       break;
49030b57cec5SDimitry Andric     case Mips::ORi64:
49040b57cec5SDimitry Andric       FinalOpcode = Mips::OR64;
49050b57cec5SDimitry Andric       break;
49060b57cec5SDimitry Andric     case Mips::SLTImm64:
49070b57cec5SDimitry Andric       FinalOpcode = Mips::SLT64;
49080b57cec5SDimitry Andric       break;
49090b57cec5SDimitry Andric     case Mips::SLTUImm64:
49100b57cec5SDimitry Andric       FinalOpcode = Mips::SLTu64;
49110b57cec5SDimitry Andric       break;
49120b57cec5SDimitry Andric     case Mips::XORi64:
49130b57cec5SDimitry Andric       FinalOpcode = Mips::XOR64;
49140b57cec5SDimitry Andric       break;
49150b57cec5SDimitry Andric     }
49160b57cec5SDimitry Andric 
49170b57cec5SDimitry Andric     if (FinalDstReg == Mips::NoRegister)
49180b57cec5SDimitry Andric       TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
49190b57cec5SDimitry Andric     else
49200b57cec5SDimitry Andric       TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
49210b57cec5SDimitry Andric     return false;
49220b57cec5SDimitry Andric   }
49230b57cec5SDimitry Andric   return true;
49240b57cec5SDimitry Andric }
49250b57cec5SDimitry Andric 
expandRotation(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)49260b57cec5SDimitry Andric bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
49270b57cec5SDimitry Andric                                    const MCSubtargetInfo *STI) {
49280b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
49290b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
49300b57cec5SDimitry Andric   unsigned DReg = Inst.getOperand(0).getReg();
49310b57cec5SDimitry Andric   unsigned SReg = Inst.getOperand(1).getReg();
49320b57cec5SDimitry Andric   unsigned TReg = Inst.getOperand(2).getReg();
49330b57cec5SDimitry Andric   unsigned TmpReg = DReg;
49340b57cec5SDimitry Andric 
49350b57cec5SDimitry Andric   unsigned FirstShift = Mips::NOP;
49360b57cec5SDimitry Andric   unsigned SecondShift = Mips::NOP;
49370b57cec5SDimitry Andric 
49380b57cec5SDimitry Andric   if (hasMips32r2()) {
49390b57cec5SDimitry Andric     if (DReg == SReg) {
49400b57cec5SDimitry Andric       TmpReg = getATReg(Inst.getLoc());
49410b57cec5SDimitry Andric       if (!TmpReg)
49420b57cec5SDimitry Andric         return true;
49430b57cec5SDimitry Andric     }
49440b57cec5SDimitry Andric 
49450b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::ROL) {
49460b57cec5SDimitry Andric       TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
49470b57cec5SDimitry Andric       TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
49480b57cec5SDimitry Andric       return false;
49490b57cec5SDimitry Andric     }
49500b57cec5SDimitry Andric 
49510b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::ROR) {
49520b57cec5SDimitry Andric       TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
49530b57cec5SDimitry Andric       return false;
49540b57cec5SDimitry Andric     }
49550b57cec5SDimitry Andric 
49560b57cec5SDimitry Andric     return true;
49570b57cec5SDimitry Andric   }
49580b57cec5SDimitry Andric 
49590b57cec5SDimitry Andric   if (hasMips32()) {
49600b57cec5SDimitry Andric     switch (Inst.getOpcode()) {
49610b57cec5SDimitry Andric     default:
49620b57cec5SDimitry Andric       llvm_unreachable("unexpected instruction opcode");
49630b57cec5SDimitry Andric     case Mips::ROL:
49640b57cec5SDimitry Andric       FirstShift = Mips::SRLV;
49650b57cec5SDimitry Andric       SecondShift = Mips::SLLV;
49660b57cec5SDimitry Andric       break;
49670b57cec5SDimitry Andric     case Mips::ROR:
49680b57cec5SDimitry Andric       FirstShift = Mips::SLLV;
49690b57cec5SDimitry Andric       SecondShift = Mips::SRLV;
49700b57cec5SDimitry Andric       break;
49710b57cec5SDimitry Andric     }
49720b57cec5SDimitry Andric 
49730b57cec5SDimitry Andric     ATReg = getATReg(Inst.getLoc());
49740b57cec5SDimitry Andric     if (!ATReg)
49750b57cec5SDimitry Andric       return true;
49760b57cec5SDimitry Andric 
49770b57cec5SDimitry Andric     TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
49780b57cec5SDimitry Andric     TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
49790b57cec5SDimitry Andric     TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
49800b57cec5SDimitry Andric     TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
49810b57cec5SDimitry Andric 
49820b57cec5SDimitry Andric     return false;
49830b57cec5SDimitry Andric   }
49840b57cec5SDimitry Andric 
49850b57cec5SDimitry Andric   return true;
49860b57cec5SDimitry Andric }
49870b57cec5SDimitry Andric 
expandRotationImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)49880b57cec5SDimitry Andric bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
49890b57cec5SDimitry Andric                                       MCStreamer &Out,
49900b57cec5SDimitry Andric                                       const MCSubtargetInfo *STI) {
49910b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
49920b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
49930b57cec5SDimitry Andric   unsigned DReg = Inst.getOperand(0).getReg();
49940b57cec5SDimitry Andric   unsigned SReg = Inst.getOperand(1).getReg();
49950b57cec5SDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm();
49960b57cec5SDimitry Andric 
49970b57cec5SDimitry Andric   unsigned FirstShift = Mips::NOP;
49980b57cec5SDimitry Andric   unsigned SecondShift = Mips::NOP;
49990b57cec5SDimitry Andric 
50000b57cec5SDimitry Andric   if (hasMips32r2()) {
50010b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::ROLImm) {
50020b57cec5SDimitry Andric       uint64_t MaxShift = 32;
50030b57cec5SDimitry Andric       uint64_t ShiftValue = ImmValue;
50040b57cec5SDimitry Andric       if (ImmValue != 0)
50050b57cec5SDimitry Andric         ShiftValue = MaxShift - ImmValue;
50060b57cec5SDimitry Andric       TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
50070b57cec5SDimitry Andric       return false;
50080b57cec5SDimitry Andric     }
50090b57cec5SDimitry Andric 
50100b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::RORImm) {
50110b57cec5SDimitry Andric       TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
50120b57cec5SDimitry Andric       return false;
50130b57cec5SDimitry Andric     }
50140b57cec5SDimitry Andric 
50150b57cec5SDimitry Andric     return true;
50160b57cec5SDimitry Andric   }
50170b57cec5SDimitry Andric 
50180b57cec5SDimitry Andric   if (hasMips32()) {
50190b57cec5SDimitry Andric     if (ImmValue == 0) {
50200b57cec5SDimitry Andric       TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
50210b57cec5SDimitry Andric       return false;
50220b57cec5SDimitry Andric     }
50230b57cec5SDimitry Andric 
50240b57cec5SDimitry Andric     switch (Inst.getOpcode()) {
50250b57cec5SDimitry Andric     default:
50260b57cec5SDimitry Andric       llvm_unreachable("unexpected instruction opcode");
50270b57cec5SDimitry Andric     case Mips::ROLImm:
50280b57cec5SDimitry Andric       FirstShift = Mips::SLL;
50290b57cec5SDimitry Andric       SecondShift = Mips::SRL;
50300b57cec5SDimitry Andric       break;
50310b57cec5SDimitry Andric     case Mips::RORImm:
50320b57cec5SDimitry Andric       FirstShift = Mips::SRL;
50330b57cec5SDimitry Andric       SecondShift = Mips::SLL;
50340b57cec5SDimitry Andric       break;
50350b57cec5SDimitry Andric     }
50360b57cec5SDimitry Andric 
50370b57cec5SDimitry Andric     ATReg = getATReg(Inst.getLoc());
50380b57cec5SDimitry Andric     if (!ATReg)
50390b57cec5SDimitry Andric       return true;
50400b57cec5SDimitry Andric 
50410b57cec5SDimitry Andric     TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
50420b57cec5SDimitry Andric     TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
50430b57cec5SDimitry Andric     TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
50440b57cec5SDimitry Andric 
50450b57cec5SDimitry Andric     return false;
50460b57cec5SDimitry Andric   }
50470b57cec5SDimitry Andric 
50480b57cec5SDimitry Andric   return true;
50490b57cec5SDimitry Andric }
50500b57cec5SDimitry Andric 
expandDRotation(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)50510b57cec5SDimitry Andric bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
50520b57cec5SDimitry Andric                                     const MCSubtargetInfo *STI) {
50530b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
50540b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
50550b57cec5SDimitry Andric   unsigned DReg = Inst.getOperand(0).getReg();
50560b57cec5SDimitry Andric   unsigned SReg = Inst.getOperand(1).getReg();
50570b57cec5SDimitry Andric   unsigned TReg = Inst.getOperand(2).getReg();
50580b57cec5SDimitry Andric   unsigned TmpReg = DReg;
50590b57cec5SDimitry Andric 
50600b57cec5SDimitry Andric   unsigned FirstShift = Mips::NOP;
50610b57cec5SDimitry Andric   unsigned SecondShift = Mips::NOP;
50620b57cec5SDimitry Andric 
50630b57cec5SDimitry Andric   if (hasMips64r2()) {
50640b57cec5SDimitry Andric     if (TmpReg == SReg) {
50650b57cec5SDimitry Andric       TmpReg = getATReg(Inst.getLoc());
50660b57cec5SDimitry Andric       if (!TmpReg)
50670b57cec5SDimitry Andric         return true;
50680b57cec5SDimitry Andric     }
50690b57cec5SDimitry Andric 
50700b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::DROL) {
50710b57cec5SDimitry Andric       TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
50720b57cec5SDimitry Andric       TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
50730b57cec5SDimitry Andric       return false;
50740b57cec5SDimitry Andric     }
50750b57cec5SDimitry Andric 
50760b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::DROR) {
50770b57cec5SDimitry Andric       TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
50780b57cec5SDimitry Andric       return false;
50790b57cec5SDimitry Andric     }
50800b57cec5SDimitry Andric 
50810b57cec5SDimitry Andric     return true;
50820b57cec5SDimitry Andric   }
50830b57cec5SDimitry Andric 
50840b57cec5SDimitry Andric   if (hasMips64()) {
50850b57cec5SDimitry Andric     switch (Inst.getOpcode()) {
50860b57cec5SDimitry Andric     default:
50870b57cec5SDimitry Andric       llvm_unreachable("unexpected instruction opcode");
50880b57cec5SDimitry Andric     case Mips::DROL:
50890b57cec5SDimitry Andric       FirstShift = Mips::DSRLV;
50900b57cec5SDimitry Andric       SecondShift = Mips::DSLLV;
50910b57cec5SDimitry Andric       break;
50920b57cec5SDimitry Andric     case Mips::DROR:
50930b57cec5SDimitry Andric       FirstShift = Mips::DSLLV;
50940b57cec5SDimitry Andric       SecondShift = Mips::DSRLV;
50950b57cec5SDimitry Andric       break;
50960b57cec5SDimitry Andric     }
50970b57cec5SDimitry Andric 
50980b57cec5SDimitry Andric     ATReg = getATReg(Inst.getLoc());
50990b57cec5SDimitry Andric     if (!ATReg)
51000b57cec5SDimitry Andric       return true;
51010b57cec5SDimitry Andric 
51020b57cec5SDimitry Andric     TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
51030b57cec5SDimitry Andric     TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
51040b57cec5SDimitry Andric     TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
51050b57cec5SDimitry Andric     TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
51060b57cec5SDimitry Andric 
51070b57cec5SDimitry Andric     return false;
51080b57cec5SDimitry Andric   }
51090b57cec5SDimitry Andric 
51100b57cec5SDimitry Andric   return true;
51110b57cec5SDimitry Andric }
51120b57cec5SDimitry Andric 
expandDRotationImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)51130b57cec5SDimitry Andric bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
51140b57cec5SDimitry Andric                                        MCStreamer &Out,
51150b57cec5SDimitry Andric                                        const MCSubtargetInfo *STI) {
51160b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
51170b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
51180b57cec5SDimitry Andric   unsigned DReg = Inst.getOperand(0).getReg();
51190b57cec5SDimitry Andric   unsigned SReg = Inst.getOperand(1).getReg();
51200b57cec5SDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
51210b57cec5SDimitry Andric 
51220b57cec5SDimitry Andric   unsigned FirstShift = Mips::NOP;
51230b57cec5SDimitry Andric   unsigned SecondShift = Mips::NOP;
51240b57cec5SDimitry Andric 
51250b57cec5SDimitry Andric   MCInst TmpInst;
51260b57cec5SDimitry Andric 
51270b57cec5SDimitry Andric   if (hasMips64r2()) {
51280b57cec5SDimitry Andric     unsigned FinalOpcode = Mips::NOP;
51290b57cec5SDimitry Andric     if (ImmValue == 0)
51300b57cec5SDimitry Andric       FinalOpcode = Mips::DROTR;
51310b57cec5SDimitry Andric     else if (ImmValue % 32 == 0)
51320b57cec5SDimitry Andric       FinalOpcode = Mips::DROTR32;
51330b57cec5SDimitry Andric     else if ((ImmValue >= 1) && (ImmValue <= 32)) {
51340b57cec5SDimitry Andric       if (Inst.getOpcode() == Mips::DROLImm)
51350b57cec5SDimitry Andric         FinalOpcode = Mips::DROTR32;
51360b57cec5SDimitry Andric       else
51370b57cec5SDimitry Andric         FinalOpcode = Mips::DROTR;
51380b57cec5SDimitry Andric     } else if (ImmValue >= 33) {
51390b57cec5SDimitry Andric       if (Inst.getOpcode() == Mips::DROLImm)
51400b57cec5SDimitry Andric         FinalOpcode = Mips::DROTR;
51410b57cec5SDimitry Andric       else
51420b57cec5SDimitry Andric         FinalOpcode = Mips::DROTR32;
51430b57cec5SDimitry Andric     }
51440b57cec5SDimitry Andric 
51450b57cec5SDimitry Andric     uint64_t ShiftValue = ImmValue % 32;
51460b57cec5SDimitry Andric     if (Inst.getOpcode() == Mips::DROLImm)
51470b57cec5SDimitry Andric       ShiftValue = (32 - ImmValue % 32) % 32;
51480b57cec5SDimitry Andric 
51490b57cec5SDimitry Andric     TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
51500b57cec5SDimitry Andric 
51510b57cec5SDimitry Andric     return false;
51520b57cec5SDimitry Andric   }
51530b57cec5SDimitry Andric 
51540b57cec5SDimitry Andric   if (hasMips64()) {
51550b57cec5SDimitry Andric     if (ImmValue == 0) {
51560b57cec5SDimitry Andric       TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
51570b57cec5SDimitry Andric       return false;
51580b57cec5SDimitry Andric     }
51590b57cec5SDimitry Andric 
51600b57cec5SDimitry Andric     switch (Inst.getOpcode()) {
51610b57cec5SDimitry Andric     default:
51620b57cec5SDimitry Andric       llvm_unreachable("unexpected instruction opcode");
51630b57cec5SDimitry Andric     case Mips::DROLImm:
51640b57cec5SDimitry Andric       if ((ImmValue >= 1) && (ImmValue <= 31)) {
51650b57cec5SDimitry Andric         FirstShift = Mips::DSLL;
51660b57cec5SDimitry Andric         SecondShift = Mips::DSRL32;
51670b57cec5SDimitry Andric       }
51680b57cec5SDimitry Andric       if (ImmValue == 32) {
51690b57cec5SDimitry Andric         FirstShift = Mips::DSLL32;
51700b57cec5SDimitry Andric         SecondShift = Mips::DSRL32;
51710b57cec5SDimitry Andric       }
51720b57cec5SDimitry Andric       if ((ImmValue >= 33) && (ImmValue <= 63)) {
51730b57cec5SDimitry Andric         FirstShift = Mips::DSLL32;
51740b57cec5SDimitry Andric         SecondShift = Mips::DSRL;
51750b57cec5SDimitry Andric       }
51760b57cec5SDimitry Andric       break;
51770b57cec5SDimitry Andric     case Mips::DRORImm:
51780b57cec5SDimitry Andric       if ((ImmValue >= 1) && (ImmValue <= 31)) {
51790b57cec5SDimitry Andric         FirstShift = Mips::DSRL;
51800b57cec5SDimitry Andric         SecondShift = Mips::DSLL32;
51810b57cec5SDimitry Andric       }
51820b57cec5SDimitry Andric       if (ImmValue == 32) {
51830b57cec5SDimitry Andric         FirstShift = Mips::DSRL32;
51840b57cec5SDimitry Andric         SecondShift = Mips::DSLL32;
51850b57cec5SDimitry Andric       }
51860b57cec5SDimitry Andric       if ((ImmValue >= 33) && (ImmValue <= 63)) {
51870b57cec5SDimitry Andric         FirstShift = Mips::DSRL32;
51880b57cec5SDimitry Andric         SecondShift = Mips::DSLL;
51890b57cec5SDimitry Andric       }
51900b57cec5SDimitry Andric       break;
51910b57cec5SDimitry Andric     }
51920b57cec5SDimitry Andric 
51930b57cec5SDimitry Andric     ATReg = getATReg(Inst.getLoc());
51940b57cec5SDimitry Andric     if (!ATReg)
51950b57cec5SDimitry Andric       return true;
51960b57cec5SDimitry Andric 
51970b57cec5SDimitry Andric     TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
51980b57cec5SDimitry Andric     TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
51990b57cec5SDimitry Andric                  Inst.getLoc(), STI);
52000b57cec5SDimitry Andric     TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
52010b57cec5SDimitry Andric 
52020b57cec5SDimitry Andric     return false;
52030b57cec5SDimitry Andric   }
52040b57cec5SDimitry Andric 
52050b57cec5SDimitry Andric   return true;
52060b57cec5SDimitry Andric }
52070b57cec5SDimitry Andric 
expandAbs(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52080b57cec5SDimitry Andric bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52090b57cec5SDimitry Andric                               const MCSubtargetInfo *STI) {
52100b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
52110b57cec5SDimitry Andric   unsigned FirstRegOp = Inst.getOperand(0).getReg();
52120b57cec5SDimitry Andric   unsigned SecondRegOp = Inst.getOperand(1).getReg();
52130b57cec5SDimitry Andric 
52140b57cec5SDimitry Andric   TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
52150b57cec5SDimitry Andric   if (FirstRegOp != SecondRegOp)
52160b57cec5SDimitry Andric     TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
52170b57cec5SDimitry Andric   else
52180b57cec5SDimitry Andric     TOut.emitEmptyDelaySlot(false, IDLoc, STI);
52190b57cec5SDimitry Andric   TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
52200b57cec5SDimitry Andric 
52210b57cec5SDimitry Andric   return false;
52220b57cec5SDimitry Andric }
52230b57cec5SDimitry Andric 
expandMulImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52240b57cec5SDimitry Andric bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52250b57cec5SDimitry Andric                                  const MCSubtargetInfo *STI) {
52260b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
52270b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
52280b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
52290b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
52300b57cec5SDimitry Andric   int32_t ImmValue = Inst.getOperand(2).getImm();
52310b57cec5SDimitry Andric 
52320b57cec5SDimitry Andric   ATReg = getATReg(IDLoc);
52330b57cec5SDimitry Andric   if (!ATReg)
52340b57cec5SDimitry Andric     return true;
52350b57cec5SDimitry Andric 
52360b57cec5SDimitry Andric   loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
52370b57cec5SDimitry Andric                 STI);
52380b57cec5SDimitry Andric 
52390b57cec5SDimitry Andric   TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
52400b57cec5SDimitry Andric               SrcReg, ATReg, IDLoc, STI);
52410b57cec5SDimitry Andric 
52420b57cec5SDimitry Andric   TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
52430b57cec5SDimitry Andric 
52440b57cec5SDimitry Andric   return false;
52450b57cec5SDimitry Andric }
52460b57cec5SDimitry Andric 
expandMulO(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52470b57cec5SDimitry Andric bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52480b57cec5SDimitry Andric                                const MCSubtargetInfo *STI) {
52490b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
52500b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
52510b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
52520b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
52530b57cec5SDimitry Andric   unsigned TmpReg = Inst.getOperand(2).getReg();
52540b57cec5SDimitry Andric 
52550b57cec5SDimitry Andric   ATReg = getATReg(Inst.getLoc());
52560b57cec5SDimitry Andric   if (!ATReg)
52570b57cec5SDimitry Andric     return true;
52580b57cec5SDimitry Andric 
52590b57cec5SDimitry Andric   TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
52600b57cec5SDimitry Andric               SrcReg, TmpReg, IDLoc, STI);
52610b57cec5SDimitry Andric 
52620b57cec5SDimitry Andric   TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
52630b57cec5SDimitry Andric 
52640b57cec5SDimitry Andric   TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
52650b57cec5SDimitry Andric                DstReg, DstReg, 0x1F, IDLoc, STI);
52660b57cec5SDimitry Andric 
52670b57cec5SDimitry Andric   TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
52680b57cec5SDimitry Andric 
52690b57cec5SDimitry Andric   if (useTraps()) {
52700b57cec5SDimitry Andric     TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
52710b57cec5SDimitry Andric   } else {
52720b57cec5SDimitry Andric     MCContext & Context = TOut.getStreamer().getContext();
52730b57cec5SDimitry Andric     MCSymbol * BrTarget = Context.createTempSymbol();
52740b57cec5SDimitry Andric     MCOperand LabelOp =
52750b57cec5SDimitry Andric         MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
52760b57cec5SDimitry Andric 
52770b57cec5SDimitry Andric     TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
52780b57cec5SDimitry Andric     if (AssemblerOptions.back()->isReorder())
52790b57cec5SDimitry Andric       TOut.emitNop(IDLoc, STI);
52800b57cec5SDimitry Andric     TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
52810b57cec5SDimitry Andric 
52825ffd83dbSDimitry Andric     TOut.getStreamer().emitLabel(BrTarget);
52830b57cec5SDimitry Andric   }
52840b57cec5SDimitry Andric   TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
52850b57cec5SDimitry Andric 
52860b57cec5SDimitry Andric   return false;
52870b57cec5SDimitry Andric }
52880b57cec5SDimitry Andric 
expandMulOU(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52890b57cec5SDimitry Andric bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52900b57cec5SDimitry Andric                                 const MCSubtargetInfo *STI) {
52910b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
52920b57cec5SDimitry Andric   unsigned ATReg = Mips::NoRegister;
52930b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
52940b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
52950b57cec5SDimitry Andric   unsigned TmpReg = Inst.getOperand(2).getReg();
52960b57cec5SDimitry Andric 
52970b57cec5SDimitry Andric   ATReg = getATReg(IDLoc);
52980b57cec5SDimitry Andric   if (!ATReg)
52990b57cec5SDimitry Andric     return true;
53000b57cec5SDimitry Andric 
53010b57cec5SDimitry Andric   TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
53020b57cec5SDimitry Andric               SrcReg, TmpReg, IDLoc, STI);
53030b57cec5SDimitry Andric 
53040b57cec5SDimitry Andric   TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
53050b57cec5SDimitry Andric   TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
53060b57cec5SDimitry Andric   if (useTraps()) {
53070b57cec5SDimitry Andric     TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
53080b57cec5SDimitry Andric   } else {
53090b57cec5SDimitry Andric     MCContext & Context = TOut.getStreamer().getContext();
53100b57cec5SDimitry Andric     MCSymbol * BrTarget = Context.createTempSymbol();
53110b57cec5SDimitry Andric     MCOperand LabelOp =
53120b57cec5SDimitry Andric         MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
53130b57cec5SDimitry Andric 
53140b57cec5SDimitry Andric     TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
53150b57cec5SDimitry Andric     if (AssemblerOptions.back()->isReorder())
53160b57cec5SDimitry Andric       TOut.emitNop(IDLoc, STI);
53170b57cec5SDimitry Andric     TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
53180b57cec5SDimitry Andric 
53195ffd83dbSDimitry Andric     TOut.getStreamer().emitLabel(BrTarget);
53200b57cec5SDimitry Andric   }
53210b57cec5SDimitry Andric 
53220b57cec5SDimitry Andric   return false;
53230b57cec5SDimitry Andric }
53240b57cec5SDimitry Andric 
expandDMULMacro(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)53250b57cec5SDimitry Andric bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
53260b57cec5SDimitry Andric                                     const MCSubtargetInfo *STI) {
53270b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
53280b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
53290b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
53300b57cec5SDimitry Andric   unsigned TmpReg = Inst.getOperand(2).getReg();
53310b57cec5SDimitry Andric 
53320b57cec5SDimitry Andric   TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
53330b57cec5SDimitry Andric   TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
53340b57cec5SDimitry Andric 
53350b57cec5SDimitry Andric   return false;
53360b57cec5SDimitry Andric }
53370b57cec5SDimitry Andric 
53380b57cec5SDimitry Andric // Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
53390b57cec5SDimitry Andric //                                      lw $<reg+1>>, offset+4($reg2)'
53400b57cec5SDimitry Andric // or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
53410b57cec5SDimitry Andric //                                         sw $<reg+1>>, offset+4($reg2)'
53420b57cec5SDimitry Andric // for O32.
expandLoadStoreDMacro(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad)53430b57cec5SDimitry Andric bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
53440b57cec5SDimitry Andric                                           MCStreamer &Out,
53450b57cec5SDimitry Andric                                           const MCSubtargetInfo *STI,
53460b57cec5SDimitry Andric                                           bool IsLoad) {
53470b57cec5SDimitry Andric   if (!isABI_O32())
53480b57cec5SDimitry Andric     return true;
53490b57cec5SDimitry Andric 
53500b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
53510b57cec5SDimitry Andric 
53520b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
53530b57cec5SDimitry Andric   unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
53540b57cec5SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
53550b57cec5SDimitry Andric   unsigned SecondReg = nextReg(FirstReg);
53560b57cec5SDimitry Andric   unsigned BaseReg = Inst.getOperand(1).getReg();
53570b57cec5SDimitry Andric   if (!SecondReg)
53580b57cec5SDimitry Andric     return true;
53590b57cec5SDimitry Andric 
53600b57cec5SDimitry Andric   warnIfRegIndexIsAT(FirstReg, IDLoc);
53610b57cec5SDimitry Andric 
53620b57cec5SDimitry Andric   assert(Inst.getOperand(2).isImm() &&
53630b57cec5SDimitry Andric          "Offset for load macro is not immediate!");
53640b57cec5SDimitry Andric 
53650b57cec5SDimitry Andric   MCOperand &FirstOffset = Inst.getOperand(2);
53660b57cec5SDimitry Andric   signed NextOffset = FirstOffset.getImm() + 4;
53670b57cec5SDimitry Andric   MCOperand SecondOffset = MCOperand::createImm(NextOffset);
53680b57cec5SDimitry Andric 
53690b57cec5SDimitry Andric   if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
53700b57cec5SDimitry Andric     return true;
53710b57cec5SDimitry Andric 
53720b57cec5SDimitry Andric   // For loads, clobber the base register with the second load instead of the
53730b57cec5SDimitry Andric   // first if the BaseReg == FirstReg.
53740b57cec5SDimitry Andric   if (FirstReg != BaseReg || !IsLoad) {
53750b57cec5SDimitry Andric     TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
53760b57cec5SDimitry Andric     TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
53770b57cec5SDimitry Andric   } else {
53780b57cec5SDimitry Andric     TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
53790b57cec5SDimitry Andric     TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
53800b57cec5SDimitry Andric   }
53810b57cec5SDimitry Andric 
53820b57cec5SDimitry Andric   return false;
53830b57cec5SDimitry Andric }
53840b57cec5SDimitry Andric 
53850b57cec5SDimitry Andric 
53860b57cec5SDimitry Andric // Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2);
53870b57cec5SDimitry Andric //                                       swc1 $<reg>, offset+4($reg2)'
53880b57cec5SDimitry Andric // or if little endian to 'swc1 $<reg>, offset($reg2);
53890b57cec5SDimitry Andric //                         swc1 $<reg+1>, offset+4($reg2)'
53900b57cec5SDimitry Andric // for Mips1.
expandStoreDM1Macro(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)53910b57cec5SDimitry Andric bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc,
53920b57cec5SDimitry Andric                                         MCStreamer &Out,
53930b57cec5SDimitry Andric                                         const MCSubtargetInfo *STI) {
53940b57cec5SDimitry Andric   if (!isABI_O32())
53950b57cec5SDimitry Andric     return true;
53960b57cec5SDimitry Andric 
53970b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
53980b57cec5SDimitry Andric 
53990b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
54000b57cec5SDimitry Andric   unsigned Opcode = Mips::SWC1;
54010b57cec5SDimitry Andric   unsigned FirstReg = Inst.getOperand(0).getReg();
54020b57cec5SDimitry Andric   unsigned SecondReg = nextReg(FirstReg);
54030b57cec5SDimitry Andric   unsigned BaseReg = Inst.getOperand(1).getReg();
54040b57cec5SDimitry Andric   if (!SecondReg)
54050b57cec5SDimitry Andric     return true;
54060b57cec5SDimitry Andric 
54070b57cec5SDimitry Andric   warnIfRegIndexIsAT(FirstReg, IDLoc);
54080b57cec5SDimitry Andric 
54090b57cec5SDimitry Andric   assert(Inst.getOperand(2).isImm() &&
54100b57cec5SDimitry Andric          "Offset for macro is not immediate!");
54110b57cec5SDimitry Andric 
54120b57cec5SDimitry Andric   MCOperand &FirstOffset = Inst.getOperand(2);
54130b57cec5SDimitry Andric   signed NextOffset = FirstOffset.getImm() + 4;
54140b57cec5SDimitry Andric   MCOperand SecondOffset = MCOperand::createImm(NextOffset);
54150b57cec5SDimitry Andric 
54160b57cec5SDimitry Andric   if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
54170b57cec5SDimitry Andric     return true;
54180b57cec5SDimitry Andric 
54190b57cec5SDimitry Andric   if (!IsLittleEndian)
54200b57cec5SDimitry Andric     std::swap(FirstReg, SecondReg);
54210b57cec5SDimitry Andric 
54220b57cec5SDimitry Andric   TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
54230b57cec5SDimitry Andric   TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
54240b57cec5SDimitry Andric 
54250b57cec5SDimitry Andric   return false;
54260b57cec5SDimitry Andric }
54270b57cec5SDimitry Andric 
expandSeq(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)54280b57cec5SDimitry Andric bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
54290b57cec5SDimitry Andric                               const MCSubtargetInfo *STI) {
54300b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
54310b57cec5SDimitry Andric 
54320b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
54330b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() &&
54340b57cec5SDimitry Andric          Inst.getOperand(1).isReg() &&
54350b57cec5SDimitry Andric          Inst.getOperand(2).isReg() && "Invalid instruction operand.");
54360b57cec5SDimitry Andric 
54370b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
54380b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
54390b57cec5SDimitry Andric   unsigned OpReg = Inst.getOperand(2).getReg();
54400b57cec5SDimitry Andric 
54410b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
54420b57cec5SDimitry Andric 
54430b57cec5SDimitry Andric   if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
54440b57cec5SDimitry Andric     TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
54450b57cec5SDimitry Andric     TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
54460b57cec5SDimitry Andric     return false;
54470b57cec5SDimitry Andric   }
54480b57cec5SDimitry Andric 
54490b57cec5SDimitry Andric   unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
54500b57cec5SDimitry Andric   TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI);
54510b57cec5SDimitry Andric   return false;
54520b57cec5SDimitry Andric }
54530b57cec5SDimitry Andric 
expandSeqI(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)54540b57cec5SDimitry Andric bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
54550b57cec5SDimitry Andric                                const MCSubtargetInfo *STI) {
54560b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
54570b57cec5SDimitry Andric 
54580b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
54590b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() &&
54600b57cec5SDimitry Andric          Inst.getOperand(1).isReg() &&
54610b57cec5SDimitry Andric          Inst.getOperand(2).isImm() && "Invalid instruction operand.");
54620b57cec5SDimitry Andric 
54630b57cec5SDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
54640b57cec5SDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
54650b57cec5SDimitry Andric   int64_t Imm = Inst.getOperand(2).getImm();
54660b57cec5SDimitry Andric 
54670b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
54680b57cec5SDimitry Andric 
54690b57cec5SDimitry Andric   if (Imm == 0) {
54700b57cec5SDimitry Andric     TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI);
54710b57cec5SDimitry Andric     return false;
54720b57cec5SDimitry Andric   }
54730b57cec5SDimitry Andric 
54740b57cec5SDimitry Andric   if (SrcReg == Mips::ZERO) {
54750b57cec5SDimitry Andric     Warning(IDLoc, "comparison is always false");
54760b57cec5SDimitry Andric     TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
54770b57cec5SDimitry Andric                  DstReg, SrcReg, SrcReg, IDLoc, STI);
54780b57cec5SDimitry Andric     return false;
54790b57cec5SDimitry Andric   }
54800b57cec5SDimitry Andric 
54810b57cec5SDimitry Andric   unsigned Opc;
54820b57cec5SDimitry Andric   if (Imm > -0x8000 && Imm < 0) {
54830b57cec5SDimitry Andric     Imm = -Imm;
54840b57cec5SDimitry Andric     Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
54850b57cec5SDimitry Andric   } else {
54860b57cec5SDimitry Andric     Opc = Mips::XORi;
54870b57cec5SDimitry Andric   }
54880b57cec5SDimitry Andric 
54890b57cec5SDimitry Andric   if (!isUInt<16>(Imm)) {
54900b57cec5SDimitry Andric     unsigned ATReg = getATReg(IDLoc);
54910b57cec5SDimitry Andric     if (!ATReg)
54920b57cec5SDimitry Andric       return true;
54930b57cec5SDimitry Andric 
54940b57cec5SDimitry Andric     if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
54950b57cec5SDimitry Andric                       Out, STI))
54960b57cec5SDimitry Andric       return true;
54970b57cec5SDimitry Andric 
54980b57cec5SDimitry Andric     TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
54990b57cec5SDimitry Andric     TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
55000b57cec5SDimitry Andric     return false;
55010b57cec5SDimitry Andric   }
55020b57cec5SDimitry Andric 
55030b57cec5SDimitry Andric   TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI);
55040b57cec5SDimitry Andric   TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
55050b57cec5SDimitry Andric   return false;
55060b57cec5SDimitry Andric }
55070b57cec5SDimitry Andric 
expandSne(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)55085ffd83dbSDimitry Andric bool MipsAsmParser::expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
55095ffd83dbSDimitry Andric                               const MCSubtargetInfo *STI) {
55105ffd83dbSDimitry Andric 
55115ffd83dbSDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
55125ffd83dbSDimitry Andric 
55135ffd83dbSDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
55145ffd83dbSDimitry Andric   assert(Inst.getOperand(0).isReg() &&
55155ffd83dbSDimitry Andric          Inst.getOperand(1).isReg() &&
55165ffd83dbSDimitry Andric          Inst.getOperand(2).isReg() && "Invalid instruction operand.");
55175ffd83dbSDimitry Andric 
55185ffd83dbSDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
55195ffd83dbSDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
55205ffd83dbSDimitry Andric   unsigned OpReg = Inst.getOperand(2).getReg();
55215ffd83dbSDimitry Andric 
55225ffd83dbSDimitry Andric   warnIfNoMacro(IDLoc);
55235ffd83dbSDimitry Andric 
55245ffd83dbSDimitry Andric   if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
55255ffd83dbSDimitry Andric     TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
55265ffd83dbSDimitry Andric     TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
55275ffd83dbSDimitry Andric     return false;
55285ffd83dbSDimitry Andric   }
55295ffd83dbSDimitry Andric 
55305ffd83dbSDimitry Andric   unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
55315ffd83dbSDimitry Andric   TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, Reg, IDLoc, STI);
55325ffd83dbSDimitry Andric   return false;
55335ffd83dbSDimitry Andric }
55345ffd83dbSDimitry Andric 
expandSneI(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)55355ffd83dbSDimitry Andric bool MipsAsmParser::expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
55365ffd83dbSDimitry Andric                                const MCSubtargetInfo *STI) {
55375ffd83dbSDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
55385ffd83dbSDimitry Andric 
55395ffd83dbSDimitry Andric   assert(Inst.getNumOperands() == 3 && "Invalid operand count");
55405ffd83dbSDimitry Andric   assert(Inst.getOperand(0).isReg() &&
55415ffd83dbSDimitry Andric          Inst.getOperand(1).isReg() &&
55425ffd83dbSDimitry Andric          Inst.getOperand(2).isImm() && "Invalid instruction operand.");
55435ffd83dbSDimitry Andric 
55445ffd83dbSDimitry Andric   unsigned DstReg = Inst.getOperand(0).getReg();
55455ffd83dbSDimitry Andric   unsigned SrcReg = Inst.getOperand(1).getReg();
55465ffd83dbSDimitry Andric   int64_t ImmValue = Inst.getOperand(2).getImm();
55475ffd83dbSDimitry Andric 
55485ffd83dbSDimitry Andric   warnIfNoMacro(IDLoc);
55495ffd83dbSDimitry Andric 
55505ffd83dbSDimitry Andric   if (ImmValue == 0) {
55515ffd83dbSDimitry Andric     TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, SrcReg, IDLoc, STI);
55525ffd83dbSDimitry Andric     return false;
55535ffd83dbSDimitry Andric   }
55545ffd83dbSDimitry Andric 
55555ffd83dbSDimitry Andric   if (SrcReg == Mips::ZERO) {
55565ffd83dbSDimitry Andric     Warning(IDLoc, "comparison is always true");
55575ffd83dbSDimitry Andric     if (loadImmediate(1, DstReg, Mips::NoRegister, true, false, IDLoc, Out,
55585ffd83dbSDimitry Andric                       STI))
55595ffd83dbSDimitry Andric       return true;
55605ffd83dbSDimitry Andric     return false;
55615ffd83dbSDimitry Andric   }
55625ffd83dbSDimitry Andric 
55635ffd83dbSDimitry Andric   unsigned Opc;
55645ffd83dbSDimitry Andric   if (ImmValue > -0x8000 && ImmValue < 0) {
55655ffd83dbSDimitry Andric     ImmValue = -ImmValue;
55665ffd83dbSDimitry Andric     Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
55675ffd83dbSDimitry Andric   } else {
55685ffd83dbSDimitry Andric     Opc = Mips::XORi;
55695ffd83dbSDimitry Andric   }
55705ffd83dbSDimitry Andric 
55715ffd83dbSDimitry Andric   if (isUInt<16>(ImmValue)) {
55725ffd83dbSDimitry Andric     TOut.emitRRI(Opc, DstReg, SrcReg, ImmValue, IDLoc, STI);
55735ffd83dbSDimitry Andric     TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
55745ffd83dbSDimitry Andric     return false;
55755ffd83dbSDimitry Andric   }
55765ffd83dbSDimitry Andric 
55775ffd83dbSDimitry Andric   unsigned ATReg = getATReg(IDLoc);
55785ffd83dbSDimitry Andric   if (!ATReg)
55795ffd83dbSDimitry Andric     return true;
55805ffd83dbSDimitry Andric 
55815ffd83dbSDimitry Andric   if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
55825ffd83dbSDimitry Andric                     false, IDLoc, Out, STI))
55835ffd83dbSDimitry Andric     return true;
55845ffd83dbSDimitry Andric 
55855ffd83dbSDimitry Andric   TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
55865ffd83dbSDimitry Andric   TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
55875ffd83dbSDimitry Andric   return false;
55885ffd83dbSDimitry Andric }
55895ffd83dbSDimitry Andric 
55900b57cec5SDimitry Andric // Map the DSP accumulator and control register to the corresponding gpr
55910b57cec5SDimitry Andric // operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
55920b57cec5SDimitry Andric // do not map the DSP registers contigously to gpr registers.
getRegisterForMxtrDSP(MCInst & Inst,bool IsMFDSP)55930b57cec5SDimitry Andric static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
55940b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
55950b57cec5SDimitry Andric     case Mips::MFTLO:
55960b57cec5SDimitry Andric     case Mips::MTTLO:
55970b57cec5SDimitry Andric       switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
55980b57cec5SDimitry Andric         case Mips::AC0:
55990b57cec5SDimitry Andric           return Mips::ZERO;
56000b57cec5SDimitry Andric         case Mips::AC1:
56010b57cec5SDimitry Andric           return Mips::A0;
56020b57cec5SDimitry Andric         case Mips::AC2:
56030b57cec5SDimitry Andric           return Mips::T0;
56040b57cec5SDimitry Andric         case Mips::AC3:
56050b57cec5SDimitry Andric           return Mips::T4;
56060b57cec5SDimitry Andric         default:
56070b57cec5SDimitry Andric           llvm_unreachable("Unknown register for 'mttr' alias!");
56080b57cec5SDimitry Andric     }
56090b57cec5SDimitry Andric     case Mips::MFTHI:
56100b57cec5SDimitry Andric     case Mips::MTTHI:
56110b57cec5SDimitry Andric       switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
56120b57cec5SDimitry Andric         case Mips::AC0:
56130b57cec5SDimitry Andric           return Mips::AT;
56140b57cec5SDimitry Andric         case Mips::AC1:
56150b57cec5SDimitry Andric           return Mips::A1;
56160b57cec5SDimitry Andric         case Mips::AC2:
56170b57cec5SDimitry Andric           return Mips::T1;
56180b57cec5SDimitry Andric         case Mips::AC3:
56190b57cec5SDimitry Andric           return Mips::T5;
56200b57cec5SDimitry Andric         default:
56210b57cec5SDimitry Andric           llvm_unreachable("Unknown register for 'mttr' alias!");
56220b57cec5SDimitry Andric     }
56230b57cec5SDimitry Andric     case Mips::MFTACX:
56240b57cec5SDimitry Andric     case Mips::MTTACX:
56250b57cec5SDimitry Andric       switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
56260b57cec5SDimitry Andric         case Mips::AC0:
56270b57cec5SDimitry Andric           return Mips::V0;
56280b57cec5SDimitry Andric         case Mips::AC1:
56290b57cec5SDimitry Andric           return Mips::A2;
56300b57cec5SDimitry Andric         case Mips::AC2:
56310b57cec5SDimitry Andric           return Mips::T2;
56320b57cec5SDimitry Andric         case Mips::AC3:
56330b57cec5SDimitry Andric           return Mips::T6;
56340b57cec5SDimitry Andric         default:
56350b57cec5SDimitry Andric           llvm_unreachable("Unknown register for 'mttr' alias!");
56360b57cec5SDimitry Andric     }
56370b57cec5SDimitry Andric     case Mips::MFTDSP:
56380b57cec5SDimitry Andric     case Mips::MTTDSP:
56390b57cec5SDimitry Andric       return Mips::S0;
56400b57cec5SDimitry Andric     default:
56410b57cec5SDimitry Andric       llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
56420b57cec5SDimitry Andric   }
56430b57cec5SDimitry Andric }
56440b57cec5SDimitry Andric 
56450b57cec5SDimitry Andric // Map the floating point register operand to the corresponding register
56460b57cec5SDimitry Andric // operand.
getRegisterForMxtrFP(MCInst & Inst,bool IsMFTC1)56470b57cec5SDimitry Andric static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
56480b57cec5SDimitry Andric   switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
56490b57cec5SDimitry Andric     case Mips::F0:  return Mips::ZERO;
56500b57cec5SDimitry Andric     case Mips::F1:  return Mips::AT;
56510b57cec5SDimitry Andric     case Mips::F2:  return Mips::V0;
56520b57cec5SDimitry Andric     case Mips::F3:  return Mips::V1;
56530b57cec5SDimitry Andric     case Mips::F4:  return Mips::A0;
56540b57cec5SDimitry Andric     case Mips::F5:  return Mips::A1;
56550b57cec5SDimitry Andric     case Mips::F6:  return Mips::A2;
56560b57cec5SDimitry Andric     case Mips::F7:  return Mips::A3;
56570b57cec5SDimitry Andric     case Mips::F8:  return Mips::T0;
56580b57cec5SDimitry Andric     case Mips::F9:  return Mips::T1;
56590b57cec5SDimitry Andric     case Mips::F10: return Mips::T2;
56600b57cec5SDimitry Andric     case Mips::F11: return Mips::T3;
56610b57cec5SDimitry Andric     case Mips::F12: return Mips::T4;
56620b57cec5SDimitry Andric     case Mips::F13: return Mips::T5;
56630b57cec5SDimitry Andric     case Mips::F14: return Mips::T6;
56640b57cec5SDimitry Andric     case Mips::F15: return Mips::T7;
56650b57cec5SDimitry Andric     case Mips::F16: return Mips::S0;
56660b57cec5SDimitry Andric     case Mips::F17: return Mips::S1;
56670b57cec5SDimitry Andric     case Mips::F18: return Mips::S2;
56680b57cec5SDimitry Andric     case Mips::F19: return Mips::S3;
56690b57cec5SDimitry Andric     case Mips::F20: return Mips::S4;
56700b57cec5SDimitry Andric     case Mips::F21: return Mips::S5;
56710b57cec5SDimitry Andric     case Mips::F22: return Mips::S6;
56720b57cec5SDimitry Andric     case Mips::F23: return Mips::S7;
56730b57cec5SDimitry Andric     case Mips::F24: return Mips::T8;
56740b57cec5SDimitry Andric     case Mips::F25: return Mips::T9;
56750b57cec5SDimitry Andric     case Mips::F26: return Mips::K0;
56760b57cec5SDimitry Andric     case Mips::F27: return Mips::K1;
56770b57cec5SDimitry Andric     case Mips::F28: return Mips::GP;
56780b57cec5SDimitry Andric     case Mips::F29: return Mips::SP;
56790b57cec5SDimitry Andric     case Mips::F30: return Mips::FP;
56800b57cec5SDimitry Andric     case Mips::F31: return Mips::RA;
56810b57cec5SDimitry Andric     default: llvm_unreachable("Unknown register for mttc1 alias!");
56820b57cec5SDimitry Andric   }
56830b57cec5SDimitry Andric }
56840b57cec5SDimitry Andric 
56850b57cec5SDimitry Andric // Map the coprocessor operand the corresponding gpr register operand.
getRegisterForMxtrC0(MCInst & Inst,bool IsMFTC0)56860b57cec5SDimitry Andric static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
56870b57cec5SDimitry Andric   switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
56880b57cec5SDimitry Andric     case Mips::COP00:  return Mips::ZERO;
56890b57cec5SDimitry Andric     case Mips::COP01:  return Mips::AT;
56900b57cec5SDimitry Andric     case Mips::COP02:  return Mips::V0;
56910b57cec5SDimitry Andric     case Mips::COP03:  return Mips::V1;
56920b57cec5SDimitry Andric     case Mips::COP04:  return Mips::A0;
56930b57cec5SDimitry Andric     case Mips::COP05:  return Mips::A1;
56940b57cec5SDimitry Andric     case Mips::COP06:  return Mips::A2;
56950b57cec5SDimitry Andric     case Mips::COP07:  return Mips::A3;
56960b57cec5SDimitry Andric     case Mips::COP08:  return Mips::T0;
56970b57cec5SDimitry Andric     case Mips::COP09:  return Mips::T1;
56980b57cec5SDimitry Andric     case Mips::COP010: return Mips::T2;
56990b57cec5SDimitry Andric     case Mips::COP011: return Mips::T3;
57000b57cec5SDimitry Andric     case Mips::COP012: return Mips::T4;
57010b57cec5SDimitry Andric     case Mips::COP013: return Mips::T5;
57020b57cec5SDimitry Andric     case Mips::COP014: return Mips::T6;
57030b57cec5SDimitry Andric     case Mips::COP015: return Mips::T7;
57040b57cec5SDimitry Andric     case Mips::COP016: return Mips::S0;
57050b57cec5SDimitry Andric     case Mips::COP017: return Mips::S1;
57060b57cec5SDimitry Andric     case Mips::COP018: return Mips::S2;
57070b57cec5SDimitry Andric     case Mips::COP019: return Mips::S3;
57080b57cec5SDimitry Andric     case Mips::COP020: return Mips::S4;
57090b57cec5SDimitry Andric     case Mips::COP021: return Mips::S5;
57100b57cec5SDimitry Andric     case Mips::COP022: return Mips::S6;
57110b57cec5SDimitry Andric     case Mips::COP023: return Mips::S7;
57120b57cec5SDimitry Andric     case Mips::COP024: return Mips::T8;
57130b57cec5SDimitry Andric     case Mips::COP025: return Mips::T9;
57140b57cec5SDimitry Andric     case Mips::COP026: return Mips::K0;
57150b57cec5SDimitry Andric     case Mips::COP027: return Mips::K1;
57160b57cec5SDimitry Andric     case Mips::COP028: return Mips::GP;
57170b57cec5SDimitry Andric     case Mips::COP029: return Mips::SP;
57180b57cec5SDimitry Andric     case Mips::COP030: return Mips::FP;
57190b57cec5SDimitry Andric     case Mips::COP031: return Mips::RA;
57200b57cec5SDimitry Andric     default: llvm_unreachable("Unknown register for mttc0 alias!");
57210b57cec5SDimitry Andric   }
57220b57cec5SDimitry Andric }
57230b57cec5SDimitry Andric 
57240b57cec5SDimitry Andric /// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
57250b57cec5SDimitry Andric /// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
expandMXTRAlias(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)57260b57cec5SDimitry Andric bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
57270b57cec5SDimitry Andric                                     const MCSubtargetInfo *STI) {
57280b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
57290b57cec5SDimitry Andric   unsigned rd = 0;
57300b57cec5SDimitry Andric   unsigned u = 1;
57310b57cec5SDimitry Andric   unsigned sel = 0;
57320b57cec5SDimitry Andric   unsigned h = 0;
57330b57cec5SDimitry Andric   bool IsMFTR = false;
57340b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
57350b57cec5SDimitry Andric     case Mips::MFTC0:
57360b57cec5SDimitry Andric       IsMFTR = true;
5737bdd1243dSDimitry Andric       [[fallthrough]];
57380b57cec5SDimitry Andric     case Mips::MTTC0:
57390b57cec5SDimitry Andric       u = 0;
57400b57cec5SDimitry Andric       rd = getRegisterForMxtrC0(Inst, IsMFTR);
57410b57cec5SDimitry Andric       sel = Inst.getOperand(2).getImm();
57420b57cec5SDimitry Andric       break;
57430b57cec5SDimitry Andric     case Mips::MFTGPR:
57440b57cec5SDimitry Andric       IsMFTR = true;
5745bdd1243dSDimitry Andric       [[fallthrough]];
57460b57cec5SDimitry Andric     case Mips::MTTGPR:
57470b57cec5SDimitry Andric       rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
57480b57cec5SDimitry Andric       break;
57490b57cec5SDimitry Andric     case Mips::MFTLO:
57500b57cec5SDimitry Andric     case Mips::MFTHI:
57510b57cec5SDimitry Andric     case Mips::MFTACX:
57520b57cec5SDimitry Andric     case Mips::MFTDSP:
57530b57cec5SDimitry Andric       IsMFTR = true;
5754bdd1243dSDimitry Andric       [[fallthrough]];
57550b57cec5SDimitry Andric     case Mips::MTTLO:
57560b57cec5SDimitry Andric     case Mips::MTTHI:
57570b57cec5SDimitry Andric     case Mips::MTTACX:
57580b57cec5SDimitry Andric     case Mips::MTTDSP:
57590b57cec5SDimitry Andric       rd = getRegisterForMxtrDSP(Inst, IsMFTR);
57600b57cec5SDimitry Andric       sel = 1;
57610b57cec5SDimitry Andric       break;
57620b57cec5SDimitry Andric     case Mips::MFTHC1:
57630b57cec5SDimitry Andric       h = 1;
5764bdd1243dSDimitry Andric       [[fallthrough]];
57650b57cec5SDimitry Andric     case Mips::MFTC1:
57660b57cec5SDimitry Andric       IsMFTR = true;
57670b57cec5SDimitry Andric       rd = getRegisterForMxtrFP(Inst, IsMFTR);
57680b57cec5SDimitry Andric       sel = 2;
57690b57cec5SDimitry Andric       break;
57700b57cec5SDimitry Andric     case Mips::MTTHC1:
57710b57cec5SDimitry Andric       h = 1;
5772bdd1243dSDimitry Andric       [[fallthrough]];
57730b57cec5SDimitry Andric     case Mips::MTTC1:
57740b57cec5SDimitry Andric       rd = getRegisterForMxtrFP(Inst, IsMFTR);
57750b57cec5SDimitry Andric       sel = 2;
57760b57cec5SDimitry Andric       break;
57770b57cec5SDimitry Andric     case Mips::CFTC1:
57780b57cec5SDimitry Andric       IsMFTR = true;
5779bdd1243dSDimitry Andric       [[fallthrough]];
57800b57cec5SDimitry Andric     case Mips::CTTC1:
57810b57cec5SDimitry Andric       rd = getRegisterForMxtrFP(Inst, IsMFTR);
57820b57cec5SDimitry Andric       sel = 3;
57830b57cec5SDimitry Andric       break;
57840b57cec5SDimitry Andric   }
57850b57cec5SDimitry Andric   unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
57860b57cec5SDimitry Andric   unsigned Op1 =
57870b57cec5SDimitry Andric       IsMFTR ? rd
57880b57cec5SDimitry Andric              : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
57890b57cec5SDimitry Andric                                                  : Inst.getOperand(0).getReg());
57900b57cec5SDimitry Andric 
57910b57cec5SDimitry Andric   TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
57920b57cec5SDimitry Andric                  STI);
57930b57cec5SDimitry Andric   return false;
57940b57cec5SDimitry Andric }
57950b57cec5SDimitry Andric 
expandSaaAddr(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)57960b57cec5SDimitry Andric bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
57970b57cec5SDimitry Andric                                   const MCSubtargetInfo *STI) {
57980b57cec5SDimitry Andric   assert(Inst.getNumOperands() == 3 && "expected three operands");
57990b57cec5SDimitry Andric   assert(Inst.getOperand(0).isReg() && "expected register operand kind");
58000b57cec5SDimitry Andric   assert(Inst.getOperand(1).isReg() && "expected register operand kind");
58010b57cec5SDimitry Andric 
58020b57cec5SDimitry Andric   warnIfNoMacro(IDLoc);
58030b57cec5SDimitry Andric 
58040b57cec5SDimitry Andric   MipsTargetStreamer &TOut = getTargetStreamer();
58050b57cec5SDimitry Andric   unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD;
58060b57cec5SDimitry Andric   unsigned RtReg = Inst.getOperand(0).getReg();
58070b57cec5SDimitry Andric   unsigned BaseReg = Inst.getOperand(1).getReg();
58080b57cec5SDimitry Andric   const MCOperand &BaseOp = Inst.getOperand(2);
58090b57cec5SDimitry Andric 
58100b57cec5SDimitry Andric   if (BaseOp.isImm()) {
58110b57cec5SDimitry Andric     int64_t ImmValue = BaseOp.getImm();
58120b57cec5SDimitry Andric     if (ImmValue == 0) {
58130b57cec5SDimitry Andric       TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI);
58140b57cec5SDimitry Andric       return false;
58150b57cec5SDimitry Andric     }
58160b57cec5SDimitry Andric   }
58170b57cec5SDimitry Andric 
58180b57cec5SDimitry Andric   unsigned ATReg = getATReg(IDLoc);
58190b57cec5SDimitry Andric   if (!ATReg)
58200b57cec5SDimitry Andric     return true;
58210b57cec5SDimitry Andric 
58220b57cec5SDimitry Andric   if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI))
58230b57cec5SDimitry Andric     return true;
58240b57cec5SDimitry Andric 
58250b57cec5SDimitry Andric   TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI);
58260b57cec5SDimitry Andric   return false;
58270b57cec5SDimitry Andric }
58280b57cec5SDimitry Andric 
58290b57cec5SDimitry Andric unsigned
checkEarlyTargetMatchPredicate(MCInst & Inst,const OperandVector & Operands)58300b57cec5SDimitry Andric MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
58310b57cec5SDimitry Andric                                               const OperandVector &Operands) {
58320b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
58330b57cec5SDimitry Andric   default:
58340b57cec5SDimitry Andric     return Match_Success;
58350b57cec5SDimitry Andric   case Mips::DATI:
58360b57cec5SDimitry Andric   case Mips::DAHI:
58370b57cec5SDimitry Andric     if (static_cast<MipsOperand &>(*Operands[1])
58380b57cec5SDimitry Andric             .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
58390b57cec5SDimitry Andric       return Match_Success;
58400b57cec5SDimitry Andric     return Match_RequiresSameSrcAndDst;
58410b57cec5SDimitry Andric   }
58420b57cec5SDimitry Andric }
58430b57cec5SDimitry Andric 
checkTargetMatchPredicate(MCInst & Inst)58440b57cec5SDimitry Andric unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
58450b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
58460b57cec5SDimitry Andric   // As described by the MIPSR6 spec, daui must not use the zero operand for
58470b57cec5SDimitry Andric   // its source operand.
58480b57cec5SDimitry Andric   case Mips::DAUI:
58490b57cec5SDimitry Andric     if (Inst.getOperand(1).getReg() == Mips::ZERO ||
58500b57cec5SDimitry Andric         Inst.getOperand(1).getReg() == Mips::ZERO_64)
58510b57cec5SDimitry Andric       return Match_RequiresNoZeroRegister;
58520b57cec5SDimitry Andric     return Match_Success;
58530b57cec5SDimitry Andric   // As described by the Mips32r2 spec, the registers Rd and Rs for
58540b57cec5SDimitry Andric   // jalr.hb must be different.
58550b57cec5SDimitry Andric   // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
58560b57cec5SDimitry Andric   // and registers Rd and Base for microMIPS lwp instruction
58570b57cec5SDimitry Andric   case Mips::JALR_HB:
58580b57cec5SDimitry Andric   case Mips::JALR_HB64:
58590b57cec5SDimitry Andric   case Mips::JALRC_HB_MMR6:
58600b57cec5SDimitry Andric   case Mips::JALRC_MMR6:
58610b57cec5SDimitry Andric     if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
58620b57cec5SDimitry Andric       return Match_RequiresDifferentSrcAndDst;
58630b57cec5SDimitry Andric     return Match_Success;
58640b57cec5SDimitry Andric   case Mips::LWP_MM:
58650b57cec5SDimitry Andric     if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
58660b57cec5SDimitry Andric       return Match_RequiresDifferentSrcAndDst;
58670b57cec5SDimitry Andric     return Match_Success;
58680b57cec5SDimitry Andric   case Mips::SYNC:
58690b57cec5SDimitry Andric     if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
58700b57cec5SDimitry Andric       return Match_NonZeroOperandForSync;
58710b57cec5SDimitry Andric     return Match_Success;
58720b57cec5SDimitry Andric   case Mips::MFC0:
58730b57cec5SDimitry Andric   case Mips::MTC0:
58740b57cec5SDimitry Andric   case Mips::MTC2:
58750b57cec5SDimitry Andric   case Mips::MFC2:
58760b57cec5SDimitry Andric     if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
58770b57cec5SDimitry Andric       return Match_NonZeroOperandForMTCX;
58780b57cec5SDimitry Andric     return Match_Success;
58790b57cec5SDimitry Andric   // As described the MIPSR6 spec, the compact branches that compare registers
58800b57cec5SDimitry Andric   // must:
58810b57cec5SDimitry Andric   // a) Not use the zero register.
58820b57cec5SDimitry Andric   // b) Not use the same register twice.
58830b57cec5SDimitry Andric   // c) rs < rt for bnec, beqc.
58840b57cec5SDimitry Andric   //    NB: For this case, the encoding will swap the operands as their
58850b57cec5SDimitry Andric   //    ordering doesn't matter. GAS performs this transformation  too.
58860b57cec5SDimitry Andric   //    Hence, that constraint does not have to be enforced.
58870b57cec5SDimitry Andric   //
58880b57cec5SDimitry Andric   // The compact branches that branch iff the signed addition of two registers
58890b57cec5SDimitry Andric   // would overflow must have rs >= rt. That can be handled like beqc/bnec with
58900b57cec5SDimitry Andric   // operand swapping. They do not have restriction of using the zero register.
58910b57cec5SDimitry Andric   case Mips::BLEZC:   case Mips::BLEZC_MMR6:
58920b57cec5SDimitry Andric   case Mips::BGEZC:   case Mips::BGEZC_MMR6:
58930b57cec5SDimitry Andric   case Mips::BGTZC:   case Mips::BGTZC_MMR6:
58940b57cec5SDimitry Andric   case Mips::BLTZC:   case Mips::BLTZC_MMR6:
58950b57cec5SDimitry Andric   case Mips::BEQZC:   case Mips::BEQZC_MMR6:
58960b57cec5SDimitry Andric   case Mips::BNEZC:   case Mips::BNEZC_MMR6:
58970b57cec5SDimitry Andric   case Mips::BLEZC64:
58980b57cec5SDimitry Andric   case Mips::BGEZC64:
58990b57cec5SDimitry Andric   case Mips::BGTZC64:
59000b57cec5SDimitry Andric   case Mips::BLTZC64:
59010b57cec5SDimitry Andric   case Mips::BEQZC64:
59020b57cec5SDimitry Andric   case Mips::BNEZC64:
59030b57cec5SDimitry Andric     if (Inst.getOperand(0).getReg() == Mips::ZERO ||
59040b57cec5SDimitry Andric         Inst.getOperand(0).getReg() == Mips::ZERO_64)
59050b57cec5SDimitry Andric       return Match_RequiresNoZeroRegister;
59060b57cec5SDimitry Andric     return Match_Success;
59070b57cec5SDimitry Andric   case Mips::BGEC:    case Mips::BGEC_MMR6:
59080b57cec5SDimitry Andric   case Mips::BLTC:    case Mips::BLTC_MMR6:
59090b57cec5SDimitry Andric   case Mips::BGEUC:   case Mips::BGEUC_MMR6:
59100b57cec5SDimitry Andric   case Mips::BLTUC:   case Mips::BLTUC_MMR6:
59110b57cec5SDimitry Andric   case Mips::BEQC:    case Mips::BEQC_MMR6:
59120b57cec5SDimitry Andric   case Mips::BNEC:    case Mips::BNEC_MMR6:
59130b57cec5SDimitry Andric   case Mips::BGEC64:
59140b57cec5SDimitry Andric   case Mips::BLTC64:
59150b57cec5SDimitry Andric   case Mips::BGEUC64:
59160b57cec5SDimitry Andric   case Mips::BLTUC64:
59170b57cec5SDimitry Andric   case Mips::BEQC64:
59180b57cec5SDimitry Andric   case Mips::BNEC64:
59190b57cec5SDimitry Andric     if (Inst.getOperand(0).getReg() == Mips::ZERO ||
59200b57cec5SDimitry Andric         Inst.getOperand(0).getReg() == Mips::ZERO_64)
59210b57cec5SDimitry Andric       return Match_RequiresNoZeroRegister;
59220b57cec5SDimitry Andric     if (Inst.getOperand(1).getReg() == Mips::ZERO ||
59230b57cec5SDimitry Andric         Inst.getOperand(1).getReg() == Mips::ZERO_64)
59240b57cec5SDimitry Andric       return Match_RequiresNoZeroRegister;
59250b57cec5SDimitry Andric     if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
59260b57cec5SDimitry Andric       return Match_RequiresDifferentOperands;
59270b57cec5SDimitry Andric     return Match_Success;
59280b57cec5SDimitry Andric   case Mips::DINS: {
59290b57cec5SDimitry Andric     assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59300b57cec5SDimitry Andric            "Operands must be immediates for dins!");
59310b57cec5SDimitry Andric     const signed Pos = Inst.getOperand(2).getImm();
59320b57cec5SDimitry Andric     const signed Size = Inst.getOperand(3).getImm();
59330b57cec5SDimitry Andric     if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
59340b57cec5SDimitry Andric       return Match_RequiresPosSizeRange0_32;
59350b57cec5SDimitry Andric     return Match_Success;
59360b57cec5SDimitry Andric   }
59370b57cec5SDimitry Andric   case Mips::DINSM:
59380b57cec5SDimitry Andric   case Mips::DINSU: {
59390b57cec5SDimitry Andric     assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59400b57cec5SDimitry Andric            "Operands must be immediates for dinsm/dinsu!");
59410b57cec5SDimitry Andric     const signed Pos = Inst.getOperand(2).getImm();
59420b57cec5SDimitry Andric     const signed Size = Inst.getOperand(3).getImm();
59430b57cec5SDimitry Andric     if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
59440b57cec5SDimitry Andric       return Match_RequiresPosSizeRange33_64;
59450b57cec5SDimitry Andric     return Match_Success;
59460b57cec5SDimitry Andric   }
59470b57cec5SDimitry Andric   case Mips::DEXT: {
59480b57cec5SDimitry Andric     assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59490b57cec5SDimitry Andric            "Operands must be immediates for DEXTM!");
59500b57cec5SDimitry Andric     const signed Pos = Inst.getOperand(2).getImm();
59510b57cec5SDimitry Andric     const signed Size = Inst.getOperand(3).getImm();
59520b57cec5SDimitry Andric     if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
59530b57cec5SDimitry Andric       return Match_RequiresPosSizeUImm6;
59540b57cec5SDimitry Andric     return Match_Success;
59550b57cec5SDimitry Andric   }
59560b57cec5SDimitry Andric   case Mips::DEXTM:
59570b57cec5SDimitry Andric   case Mips::DEXTU: {
59580b57cec5SDimitry Andric     assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59590b57cec5SDimitry Andric            "Operands must be immediates for dextm/dextu!");
59600b57cec5SDimitry Andric     const signed Pos = Inst.getOperand(2).getImm();
59610b57cec5SDimitry Andric     const signed Size = Inst.getOperand(3).getImm();
59620b57cec5SDimitry Andric     if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
59630b57cec5SDimitry Andric       return Match_RequiresPosSizeRange33_64;
59640b57cec5SDimitry Andric     return Match_Success;
59650b57cec5SDimitry Andric   }
59660b57cec5SDimitry Andric   case Mips::CRC32B: case Mips::CRC32CB:
59670b57cec5SDimitry Andric   case Mips::CRC32H: case Mips::CRC32CH:
59680b57cec5SDimitry Andric   case Mips::CRC32W: case Mips::CRC32CW:
59690b57cec5SDimitry Andric   case Mips::CRC32D: case Mips::CRC32CD:
59700b57cec5SDimitry Andric     if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
59710b57cec5SDimitry Andric       return Match_RequiresSameSrcAndDst;
59720b57cec5SDimitry Andric     return Match_Success;
59730b57cec5SDimitry Andric   }
59740b57cec5SDimitry Andric 
5975bdd1243dSDimitry Andric   uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
59760b57cec5SDimitry Andric   if ((TSFlags & MipsII::HasFCCRegOperand) &&
59770b57cec5SDimitry Andric       (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
59780b57cec5SDimitry Andric     return Match_NoFCCRegisterForCurrentISA;
59790b57cec5SDimitry Andric 
59800b57cec5SDimitry Andric   return Match_Success;
59810b57cec5SDimitry Andric 
59820b57cec5SDimitry Andric }
59830b57cec5SDimitry Andric 
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)59840b57cec5SDimitry Andric static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
59850b57cec5SDimitry Andric                             uint64_t ErrorInfo) {
59860b57cec5SDimitry Andric   if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
59870b57cec5SDimitry Andric     SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
59880b57cec5SDimitry Andric     if (ErrorLoc == SMLoc())
59890b57cec5SDimitry Andric       return Loc;
59900b57cec5SDimitry Andric     return ErrorLoc;
59910b57cec5SDimitry Andric   }
59920b57cec5SDimitry Andric   return Loc;
59930b57cec5SDimitry Andric }
59940b57cec5SDimitry Andric 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)59950b57cec5SDimitry Andric bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
59960b57cec5SDimitry Andric                                             OperandVector &Operands,
59970b57cec5SDimitry Andric                                             MCStreamer &Out,
59980b57cec5SDimitry Andric                                             uint64_t &ErrorInfo,
59990b57cec5SDimitry Andric                                             bool MatchingInlineAsm) {
60000b57cec5SDimitry Andric   MCInst Inst;
60010b57cec5SDimitry Andric   unsigned MatchResult =
60020b57cec5SDimitry Andric       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
60030b57cec5SDimitry Andric 
60040b57cec5SDimitry Andric   switch (MatchResult) {
60050b57cec5SDimitry Andric   case Match_Success:
60060b57cec5SDimitry Andric     if (processInstruction(Inst, IDLoc, Out, STI))
60070b57cec5SDimitry Andric       return true;
60080b57cec5SDimitry Andric     return false;
60090b57cec5SDimitry Andric   case Match_MissingFeature:
60100b57cec5SDimitry Andric     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
60110b57cec5SDimitry Andric     return true;
6012bdd1243dSDimitry Andric   case Match_InvalidTiedOperand:
6013bdd1243dSDimitry Andric     Error(IDLoc, "operand must match destination register");
6014bdd1243dSDimitry Andric     return true;
60150b57cec5SDimitry Andric   case Match_InvalidOperand: {
60160b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
60170b57cec5SDimitry Andric     if (ErrorInfo != ~0ULL) {
60180b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
60190b57cec5SDimitry Andric         return Error(IDLoc, "too few operands for instruction");
60200b57cec5SDimitry Andric 
60210b57cec5SDimitry Andric       ErrorLoc = Operands[ErrorInfo]->getStartLoc();
60220b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
60230b57cec5SDimitry Andric         ErrorLoc = IDLoc;
60240b57cec5SDimitry Andric     }
60250b57cec5SDimitry Andric 
60260b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
60270b57cec5SDimitry Andric   }
60280b57cec5SDimitry Andric   case Match_NonZeroOperandForSync:
60290b57cec5SDimitry Andric     return Error(IDLoc,
60300b57cec5SDimitry Andric                  "s-type must be zero or unspecified for pre-MIPS32 ISAs");
60310b57cec5SDimitry Andric   case Match_NonZeroOperandForMTCX:
60320b57cec5SDimitry Andric     return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
60330b57cec5SDimitry Andric   case Match_MnemonicFail:
60340b57cec5SDimitry Andric     return Error(IDLoc, "invalid instruction");
60350b57cec5SDimitry Andric   case Match_RequiresDifferentSrcAndDst:
60360b57cec5SDimitry Andric     return Error(IDLoc, "source and destination must be different");
60370b57cec5SDimitry Andric   case Match_RequiresDifferentOperands:
60380b57cec5SDimitry Andric     return Error(IDLoc, "registers must be different");
60390b57cec5SDimitry Andric   case Match_RequiresNoZeroRegister:
60400b57cec5SDimitry Andric     return Error(IDLoc, "invalid operand ($zero) for instruction");
60410b57cec5SDimitry Andric   case Match_RequiresSameSrcAndDst:
60420b57cec5SDimitry Andric     return Error(IDLoc, "source and destination must match");
60430b57cec5SDimitry Andric   case Match_NoFCCRegisterForCurrentISA:
60440b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60450b57cec5SDimitry Andric                  "non-zero fcc register doesn't exist in current ISA level");
60460b57cec5SDimitry Andric   case Match_Immz:
60470b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
60480b57cec5SDimitry Andric   case Match_UImm1_0:
60490b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60500b57cec5SDimitry Andric                  "expected 1-bit unsigned immediate");
60510b57cec5SDimitry Andric   case Match_UImm2_0:
60520b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60530b57cec5SDimitry Andric                  "expected 2-bit unsigned immediate");
60540b57cec5SDimitry Andric   case Match_UImm2_1:
60550b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60560b57cec5SDimitry Andric                  "expected immediate in range 1 .. 4");
60570b57cec5SDimitry Andric   case Match_UImm3_0:
60580b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60590b57cec5SDimitry Andric                  "expected 3-bit unsigned immediate");
60600b57cec5SDimitry Andric   case Match_UImm4_0:
60610b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60620b57cec5SDimitry Andric                  "expected 4-bit unsigned immediate");
60630b57cec5SDimitry Andric   case Match_SImm4_0:
60640b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60650b57cec5SDimitry Andric                  "expected 4-bit signed immediate");
60660b57cec5SDimitry Andric   case Match_UImm5_0:
60670b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60680b57cec5SDimitry Andric                  "expected 5-bit unsigned immediate");
60690b57cec5SDimitry Andric   case Match_SImm5_0:
60700b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60710b57cec5SDimitry Andric                  "expected 5-bit signed immediate");
60720b57cec5SDimitry Andric   case Match_UImm5_1:
60730b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60740b57cec5SDimitry Andric                  "expected immediate in range 1 .. 32");
60750b57cec5SDimitry Andric   case Match_UImm5_32:
60760b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60770b57cec5SDimitry Andric                  "expected immediate in range 32 .. 63");
60780b57cec5SDimitry Andric   case Match_UImm5_33:
60790b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60800b57cec5SDimitry Andric                  "expected immediate in range 33 .. 64");
60810b57cec5SDimitry Andric   case Match_UImm5_0_Report_UImm6:
60820b57cec5SDimitry Andric     // This is used on UImm5 operands that have a corresponding UImm5_32
60830b57cec5SDimitry Andric     // operand to avoid confusing the user.
60840b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60850b57cec5SDimitry Andric                  "expected 6-bit unsigned immediate");
60860b57cec5SDimitry Andric   case Match_UImm5_Lsl2:
60870b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60880b57cec5SDimitry Andric                  "expected both 7-bit unsigned immediate and multiple of 4");
60890b57cec5SDimitry Andric   case Match_UImmRange2_64:
60900b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60910b57cec5SDimitry Andric                  "expected immediate in range 2 .. 64");
60920b57cec5SDimitry Andric   case Match_UImm6_0:
60930b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60940b57cec5SDimitry Andric                  "expected 6-bit unsigned immediate");
60950b57cec5SDimitry Andric   case Match_UImm6_Lsl2:
60960b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60970b57cec5SDimitry Andric                  "expected both 8-bit unsigned immediate and multiple of 4");
60980b57cec5SDimitry Andric   case Match_SImm6_0:
60990b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61000b57cec5SDimitry Andric                  "expected 6-bit signed immediate");
61010b57cec5SDimitry Andric   case Match_UImm7_0:
61020b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61030b57cec5SDimitry Andric                  "expected 7-bit unsigned immediate");
61040b57cec5SDimitry Andric   case Match_UImm7_N1:
61050b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61060b57cec5SDimitry Andric                  "expected immediate in range -1 .. 126");
61070b57cec5SDimitry Andric   case Match_SImm7_Lsl2:
61080b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61090b57cec5SDimitry Andric                  "expected both 9-bit signed immediate and multiple of 4");
61100b57cec5SDimitry Andric   case Match_UImm8_0:
61110b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61120b57cec5SDimitry Andric                  "expected 8-bit unsigned immediate");
61130b57cec5SDimitry Andric   case Match_UImm10_0:
61140b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61150b57cec5SDimitry Andric                  "expected 10-bit unsigned immediate");
61160b57cec5SDimitry Andric   case Match_SImm10_0:
61170b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61180b57cec5SDimitry Andric                  "expected 10-bit signed immediate");
61190b57cec5SDimitry Andric   case Match_SImm11_0:
61200b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61210b57cec5SDimitry Andric                  "expected 11-bit signed immediate");
61220b57cec5SDimitry Andric   case Match_UImm16:
61230b57cec5SDimitry Andric   case Match_UImm16_Relaxed:
61240b57cec5SDimitry Andric   case Match_UImm16_AltRelaxed:
61250b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61260b57cec5SDimitry Andric                  "expected 16-bit unsigned immediate");
61270b57cec5SDimitry Andric   case Match_SImm16:
61280b57cec5SDimitry Andric   case Match_SImm16_Relaxed:
61290b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61300b57cec5SDimitry Andric                  "expected 16-bit signed immediate");
61310b57cec5SDimitry Andric   case Match_SImm19_Lsl2:
61320b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61330b57cec5SDimitry Andric                  "expected both 19-bit signed immediate and multiple of 4");
61340b57cec5SDimitry Andric   case Match_UImm20_0:
61350b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61360b57cec5SDimitry Andric                  "expected 20-bit unsigned immediate");
61370b57cec5SDimitry Andric   case Match_UImm26_0:
61380b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61390b57cec5SDimitry Andric                  "expected 26-bit unsigned immediate");
61400b57cec5SDimitry Andric   case Match_SImm32:
61410b57cec5SDimitry Andric   case Match_SImm32_Relaxed:
61420b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61430b57cec5SDimitry Andric                  "expected 32-bit signed immediate");
61440b57cec5SDimitry Andric   case Match_UImm32_Coerced:
61450b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61460b57cec5SDimitry Andric                  "expected 32-bit immediate");
61470b57cec5SDimitry Andric   case Match_MemSImm9:
61480b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61490b57cec5SDimitry Andric                  "expected memory with 9-bit signed offset");
61500b57cec5SDimitry Andric   case Match_MemSImm10:
61510b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61520b57cec5SDimitry Andric                  "expected memory with 10-bit signed offset");
61530b57cec5SDimitry Andric   case Match_MemSImm10Lsl1:
61540b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61550b57cec5SDimitry Andric                  "expected memory with 11-bit signed offset and multiple of 2");
61560b57cec5SDimitry Andric   case Match_MemSImm10Lsl2:
61570b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61580b57cec5SDimitry Andric                  "expected memory with 12-bit signed offset and multiple of 4");
61590b57cec5SDimitry Andric   case Match_MemSImm10Lsl3:
61600b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61610b57cec5SDimitry Andric                  "expected memory with 13-bit signed offset and multiple of 8");
61620b57cec5SDimitry Andric   case Match_MemSImm11:
61630b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61640b57cec5SDimitry Andric                  "expected memory with 11-bit signed offset");
61650b57cec5SDimitry Andric   case Match_MemSImm12:
61660b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61670b57cec5SDimitry Andric                  "expected memory with 12-bit signed offset");
61680b57cec5SDimitry Andric   case Match_MemSImm16:
61690b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61700b57cec5SDimitry Andric                  "expected memory with 16-bit signed offset");
61710b57cec5SDimitry Andric   case Match_MemSImmPtr:
61720b57cec5SDimitry Andric     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61730b57cec5SDimitry Andric                  "expected memory with 32-bit signed offset");
61740b57cec5SDimitry Andric   case Match_RequiresPosSizeRange0_32: {
61750b57cec5SDimitry Andric     SMLoc ErrorStart = Operands[3]->getStartLoc();
61760b57cec5SDimitry Andric     SMLoc ErrorEnd = Operands[4]->getEndLoc();
61770b57cec5SDimitry Andric     return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
61780b57cec5SDimitry Andric                  SMRange(ErrorStart, ErrorEnd));
61790b57cec5SDimitry Andric     }
61800b57cec5SDimitry Andric   case Match_RequiresPosSizeUImm6: {
61810b57cec5SDimitry Andric     SMLoc ErrorStart = Operands[3]->getStartLoc();
61820b57cec5SDimitry Andric     SMLoc ErrorEnd = Operands[4]->getEndLoc();
61830b57cec5SDimitry Andric     return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
61840b57cec5SDimitry Andric                  SMRange(ErrorStart, ErrorEnd));
61850b57cec5SDimitry Andric     }
61860b57cec5SDimitry Andric   case Match_RequiresPosSizeRange33_64: {
61870b57cec5SDimitry Andric     SMLoc ErrorStart = Operands[3]->getStartLoc();
61880b57cec5SDimitry Andric     SMLoc ErrorEnd = Operands[4]->getEndLoc();
61890b57cec5SDimitry Andric     return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
61900b57cec5SDimitry Andric                  SMRange(ErrorStart, ErrorEnd));
61910b57cec5SDimitry Andric     }
61920b57cec5SDimitry Andric   }
61930b57cec5SDimitry Andric 
61940b57cec5SDimitry Andric   llvm_unreachable("Implement any new match types added!");
61950b57cec5SDimitry Andric }
61960b57cec5SDimitry Andric 
warnIfRegIndexIsAT(unsigned RegIndex,SMLoc Loc)61970b57cec5SDimitry Andric void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
61980b57cec5SDimitry Andric   if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
61990b57cec5SDimitry Andric     Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
62000b57cec5SDimitry Andric                      ") without \".set noat\"");
62010b57cec5SDimitry Andric }
62020b57cec5SDimitry Andric 
warnIfNoMacro(SMLoc Loc)62030b57cec5SDimitry Andric void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
62040b57cec5SDimitry Andric   if (!AssemblerOptions.back()->isMacro())
62050b57cec5SDimitry Andric     Warning(Loc, "macro instruction expanded into multiple instructions");
62060b57cec5SDimitry Andric }
62070b57cec5SDimitry Andric 
ConvertXWPOperands(MCInst & Inst,const OperandVector & Operands)62080b57cec5SDimitry Andric void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
62090b57cec5SDimitry Andric                                        const OperandVector &Operands) {
62100b57cec5SDimitry Andric   assert(
62110b57cec5SDimitry Andric       (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
62120b57cec5SDimitry Andric       "Unexpected instruction!");
62130b57cec5SDimitry Andric   ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
62140b57cec5SDimitry Andric   int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
62150b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(NextReg));
62160b57cec5SDimitry Andric   ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
62170b57cec5SDimitry Andric }
62180b57cec5SDimitry Andric 
62190b57cec5SDimitry Andric void
printWarningWithFixIt(const Twine & Msg,const Twine & FixMsg,SMRange Range,bool ShowColors)62200b57cec5SDimitry Andric MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
62210b57cec5SDimitry Andric                                      SMRange Range, bool ShowColors) {
62220b57cec5SDimitry Andric   getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
62230b57cec5SDimitry Andric                                   Range, SMFixIt(Range, FixMsg),
62240b57cec5SDimitry Andric                                   ShowColors);
62250b57cec5SDimitry Andric }
62260b57cec5SDimitry Andric 
matchCPURegisterName(StringRef Name)62270b57cec5SDimitry Andric int MipsAsmParser::matchCPURegisterName(StringRef Name) {
62280b57cec5SDimitry Andric   int CC;
62290b57cec5SDimitry Andric 
62300b57cec5SDimitry Andric   CC = StringSwitch<unsigned>(Name)
62310b57cec5SDimitry Andric            .Case("zero", 0)
62320b57cec5SDimitry Andric            .Cases("at", "AT", 1)
62330b57cec5SDimitry Andric            .Case("a0", 4)
62340b57cec5SDimitry Andric            .Case("a1", 5)
62350b57cec5SDimitry Andric            .Case("a2", 6)
62360b57cec5SDimitry Andric            .Case("a3", 7)
62370b57cec5SDimitry Andric            .Case("v0", 2)
62380b57cec5SDimitry Andric            .Case("v1", 3)
62390b57cec5SDimitry Andric            .Case("s0", 16)
62400b57cec5SDimitry Andric            .Case("s1", 17)
62410b57cec5SDimitry Andric            .Case("s2", 18)
62420b57cec5SDimitry Andric            .Case("s3", 19)
62430b57cec5SDimitry Andric            .Case("s4", 20)
62440b57cec5SDimitry Andric            .Case("s5", 21)
62450b57cec5SDimitry Andric            .Case("s6", 22)
62460b57cec5SDimitry Andric            .Case("s7", 23)
62470b57cec5SDimitry Andric            .Case("k0", 26)
62480b57cec5SDimitry Andric            .Case("k1", 27)
62490b57cec5SDimitry Andric            .Case("gp", 28)
62500b57cec5SDimitry Andric            .Case("sp", 29)
62510b57cec5SDimitry Andric            .Case("fp", 30)
62520b57cec5SDimitry Andric            .Case("s8", 30)
62530b57cec5SDimitry Andric            .Case("ra", 31)
62540b57cec5SDimitry Andric            .Case("t0", 8)
62550b57cec5SDimitry Andric            .Case("t1", 9)
62560b57cec5SDimitry Andric            .Case("t2", 10)
62570b57cec5SDimitry Andric            .Case("t3", 11)
62580b57cec5SDimitry Andric            .Case("t4", 12)
62590b57cec5SDimitry Andric            .Case("t5", 13)
62600b57cec5SDimitry Andric            .Case("t6", 14)
62610b57cec5SDimitry Andric            .Case("t7", 15)
62620b57cec5SDimitry Andric            .Case("t8", 24)
62630b57cec5SDimitry Andric            .Case("t9", 25)
62640b57cec5SDimitry Andric            .Default(-1);
62650b57cec5SDimitry Andric 
62660b57cec5SDimitry Andric   if (!(isABI_N32() || isABI_N64()))
62670b57cec5SDimitry Andric     return CC;
62680b57cec5SDimitry Andric 
62690b57cec5SDimitry Andric   if (12 <= CC && CC <= 15) {
62700b57cec5SDimitry Andric     // Name is one of t4-t7
62710b57cec5SDimitry Andric     AsmToken RegTok = getLexer().peekTok();
62720b57cec5SDimitry Andric     SMRange RegRange = RegTok.getLocRange();
62730b57cec5SDimitry Andric 
62740b57cec5SDimitry Andric     StringRef FixedName = StringSwitch<StringRef>(Name)
62750b57cec5SDimitry Andric                               .Case("t4", "t0")
62760b57cec5SDimitry Andric                               .Case("t5", "t1")
62770b57cec5SDimitry Andric                               .Case("t6", "t2")
62780b57cec5SDimitry Andric                               .Case("t7", "t3")
62790b57cec5SDimitry Andric                               .Default("");
62800b57cec5SDimitry Andric     assert(FixedName != "" &&  "Register name is not one of t4-t7.");
62810b57cec5SDimitry Andric 
62820b57cec5SDimitry Andric     printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
62830b57cec5SDimitry Andric                           "Did you mean $" + FixedName + "?", RegRange);
62840b57cec5SDimitry Andric   }
62850b57cec5SDimitry Andric 
62860b57cec5SDimitry Andric   // Although SGI documentation just cuts out t0-t3 for n32/n64,
62870b57cec5SDimitry Andric   // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
62880b57cec5SDimitry Andric   // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
62890b57cec5SDimitry Andric   if (8 <= CC && CC <= 11)
62900b57cec5SDimitry Andric     CC += 4;
62910b57cec5SDimitry Andric 
62920b57cec5SDimitry Andric   if (CC == -1)
62930b57cec5SDimitry Andric     CC = StringSwitch<unsigned>(Name)
62940b57cec5SDimitry Andric              .Case("a4", 8)
62950b57cec5SDimitry Andric              .Case("a5", 9)
62960b57cec5SDimitry Andric              .Case("a6", 10)
62970b57cec5SDimitry Andric              .Case("a7", 11)
62980b57cec5SDimitry Andric              .Case("kt0", 26)
62990b57cec5SDimitry Andric              .Case("kt1", 27)
63000b57cec5SDimitry Andric              .Default(-1);
63010b57cec5SDimitry Andric 
63020b57cec5SDimitry Andric   return CC;
63030b57cec5SDimitry Andric }
63040b57cec5SDimitry Andric 
matchHWRegsRegisterName(StringRef Name)63050b57cec5SDimitry Andric int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
63060b57cec5SDimitry Andric   int CC;
63070b57cec5SDimitry Andric 
63080b57cec5SDimitry Andric   CC = StringSwitch<unsigned>(Name)
63090b57cec5SDimitry Andric             .Case("hwr_cpunum", 0)
63100b57cec5SDimitry Andric             .Case("hwr_synci_step", 1)
63110b57cec5SDimitry Andric             .Case("hwr_cc", 2)
63120b57cec5SDimitry Andric             .Case("hwr_ccres", 3)
63130b57cec5SDimitry Andric             .Case("hwr_ulr", 29)
63140b57cec5SDimitry Andric             .Default(-1);
63150b57cec5SDimitry Andric 
63160b57cec5SDimitry Andric   return CC;
63170b57cec5SDimitry Andric }
63180b57cec5SDimitry Andric 
matchFPURegisterName(StringRef Name)63190b57cec5SDimitry Andric int MipsAsmParser::matchFPURegisterName(StringRef Name) {
63200b57cec5SDimitry Andric   if (Name[0] == 'f') {
63210b57cec5SDimitry Andric     StringRef NumString = Name.substr(1);
63220b57cec5SDimitry Andric     unsigned IntVal;
63230b57cec5SDimitry Andric     if (NumString.getAsInteger(10, IntVal))
63240b57cec5SDimitry Andric       return -1;     // This is not an integer.
63250b57cec5SDimitry Andric     if (IntVal > 31) // Maximum index for fpu register.
63260b57cec5SDimitry Andric       return -1;
63270b57cec5SDimitry Andric     return IntVal;
63280b57cec5SDimitry Andric   }
63290b57cec5SDimitry Andric   return -1;
63300b57cec5SDimitry Andric }
63310b57cec5SDimitry Andric 
matchFCCRegisterName(StringRef Name)63320b57cec5SDimitry Andric int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
63335f757f3fSDimitry Andric   if (Name.starts_with("fcc")) {
63340b57cec5SDimitry Andric     StringRef NumString = Name.substr(3);
63350b57cec5SDimitry Andric     unsigned IntVal;
63360b57cec5SDimitry Andric     if (NumString.getAsInteger(10, IntVal))
63370b57cec5SDimitry Andric       return -1;    // This is not an integer.
63380b57cec5SDimitry Andric     if (IntVal > 7) // There are only 8 fcc registers.
63390b57cec5SDimitry Andric       return -1;
63400b57cec5SDimitry Andric     return IntVal;
63410b57cec5SDimitry Andric   }
63420b57cec5SDimitry Andric   return -1;
63430b57cec5SDimitry Andric }
63440b57cec5SDimitry Andric 
matchACRegisterName(StringRef Name)63450b57cec5SDimitry Andric int MipsAsmParser::matchACRegisterName(StringRef Name) {
63465f757f3fSDimitry Andric   if (Name.starts_with("ac")) {
63470b57cec5SDimitry Andric     StringRef NumString = Name.substr(2);
63480b57cec5SDimitry Andric     unsigned IntVal;
63490b57cec5SDimitry Andric     if (NumString.getAsInteger(10, IntVal))
63500b57cec5SDimitry Andric       return -1;    // This is not an integer.
63510b57cec5SDimitry Andric     if (IntVal > 3) // There are only 3 acc registers.
63520b57cec5SDimitry Andric       return -1;
63530b57cec5SDimitry Andric     return IntVal;
63540b57cec5SDimitry Andric   }
63550b57cec5SDimitry Andric   return -1;
63560b57cec5SDimitry Andric }
63570b57cec5SDimitry Andric 
matchMSA128RegisterName(StringRef Name)63580b57cec5SDimitry Andric int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
63590b57cec5SDimitry Andric   unsigned IntVal;
63600b57cec5SDimitry Andric 
63610b57cec5SDimitry Andric   if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
63620b57cec5SDimitry Andric     return -1;
63630b57cec5SDimitry Andric 
63640b57cec5SDimitry Andric   if (IntVal > 31)
63650b57cec5SDimitry Andric     return -1;
63660b57cec5SDimitry Andric 
63670b57cec5SDimitry Andric   return IntVal;
63680b57cec5SDimitry Andric }
63690b57cec5SDimitry Andric 
matchMSA128CtrlRegisterName(StringRef Name)63700b57cec5SDimitry Andric int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
63710b57cec5SDimitry Andric   int CC;
63720b57cec5SDimitry Andric 
63730b57cec5SDimitry Andric   CC = StringSwitch<unsigned>(Name)
63740b57cec5SDimitry Andric            .Case("msair", 0)
63750b57cec5SDimitry Andric            .Case("msacsr", 1)
63760b57cec5SDimitry Andric            .Case("msaaccess", 2)
63770b57cec5SDimitry Andric            .Case("msasave", 3)
63780b57cec5SDimitry Andric            .Case("msamodify", 4)
63790b57cec5SDimitry Andric            .Case("msarequest", 5)
63800b57cec5SDimitry Andric            .Case("msamap", 6)
63810b57cec5SDimitry Andric            .Case("msaunmap", 7)
63820b57cec5SDimitry Andric            .Default(-1);
63830b57cec5SDimitry Andric 
63840b57cec5SDimitry Andric   return CC;
63850b57cec5SDimitry Andric }
63860b57cec5SDimitry Andric 
canUseATReg()63870b57cec5SDimitry Andric bool MipsAsmParser::canUseATReg() {
63880b57cec5SDimitry Andric   return AssemblerOptions.back()->getATRegIndex() != 0;
63890b57cec5SDimitry Andric }
63900b57cec5SDimitry Andric 
getATReg(SMLoc Loc)63910b57cec5SDimitry Andric unsigned MipsAsmParser::getATReg(SMLoc Loc) {
63920b57cec5SDimitry Andric   unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
63930b57cec5SDimitry Andric   if (ATIndex == 0) {
63940b57cec5SDimitry Andric     reportParseError(Loc,
63950b57cec5SDimitry Andric                      "pseudo-instruction requires $at, which is not available");
63960b57cec5SDimitry Andric     return 0;
63970b57cec5SDimitry Andric   }
63980b57cec5SDimitry Andric   unsigned AT = getReg(
63990b57cec5SDimitry Andric       (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
64000b57cec5SDimitry Andric   return AT;
64010b57cec5SDimitry Andric }
64020b57cec5SDimitry Andric 
getReg(int RC,int RegNo)64030b57cec5SDimitry Andric unsigned MipsAsmParser::getReg(int RC, int RegNo) {
64040b57cec5SDimitry Andric   return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
64050b57cec5SDimitry Andric }
64060b57cec5SDimitry Andric 
parseOperand(OperandVector & Operands,StringRef Mnemonic)64070b57cec5SDimitry Andric bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
64080b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
64090b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "parseOperand\n");
64100b57cec5SDimitry Andric 
64110b57cec5SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
64120b57cec5SDimitry Andric   // custom parse the operand, or fallback to the general approach.
641306c3fb27SDimitry Andric   ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
641406c3fb27SDimitry Andric   if (Res.isSuccess())
64150b57cec5SDimitry Andric     return false;
64160b57cec5SDimitry Andric   // If there wasn't a custom match, try the generic matcher below. Otherwise,
64170b57cec5SDimitry Andric   // there was a match, but an error occurred, in which case, just return that
64180b57cec5SDimitry Andric   // the operand parsing failed.
641906c3fb27SDimitry Andric   if (Res.isFailure())
64200b57cec5SDimitry Andric     return true;
64210b57cec5SDimitry Andric 
64220b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
64230b57cec5SDimitry Andric 
64240b57cec5SDimitry Andric   switch (getLexer().getKind()) {
64250b57cec5SDimitry Andric   case AsmToken::Dollar: {
64260b57cec5SDimitry Andric     // Parse the register.
64270b57cec5SDimitry Andric     SMLoc S = Parser.getTok().getLoc();
64280b57cec5SDimitry Andric 
64290b57cec5SDimitry Andric     // Almost all registers have been parsed by custom parsers. There is only
64300b57cec5SDimitry Andric     // one exception to this. $zero (and it's alias $0) will reach this point
64310b57cec5SDimitry Andric     // for div, divu, and similar instructions because it is not an operand
64320b57cec5SDimitry Andric     // to the instruction definition but an explicit register. Special case
64330b57cec5SDimitry Andric     // this situation for now.
643406c3fb27SDimitry Andric     if (!parseAnyRegister(Operands).isNoMatch())
64350b57cec5SDimitry Andric       return false;
64360b57cec5SDimitry Andric 
64370b57cec5SDimitry Andric     // Maybe it is a symbol reference.
64380b57cec5SDimitry Andric     StringRef Identifier;
64390b57cec5SDimitry Andric     if (Parser.parseIdentifier(Identifier))
64400b57cec5SDimitry Andric       return true;
64410b57cec5SDimitry Andric 
64420b57cec5SDimitry Andric     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
644374626c16SDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
64440b57cec5SDimitry Andric     // Otherwise create a symbol reference.
644506c3fb27SDimitry Andric     const MCExpr *SymRef =
64460b57cec5SDimitry Andric         MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
64470b57cec5SDimitry Andric 
644806c3fb27SDimitry Andric     Operands.push_back(MipsOperand::CreateImm(SymRef, S, E, *this));
64490b57cec5SDimitry Andric     return false;
64500b57cec5SDimitry Andric   }
64510b57cec5SDimitry Andric   default: {
64520b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
64530b57cec5SDimitry Andric 
64540b57cec5SDimitry Andric     const MCExpr *Expr;
64550b57cec5SDimitry Andric     SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
64560b57cec5SDimitry Andric     if (getParser().parseExpression(Expr))
64570b57cec5SDimitry Andric       return true;
64580b57cec5SDimitry Andric 
64590b57cec5SDimitry Andric     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
64600b57cec5SDimitry Andric 
64610b57cec5SDimitry Andric     Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
64620b57cec5SDimitry Andric     return false;
64630b57cec5SDimitry Andric   }
64640b57cec5SDimitry Andric   } // switch(getLexer().getKind())
64650b57cec5SDimitry Andric   return true;
64660b57cec5SDimitry Andric }
64670b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)64685f757f3fSDimitry Andric bool MipsAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
64690b57cec5SDimitry Andric                                   SMLoc &EndLoc) {
64705f757f3fSDimitry Andric   return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
64715ffd83dbSDimitry Andric }
64725ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)64735f757f3fSDimitry Andric ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
64745ffd83dbSDimitry Andric                                             SMLoc &EndLoc) {
64750b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
647606c3fb27SDimitry Andric   ParseStatus Res = parseAnyRegister(Operands);
647706c3fb27SDimitry Andric   if (Res.isSuccess()) {
64780b57cec5SDimitry Andric     assert(Operands.size() == 1);
64790b57cec5SDimitry Andric     MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
64800b57cec5SDimitry Andric     StartLoc = Operand.getStartLoc();
64810b57cec5SDimitry Andric     EndLoc = Operand.getEndLoc();
64820b57cec5SDimitry Andric 
64830b57cec5SDimitry Andric     // AFAIK, we only support numeric registers and named GPR's in CFI
64840b57cec5SDimitry Andric     // directives.
64850b57cec5SDimitry Andric     // Don't worry about eating tokens before failing. Using an unrecognised
64860b57cec5SDimitry Andric     // register is a parse error.
64870b57cec5SDimitry Andric     if (Operand.isGPRAsmReg()) {
64880b57cec5SDimitry Andric       // Resolve to GPR32 or GPR64 appropriately.
64895f757f3fSDimitry Andric       Reg = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
64900b57cec5SDimitry Andric     }
64910b57cec5SDimitry Andric 
64925f757f3fSDimitry Andric     return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
64930b57cec5SDimitry Andric   }
64940b57cec5SDimitry Andric 
64950b57cec5SDimitry Andric   assert(Operands.size() == 0);
64965f757f3fSDimitry Andric   return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
64970b57cec5SDimitry Andric }
64980b57cec5SDimitry Andric 
parseMemOffset(const MCExpr * & Res,bool isParenExpr)64990b57cec5SDimitry Andric bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
65000b57cec5SDimitry Andric   SMLoc S;
65010b57cec5SDimitry Andric 
65020b57cec5SDimitry Andric   if (isParenExpr)
65030b57cec5SDimitry Andric     return getParser().parseParenExprOfDepth(0, Res, S);
65040b57cec5SDimitry Andric   return getParser().parseExpression(Res);
65050b57cec5SDimitry Andric }
65060b57cec5SDimitry Andric 
parseMemOperand(OperandVector & Operands)650706c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
65080b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
65090b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "parseMemOperand\n");
65100b57cec5SDimitry Andric   const MCExpr *IdVal = nullptr;
65110b57cec5SDimitry Andric   SMLoc S;
65120b57cec5SDimitry Andric   bool isParenExpr = false;
651306c3fb27SDimitry Andric   ParseStatus Res = ParseStatus::NoMatch;
65140b57cec5SDimitry Andric   // First operand is the offset.
65150b57cec5SDimitry Andric   S = Parser.getTok().getLoc();
65160b57cec5SDimitry Andric 
65170b57cec5SDimitry Andric   if (getLexer().getKind() == AsmToken::LParen) {
65180b57cec5SDimitry Andric     Parser.Lex();
65190b57cec5SDimitry Andric     isParenExpr = true;
65200b57cec5SDimitry Andric   }
65210b57cec5SDimitry Andric 
65220b57cec5SDimitry Andric   if (getLexer().getKind() != AsmToken::Dollar) {
65230b57cec5SDimitry Andric     if (parseMemOffset(IdVal, isParenExpr))
652406c3fb27SDimitry Andric       return ParseStatus::Failure;
65250b57cec5SDimitry Andric 
65260b57cec5SDimitry Andric     const AsmToken &Tok = Parser.getTok(); // Get the next token.
65270b57cec5SDimitry Andric     if (Tok.isNot(AsmToken::LParen)) {
65280b57cec5SDimitry Andric       MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
65290b57cec5SDimitry Andric       if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
65300b57cec5SDimitry Andric         SMLoc E =
65310b57cec5SDimitry Andric             SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
65320b57cec5SDimitry Andric         Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
653306c3fb27SDimitry Andric         return ParseStatus::Success;
65340b57cec5SDimitry Andric       }
65350b57cec5SDimitry Andric       if (Tok.is(AsmToken::EndOfStatement)) {
65360b57cec5SDimitry Andric         SMLoc E =
65370b57cec5SDimitry Andric             SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
65380b57cec5SDimitry Andric 
65390b57cec5SDimitry Andric         // Zero register assumed, add a memory operand with ZERO as its base.
65400b57cec5SDimitry Andric         // "Base" will be managed by k_Memory.
65410b57cec5SDimitry Andric         auto Base = MipsOperand::createGPRReg(
65420b57cec5SDimitry Andric             0, "0", getContext().getRegisterInfo(), S, E, *this);
65430b57cec5SDimitry Andric         Operands.push_back(
65440b57cec5SDimitry Andric             MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
654506c3fb27SDimitry Andric         return ParseStatus::Success;
65460b57cec5SDimitry Andric       }
65470b57cec5SDimitry Andric       MCBinaryExpr::Opcode Opcode;
65480b57cec5SDimitry Andric       // GAS and LLVM treat comparison operators different. GAS will generate -1
65490b57cec5SDimitry Andric       // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
65500b57cec5SDimitry Andric       // highly unlikely to be found in a memory offset expression, we don't
65510b57cec5SDimitry Andric       // handle them.
65520b57cec5SDimitry Andric       switch (Tok.getKind()) {
65530b57cec5SDimitry Andric       case AsmToken::Plus:
65540b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Add;
65550b57cec5SDimitry Andric         Parser.Lex();
65560b57cec5SDimitry Andric         break;
65570b57cec5SDimitry Andric       case AsmToken::Minus:
65580b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Sub;
65590b57cec5SDimitry Andric         Parser.Lex();
65600b57cec5SDimitry Andric         break;
65610b57cec5SDimitry Andric       case AsmToken::Star:
65620b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Mul;
65630b57cec5SDimitry Andric         Parser.Lex();
65640b57cec5SDimitry Andric         break;
65650b57cec5SDimitry Andric       case AsmToken::Pipe:
65660b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Or;
65670b57cec5SDimitry Andric         Parser.Lex();
65680b57cec5SDimitry Andric         break;
65690b57cec5SDimitry Andric       case AsmToken::Amp:
65700b57cec5SDimitry Andric         Opcode = MCBinaryExpr::And;
65710b57cec5SDimitry Andric         Parser.Lex();
65720b57cec5SDimitry Andric         break;
65730b57cec5SDimitry Andric       case AsmToken::LessLess:
65740b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Shl;
65750b57cec5SDimitry Andric         Parser.Lex();
65760b57cec5SDimitry Andric         break;
65770b57cec5SDimitry Andric       case AsmToken::GreaterGreater:
65780b57cec5SDimitry Andric         Opcode = MCBinaryExpr::LShr;
65790b57cec5SDimitry Andric         Parser.Lex();
65800b57cec5SDimitry Andric         break;
65810b57cec5SDimitry Andric       case AsmToken::Caret:
65820b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Xor;
65830b57cec5SDimitry Andric         Parser.Lex();
65840b57cec5SDimitry Andric         break;
65850b57cec5SDimitry Andric       case AsmToken::Slash:
65860b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Div;
65870b57cec5SDimitry Andric         Parser.Lex();
65880b57cec5SDimitry Andric         break;
65890b57cec5SDimitry Andric       case AsmToken::Percent:
65900b57cec5SDimitry Andric         Opcode = MCBinaryExpr::Mod;
65910b57cec5SDimitry Andric         Parser.Lex();
65920b57cec5SDimitry Andric         break;
65930b57cec5SDimitry Andric       default:
659406c3fb27SDimitry Andric         return Error(Parser.getTok().getLoc(), "'(' or expression expected");
65950b57cec5SDimitry Andric       }
65960b57cec5SDimitry Andric       const MCExpr * NextExpr;
65970b57cec5SDimitry Andric       if (getParser().parseExpression(NextExpr))
659806c3fb27SDimitry Andric         return ParseStatus::Failure;
65990b57cec5SDimitry Andric       IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
66000b57cec5SDimitry Andric     }
66010b57cec5SDimitry Andric 
66020b57cec5SDimitry Andric     Parser.Lex(); // Eat the '(' token.
66030b57cec5SDimitry Andric   }
66040b57cec5SDimitry Andric 
66050b57cec5SDimitry Andric   Res = parseAnyRegister(Operands);
660606c3fb27SDimitry Andric   if (!Res.isSuccess())
66070b57cec5SDimitry Andric     return Res;
66080b57cec5SDimitry Andric 
660906c3fb27SDimitry Andric   if (Parser.getTok().isNot(AsmToken::RParen))
661006c3fb27SDimitry Andric     return Error(Parser.getTok().getLoc(), "')' expected");
66110b57cec5SDimitry Andric 
66120b57cec5SDimitry Andric   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
66130b57cec5SDimitry Andric 
66140b57cec5SDimitry Andric   Parser.Lex(); // Eat the ')' token.
66150b57cec5SDimitry Andric 
66160b57cec5SDimitry Andric   if (!IdVal)
66170b57cec5SDimitry Andric     IdVal = MCConstantExpr::create(0, getContext());
66180b57cec5SDimitry Andric 
66190b57cec5SDimitry Andric   // Replace the register operand with the memory operand.
66200b57cec5SDimitry Andric   std::unique_ptr<MipsOperand> op(
66210b57cec5SDimitry Andric       static_cast<MipsOperand *>(Operands.back().release()));
66220b57cec5SDimitry Andric   // Remove the register from the operands.
66230b57cec5SDimitry Andric   // "op" will be managed by k_Memory.
66240b57cec5SDimitry Andric   Operands.pop_back();
66250b57cec5SDimitry Andric   // Add the memory operand.
66260b57cec5SDimitry Andric   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
66270b57cec5SDimitry Andric     int64_t Imm;
66280b57cec5SDimitry Andric     if (IdVal->evaluateAsAbsolute(Imm))
66290b57cec5SDimitry Andric       IdVal = MCConstantExpr::create(Imm, getContext());
66300b57cec5SDimitry Andric     else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
66310b57cec5SDimitry Andric       IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
66320b57cec5SDimitry Andric                                    getContext());
66330b57cec5SDimitry Andric   }
66340b57cec5SDimitry Andric 
66350b57cec5SDimitry Andric   Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
663606c3fb27SDimitry Andric   return ParseStatus::Success;
66370b57cec5SDimitry Andric }
66380b57cec5SDimitry Andric 
searchSymbolAlias(OperandVector & Operands)66390b57cec5SDimitry Andric bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
66400b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
66410b57cec5SDimitry Andric   MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
66420b57cec5SDimitry Andric   if (!Sym)
66430b57cec5SDimitry Andric     return false;
66440b57cec5SDimitry Andric 
66450b57cec5SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
66460b57cec5SDimitry Andric   if (Sym->isVariable()) {
66470b57cec5SDimitry Andric     const MCExpr *Expr = Sym->getVariableValue();
66480b57cec5SDimitry Andric     if (Expr->getKind() == MCExpr::SymbolRef) {
66490b57cec5SDimitry Andric       const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
66500b57cec5SDimitry Andric       StringRef DefSymbol = Ref->getSymbol().getName();
66515f757f3fSDimitry Andric       if (DefSymbol.starts_with("$")) {
665206c3fb27SDimitry Andric         ParseStatus Res =
66530b57cec5SDimitry Andric             matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
665406c3fb27SDimitry Andric         if (Res.isSuccess()) {
66550b57cec5SDimitry Andric           Parser.Lex();
66560b57cec5SDimitry Andric           return true;
66570b57cec5SDimitry Andric         }
665806c3fb27SDimitry Andric         if (Res.isFailure())
665906c3fb27SDimitry Andric           llvm_unreachable("Should never fail");
66600b57cec5SDimitry Andric       }
66610b57cec5SDimitry Andric     }
66620b57cec5SDimitry Andric   } else if (Sym->isUnset()) {
66630b57cec5SDimitry Andric     // If symbol is unset, it might be created in the `parseSetAssignment`
66640b57cec5SDimitry Andric     // routine as an alias for a numeric register name.
66650b57cec5SDimitry Andric     // Lookup in the aliases list.
66660b57cec5SDimitry Andric     auto Entry = RegisterSets.find(Sym->getName());
66670b57cec5SDimitry Andric     if (Entry != RegisterSets.end()) {
666806c3fb27SDimitry Andric       ParseStatus Res =
66690b57cec5SDimitry Andric           matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
667006c3fb27SDimitry Andric       if (Res.isSuccess()) {
66710b57cec5SDimitry Andric         Parser.Lex();
66720b57cec5SDimitry Andric         return true;
66730b57cec5SDimitry Andric       }
66740b57cec5SDimitry Andric     }
66750b57cec5SDimitry Andric   }
66760b57cec5SDimitry Andric 
66770b57cec5SDimitry Andric   return false;
66780b57cec5SDimitry Andric }
66790b57cec5SDimitry Andric 
matchAnyRegisterNameWithoutDollar(OperandVector & Operands,StringRef Identifier,SMLoc S)668006c3fb27SDimitry Andric ParseStatus MipsAsmParser::matchAnyRegisterNameWithoutDollar(
668106c3fb27SDimitry Andric     OperandVector &Operands, StringRef Identifier, SMLoc S) {
66820b57cec5SDimitry Andric   int Index = matchCPURegisterName(Identifier);
66830b57cec5SDimitry Andric   if (Index != -1) {
66840b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createGPRReg(
66850b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
66860b57cec5SDimitry Andric         getLexer().getLoc(), *this));
668706c3fb27SDimitry Andric     return ParseStatus::Success;
66880b57cec5SDimitry Andric   }
66890b57cec5SDimitry Andric 
66900b57cec5SDimitry Andric   Index = matchHWRegsRegisterName(Identifier);
66910b57cec5SDimitry Andric   if (Index != -1) {
66920b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createHWRegsReg(
66930b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
66940b57cec5SDimitry Andric         getLexer().getLoc(), *this));
669506c3fb27SDimitry Andric     return ParseStatus::Success;
66960b57cec5SDimitry Andric   }
66970b57cec5SDimitry Andric 
66980b57cec5SDimitry Andric   Index = matchFPURegisterName(Identifier);
66990b57cec5SDimitry Andric   if (Index != -1) {
67000b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createFGRReg(
67010b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
67020b57cec5SDimitry Andric         getLexer().getLoc(), *this));
670306c3fb27SDimitry Andric     return ParseStatus::Success;
67040b57cec5SDimitry Andric   }
67050b57cec5SDimitry Andric 
67060b57cec5SDimitry Andric   Index = matchFCCRegisterName(Identifier);
67070b57cec5SDimitry Andric   if (Index != -1) {
67080b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createFCCReg(
67090b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
67100b57cec5SDimitry Andric         getLexer().getLoc(), *this));
671106c3fb27SDimitry Andric     return ParseStatus::Success;
67120b57cec5SDimitry Andric   }
67130b57cec5SDimitry Andric 
67140b57cec5SDimitry Andric   Index = matchACRegisterName(Identifier);
67150b57cec5SDimitry Andric   if (Index != -1) {
67160b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createACCReg(
67170b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
67180b57cec5SDimitry Andric         getLexer().getLoc(), *this));
671906c3fb27SDimitry Andric     return ParseStatus::Success;
67200b57cec5SDimitry Andric   }
67210b57cec5SDimitry Andric 
67220b57cec5SDimitry Andric   Index = matchMSA128RegisterName(Identifier);
67230b57cec5SDimitry Andric   if (Index != -1) {
67240b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createMSA128Reg(
67250b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
67260b57cec5SDimitry Andric         getLexer().getLoc(), *this));
672706c3fb27SDimitry Andric     return ParseStatus::Success;
67280b57cec5SDimitry Andric   }
67290b57cec5SDimitry Andric 
67300b57cec5SDimitry Andric   Index = matchMSA128CtrlRegisterName(Identifier);
67310b57cec5SDimitry Andric   if (Index != -1) {
67320b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createMSACtrlReg(
67330b57cec5SDimitry Andric         Index, Identifier, getContext().getRegisterInfo(), S,
67340b57cec5SDimitry Andric         getLexer().getLoc(), *this));
673506c3fb27SDimitry Andric     return ParseStatus::Success;
67360b57cec5SDimitry Andric   }
67370b57cec5SDimitry Andric 
673806c3fb27SDimitry Andric   return ParseStatus::NoMatch;
67390b57cec5SDimitry Andric }
67400b57cec5SDimitry Andric 
674106c3fb27SDimitry Andric ParseStatus
matchAnyRegisterWithoutDollar(OperandVector & Operands,const AsmToken & Token,SMLoc S)67420b57cec5SDimitry Andric MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
67430b57cec5SDimitry Andric                                              const AsmToken &Token, SMLoc S) {
67440b57cec5SDimitry Andric   if (Token.is(AsmToken::Identifier)) {
67450b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. identifier\n");
67460b57cec5SDimitry Andric     StringRef Identifier = Token.getIdentifier();
674706c3fb27SDimitry Andric     return matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
674806c3fb27SDimitry Andric   }
674906c3fb27SDimitry Andric   if (Token.is(AsmToken::Integer)) {
67500b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. integer\n");
67510b57cec5SDimitry Andric     int64_t RegNum = Token.getIntVal();
67520b57cec5SDimitry Andric     if (RegNum < 0 || RegNum > 31) {
67530b57cec5SDimitry Andric       // Show the error, but treat invalid register
67540b57cec5SDimitry Andric       // number as a normal one to continue parsing
67550b57cec5SDimitry Andric       // and catch other possible errors.
67560b57cec5SDimitry Andric       Error(getLexer().getLoc(), "invalid register number");
67570b57cec5SDimitry Andric     }
67580b57cec5SDimitry Andric     Operands.push_back(MipsOperand::createNumericReg(
67590b57cec5SDimitry Andric         RegNum, Token.getString(), getContext().getRegisterInfo(), S,
67600b57cec5SDimitry Andric         Token.getLoc(), *this));
676106c3fb27SDimitry Andric     return ParseStatus::Success;
67620b57cec5SDimitry Andric   }
67630b57cec5SDimitry Andric 
67640b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
67650b57cec5SDimitry Andric 
676606c3fb27SDimitry Andric   return ParseStatus::NoMatch;
67670b57cec5SDimitry Andric }
67680b57cec5SDimitry Andric 
676906c3fb27SDimitry Andric ParseStatus
matchAnyRegisterWithoutDollar(OperandVector & Operands,SMLoc S)67700b57cec5SDimitry Andric MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
67710b57cec5SDimitry Andric   auto Token = getLexer().peekTok(false);
67720b57cec5SDimitry Andric   return matchAnyRegisterWithoutDollar(Operands, Token, S);
67730b57cec5SDimitry Andric }
67740b57cec5SDimitry Andric 
parseAnyRegister(OperandVector & Operands)677506c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
67760b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
67770b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
67780b57cec5SDimitry Andric 
67790b57cec5SDimitry Andric   auto Token = Parser.getTok();
67800b57cec5SDimitry Andric 
67810b57cec5SDimitry Andric   SMLoc S = Token.getLoc();
67820b57cec5SDimitry Andric 
67830b57cec5SDimitry Andric   if (Token.isNot(AsmToken::Dollar)) {
67840b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
67850b57cec5SDimitry Andric     if (Token.is(AsmToken::Identifier)) {
67860b57cec5SDimitry Andric       if (searchSymbolAlias(Operands))
678706c3fb27SDimitry Andric         return ParseStatus::Success;
67880b57cec5SDimitry Andric     }
67890b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
679006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
67910b57cec5SDimitry Andric   }
67920b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << ".. $\n");
67930b57cec5SDimitry Andric 
679406c3fb27SDimitry Andric   ParseStatus Res = matchAnyRegisterWithoutDollar(Operands, S);
679506c3fb27SDimitry Andric   if (Res.isSuccess()) {
67960b57cec5SDimitry Andric     Parser.Lex(); // $
67970b57cec5SDimitry Andric     Parser.Lex(); // identifier
67980b57cec5SDimitry Andric   }
679906c3fb27SDimitry Andric   return Res;
68000b57cec5SDimitry Andric }
68010b57cec5SDimitry Andric 
parseJumpTarget(OperandVector & Operands)680206c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
68030b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
68040b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
68050b57cec5SDimitry Andric 
68060b57cec5SDimitry Andric   SMLoc S = getLexer().getLoc();
68070b57cec5SDimitry Andric 
68080b57cec5SDimitry Andric   // Registers are a valid target and have priority over symbols.
680906c3fb27SDimitry Andric   ParseStatus Res = parseAnyRegister(Operands);
681006c3fb27SDimitry Andric   if (!Res.isNoMatch())
681106c3fb27SDimitry Andric     return Res;
68120b57cec5SDimitry Andric 
68130b57cec5SDimitry Andric   // Integers and expressions are acceptable
68140b57cec5SDimitry Andric   const MCExpr *Expr = nullptr;
68150b57cec5SDimitry Andric   if (Parser.parseExpression(Expr)) {
68160b57cec5SDimitry Andric     // We have no way of knowing if a symbol was consumed so we must ParseFail
681706c3fb27SDimitry Andric     return ParseStatus::Failure;
68180b57cec5SDimitry Andric   }
68190b57cec5SDimitry Andric   Operands.push_back(
68200b57cec5SDimitry Andric       MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
682106c3fb27SDimitry Andric   return ParseStatus::Success;
68220b57cec5SDimitry Andric }
68230b57cec5SDimitry Andric 
parseInvNum(OperandVector & Operands)682406c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseInvNum(OperandVector &Operands) {
68250b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
68260b57cec5SDimitry Andric   const MCExpr *IdVal;
68270b57cec5SDimitry Andric   // If the first token is '$' we may have register operand. We have to reject
68280b57cec5SDimitry Andric   // cases where it is not a register. Complicating the matter is that
68290b57cec5SDimitry Andric   // register names are not reserved across all ABIs.
68300b57cec5SDimitry Andric   // Peek past the dollar to see if it's a register name for this ABI.
68310b57cec5SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
68320b57cec5SDimitry Andric   if (Parser.getTok().is(AsmToken::Dollar)) {
68330b57cec5SDimitry Andric     return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
683406c3fb27SDimitry Andric                ? ParseStatus::Failure
683506c3fb27SDimitry Andric                : ParseStatus::NoMatch;
68360b57cec5SDimitry Andric   }
68370b57cec5SDimitry Andric   if (getParser().parseExpression(IdVal))
683806c3fb27SDimitry Andric     return ParseStatus::Failure;
68390b57cec5SDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
68400b57cec5SDimitry Andric   if (!MCE)
684106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
68420b57cec5SDimitry Andric   int64_t Val = MCE->getValue();
68430b57cec5SDimitry Andric   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
68440b57cec5SDimitry Andric   Operands.push_back(MipsOperand::CreateImm(
68450b57cec5SDimitry Andric       MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
684606c3fb27SDimitry Andric   return ParseStatus::Success;
68470b57cec5SDimitry Andric }
68480b57cec5SDimitry Andric 
parseRegisterList(OperandVector & Operands)684906c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {
68500b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
68510b57cec5SDimitry Andric   SmallVector<unsigned, 10> Regs;
68520b57cec5SDimitry Andric   unsigned RegNo;
68530b57cec5SDimitry Andric   unsigned PrevReg = Mips::NoRegister;
68540b57cec5SDimitry Andric   bool RegRange = false;
68550b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
68560b57cec5SDimitry Andric 
68570b57cec5SDimitry Andric   if (Parser.getTok().isNot(AsmToken::Dollar))
685806c3fb27SDimitry Andric     return ParseStatus::Failure;
68590b57cec5SDimitry Andric 
68600b57cec5SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
686106c3fb27SDimitry Andric   while (parseAnyRegister(TmpOperands).isSuccess()) {
68620b57cec5SDimitry Andric     SMLoc E = getLexer().getLoc();
68630b57cec5SDimitry Andric     MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
68640b57cec5SDimitry Andric     RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
68650b57cec5SDimitry Andric     if (RegRange) {
68660b57cec5SDimitry Andric       // Remove last register operand because registers from register range
68670b57cec5SDimitry Andric       // should be inserted first.
68680b57cec5SDimitry Andric       if ((isGP64bit() && RegNo == Mips::RA_64) ||
68690b57cec5SDimitry Andric           (!isGP64bit() && RegNo == Mips::RA)) {
68700b57cec5SDimitry Andric         Regs.push_back(RegNo);
68710b57cec5SDimitry Andric       } else {
68720b57cec5SDimitry Andric         unsigned TmpReg = PrevReg + 1;
68730b57cec5SDimitry Andric         while (TmpReg <= RegNo) {
68740b57cec5SDimitry Andric           if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
68750b57cec5SDimitry Andric               (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
687606c3fb27SDimitry Andric                isGP64bit()))
687706c3fb27SDimitry Andric             return Error(E, "invalid register operand");
68780b57cec5SDimitry Andric 
68790b57cec5SDimitry Andric           PrevReg = TmpReg;
68800b57cec5SDimitry Andric           Regs.push_back(TmpReg++);
68810b57cec5SDimitry Andric         }
68820b57cec5SDimitry Andric       }
68830b57cec5SDimitry Andric 
68840b57cec5SDimitry Andric       RegRange = false;
68850b57cec5SDimitry Andric     } else {
68860b57cec5SDimitry Andric       if ((PrevReg == Mips::NoRegister) &&
68870b57cec5SDimitry Andric           ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
688806c3fb27SDimitry Andric            (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA))))
688906c3fb27SDimitry Andric         return Error(E, "$16 or $31 expected");
689006c3fb27SDimitry Andric       if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
68910b57cec5SDimitry Andric               (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
68920b57cec5SDimitry Andric              !isGP64bit()) ||
68930b57cec5SDimitry Andric             ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
68940b57cec5SDimitry Andric               (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
689506c3fb27SDimitry Andric              isGP64bit())))
689606c3fb27SDimitry Andric         return Error(E, "invalid register operand");
689706c3fb27SDimitry Andric       if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
68980b57cec5SDimitry Andric           ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
689906c3fb27SDimitry Andric            (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && isGP64bit())))
690006c3fb27SDimitry Andric         return Error(E, "consecutive register numbers expected");
69010b57cec5SDimitry Andric 
69020b57cec5SDimitry Andric       Regs.push_back(RegNo);
69030b57cec5SDimitry Andric     }
69040b57cec5SDimitry Andric 
69050b57cec5SDimitry Andric     if (Parser.getTok().is(AsmToken::Minus))
69060b57cec5SDimitry Andric       RegRange = true;
69070b57cec5SDimitry Andric 
69080b57cec5SDimitry Andric     if (!Parser.getTok().isNot(AsmToken::Minus) &&
690906c3fb27SDimitry Andric         !Parser.getTok().isNot(AsmToken::Comma))
691006c3fb27SDimitry Andric       return Error(E, "',' or '-' expected");
69110b57cec5SDimitry Andric 
69120b57cec5SDimitry Andric     Lex(); // Consume comma or minus
69130b57cec5SDimitry Andric     if (Parser.getTok().isNot(AsmToken::Dollar))
69140b57cec5SDimitry Andric       break;
69150b57cec5SDimitry Andric 
69160b57cec5SDimitry Andric     PrevReg = RegNo;
69170b57cec5SDimitry Andric   }
69180b57cec5SDimitry Andric 
69190b57cec5SDimitry Andric   SMLoc E = Parser.getTok().getLoc();
69200b57cec5SDimitry Andric   Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
69210b57cec5SDimitry Andric   parseMemOperand(Operands);
692206c3fb27SDimitry Andric   return ParseStatus::Success;
69230b57cec5SDimitry Andric }
69240b57cec5SDimitry Andric 
69250b57cec5SDimitry Andric /// Sometimes (i.e. load/stores) the operand may be followed immediately by
69260b57cec5SDimitry Andric /// either this.
69270b57cec5SDimitry Andric /// ::= '(', register, ')'
69280b57cec5SDimitry Andric /// handle it before we iterate so we don't get tripped up by the lack of
69290b57cec5SDimitry Andric /// a comma.
parseParenSuffix(StringRef Name,OperandVector & Operands)69300b57cec5SDimitry Andric bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
69310b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
69320b57cec5SDimitry Andric   if (getLexer().is(AsmToken::LParen)) {
69330b57cec5SDimitry Andric     Operands.push_back(
69340b57cec5SDimitry Andric         MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
69350b57cec5SDimitry Andric     Parser.Lex();
69360b57cec5SDimitry Andric     if (parseOperand(Operands, Name)) {
69370b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
69380b57cec5SDimitry Andric       return Error(Loc, "unexpected token in argument list");
69390b57cec5SDimitry Andric     }
69400b57cec5SDimitry Andric     if (Parser.getTok().isNot(AsmToken::RParen)) {
69410b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
69420b57cec5SDimitry Andric       return Error(Loc, "unexpected token, expected ')'");
69430b57cec5SDimitry Andric     }
69440b57cec5SDimitry Andric     Operands.push_back(
69450b57cec5SDimitry Andric         MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
69460b57cec5SDimitry Andric     Parser.Lex();
69470b57cec5SDimitry Andric   }
69480b57cec5SDimitry Andric   return false;
69490b57cec5SDimitry Andric }
69500b57cec5SDimitry Andric 
69510b57cec5SDimitry Andric /// Sometimes (i.e. in MSA) the operand may be followed immediately by
69520b57cec5SDimitry Andric /// either one of these.
69530b57cec5SDimitry Andric /// ::= '[', register, ']'
69540b57cec5SDimitry Andric /// ::= '[', integer, ']'
69550b57cec5SDimitry Andric /// handle it before we iterate so we don't get tripped up by the lack of
69560b57cec5SDimitry Andric /// a comma.
parseBracketSuffix(StringRef Name,OperandVector & Operands)69570b57cec5SDimitry Andric bool MipsAsmParser::parseBracketSuffix(StringRef Name,
69580b57cec5SDimitry Andric                                        OperandVector &Operands) {
69590b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
69600b57cec5SDimitry Andric   if (getLexer().is(AsmToken::LBrac)) {
69610b57cec5SDimitry Andric     Operands.push_back(
69620b57cec5SDimitry Andric         MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
69630b57cec5SDimitry Andric     Parser.Lex();
69640b57cec5SDimitry Andric     if (parseOperand(Operands, Name)) {
69650b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
69660b57cec5SDimitry Andric       return Error(Loc, "unexpected token in argument list");
69670b57cec5SDimitry Andric     }
69680b57cec5SDimitry Andric     if (Parser.getTok().isNot(AsmToken::RBrac)) {
69690b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
69700b57cec5SDimitry Andric       return Error(Loc, "unexpected token, expected ']'");
69710b57cec5SDimitry Andric     }
69720b57cec5SDimitry Andric     Operands.push_back(
69730b57cec5SDimitry Andric         MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
69740b57cec5SDimitry Andric     Parser.Lex();
69750b57cec5SDimitry Andric   }
69760b57cec5SDimitry Andric   return false;
69770b57cec5SDimitry Andric }
69780b57cec5SDimitry Andric 
69790b57cec5SDimitry Andric static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
69800b57cec5SDimitry Andric                                           unsigned VariantID = 0);
69810b57cec5SDimitry Andric 
areEqualRegs(const MCParsedAsmOperand & Op1,const MCParsedAsmOperand & Op2) const6982bdd1243dSDimitry Andric bool MipsAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,
6983bdd1243dSDimitry Andric                                  const MCParsedAsmOperand &Op2) const {
6984bdd1243dSDimitry Andric   // This target-overriden function exists to maintain current behaviour for
6985bdd1243dSDimitry Andric   // e.g.
6986bdd1243dSDimitry Andric   //   dahi    $3, $3, 0x5678
6987bdd1243dSDimitry Andric   // as tested in test/MC/Mips/mips64r6/valid.s.
6988bdd1243dSDimitry Andric   // FIXME: Should this test actually fail with an error? If so, then remove
6989bdd1243dSDimitry Andric   // this overloaded method.
6990bdd1243dSDimitry Andric   if (!Op1.isReg() || !Op2.isReg())
6991bdd1243dSDimitry Andric     return true;
6992bdd1243dSDimitry Andric   return Op1.getReg() == Op2.getReg();
6993bdd1243dSDimitry Andric }
6994bdd1243dSDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)69950b57cec5SDimitry Andric bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
69960b57cec5SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
69970b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
69980b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "ParseInstruction\n");
69990b57cec5SDimitry Andric 
70000b57cec5SDimitry Andric   // We have reached first instruction, module directive are now forbidden.
70010b57cec5SDimitry Andric   getTargetStreamer().forbidModuleDirective();
70020b57cec5SDimitry Andric 
70030b57cec5SDimitry Andric   // Check if we have valid mnemonic
70040b57cec5SDimitry Andric   if (!mnemonicIsValid(Name, 0)) {
70050b57cec5SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
70060b57cec5SDimitry Andric     std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
70070b57cec5SDimitry Andric     return Error(NameLoc, "unknown instruction" + Suggestion);
70080b57cec5SDimitry Andric   }
70090b57cec5SDimitry Andric   // First operand in MCInst is instruction mnemonic.
70100b57cec5SDimitry Andric   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
70110b57cec5SDimitry Andric 
70120b57cec5SDimitry Andric   // Read the remaining operands.
70130b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
70140b57cec5SDimitry Andric     // Read the first operand.
70150b57cec5SDimitry Andric     if (parseOperand(Operands, Name)) {
70160b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
70170b57cec5SDimitry Andric       return Error(Loc, "unexpected token in argument list");
70180b57cec5SDimitry Andric     }
70190b57cec5SDimitry Andric     if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
70200b57cec5SDimitry Andric       return true;
70210b57cec5SDimitry Andric     // AFAIK, parenthesis suffixes are never on the first operand
70220b57cec5SDimitry Andric 
70230b57cec5SDimitry Andric     while (getLexer().is(AsmToken::Comma)) {
70240b57cec5SDimitry Andric       Parser.Lex(); // Eat the comma.
70250b57cec5SDimitry Andric       // Parse and remember the operand.
70260b57cec5SDimitry Andric       if (parseOperand(Operands, Name)) {
70270b57cec5SDimitry Andric         SMLoc Loc = getLexer().getLoc();
70280b57cec5SDimitry Andric         return Error(Loc, "unexpected token in argument list");
70290b57cec5SDimitry Andric       }
70300b57cec5SDimitry Andric       // Parse bracket and parenthesis suffixes before we iterate
70310b57cec5SDimitry Andric       if (getLexer().is(AsmToken::LBrac)) {
70320b57cec5SDimitry Andric         if (parseBracketSuffix(Name, Operands))
70330b57cec5SDimitry Andric           return true;
70340b57cec5SDimitry Andric       } else if (getLexer().is(AsmToken::LParen) &&
70350b57cec5SDimitry Andric                  parseParenSuffix(Name, Operands))
70360b57cec5SDimitry Andric         return true;
70370b57cec5SDimitry Andric     }
70380b57cec5SDimitry Andric   }
70390b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
70400b57cec5SDimitry Andric     SMLoc Loc = getLexer().getLoc();
70410b57cec5SDimitry Andric     return Error(Loc, "unexpected token in argument list");
70420b57cec5SDimitry Andric   }
70430b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
70440b57cec5SDimitry Andric   return false;
70450b57cec5SDimitry Andric }
70460b57cec5SDimitry Andric 
70470b57cec5SDimitry Andric // FIXME: Given that these have the same name, these should both be
70480b57cec5SDimitry Andric // consistent on affecting the Parser.
reportParseError(const Twine & ErrorMsg)7049e8d8bef9SDimitry Andric bool MipsAsmParser::reportParseError(const Twine &ErrorMsg) {
70500b57cec5SDimitry Andric   SMLoc Loc = getLexer().getLoc();
70510b57cec5SDimitry Andric   return Error(Loc, ErrorMsg);
70520b57cec5SDimitry Andric }
70530b57cec5SDimitry Andric 
reportParseError(SMLoc Loc,const Twine & ErrorMsg)7054e8d8bef9SDimitry Andric bool MipsAsmParser::reportParseError(SMLoc Loc, const Twine &ErrorMsg) {
70550b57cec5SDimitry Andric   return Error(Loc, ErrorMsg);
70560b57cec5SDimitry Andric }
70570b57cec5SDimitry Andric 
parseSetNoAtDirective()70580b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoAtDirective() {
70590b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
70600b57cec5SDimitry Andric   // Line should look like: ".set noat".
70610b57cec5SDimitry Andric 
70620b57cec5SDimitry Andric   // Set the $at register to $0.
70630b57cec5SDimitry Andric   AssemblerOptions.back()->setATRegIndex(0);
70640b57cec5SDimitry Andric 
70650b57cec5SDimitry Andric   Parser.Lex(); // Eat "noat".
70660b57cec5SDimitry Andric 
70670b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
70680b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
70690b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
70700b57cec5SDimitry Andric     return false;
70710b57cec5SDimitry Andric   }
70720b57cec5SDimitry Andric 
70730b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoAt();
70740b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
70750b57cec5SDimitry Andric   return false;
70760b57cec5SDimitry Andric }
70770b57cec5SDimitry Andric 
parseSetAtDirective()70780b57cec5SDimitry Andric bool MipsAsmParser::parseSetAtDirective() {
70790b57cec5SDimitry Andric   // Line can be: ".set at", which sets $at to $1
70800b57cec5SDimitry Andric   //          or  ".set at=$reg", which sets $at to $reg.
70810b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
70820b57cec5SDimitry Andric   Parser.Lex(); // Eat "at".
70830b57cec5SDimitry Andric 
70840b57cec5SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement)) {
70850b57cec5SDimitry Andric     // No register was specified, so we set $at to $1.
70860b57cec5SDimitry Andric     AssemblerOptions.back()->setATRegIndex(1);
70870b57cec5SDimitry Andric 
70880b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetAt();
70890b57cec5SDimitry Andric     Parser.Lex(); // Consume the EndOfStatement.
70900b57cec5SDimitry Andric     return false;
70910b57cec5SDimitry Andric   }
70920b57cec5SDimitry Andric 
70930b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Equal)) {
70940b57cec5SDimitry Andric     reportParseError("unexpected token, expected equals sign");
70950b57cec5SDimitry Andric     return false;
70960b57cec5SDimitry Andric   }
70970b57cec5SDimitry Andric   Parser.Lex(); // Eat "=".
70980b57cec5SDimitry Andric 
70990b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Dollar)) {
71000b57cec5SDimitry Andric     if (getLexer().is(AsmToken::EndOfStatement)) {
71010b57cec5SDimitry Andric       reportParseError("no register specified");
71020b57cec5SDimitry Andric       return false;
71030b57cec5SDimitry Andric     } else {
71040b57cec5SDimitry Andric       reportParseError("unexpected token, expected dollar sign '$'");
71050b57cec5SDimitry Andric       return false;
71060b57cec5SDimitry Andric     }
71070b57cec5SDimitry Andric   }
71080b57cec5SDimitry Andric   Parser.Lex(); // Eat "$".
71090b57cec5SDimitry Andric 
71100b57cec5SDimitry Andric   // Find out what "reg" is.
71110b57cec5SDimitry Andric   unsigned AtRegNo;
71120b57cec5SDimitry Andric   const AsmToken &Reg = Parser.getTok();
71130b57cec5SDimitry Andric   if (Reg.is(AsmToken::Identifier)) {
71140b57cec5SDimitry Andric     AtRegNo = matchCPURegisterName(Reg.getIdentifier());
71150b57cec5SDimitry Andric   } else if (Reg.is(AsmToken::Integer)) {
71160b57cec5SDimitry Andric     AtRegNo = Reg.getIntVal();
71170b57cec5SDimitry Andric   } else {
71180b57cec5SDimitry Andric     reportParseError("unexpected token, expected identifier or integer");
71190b57cec5SDimitry Andric     return false;
71200b57cec5SDimitry Andric   }
71210b57cec5SDimitry Andric 
71220b57cec5SDimitry Andric   // Check if $reg is a valid register. If it is, set $at to $reg.
71230b57cec5SDimitry Andric   if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
71240b57cec5SDimitry Andric     reportParseError("invalid register");
71250b57cec5SDimitry Andric     return false;
71260b57cec5SDimitry Andric   }
71270b57cec5SDimitry Andric   Parser.Lex(); // Eat "reg".
71280b57cec5SDimitry Andric 
71290b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
71300b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
71310b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
71320b57cec5SDimitry Andric     return false;
71330b57cec5SDimitry Andric   }
71340b57cec5SDimitry Andric 
71350b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
71360b57cec5SDimitry Andric 
71370b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
71380b57cec5SDimitry Andric   return false;
71390b57cec5SDimitry Andric }
71400b57cec5SDimitry Andric 
parseSetReorderDirective()71410b57cec5SDimitry Andric bool MipsAsmParser::parseSetReorderDirective() {
71420b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
71430b57cec5SDimitry Andric   Parser.Lex();
71440b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
71450b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
71460b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
71470b57cec5SDimitry Andric     return false;
71480b57cec5SDimitry Andric   }
71490b57cec5SDimitry Andric   AssemblerOptions.back()->setReorder();
71500b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetReorder();
71510b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
71520b57cec5SDimitry Andric   return false;
71530b57cec5SDimitry Andric }
71540b57cec5SDimitry Andric 
parseSetNoReorderDirective()71550b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoReorderDirective() {
71560b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
71570b57cec5SDimitry Andric   Parser.Lex();
71580b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
71590b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
71600b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
71610b57cec5SDimitry Andric     return false;
71620b57cec5SDimitry Andric   }
71630b57cec5SDimitry Andric   AssemblerOptions.back()->setNoReorder();
71640b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoReorder();
71650b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
71660b57cec5SDimitry Andric   return false;
71670b57cec5SDimitry Andric }
71680b57cec5SDimitry Andric 
parseSetMacroDirective()71690b57cec5SDimitry Andric bool MipsAsmParser::parseSetMacroDirective() {
71700b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
71710b57cec5SDimitry Andric   Parser.Lex();
71720b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
71730b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
71740b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
71750b57cec5SDimitry Andric     return false;
71760b57cec5SDimitry Andric   }
71770b57cec5SDimitry Andric   AssemblerOptions.back()->setMacro();
71780b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetMacro();
71790b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
71800b57cec5SDimitry Andric   return false;
71810b57cec5SDimitry Andric }
71820b57cec5SDimitry Andric 
parseSetNoMacroDirective()71830b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMacroDirective() {
71840b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
71850b57cec5SDimitry Andric   Parser.Lex();
71860b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
71870b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
71880b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
71890b57cec5SDimitry Andric     return false;
71900b57cec5SDimitry Andric   }
71910b57cec5SDimitry Andric   if (AssemblerOptions.back()->isReorder()) {
71920b57cec5SDimitry Andric     reportParseError("`noreorder' must be set before `nomacro'");
71930b57cec5SDimitry Andric     return false;
71940b57cec5SDimitry Andric   }
71950b57cec5SDimitry Andric   AssemblerOptions.back()->setNoMacro();
71960b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoMacro();
71970b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
71980b57cec5SDimitry Andric   return false;
71990b57cec5SDimitry Andric }
72000b57cec5SDimitry Andric 
parseSetMsaDirective()72010b57cec5SDimitry Andric bool MipsAsmParser::parseSetMsaDirective() {
72020b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
72030b57cec5SDimitry Andric   Parser.Lex();
72040b57cec5SDimitry Andric 
72050b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
72060b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
72070b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
72080b57cec5SDimitry Andric 
72090b57cec5SDimitry Andric   setFeatureBits(Mips::FeatureMSA, "msa");
72100b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetMsa();
72110b57cec5SDimitry Andric   return false;
72120b57cec5SDimitry Andric }
72130b57cec5SDimitry Andric 
parseSetNoMsaDirective()72140b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMsaDirective() {
72150b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
72160b57cec5SDimitry Andric   Parser.Lex();
72170b57cec5SDimitry Andric 
72180b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
72190b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
72200b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
72210b57cec5SDimitry Andric 
72220b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureMSA, "msa");
72230b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoMsa();
72240b57cec5SDimitry Andric   return false;
72250b57cec5SDimitry Andric }
72260b57cec5SDimitry Andric 
parseSetNoDspDirective()72270b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoDspDirective() {
72280b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
72290b57cec5SDimitry Andric   Parser.Lex(); // Eat "nodsp".
72300b57cec5SDimitry Andric 
72310b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
72320b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
72330b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
72340b57cec5SDimitry Andric     return false;
72350b57cec5SDimitry Andric   }
72360b57cec5SDimitry Andric 
72370b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureDSP, "dsp");
72380b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoDsp();
72390b57cec5SDimitry Andric   return false;
72400b57cec5SDimitry Andric }
72410b57cec5SDimitry Andric 
parseSetNoMips3DDirective()72425ffd83dbSDimitry Andric bool MipsAsmParser::parseSetNoMips3DDirective() {
72435ffd83dbSDimitry Andric   MCAsmParser &Parser = getParser();
72445ffd83dbSDimitry Andric   Parser.Lex(); // Eat "nomips3d".
72455ffd83dbSDimitry Andric 
72465ffd83dbSDimitry Andric   // If this is not the end of the statement, report an error.
72475ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
72485ffd83dbSDimitry Andric     reportParseError("unexpected token, expected end of statement");
72495ffd83dbSDimitry Andric     return false;
72505ffd83dbSDimitry Andric   }
72515ffd83dbSDimitry Andric 
72525ffd83dbSDimitry Andric   clearFeatureBits(Mips::FeatureMips3D, "mips3d");
72535ffd83dbSDimitry Andric   getTargetStreamer().emitDirectiveSetNoMips3D();
72545ffd83dbSDimitry Andric   return false;
72555ffd83dbSDimitry Andric }
72565ffd83dbSDimitry Andric 
parseSetMips16Directive()72570b57cec5SDimitry Andric bool MipsAsmParser::parseSetMips16Directive() {
72580b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
72590b57cec5SDimitry Andric   Parser.Lex(); // Eat "mips16".
72600b57cec5SDimitry Andric 
72610b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
72620b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
72630b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
72640b57cec5SDimitry Andric     return false;
72650b57cec5SDimitry Andric   }
72660b57cec5SDimitry Andric 
72670b57cec5SDimitry Andric   setFeatureBits(Mips::FeatureMips16, "mips16");
72680b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetMips16();
72690b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
72700b57cec5SDimitry Andric   return false;
72710b57cec5SDimitry Andric }
72720b57cec5SDimitry Andric 
parseSetNoMips16Directive()72730b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMips16Directive() {
72740b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
72750b57cec5SDimitry Andric   Parser.Lex(); // Eat "nomips16".
72760b57cec5SDimitry Andric 
72770b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
72780b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
72790b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
72800b57cec5SDimitry Andric     return false;
72810b57cec5SDimitry Andric   }
72820b57cec5SDimitry Andric 
72830b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureMips16, "mips16");
72840b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoMips16();
72850b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
72860b57cec5SDimitry Andric   return false;
72870b57cec5SDimitry Andric }
72880b57cec5SDimitry Andric 
parseSetFpDirective()72890b57cec5SDimitry Andric bool MipsAsmParser::parseSetFpDirective() {
72900b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
72910b57cec5SDimitry Andric   MipsABIFlagsSection::FpABIKind FpAbiVal;
72920b57cec5SDimitry Andric   // Line can be: .set fp=32
72930b57cec5SDimitry Andric   //              .set fp=xx
72940b57cec5SDimitry Andric   //              .set fp=64
72950b57cec5SDimitry Andric   Parser.Lex(); // Eat fp token
72960b57cec5SDimitry Andric   AsmToken Tok = Parser.getTok();
72970b57cec5SDimitry Andric   if (Tok.isNot(AsmToken::Equal)) {
72980b57cec5SDimitry Andric     reportParseError("unexpected token, expected equals sign '='");
72990b57cec5SDimitry Andric     return false;
73000b57cec5SDimitry Andric   }
73010b57cec5SDimitry Andric   Parser.Lex(); // Eat '=' token.
73020b57cec5SDimitry Andric   Tok = Parser.getTok();
73030b57cec5SDimitry Andric 
73040b57cec5SDimitry Andric   if (!parseFpABIValue(FpAbiVal, ".set"))
73050b57cec5SDimitry Andric     return false;
73060b57cec5SDimitry Andric 
73070b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
73080b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
73090b57cec5SDimitry Andric     return false;
73100b57cec5SDimitry Andric   }
73110b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
73120b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
73130b57cec5SDimitry Andric   return false;
73140b57cec5SDimitry Andric }
73150b57cec5SDimitry Andric 
parseSetOddSPRegDirective()73160b57cec5SDimitry Andric bool MipsAsmParser::parseSetOddSPRegDirective() {
73170b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
73180b57cec5SDimitry Andric 
73190b57cec5SDimitry Andric   Parser.Lex(); // Eat "oddspreg".
73200b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
73210b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
73220b57cec5SDimitry Andric     return false;
73230b57cec5SDimitry Andric   }
73240b57cec5SDimitry Andric 
73250b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
73260b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetOddSPReg();
73270b57cec5SDimitry Andric   return false;
73280b57cec5SDimitry Andric }
73290b57cec5SDimitry Andric 
parseSetNoOddSPRegDirective()73300b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoOddSPRegDirective() {
73310b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
73320b57cec5SDimitry Andric 
73330b57cec5SDimitry Andric   Parser.Lex(); // Eat "nooddspreg".
73340b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
73350b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
73360b57cec5SDimitry Andric     return false;
73370b57cec5SDimitry Andric   }
73380b57cec5SDimitry Andric 
73390b57cec5SDimitry Andric   setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
73400b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoOddSPReg();
73410b57cec5SDimitry Andric   return false;
73420b57cec5SDimitry Andric }
73430b57cec5SDimitry Andric 
parseSetMtDirective()73440b57cec5SDimitry Andric bool MipsAsmParser::parseSetMtDirective() {
73450b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
73460b57cec5SDimitry Andric   Parser.Lex(); // Eat "mt".
73470b57cec5SDimitry Andric 
73480b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
73490b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
73500b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
73510b57cec5SDimitry Andric     return false;
73520b57cec5SDimitry Andric   }
73530b57cec5SDimitry Andric 
73540b57cec5SDimitry Andric   setFeatureBits(Mips::FeatureMT, "mt");
73550b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetMt();
73560b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
73570b57cec5SDimitry Andric   return false;
73580b57cec5SDimitry Andric }
73590b57cec5SDimitry Andric 
parseSetNoMtDirective()73600b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMtDirective() {
73610b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
73620b57cec5SDimitry Andric   Parser.Lex(); // Eat "nomt".
73630b57cec5SDimitry Andric 
73640b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
73650b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
73660b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
73670b57cec5SDimitry Andric     return false;
73680b57cec5SDimitry Andric   }
73690b57cec5SDimitry Andric 
73700b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureMT, "mt");
73710b57cec5SDimitry Andric 
73720b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoMt();
73730b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
73740b57cec5SDimitry Andric   return false;
73750b57cec5SDimitry Andric }
73760b57cec5SDimitry Andric 
parseSetNoCRCDirective()73770b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoCRCDirective() {
73780b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
73790b57cec5SDimitry Andric   Parser.Lex(); // Eat "nocrc".
73800b57cec5SDimitry Andric 
73810b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
73820b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
73830b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
73840b57cec5SDimitry Andric     return false;
73850b57cec5SDimitry Andric   }
73860b57cec5SDimitry Andric 
73870b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureCRC, "crc");
73880b57cec5SDimitry Andric 
73890b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoCRC();
73900b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
73910b57cec5SDimitry Andric   return false;
73920b57cec5SDimitry Andric }
73930b57cec5SDimitry Andric 
parseSetNoVirtDirective()73940b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoVirtDirective() {
73950b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
73960b57cec5SDimitry Andric   Parser.Lex(); // Eat "novirt".
73970b57cec5SDimitry Andric 
73980b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
73990b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
74000b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
74010b57cec5SDimitry Andric     return false;
74020b57cec5SDimitry Andric   }
74030b57cec5SDimitry Andric 
74040b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureVirt, "virt");
74050b57cec5SDimitry Andric 
74060b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoVirt();
74070b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
74080b57cec5SDimitry Andric   return false;
74090b57cec5SDimitry Andric }
74100b57cec5SDimitry Andric 
parseSetNoGINVDirective()74110b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoGINVDirective() {
74120b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
74130b57cec5SDimitry Andric   Parser.Lex(); // Eat "noginv".
74140b57cec5SDimitry Andric 
74150b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
74160b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
74170b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
74180b57cec5SDimitry Andric     return false;
74190b57cec5SDimitry Andric   }
74200b57cec5SDimitry Andric 
74210b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureGINV, "ginv");
74220b57cec5SDimitry Andric 
74230b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetNoGINV();
74240b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
74250b57cec5SDimitry Andric   return false;
74260b57cec5SDimitry Andric }
74270b57cec5SDimitry Andric 
parseSetPopDirective()74280b57cec5SDimitry Andric bool MipsAsmParser::parseSetPopDirective() {
74290b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
74300b57cec5SDimitry Andric   SMLoc Loc = getLexer().getLoc();
74310b57cec5SDimitry Andric 
74320b57cec5SDimitry Andric   Parser.Lex();
74330b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
74340b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
74350b57cec5SDimitry Andric 
74360b57cec5SDimitry Andric   // Always keep an element on the options "stack" to prevent the user
74370b57cec5SDimitry Andric   // from changing the initial options. This is how we remember them.
74380b57cec5SDimitry Andric   if (AssemblerOptions.size() == 2)
74390b57cec5SDimitry Andric     return reportParseError(Loc, ".set pop with no .set push");
74400b57cec5SDimitry Andric 
74410b57cec5SDimitry Andric   MCSubtargetInfo &STI = copySTI();
74420b57cec5SDimitry Andric   AssemblerOptions.pop_back();
74430b57cec5SDimitry Andric   setAvailableFeatures(
74440b57cec5SDimitry Andric       ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
74450b57cec5SDimitry Andric   STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
74460b57cec5SDimitry Andric 
74470b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetPop();
74480b57cec5SDimitry Andric   return false;
74490b57cec5SDimitry Andric }
74500b57cec5SDimitry Andric 
parseSetPushDirective()74510b57cec5SDimitry Andric bool MipsAsmParser::parseSetPushDirective() {
74520b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
74530b57cec5SDimitry Andric   Parser.Lex();
74540b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
74550b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
74560b57cec5SDimitry Andric 
74570b57cec5SDimitry Andric   // Create a copy of the current assembler options environment and push it.
74580b57cec5SDimitry Andric   AssemblerOptions.push_back(
74598bcb0991SDimitry Andric         std::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
74600b57cec5SDimitry Andric 
74610b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetPush();
74620b57cec5SDimitry Andric   return false;
74630b57cec5SDimitry Andric }
74640b57cec5SDimitry Andric 
parseSetSoftFloatDirective()74650b57cec5SDimitry Andric bool MipsAsmParser::parseSetSoftFloatDirective() {
74660b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
74670b57cec5SDimitry Andric   Parser.Lex();
74680b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
74690b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
74700b57cec5SDimitry Andric 
74710b57cec5SDimitry Andric   setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
74720b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetSoftFloat();
74730b57cec5SDimitry Andric   return false;
74740b57cec5SDimitry Andric }
74750b57cec5SDimitry Andric 
parseSetHardFloatDirective()74760b57cec5SDimitry Andric bool MipsAsmParser::parseSetHardFloatDirective() {
74770b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
74780b57cec5SDimitry Andric   Parser.Lex();
74790b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
74800b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
74810b57cec5SDimitry Andric 
74820b57cec5SDimitry Andric   clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
74830b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetHardFloat();
74840b57cec5SDimitry Andric   return false;
74850b57cec5SDimitry Andric }
74860b57cec5SDimitry Andric 
parseSetAssignment()74870b57cec5SDimitry Andric bool MipsAsmParser::parseSetAssignment() {
74880b57cec5SDimitry Andric   StringRef Name;
74890b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
74900b57cec5SDimitry Andric 
74910b57cec5SDimitry Andric   if (Parser.parseIdentifier(Name))
74920b57cec5SDimitry Andric     return reportParseError("expected identifier after .set");
74930b57cec5SDimitry Andric 
74940b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
74950b57cec5SDimitry Andric     return reportParseError("unexpected token, expected comma");
74960b57cec5SDimitry Andric   Lex(); // Eat comma
74970b57cec5SDimitry Andric 
74980b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Dollar) &&
74990b57cec5SDimitry Andric       getLexer().peekTok().is(AsmToken::Integer)) {
75000b57cec5SDimitry Andric     // Parse assignment of a numeric register:
75010b57cec5SDimitry Andric     //   .set r1,$1
75020b57cec5SDimitry Andric     Parser.Lex(); // Eat $.
75030b57cec5SDimitry Andric     RegisterSets[Name] = Parser.getTok();
75040b57cec5SDimitry Andric     Parser.Lex(); // Eat identifier.
75050b57cec5SDimitry Andric     getContext().getOrCreateSymbol(Name);
75060b57cec5SDimitry Andric     return false;
75070b57cec5SDimitry Andric   }
75080b57cec5SDimitry Andric 
75090b57cec5SDimitry Andric   MCSymbol *Sym;
75100b57cec5SDimitry Andric   const MCExpr *Value;
75110b57cec5SDimitry Andric   if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
75120b57cec5SDimitry Andric                                                Parser, Sym, Value))
75130b57cec5SDimitry Andric     return true;
75140b57cec5SDimitry Andric   Sym->setVariableValue(Value);
75150b57cec5SDimitry Andric 
75160b57cec5SDimitry Andric   return false;
75170b57cec5SDimitry Andric }
75180b57cec5SDimitry Andric 
parseSetMips0Directive()75190b57cec5SDimitry Andric bool MipsAsmParser::parseSetMips0Directive() {
75200b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
75210b57cec5SDimitry Andric   Parser.Lex();
75220b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
75230b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
75240b57cec5SDimitry Andric 
75250b57cec5SDimitry Andric   // Reset assembler options to their initial values.
75260b57cec5SDimitry Andric   MCSubtargetInfo &STI = copySTI();
75270b57cec5SDimitry Andric   setAvailableFeatures(
75280b57cec5SDimitry Andric       ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
75290b57cec5SDimitry Andric   STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
75300b57cec5SDimitry Andric   AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
75310b57cec5SDimitry Andric 
75320b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetMips0();
75330b57cec5SDimitry Andric   return false;
75340b57cec5SDimitry Andric }
75350b57cec5SDimitry Andric 
parseSetArchDirective()75360b57cec5SDimitry Andric bool MipsAsmParser::parseSetArchDirective() {
75370b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
75380b57cec5SDimitry Andric   Parser.Lex();
75390b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Equal))
75400b57cec5SDimitry Andric     return reportParseError("unexpected token, expected equals sign");
75410b57cec5SDimitry Andric 
75420b57cec5SDimitry Andric   Parser.Lex();
75430b57cec5SDimitry Andric   StringRef Arch = getParser().parseStringToEndOfStatement().trim();
75440b57cec5SDimitry Andric   if (Arch.empty())
75450b57cec5SDimitry Andric     return reportParseError("expected arch identifier");
75460b57cec5SDimitry Andric 
75470b57cec5SDimitry Andric   StringRef ArchFeatureName =
75480b57cec5SDimitry Andric       StringSwitch<StringRef>(Arch)
75490b57cec5SDimitry Andric           .Case("mips1", "mips1")
75500b57cec5SDimitry Andric           .Case("mips2", "mips2")
75510b57cec5SDimitry Andric           .Case("mips3", "mips3")
75520b57cec5SDimitry Andric           .Case("mips4", "mips4")
75530b57cec5SDimitry Andric           .Case("mips5", "mips5")
75540b57cec5SDimitry Andric           .Case("mips32", "mips32")
75550b57cec5SDimitry Andric           .Case("mips32r2", "mips32r2")
75560b57cec5SDimitry Andric           .Case("mips32r3", "mips32r3")
75570b57cec5SDimitry Andric           .Case("mips32r5", "mips32r5")
75580b57cec5SDimitry Andric           .Case("mips32r6", "mips32r6")
75590b57cec5SDimitry Andric           .Case("mips64", "mips64")
75600b57cec5SDimitry Andric           .Case("mips64r2", "mips64r2")
75610b57cec5SDimitry Andric           .Case("mips64r3", "mips64r3")
75620b57cec5SDimitry Andric           .Case("mips64r5", "mips64r5")
75630b57cec5SDimitry Andric           .Case("mips64r6", "mips64r6")
75640b57cec5SDimitry Andric           .Case("octeon", "cnmips")
75650b57cec5SDimitry Andric           .Case("octeon+", "cnmipsp")
75660b57cec5SDimitry Andric           .Case("r4000", "mips3") // This is an implementation of Mips3.
75670b57cec5SDimitry Andric           .Default("");
75680b57cec5SDimitry Andric 
75690b57cec5SDimitry Andric   if (ArchFeatureName.empty())
75700b57cec5SDimitry Andric     return reportParseError("unsupported architecture");
75710b57cec5SDimitry Andric 
75720b57cec5SDimitry Andric   if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
75730b57cec5SDimitry Andric     return reportParseError("mips64r6 does not support microMIPS");
75740b57cec5SDimitry Andric 
75750b57cec5SDimitry Andric   selectArch(ArchFeatureName);
75760b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveSetArch(Arch);
75770b57cec5SDimitry Andric   return false;
75780b57cec5SDimitry Andric }
75790b57cec5SDimitry Andric 
parseSetFeature(uint64_t Feature)75800b57cec5SDimitry Andric bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
75810b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
75820b57cec5SDimitry Andric   Parser.Lex();
75830b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
75840b57cec5SDimitry Andric     return reportParseError("unexpected token, expected end of statement");
75850b57cec5SDimitry Andric 
75860b57cec5SDimitry Andric   switch (Feature) {
75870b57cec5SDimitry Andric   default:
75880b57cec5SDimitry Andric     llvm_unreachable("Unimplemented feature");
75895ffd83dbSDimitry Andric   case Mips::FeatureMips3D:
75905ffd83dbSDimitry Andric     setFeatureBits(Mips::FeatureMips3D, "mips3d");
75915ffd83dbSDimitry Andric     getTargetStreamer().emitDirectiveSetMips3D();
75925ffd83dbSDimitry Andric     break;
75930b57cec5SDimitry Andric   case Mips::FeatureDSP:
75940b57cec5SDimitry Andric     setFeatureBits(Mips::FeatureDSP, "dsp");
75950b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetDsp();
75960b57cec5SDimitry Andric     break;
75970b57cec5SDimitry Andric   case Mips::FeatureDSPR2:
75980b57cec5SDimitry Andric     setFeatureBits(Mips::FeatureDSPR2, "dspr2");
75990b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetDspr2();
76000b57cec5SDimitry Andric     break;
76010b57cec5SDimitry Andric   case Mips::FeatureMicroMips:
76020b57cec5SDimitry Andric     setFeatureBits(Mips::FeatureMicroMips, "micromips");
76030b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMicroMips();
76040b57cec5SDimitry Andric     break;
76050b57cec5SDimitry Andric   case Mips::FeatureMips1:
76060b57cec5SDimitry Andric     selectArch("mips1");
76070b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips1();
76080b57cec5SDimitry Andric     break;
76090b57cec5SDimitry Andric   case Mips::FeatureMips2:
76100b57cec5SDimitry Andric     selectArch("mips2");
76110b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips2();
76120b57cec5SDimitry Andric     break;
76130b57cec5SDimitry Andric   case Mips::FeatureMips3:
76140b57cec5SDimitry Andric     selectArch("mips3");
76150b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips3();
76160b57cec5SDimitry Andric     break;
76170b57cec5SDimitry Andric   case Mips::FeatureMips4:
76180b57cec5SDimitry Andric     selectArch("mips4");
76190b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips4();
76200b57cec5SDimitry Andric     break;
76210b57cec5SDimitry Andric   case Mips::FeatureMips5:
76220b57cec5SDimitry Andric     selectArch("mips5");
76230b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips5();
76240b57cec5SDimitry Andric     break;
76250b57cec5SDimitry Andric   case Mips::FeatureMips32:
76260b57cec5SDimitry Andric     selectArch("mips32");
76270b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips32();
76280b57cec5SDimitry Andric     break;
76290b57cec5SDimitry Andric   case Mips::FeatureMips32r2:
76300b57cec5SDimitry Andric     selectArch("mips32r2");
76310b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips32R2();
76320b57cec5SDimitry Andric     break;
76330b57cec5SDimitry Andric   case Mips::FeatureMips32r3:
76340b57cec5SDimitry Andric     selectArch("mips32r3");
76350b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips32R3();
76360b57cec5SDimitry Andric     break;
76370b57cec5SDimitry Andric   case Mips::FeatureMips32r5:
76380b57cec5SDimitry Andric     selectArch("mips32r5");
76390b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips32R5();
76400b57cec5SDimitry Andric     break;
76410b57cec5SDimitry Andric   case Mips::FeatureMips32r6:
76420b57cec5SDimitry Andric     selectArch("mips32r6");
76430b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips32R6();
76440b57cec5SDimitry Andric     break;
76450b57cec5SDimitry Andric   case Mips::FeatureMips64:
76460b57cec5SDimitry Andric     selectArch("mips64");
76470b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips64();
76480b57cec5SDimitry Andric     break;
76490b57cec5SDimitry Andric   case Mips::FeatureMips64r2:
76500b57cec5SDimitry Andric     selectArch("mips64r2");
76510b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips64R2();
76520b57cec5SDimitry Andric     break;
76530b57cec5SDimitry Andric   case Mips::FeatureMips64r3:
76540b57cec5SDimitry Andric     selectArch("mips64r3");
76550b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips64R3();
76560b57cec5SDimitry Andric     break;
76570b57cec5SDimitry Andric   case Mips::FeatureMips64r5:
76580b57cec5SDimitry Andric     selectArch("mips64r5");
76590b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips64R5();
76600b57cec5SDimitry Andric     break;
76610b57cec5SDimitry Andric   case Mips::FeatureMips64r6:
76620b57cec5SDimitry Andric     selectArch("mips64r6");
76630b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetMips64R6();
76640b57cec5SDimitry Andric     break;
76650b57cec5SDimitry Andric   case Mips::FeatureCRC:
76660b57cec5SDimitry Andric     setFeatureBits(Mips::FeatureCRC, "crc");
76670b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetCRC();
76680b57cec5SDimitry Andric     break;
76690b57cec5SDimitry Andric   case Mips::FeatureVirt:
76700b57cec5SDimitry Andric     setFeatureBits(Mips::FeatureVirt, "virt");
76710b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetVirt();
76720b57cec5SDimitry Andric     break;
76730b57cec5SDimitry Andric   case Mips::FeatureGINV:
76740b57cec5SDimitry Andric     setFeatureBits(Mips::FeatureGINV, "ginv");
76750b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetGINV();
76760b57cec5SDimitry Andric     break;
76770b57cec5SDimitry Andric   }
76780b57cec5SDimitry Andric   return false;
76790b57cec5SDimitry Andric }
76800b57cec5SDimitry Andric 
eatComma(StringRef ErrorStr)76810b57cec5SDimitry Andric bool MipsAsmParser::eatComma(StringRef ErrorStr) {
76820b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
76830b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma)) {
76840b57cec5SDimitry Andric     SMLoc Loc = getLexer().getLoc();
76850b57cec5SDimitry Andric     return Error(Loc, ErrorStr);
76860b57cec5SDimitry Andric   }
76870b57cec5SDimitry Andric 
76880b57cec5SDimitry Andric   Parser.Lex(); // Eat the comma.
76890b57cec5SDimitry Andric   return true;
76900b57cec5SDimitry Andric }
76910b57cec5SDimitry Andric 
76920b57cec5SDimitry Andric // Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
76930b57cec5SDimitry Andric // In this class, it is only used for .cprestore.
76940b57cec5SDimitry Andric // FIXME: Only keep track of IsPicEnabled in one place, instead of in both
76950b57cec5SDimitry Andric // MipsTargetELFStreamer and MipsAsmParser.
isPicAndNotNxxAbi()76960b57cec5SDimitry Andric bool MipsAsmParser::isPicAndNotNxxAbi() {
76970b57cec5SDimitry Andric   return inPicMode() && !(isABI_N32() || isABI_N64());
76980b57cec5SDimitry Andric }
76990b57cec5SDimitry Andric 
parseDirectiveCpAdd(SMLoc Loc)77005ffd83dbSDimitry Andric bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {
77015ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
770206c3fb27SDimitry Andric   ParseStatus Res = parseAnyRegister(Reg);
770306c3fb27SDimitry Andric   if (Res.isNoMatch() || Res.isFailure()) {
77045ffd83dbSDimitry Andric     reportParseError("expected register");
77055ffd83dbSDimitry Andric     return false;
77065ffd83dbSDimitry Andric   }
77075ffd83dbSDimitry Andric 
77085ffd83dbSDimitry Andric   MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
77095ffd83dbSDimitry Andric   if (!RegOpnd.isGPRAsmReg()) {
77105ffd83dbSDimitry Andric     reportParseError(RegOpnd.getStartLoc(), "invalid register");
77115ffd83dbSDimitry Andric     return false;
77125ffd83dbSDimitry Andric   }
77135ffd83dbSDimitry Andric 
77145ffd83dbSDimitry Andric   // If this is not the end of the statement, report an error.
77155ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
77165ffd83dbSDimitry Andric     reportParseError("unexpected token, expected end of statement");
77175ffd83dbSDimitry Andric     return false;
77185ffd83dbSDimitry Andric   }
77195ffd83dbSDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
77205ffd83dbSDimitry Andric 
77215ffd83dbSDimitry Andric   getTargetStreamer().emitDirectiveCpAdd(RegOpnd.getGPR32Reg());
77225ffd83dbSDimitry Andric   return false;
77235ffd83dbSDimitry Andric }
77245ffd83dbSDimitry Andric 
parseDirectiveCpLoad(SMLoc Loc)77250b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
77260b57cec5SDimitry Andric   if (AssemblerOptions.back()->isReorder())
77270b57cec5SDimitry Andric     Warning(Loc, ".cpload should be inside a noreorder section");
77280b57cec5SDimitry Andric 
77290b57cec5SDimitry Andric   if (inMips16Mode()) {
77300b57cec5SDimitry Andric     reportParseError(".cpload is not supported in Mips16 mode");
77310b57cec5SDimitry Andric     return false;
77320b57cec5SDimitry Andric   }
77330b57cec5SDimitry Andric 
77340b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
773506c3fb27SDimitry Andric   ParseStatus Res = parseAnyRegister(Reg);
773606c3fb27SDimitry Andric   if (Res.isNoMatch() || Res.isFailure()) {
77370b57cec5SDimitry Andric     reportParseError("expected register containing function address");
77380b57cec5SDimitry Andric     return false;
77390b57cec5SDimitry Andric   }
77400b57cec5SDimitry Andric 
77410b57cec5SDimitry Andric   MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
77420b57cec5SDimitry Andric   if (!RegOpnd.isGPRAsmReg()) {
77430b57cec5SDimitry Andric     reportParseError(RegOpnd.getStartLoc(), "invalid register");
77440b57cec5SDimitry Andric     return false;
77450b57cec5SDimitry Andric   }
77460b57cec5SDimitry Andric 
77470b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
77480b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
77490b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
77500b57cec5SDimitry Andric     return false;
77510b57cec5SDimitry Andric   }
77520b57cec5SDimitry Andric 
77530b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
77540b57cec5SDimitry Andric   return false;
77550b57cec5SDimitry Andric }
77560b57cec5SDimitry Andric 
parseDirectiveCpLocal(SMLoc Loc)77570b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {
77580b57cec5SDimitry Andric   if (!isABI_N32() && !isABI_N64()) {
77590b57cec5SDimitry Andric     reportParseError(".cplocal is allowed only in N32 or N64 mode");
77600b57cec5SDimitry Andric     return false;
77610b57cec5SDimitry Andric   }
77620b57cec5SDimitry Andric 
77630b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
776406c3fb27SDimitry Andric   ParseStatus Res = parseAnyRegister(Reg);
776506c3fb27SDimitry Andric   if (Res.isNoMatch() || Res.isFailure()) {
77660b57cec5SDimitry Andric     reportParseError("expected register containing global pointer");
77670b57cec5SDimitry Andric     return false;
77680b57cec5SDimitry Andric   }
77690b57cec5SDimitry Andric 
77700b57cec5SDimitry Andric   MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
77710b57cec5SDimitry Andric   if (!RegOpnd.isGPRAsmReg()) {
77720b57cec5SDimitry Andric     reportParseError(RegOpnd.getStartLoc(), "invalid register");
77730b57cec5SDimitry Andric     return false;
77740b57cec5SDimitry Andric   }
77750b57cec5SDimitry Andric 
77760b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
77770b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
77780b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
77790b57cec5SDimitry Andric     return false;
77800b57cec5SDimitry Andric   }
77810b57cec5SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
77820b57cec5SDimitry Andric 
77830b57cec5SDimitry Andric   unsigned NewReg = RegOpnd.getGPR32Reg();
77840b57cec5SDimitry Andric   if (IsPicEnabled)
77850b57cec5SDimitry Andric     GPReg = NewReg;
77860b57cec5SDimitry Andric 
77870b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveCpLocal(NewReg);
77880b57cec5SDimitry Andric   return false;
77890b57cec5SDimitry Andric }
77900b57cec5SDimitry Andric 
parseDirectiveCpRestore(SMLoc Loc)77910b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
77920b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
77930b57cec5SDimitry Andric 
77940b57cec5SDimitry Andric   // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
77950b57cec5SDimitry Andric   // is used in non-PIC mode.
77960b57cec5SDimitry Andric 
77970b57cec5SDimitry Andric   if (inMips16Mode()) {
77980b57cec5SDimitry Andric     reportParseError(".cprestore is not supported in Mips16 mode");
77990b57cec5SDimitry Andric     return false;
78000b57cec5SDimitry Andric   }
78010b57cec5SDimitry Andric 
78020b57cec5SDimitry Andric   // Get the stack offset value.
78030b57cec5SDimitry Andric   const MCExpr *StackOffset;
78040b57cec5SDimitry Andric   int64_t StackOffsetVal;
78050b57cec5SDimitry Andric   if (Parser.parseExpression(StackOffset)) {
78060b57cec5SDimitry Andric     reportParseError("expected stack offset value");
78070b57cec5SDimitry Andric     return false;
78080b57cec5SDimitry Andric   }
78090b57cec5SDimitry Andric 
78100b57cec5SDimitry Andric   if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
78110b57cec5SDimitry Andric     reportParseError("stack offset is not an absolute expression");
78120b57cec5SDimitry Andric     return false;
78130b57cec5SDimitry Andric   }
78140b57cec5SDimitry Andric 
78150b57cec5SDimitry Andric   if (StackOffsetVal < 0) {
78160b57cec5SDimitry Andric     Warning(Loc, ".cprestore with negative stack offset has no effect");
78170b57cec5SDimitry Andric     IsCpRestoreSet = false;
78180b57cec5SDimitry Andric   } else {
78190b57cec5SDimitry Andric     IsCpRestoreSet = true;
78200b57cec5SDimitry Andric     CpRestoreOffset = StackOffsetVal;
78210b57cec5SDimitry Andric   }
78220b57cec5SDimitry Andric 
78230b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
78240b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
78250b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
78260b57cec5SDimitry Andric     return false;
78270b57cec5SDimitry Andric   }
78280b57cec5SDimitry Andric 
78290b57cec5SDimitry Andric   if (!getTargetStreamer().emitDirectiveCpRestore(
78300b57cec5SDimitry Andric           CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
78310b57cec5SDimitry Andric     return true;
78320b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
78330b57cec5SDimitry Andric   return false;
78340b57cec5SDimitry Andric }
78350b57cec5SDimitry Andric 
parseDirectiveCPSetup()78360b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCPSetup() {
78370b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
78380b57cec5SDimitry Andric   unsigned FuncReg;
78390b57cec5SDimitry Andric   unsigned Save;
78400b57cec5SDimitry Andric   bool SaveIsReg = true;
78410b57cec5SDimitry Andric 
78420b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
784306c3fb27SDimitry Andric   ParseStatus Res = parseAnyRegister(TmpReg);
784406c3fb27SDimitry Andric   if (Res.isNoMatch()) {
78450b57cec5SDimitry Andric     reportParseError("expected register containing function address");
78460b57cec5SDimitry Andric     return false;
78470b57cec5SDimitry Andric   }
78480b57cec5SDimitry Andric 
78490b57cec5SDimitry Andric   MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
78500b57cec5SDimitry Andric   if (!FuncRegOpnd.isGPRAsmReg()) {
78510b57cec5SDimitry Andric     reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
78520b57cec5SDimitry Andric     return false;
78530b57cec5SDimitry Andric   }
78540b57cec5SDimitry Andric 
78550b57cec5SDimitry Andric   FuncReg = FuncRegOpnd.getGPR32Reg();
78560b57cec5SDimitry Andric   TmpReg.clear();
78570b57cec5SDimitry Andric 
78580b57cec5SDimitry Andric   if (!eatComma("unexpected token, expected comma"))
78590b57cec5SDimitry Andric     return true;
78600b57cec5SDimitry Andric 
786106c3fb27SDimitry Andric   Res = parseAnyRegister(TmpReg);
786206c3fb27SDimitry Andric   if (Res.isNoMatch()) {
78630b57cec5SDimitry Andric     const MCExpr *OffsetExpr;
78640b57cec5SDimitry Andric     int64_t OffsetVal;
78650b57cec5SDimitry Andric     SMLoc ExprLoc = getLexer().getLoc();
78660b57cec5SDimitry Andric 
78670b57cec5SDimitry Andric     if (Parser.parseExpression(OffsetExpr) ||
78680b57cec5SDimitry Andric         !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
78690b57cec5SDimitry Andric       reportParseError(ExprLoc, "expected save register or stack offset");
78700b57cec5SDimitry Andric       return false;
78710b57cec5SDimitry Andric     }
78720b57cec5SDimitry Andric 
78730b57cec5SDimitry Andric     Save = OffsetVal;
78740b57cec5SDimitry Andric     SaveIsReg = false;
78750b57cec5SDimitry Andric   } else {
78760b57cec5SDimitry Andric     MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
78770b57cec5SDimitry Andric     if (!SaveOpnd.isGPRAsmReg()) {
78780b57cec5SDimitry Andric       reportParseError(SaveOpnd.getStartLoc(), "invalid register");
78790b57cec5SDimitry Andric       return false;
78800b57cec5SDimitry Andric     }
78810b57cec5SDimitry Andric     Save = SaveOpnd.getGPR32Reg();
78820b57cec5SDimitry Andric   }
78830b57cec5SDimitry Andric 
78840b57cec5SDimitry Andric   if (!eatComma("unexpected token, expected comma"))
78850b57cec5SDimitry Andric     return true;
78860b57cec5SDimitry Andric 
78870b57cec5SDimitry Andric   const MCExpr *Expr;
78880b57cec5SDimitry Andric   if (Parser.parseExpression(Expr)) {
78890b57cec5SDimitry Andric     reportParseError("expected expression");
78900b57cec5SDimitry Andric     return false;
78910b57cec5SDimitry Andric   }
78920b57cec5SDimitry Andric 
78930b57cec5SDimitry Andric   if (Expr->getKind() != MCExpr::SymbolRef) {
78940b57cec5SDimitry Andric     reportParseError("expected symbol");
78950b57cec5SDimitry Andric     return false;
78960b57cec5SDimitry Andric   }
78970b57cec5SDimitry Andric   const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
78980b57cec5SDimitry Andric 
78990b57cec5SDimitry Andric   CpSaveLocation = Save;
79000b57cec5SDimitry Andric   CpSaveLocationIsRegister = SaveIsReg;
79010b57cec5SDimitry Andric 
79020b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
79030b57cec5SDimitry Andric                                            SaveIsReg);
79040b57cec5SDimitry Andric   return false;
79050b57cec5SDimitry Andric }
79060b57cec5SDimitry Andric 
parseDirectiveCPReturn()79070b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCPReturn() {
79080b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
79090b57cec5SDimitry Andric                                             CpSaveLocationIsRegister);
79100b57cec5SDimitry Andric   return false;
79110b57cec5SDimitry Andric }
79120b57cec5SDimitry Andric 
parseDirectiveNaN()79130b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveNaN() {
79140b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
79150b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
79160b57cec5SDimitry Andric     const AsmToken &Tok = Parser.getTok();
79170b57cec5SDimitry Andric 
79180b57cec5SDimitry Andric     if (Tok.getString() == "2008") {
79190b57cec5SDimitry Andric       Parser.Lex();
79200b57cec5SDimitry Andric       getTargetStreamer().emitDirectiveNaN2008();
79210b57cec5SDimitry Andric       return false;
79220b57cec5SDimitry Andric     } else if (Tok.getString() == "legacy") {
79230b57cec5SDimitry Andric       Parser.Lex();
79240b57cec5SDimitry Andric       getTargetStreamer().emitDirectiveNaNLegacy();
79250b57cec5SDimitry Andric       return false;
79260b57cec5SDimitry Andric     }
79270b57cec5SDimitry Andric   }
79280b57cec5SDimitry Andric   // If we don't recognize the option passed to the .nan
79290b57cec5SDimitry Andric   // directive (e.g. no option or unknown option), emit an error.
79300b57cec5SDimitry Andric   reportParseError("invalid option in .nan directive");
79310b57cec5SDimitry Andric   return false;
79320b57cec5SDimitry Andric }
79330b57cec5SDimitry Andric 
parseDirectiveSet()79340b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveSet() {
79350b57cec5SDimitry Andric   const AsmToken &Tok = getParser().getTok();
79360b57cec5SDimitry Andric   StringRef IdVal = Tok.getString();
79370b57cec5SDimitry Andric   SMLoc Loc = Tok.getLoc();
79380b57cec5SDimitry Andric 
79390b57cec5SDimitry Andric   if (IdVal == "noat")
79400b57cec5SDimitry Andric     return parseSetNoAtDirective();
79410b57cec5SDimitry Andric   if (IdVal == "at")
79420b57cec5SDimitry Andric     return parseSetAtDirective();
79430b57cec5SDimitry Andric   if (IdVal == "arch")
79440b57cec5SDimitry Andric     return parseSetArchDirective();
79450b57cec5SDimitry Andric   if (IdVal == "bopt") {
79460b57cec5SDimitry Andric     Warning(Loc, "'bopt' feature is unsupported");
79470b57cec5SDimitry Andric     getParser().Lex();
79480b57cec5SDimitry Andric     return false;
79490b57cec5SDimitry Andric   }
79500b57cec5SDimitry Andric   if (IdVal == "nobopt") {
79510b57cec5SDimitry Andric     // We're already running in nobopt mode, so nothing to do.
79520b57cec5SDimitry Andric     getParser().Lex();
79530b57cec5SDimitry Andric     return false;
79540b57cec5SDimitry Andric   }
79550b57cec5SDimitry Andric   if (IdVal == "fp")
79560b57cec5SDimitry Andric     return parseSetFpDirective();
79570b57cec5SDimitry Andric   if (IdVal == "oddspreg")
79580b57cec5SDimitry Andric     return parseSetOddSPRegDirective();
79590b57cec5SDimitry Andric   if (IdVal == "nooddspreg")
79600b57cec5SDimitry Andric     return parseSetNoOddSPRegDirective();
79610b57cec5SDimitry Andric   if (IdVal == "pop")
79620b57cec5SDimitry Andric     return parseSetPopDirective();
79630b57cec5SDimitry Andric   if (IdVal == "push")
79640b57cec5SDimitry Andric     return parseSetPushDirective();
79650b57cec5SDimitry Andric   if (IdVal == "reorder")
79660b57cec5SDimitry Andric     return parseSetReorderDirective();
79670b57cec5SDimitry Andric   if (IdVal == "noreorder")
79680b57cec5SDimitry Andric     return parseSetNoReorderDirective();
79690b57cec5SDimitry Andric   if (IdVal == "macro")
79700b57cec5SDimitry Andric     return parseSetMacroDirective();
79710b57cec5SDimitry Andric   if (IdVal == "nomacro")
79720b57cec5SDimitry Andric     return parseSetNoMacroDirective();
79730b57cec5SDimitry Andric   if (IdVal == "mips16")
79740b57cec5SDimitry Andric     return parseSetMips16Directive();
79750b57cec5SDimitry Andric   if (IdVal == "nomips16")
79760b57cec5SDimitry Andric     return parseSetNoMips16Directive();
79770b57cec5SDimitry Andric   if (IdVal == "nomicromips") {
79780b57cec5SDimitry Andric     clearFeatureBits(Mips::FeatureMicroMips, "micromips");
79790b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveSetNoMicroMips();
79800b57cec5SDimitry Andric     getParser().eatToEndOfStatement();
79810b57cec5SDimitry Andric     return false;
79820b57cec5SDimitry Andric   }
79830b57cec5SDimitry Andric   if (IdVal == "micromips") {
79840b57cec5SDimitry Andric     if (hasMips64r6()) {
79850b57cec5SDimitry Andric       Error(Loc, ".set micromips directive is not supported with MIPS64R6");
79860b57cec5SDimitry Andric       return false;
79870b57cec5SDimitry Andric     }
79880b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMicroMips);
79890b57cec5SDimitry Andric   }
79900b57cec5SDimitry Andric   if (IdVal == "mips0")
79910b57cec5SDimitry Andric     return parseSetMips0Directive();
79920b57cec5SDimitry Andric   if (IdVal == "mips1")
79930b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips1);
79940b57cec5SDimitry Andric   if (IdVal == "mips2")
79950b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips2);
79960b57cec5SDimitry Andric   if (IdVal == "mips3")
79970b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips3);
79980b57cec5SDimitry Andric   if (IdVal == "mips4")
79990b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips4);
80000b57cec5SDimitry Andric   if (IdVal == "mips5")
80010b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips5);
80020b57cec5SDimitry Andric   if (IdVal == "mips32")
80030b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips32);
80040b57cec5SDimitry Andric   if (IdVal == "mips32r2")
80050b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips32r2);
80060b57cec5SDimitry Andric   if (IdVal == "mips32r3")
80070b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips32r3);
80080b57cec5SDimitry Andric   if (IdVal == "mips32r5")
80090b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips32r5);
80100b57cec5SDimitry Andric   if (IdVal == "mips32r6")
80110b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips32r6);
80120b57cec5SDimitry Andric   if (IdVal == "mips64")
80130b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips64);
80140b57cec5SDimitry Andric   if (IdVal == "mips64r2")
80150b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips64r2);
80160b57cec5SDimitry Andric   if (IdVal == "mips64r3")
80170b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips64r3);
80180b57cec5SDimitry Andric   if (IdVal == "mips64r5")
80190b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips64r5);
80200b57cec5SDimitry Andric   if (IdVal == "mips64r6") {
80210b57cec5SDimitry Andric     if (inMicroMipsMode()) {
80220b57cec5SDimitry Andric       Error(Loc, "MIPS64R6 is not supported with microMIPS");
80230b57cec5SDimitry Andric       return false;
80240b57cec5SDimitry Andric     }
80250b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureMips64r6);
80260b57cec5SDimitry Andric   }
80270b57cec5SDimitry Andric   if (IdVal == "dsp")
80280b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureDSP);
80290b57cec5SDimitry Andric   if (IdVal == "dspr2")
80300b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureDSPR2);
80310b57cec5SDimitry Andric   if (IdVal == "nodsp")
80320b57cec5SDimitry Andric     return parseSetNoDspDirective();
80335ffd83dbSDimitry Andric   if (IdVal == "mips3d")
80345ffd83dbSDimitry Andric     return parseSetFeature(Mips::FeatureMips3D);
80355ffd83dbSDimitry Andric   if (IdVal == "nomips3d")
80365ffd83dbSDimitry Andric     return parseSetNoMips3DDirective();
80370b57cec5SDimitry Andric   if (IdVal == "msa")
80380b57cec5SDimitry Andric     return parseSetMsaDirective();
80390b57cec5SDimitry Andric   if (IdVal == "nomsa")
80400b57cec5SDimitry Andric     return parseSetNoMsaDirective();
80410b57cec5SDimitry Andric   if (IdVal == "mt")
80420b57cec5SDimitry Andric     return parseSetMtDirective();
80430b57cec5SDimitry Andric   if (IdVal == "nomt")
80440b57cec5SDimitry Andric     return parseSetNoMtDirective();
80450b57cec5SDimitry Andric   if (IdVal == "softfloat")
80460b57cec5SDimitry Andric     return parseSetSoftFloatDirective();
80470b57cec5SDimitry Andric   if (IdVal == "hardfloat")
80480b57cec5SDimitry Andric     return parseSetHardFloatDirective();
80490b57cec5SDimitry Andric   if (IdVal == "crc")
80500b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureCRC);
80510b57cec5SDimitry Andric   if (IdVal == "nocrc")
80520b57cec5SDimitry Andric     return parseSetNoCRCDirective();
80530b57cec5SDimitry Andric   if (IdVal == "virt")
80540b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureVirt);
80550b57cec5SDimitry Andric   if (IdVal == "novirt")
80560b57cec5SDimitry Andric     return parseSetNoVirtDirective();
80570b57cec5SDimitry Andric   if (IdVal == "ginv")
80580b57cec5SDimitry Andric     return parseSetFeature(Mips::FeatureGINV);
80590b57cec5SDimitry Andric   if (IdVal == "noginv")
80600b57cec5SDimitry Andric     return parseSetNoGINVDirective();
80610b57cec5SDimitry Andric 
80620b57cec5SDimitry Andric   // It is just an identifier, look for an assignment.
80630b57cec5SDimitry Andric   return parseSetAssignment();
80640b57cec5SDimitry Andric }
80650b57cec5SDimitry Andric 
80660b57cec5SDimitry Andric /// parseDirectiveGpWord
80670b57cec5SDimitry Andric ///  ::= .gpword local_sym
parseDirectiveGpWord()80680b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveGpWord() {
80690b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
80700b57cec5SDimitry Andric   const MCExpr *Value;
80710b57cec5SDimitry Andric   // EmitGPRel32Value requires an expression, so we are using base class
80720b57cec5SDimitry Andric   // method to evaluate the expression.
80730b57cec5SDimitry Andric   if (getParser().parseExpression(Value))
80740b57cec5SDimitry Andric     return true;
80755ffd83dbSDimitry Andric   getParser().getStreamer().emitGPRel32Value(Value);
80760b57cec5SDimitry Andric 
80770b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
80780b57cec5SDimitry Andric     return Error(getLexer().getLoc(),
80790b57cec5SDimitry Andric                 "unexpected token, expected end of statement");
80800b57cec5SDimitry Andric   Parser.Lex(); // Eat EndOfStatement token.
80810b57cec5SDimitry Andric   return false;
80820b57cec5SDimitry Andric }
80830b57cec5SDimitry Andric 
80840b57cec5SDimitry Andric /// parseDirectiveGpDWord
80850b57cec5SDimitry Andric ///  ::= .gpdword local_sym
parseDirectiveGpDWord()80860b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveGpDWord() {
80870b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
80880b57cec5SDimitry Andric   const MCExpr *Value;
80890b57cec5SDimitry Andric   // EmitGPRel64Value requires an expression, so we are using base class
80900b57cec5SDimitry Andric   // method to evaluate the expression.
80910b57cec5SDimitry Andric   if (getParser().parseExpression(Value))
80920b57cec5SDimitry Andric     return true;
80935ffd83dbSDimitry Andric   getParser().getStreamer().emitGPRel64Value(Value);
80940b57cec5SDimitry Andric 
80950b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
80960b57cec5SDimitry Andric     return Error(getLexer().getLoc(),
80970b57cec5SDimitry Andric                 "unexpected token, expected end of statement");
80980b57cec5SDimitry Andric   Parser.Lex(); // Eat EndOfStatement token.
80990b57cec5SDimitry Andric   return false;
81000b57cec5SDimitry Andric }
81010b57cec5SDimitry Andric 
81020b57cec5SDimitry Andric /// parseDirectiveDtpRelWord
81030b57cec5SDimitry Andric ///  ::= .dtprelword tls_sym
parseDirectiveDtpRelWord()81040b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveDtpRelWord() {
81050b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
81060b57cec5SDimitry Andric   const MCExpr *Value;
81070b57cec5SDimitry Andric   // EmitDTPRel32Value requires an expression, so we are using base class
81080b57cec5SDimitry Andric   // method to evaluate the expression.
81090b57cec5SDimitry Andric   if (getParser().parseExpression(Value))
81100b57cec5SDimitry Andric     return true;
81115ffd83dbSDimitry Andric   getParser().getStreamer().emitDTPRel32Value(Value);
81120b57cec5SDimitry Andric 
81130b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
81140b57cec5SDimitry Andric     return Error(getLexer().getLoc(),
81150b57cec5SDimitry Andric                 "unexpected token, expected end of statement");
81160b57cec5SDimitry Andric   Parser.Lex(); // Eat EndOfStatement token.
81170b57cec5SDimitry Andric   return false;
81180b57cec5SDimitry Andric }
81190b57cec5SDimitry Andric 
81200b57cec5SDimitry Andric /// parseDirectiveDtpRelDWord
81210b57cec5SDimitry Andric ///  ::= .dtpreldword tls_sym
parseDirectiveDtpRelDWord()81220b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveDtpRelDWord() {
81230b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
81240b57cec5SDimitry Andric   const MCExpr *Value;
81250b57cec5SDimitry Andric   // EmitDTPRel64Value requires an expression, so we are using base class
81260b57cec5SDimitry Andric   // method to evaluate the expression.
81270b57cec5SDimitry Andric   if (getParser().parseExpression(Value))
81280b57cec5SDimitry Andric     return true;
81295ffd83dbSDimitry Andric   getParser().getStreamer().emitDTPRel64Value(Value);
81300b57cec5SDimitry Andric 
81310b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
81320b57cec5SDimitry Andric     return Error(getLexer().getLoc(),
81330b57cec5SDimitry Andric                 "unexpected token, expected end of statement");
81340b57cec5SDimitry Andric   Parser.Lex(); // Eat EndOfStatement token.
81350b57cec5SDimitry Andric   return false;
81360b57cec5SDimitry Andric }
81370b57cec5SDimitry Andric 
81380b57cec5SDimitry Andric /// parseDirectiveTpRelWord
81390b57cec5SDimitry Andric ///  ::= .tprelword tls_sym
parseDirectiveTpRelWord()81400b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveTpRelWord() {
81410b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
81420b57cec5SDimitry Andric   const MCExpr *Value;
81430b57cec5SDimitry Andric   // EmitTPRel32Value requires an expression, so we are using base class
81440b57cec5SDimitry Andric   // method to evaluate the expression.
81450b57cec5SDimitry Andric   if (getParser().parseExpression(Value))
81460b57cec5SDimitry Andric     return true;
81475ffd83dbSDimitry Andric   getParser().getStreamer().emitTPRel32Value(Value);
81480b57cec5SDimitry Andric 
81490b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
81500b57cec5SDimitry Andric     return Error(getLexer().getLoc(),
81510b57cec5SDimitry Andric                 "unexpected token, expected end of statement");
81520b57cec5SDimitry Andric   Parser.Lex(); // Eat EndOfStatement token.
81530b57cec5SDimitry Andric   return false;
81540b57cec5SDimitry Andric }
81550b57cec5SDimitry Andric 
81560b57cec5SDimitry Andric /// parseDirectiveTpRelDWord
81570b57cec5SDimitry Andric ///  ::= .tpreldword tls_sym
parseDirectiveTpRelDWord()81580b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveTpRelDWord() {
81590b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
81600b57cec5SDimitry Andric   const MCExpr *Value;
81610b57cec5SDimitry Andric   // EmitTPRel64Value requires an expression, so we are using base class
81620b57cec5SDimitry Andric   // method to evaluate the expression.
81630b57cec5SDimitry Andric   if (getParser().parseExpression(Value))
81640b57cec5SDimitry Andric     return true;
81655ffd83dbSDimitry Andric   getParser().getStreamer().emitTPRel64Value(Value);
81660b57cec5SDimitry Andric 
81670b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
81680b57cec5SDimitry Andric     return Error(getLexer().getLoc(),
81690b57cec5SDimitry Andric                 "unexpected token, expected end of statement");
81700b57cec5SDimitry Andric   Parser.Lex(); // Eat EndOfStatement token.
81710b57cec5SDimitry Andric   return false;
81720b57cec5SDimitry Andric }
81730b57cec5SDimitry Andric 
parseDirectiveOption()81740b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveOption() {
81750b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
81760b57cec5SDimitry Andric   // Get the option token.
81770b57cec5SDimitry Andric   AsmToken Tok = Parser.getTok();
81780b57cec5SDimitry Andric   // At the moment only identifiers are supported.
81790b57cec5SDimitry Andric   if (Tok.isNot(AsmToken::Identifier)) {
81800b57cec5SDimitry Andric     return Error(Parser.getTok().getLoc(),
81810b57cec5SDimitry Andric                  "unexpected token, expected identifier");
81820b57cec5SDimitry Andric   }
81830b57cec5SDimitry Andric 
81840b57cec5SDimitry Andric   StringRef Option = Tok.getIdentifier();
81850b57cec5SDimitry Andric 
81860b57cec5SDimitry Andric   if (Option == "pic0") {
81870b57cec5SDimitry Andric     // MipsAsmParser needs to know if the current PIC mode changes.
81880b57cec5SDimitry Andric     IsPicEnabled = false;
81890b57cec5SDimitry Andric 
81900b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionPic0();
81910b57cec5SDimitry Andric     Parser.Lex();
81920b57cec5SDimitry Andric     if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
81930b57cec5SDimitry Andric       return Error(Parser.getTok().getLoc(),
81940b57cec5SDimitry Andric                    "unexpected token, expected end of statement");
81950b57cec5SDimitry Andric     }
81960b57cec5SDimitry Andric     return false;
81970b57cec5SDimitry Andric   }
81980b57cec5SDimitry Andric 
81990b57cec5SDimitry Andric   if (Option == "pic2") {
82000b57cec5SDimitry Andric     // MipsAsmParser needs to know if the current PIC mode changes.
82010b57cec5SDimitry Andric     IsPicEnabled = true;
82020b57cec5SDimitry Andric 
82030b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionPic2();
82040b57cec5SDimitry Andric     Parser.Lex();
82050b57cec5SDimitry Andric     if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
82060b57cec5SDimitry Andric       return Error(Parser.getTok().getLoc(),
82070b57cec5SDimitry Andric                    "unexpected token, expected end of statement");
82080b57cec5SDimitry Andric     }
82090b57cec5SDimitry Andric     return false;
82100b57cec5SDimitry Andric   }
82110b57cec5SDimitry Andric 
82120b57cec5SDimitry Andric   // Unknown option.
82130b57cec5SDimitry Andric   Warning(Parser.getTok().getLoc(),
82140b57cec5SDimitry Andric           "unknown option, expected 'pic0' or 'pic2'");
82150b57cec5SDimitry Andric   Parser.eatToEndOfStatement();
82160b57cec5SDimitry Andric   return false;
82170b57cec5SDimitry Andric }
82180b57cec5SDimitry Andric 
82190b57cec5SDimitry Andric /// parseInsnDirective
82200b57cec5SDimitry Andric ///  ::= .insn
parseInsnDirective()82210b57cec5SDimitry Andric bool MipsAsmParser::parseInsnDirective() {
82220b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
82230b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
82240b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
82250b57cec5SDimitry Andric     return false;
82260b57cec5SDimitry Andric   }
82270b57cec5SDimitry Andric 
82280b57cec5SDimitry Andric   // The actual label marking happens in
82290b57cec5SDimitry Andric   // MipsELFStreamer::createPendingLabelRelocs().
82300b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveInsn();
82310b57cec5SDimitry Andric 
82320b57cec5SDimitry Andric   getParser().Lex(); // Eat EndOfStatement token.
82330b57cec5SDimitry Andric   return false;
82340b57cec5SDimitry Andric }
82350b57cec5SDimitry Andric 
82360b57cec5SDimitry Andric /// parseRSectionDirective
82370b57cec5SDimitry Andric ///  ::= .rdata
parseRSectionDirective(StringRef Section)82380b57cec5SDimitry Andric bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
82390b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
82400b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
82410b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
82420b57cec5SDimitry Andric     return false;
82430b57cec5SDimitry Andric   }
82440b57cec5SDimitry Andric 
82450b57cec5SDimitry Andric   MCSection *ELFSection = getContext().getELFSection(
82460b57cec5SDimitry Andric       Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
824781ad6265SDimitry Andric   getParser().getStreamer().switchSection(ELFSection);
82480b57cec5SDimitry Andric 
82490b57cec5SDimitry Andric   getParser().Lex(); // Eat EndOfStatement token.
82500b57cec5SDimitry Andric   return false;
82510b57cec5SDimitry Andric }
82520b57cec5SDimitry Andric 
82530b57cec5SDimitry Andric /// parseSSectionDirective
82540b57cec5SDimitry Andric ///  ::= .sbss
82550b57cec5SDimitry Andric ///  ::= .sdata
parseSSectionDirective(StringRef Section,unsigned Type)82560b57cec5SDimitry Andric bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
82570b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
82580b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
82590b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
82600b57cec5SDimitry Andric     return false;
82610b57cec5SDimitry Andric   }
82620b57cec5SDimitry Andric 
82630b57cec5SDimitry Andric   MCSection *ELFSection = getContext().getELFSection(
82640b57cec5SDimitry Andric       Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
826581ad6265SDimitry Andric   getParser().getStreamer().switchSection(ELFSection);
82660b57cec5SDimitry Andric 
82670b57cec5SDimitry Andric   getParser().Lex(); // Eat EndOfStatement token.
82680b57cec5SDimitry Andric   return false;
82690b57cec5SDimitry Andric }
82700b57cec5SDimitry Andric 
82710b57cec5SDimitry Andric /// parseDirectiveModule
82720b57cec5SDimitry Andric ///  ::= .module oddspreg
82730b57cec5SDimitry Andric ///  ::= .module nooddspreg
82740b57cec5SDimitry Andric ///  ::= .module fp=value
82750b57cec5SDimitry Andric ///  ::= .module softfloat
82760b57cec5SDimitry Andric ///  ::= .module hardfloat
82770b57cec5SDimitry Andric ///  ::= .module mt
82780b57cec5SDimitry Andric ///  ::= .module crc
82790b57cec5SDimitry Andric ///  ::= .module nocrc
82800b57cec5SDimitry Andric ///  ::= .module virt
82810b57cec5SDimitry Andric ///  ::= .module novirt
82820b57cec5SDimitry Andric ///  ::= .module ginv
82830b57cec5SDimitry Andric ///  ::= .module noginv
parseDirectiveModule()82840b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveModule() {
82850b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
82860b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
82870b57cec5SDimitry Andric   SMLoc L = Lexer.getLoc();
82880b57cec5SDimitry Andric 
82890b57cec5SDimitry Andric   if (!getTargetStreamer().isModuleDirectiveAllowed()) {
82900b57cec5SDimitry Andric     // TODO : get a better message.
82910b57cec5SDimitry Andric     reportParseError(".module directive must appear before any code");
82920b57cec5SDimitry Andric     return false;
82930b57cec5SDimitry Andric   }
82940b57cec5SDimitry Andric 
82950b57cec5SDimitry Andric   StringRef Option;
82960b57cec5SDimitry Andric   if (Parser.parseIdentifier(Option)) {
82970b57cec5SDimitry Andric     reportParseError("expected .module option identifier");
82980b57cec5SDimitry Andric     return false;
82990b57cec5SDimitry Andric   }
83000b57cec5SDimitry Andric 
83010b57cec5SDimitry Andric   if (Option == "oddspreg") {
83020b57cec5SDimitry Andric     clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
83030b57cec5SDimitry Andric 
83040b57cec5SDimitry Andric     // Synchronize the abiflags information with the FeatureBits information we
83050b57cec5SDimitry Andric     // changed above.
83060b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
83070b57cec5SDimitry Andric 
83080b57cec5SDimitry Andric     // If printing assembly, use the recently updated abiflags information.
83090b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83100b57cec5SDimitry Andric     // emitted at the end).
83110b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleOddSPReg();
83120b57cec5SDimitry Andric 
83130b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
83140b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
83150b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
83160b57cec5SDimitry Andric       return false;
83170b57cec5SDimitry Andric     }
83180b57cec5SDimitry Andric 
83190b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
83200b57cec5SDimitry Andric   } else if (Option == "nooddspreg") {
83210b57cec5SDimitry Andric     if (!isABI_O32()) {
83220b57cec5SDimitry Andric       return Error(L, "'.module nooddspreg' requires the O32 ABI");
83230b57cec5SDimitry Andric     }
83240b57cec5SDimitry Andric 
83250b57cec5SDimitry Andric     setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
83260b57cec5SDimitry Andric 
83270b57cec5SDimitry Andric     // Synchronize the abiflags information with the FeatureBits information we
83280b57cec5SDimitry Andric     // changed above.
83290b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
83300b57cec5SDimitry Andric 
83310b57cec5SDimitry Andric     // If printing assembly, use the recently updated abiflags information.
83320b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83330b57cec5SDimitry Andric     // emitted at the end).
83340b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleOddSPReg();
83350b57cec5SDimitry Andric 
83360b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
83370b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
83380b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
83390b57cec5SDimitry Andric       return false;
83400b57cec5SDimitry Andric     }
83410b57cec5SDimitry Andric 
83420b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
83430b57cec5SDimitry Andric   } else if (Option == "fp") {
83440b57cec5SDimitry Andric     return parseDirectiveModuleFP();
83450b57cec5SDimitry Andric   } else if (Option == "softfloat") {
83460b57cec5SDimitry Andric     setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
83470b57cec5SDimitry Andric 
83480b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
83490b57cec5SDimitry Andric     // updated above.
83500b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
83510b57cec5SDimitry Andric 
83520b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
83530b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83540b57cec5SDimitry Andric     // emitted later).
83550b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleSoftFloat();
83560b57cec5SDimitry Andric 
83570b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
83580b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
83590b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
83600b57cec5SDimitry Andric       return false;
83610b57cec5SDimitry Andric     }
83620b57cec5SDimitry Andric 
83630b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
83640b57cec5SDimitry Andric   } else if (Option == "hardfloat") {
83650b57cec5SDimitry Andric     clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
83660b57cec5SDimitry Andric 
83670b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
83680b57cec5SDimitry Andric     // updated above.
83690b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
83700b57cec5SDimitry Andric 
83710b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
83720b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83730b57cec5SDimitry Andric     // emitted later).
83740b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleHardFloat();
83750b57cec5SDimitry Andric 
83760b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
83770b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
83780b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
83790b57cec5SDimitry Andric       return false;
83800b57cec5SDimitry Andric     }
83810b57cec5SDimitry Andric 
83820b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
83830b57cec5SDimitry Andric   } else if (Option == "mt") {
83840b57cec5SDimitry Andric     setModuleFeatureBits(Mips::FeatureMT, "mt");
83850b57cec5SDimitry Andric 
83860b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
83870b57cec5SDimitry Andric     // updated above.
83880b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
83890b57cec5SDimitry Andric 
83900b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
83910b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83920b57cec5SDimitry Andric     // emitted later).
83930b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleMT();
83940b57cec5SDimitry Andric 
83950b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
83960b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
83970b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
83980b57cec5SDimitry Andric       return false;
83990b57cec5SDimitry Andric     }
84000b57cec5SDimitry Andric 
84010b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
84020b57cec5SDimitry Andric   } else if (Option == "crc") {
84030b57cec5SDimitry Andric     setModuleFeatureBits(Mips::FeatureCRC, "crc");
84040b57cec5SDimitry Andric 
84050b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
84060b57cec5SDimitry Andric     // updated above.
84070b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
84080b57cec5SDimitry Andric 
84090b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
84100b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84110b57cec5SDimitry Andric     // emitted later).
84120b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleCRC();
84130b57cec5SDimitry Andric 
84140b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
84150b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
84160b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
84170b57cec5SDimitry Andric       return false;
84180b57cec5SDimitry Andric     }
84190b57cec5SDimitry Andric 
84200b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
84210b57cec5SDimitry Andric   } else if (Option == "nocrc") {
84220b57cec5SDimitry Andric     clearModuleFeatureBits(Mips::FeatureCRC, "crc");
84230b57cec5SDimitry Andric 
84240b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
84250b57cec5SDimitry Andric     // updated above.
84260b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
84270b57cec5SDimitry Andric 
84280b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
84290b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84300b57cec5SDimitry Andric     // emitted later).
84310b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleNoCRC();
84320b57cec5SDimitry Andric 
84330b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
84340b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
84350b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
84360b57cec5SDimitry Andric       return false;
84370b57cec5SDimitry Andric     }
84380b57cec5SDimitry Andric 
84390b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
84400b57cec5SDimitry Andric   } else if (Option == "virt") {
84410b57cec5SDimitry Andric     setModuleFeatureBits(Mips::FeatureVirt, "virt");
84420b57cec5SDimitry Andric 
84430b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
84440b57cec5SDimitry Andric     // updated above.
84450b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
84460b57cec5SDimitry Andric 
84470b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
84480b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84490b57cec5SDimitry Andric     // emitted later).
84500b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleVirt();
84510b57cec5SDimitry Andric 
84520b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
84530b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
84540b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
84550b57cec5SDimitry Andric       return false;
84560b57cec5SDimitry Andric     }
84570b57cec5SDimitry Andric 
84580b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
84590b57cec5SDimitry Andric   } else if (Option == "novirt") {
84600b57cec5SDimitry Andric     clearModuleFeatureBits(Mips::FeatureVirt, "virt");
84610b57cec5SDimitry Andric 
84620b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
84630b57cec5SDimitry Andric     // updated above.
84640b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
84650b57cec5SDimitry Andric 
84660b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
84670b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84680b57cec5SDimitry Andric     // emitted later).
84690b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleNoVirt();
84700b57cec5SDimitry Andric 
84710b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
84720b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
84730b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
84740b57cec5SDimitry Andric       return false;
84750b57cec5SDimitry Andric     }
84760b57cec5SDimitry Andric 
84770b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
84780b57cec5SDimitry Andric   } else if (Option == "ginv") {
84790b57cec5SDimitry Andric     setModuleFeatureBits(Mips::FeatureGINV, "ginv");
84800b57cec5SDimitry Andric 
84810b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
84820b57cec5SDimitry Andric     // updated above.
84830b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
84840b57cec5SDimitry Andric 
84850b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
84860b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84870b57cec5SDimitry Andric     // emitted later).
84880b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleGINV();
84890b57cec5SDimitry Andric 
84900b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
84910b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
84920b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
84930b57cec5SDimitry Andric       return false;
84940b57cec5SDimitry Andric     }
84950b57cec5SDimitry Andric 
84960b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
84970b57cec5SDimitry Andric   } else if (Option == "noginv") {
84980b57cec5SDimitry Andric     clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
84990b57cec5SDimitry Andric 
85000b57cec5SDimitry Andric     // Synchronize the ABI Flags information with the FeatureBits information we
85010b57cec5SDimitry Andric     // updated above.
85020b57cec5SDimitry Andric     getTargetStreamer().updateABIInfo(*this);
85030b57cec5SDimitry Andric 
85040b57cec5SDimitry Andric     // If printing assembly, use the recently updated ABI Flags information.
85050b57cec5SDimitry Andric     // If generating ELF, don't do anything (the .MIPS.abiflags section gets
85060b57cec5SDimitry Andric     // emitted later).
85070b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveModuleNoGINV();
85080b57cec5SDimitry Andric 
85090b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
85100b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
85110b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
85120b57cec5SDimitry Andric       return false;
85130b57cec5SDimitry Andric     }
85140b57cec5SDimitry Andric 
85150b57cec5SDimitry Andric     return false; // parseDirectiveModule has finished successfully.
85160b57cec5SDimitry Andric   } else {
85170b57cec5SDimitry Andric     return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
85180b57cec5SDimitry Andric   }
85190b57cec5SDimitry Andric }
85200b57cec5SDimitry Andric 
85210b57cec5SDimitry Andric /// parseDirectiveModuleFP
85220b57cec5SDimitry Andric ///  ::= =32
85230b57cec5SDimitry Andric ///  ::= =xx
85240b57cec5SDimitry Andric ///  ::= =64
parseDirectiveModuleFP()85250b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveModuleFP() {
85260b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
85270b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
85280b57cec5SDimitry Andric 
85290b57cec5SDimitry Andric   if (Lexer.isNot(AsmToken::Equal)) {
85300b57cec5SDimitry Andric     reportParseError("unexpected token, expected equals sign '='");
85310b57cec5SDimitry Andric     return false;
85320b57cec5SDimitry Andric   }
85330b57cec5SDimitry Andric   Parser.Lex(); // Eat '=' token.
85340b57cec5SDimitry Andric 
85350b57cec5SDimitry Andric   MipsABIFlagsSection::FpABIKind FpABI;
85360b57cec5SDimitry Andric   if (!parseFpABIValue(FpABI, ".module"))
85370b57cec5SDimitry Andric     return false;
85380b57cec5SDimitry Andric 
85390b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
85400b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
85410b57cec5SDimitry Andric     return false;
85420b57cec5SDimitry Andric   }
85430b57cec5SDimitry Andric 
85440b57cec5SDimitry Andric   // Synchronize the abiflags information with the FeatureBits information we
85450b57cec5SDimitry Andric   // changed above.
85460b57cec5SDimitry Andric   getTargetStreamer().updateABIInfo(*this);
85470b57cec5SDimitry Andric 
85480b57cec5SDimitry Andric   // If printing assembly, use the recently updated abiflags information.
85490b57cec5SDimitry Andric   // If generating ELF, don't do anything (the .MIPS.abiflags section gets
85500b57cec5SDimitry Andric   // emitted at the end).
85510b57cec5SDimitry Andric   getTargetStreamer().emitDirectiveModuleFP();
85520b57cec5SDimitry Andric 
85530b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
85540b57cec5SDimitry Andric   return false;
85550b57cec5SDimitry Andric }
85560b57cec5SDimitry Andric 
parseFpABIValue(MipsABIFlagsSection::FpABIKind & FpABI,StringRef Directive)85570b57cec5SDimitry Andric bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
85580b57cec5SDimitry Andric                                     StringRef Directive) {
85590b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
85600b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
85610b57cec5SDimitry Andric   bool ModuleLevelOptions = Directive == ".module";
85620b57cec5SDimitry Andric 
85630b57cec5SDimitry Andric   if (Lexer.is(AsmToken::Identifier)) {
85640b57cec5SDimitry Andric     StringRef Value = Parser.getTok().getString();
85650b57cec5SDimitry Andric     Parser.Lex();
85660b57cec5SDimitry Andric 
85670b57cec5SDimitry Andric     if (Value != "xx") {
85680b57cec5SDimitry Andric       reportParseError("unsupported value, expected 'xx', '32' or '64'");
85690b57cec5SDimitry Andric       return false;
85700b57cec5SDimitry Andric     }
85710b57cec5SDimitry Andric 
85720b57cec5SDimitry Andric     if (!isABI_O32()) {
85730b57cec5SDimitry Andric       reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
85740b57cec5SDimitry Andric       return false;
85750b57cec5SDimitry Andric     }
85760b57cec5SDimitry Andric 
85770b57cec5SDimitry Andric     FpABI = MipsABIFlagsSection::FpABIKind::XX;
85780b57cec5SDimitry Andric     if (ModuleLevelOptions) {
85790b57cec5SDimitry Andric       setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
85800b57cec5SDimitry Andric       clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
85810b57cec5SDimitry Andric     } else {
85820b57cec5SDimitry Andric       setFeatureBits(Mips::FeatureFPXX, "fpxx");
85830b57cec5SDimitry Andric       clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
85840b57cec5SDimitry Andric     }
85850b57cec5SDimitry Andric     return true;
85860b57cec5SDimitry Andric   }
85870b57cec5SDimitry Andric 
85880b57cec5SDimitry Andric   if (Lexer.is(AsmToken::Integer)) {
85890b57cec5SDimitry Andric     unsigned Value = Parser.getTok().getIntVal();
85900b57cec5SDimitry Andric     Parser.Lex();
85910b57cec5SDimitry Andric 
85920b57cec5SDimitry Andric     if (Value != 32 && Value != 64) {
85930b57cec5SDimitry Andric       reportParseError("unsupported value, expected 'xx', '32' or '64'");
85940b57cec5SDimitry Andric       return false;
85950b57cec5SDimitry Andric     }
85960b57cec5SDimitry Andric 
85970b57cec5SDimitry Andric     if (Value == 32) {
85980b57cec5SDimitry Andric       if (!isABI_O32()) {
85990b57cec5SDimitry Andric         reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
86000b57cec5SDimitry Andric         return false;
86010b57cec5SDimitry Andric       }
86020b57cec5SDimitry Andric 
86030b57cec5SDimitry Andric       FpABI = MipsABIFlagsSection::FpABIKind::S32;
86040b57cec5SDimitry Andric       if (ModuleLevelOptions) {
86050b57cec5SDimitry Andric         clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
86060b57cec5SDimitry Andric         clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
86070b57cec5SDimitry Andric       } else {
86080b57cec5SDimitry Andric         clearFeatureBits(Mips::FeatureFPXX, "fpxx");
86090b57cec5SDimitry Andric         clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
86100b57cec5SDimitry Andric       }
86110b57cec5SDimitry Andric     } else {
86120b57cec5SDimitry Andric       FpABI = MipsABIFlagsSection::FpABIKind::S64;
86130b57cec5SDimitry Andric       if (ModuleLevelOptions) {
86140b57cec5SDimitry Andric         clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
86150b57cec5SDimitry Andric         setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
86160b57cec5SDimitry Andric       } else {
86170b57cec5SDimitry Andric         clearFeatureBits(Mips::FeatureFPXX, "fpxx");
86180b57cec5SDimitry Andric         setFeatureBits(Mips::FeatureFP64Bit, "fp64");
86190b57cec5SDimitry Andric       }
86200b57cec5SDimitry Andric     }
86210b57cec5SDimitry Andric 
86220b57cec5SDimitry Andric     return true;
86230b57cec5SDimitry Andric   }
86240b57cec5SDimitry Andric 
86250b57cec5SDimitry Andric   return false;
86260b57cec5SDimitry Andric }
86270b57cec5SDimitry Andric 
ParseDirective(AsmToken DirectiveID)86280b57cec5SDimitry Andric bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
86290b57cec5SDimitry Andric   // This returns false if this function recognizes the directive
86300b57cec5SDimitry Andric   // regardless of whether it is successfully handles or reports an
86310b57cec5SDimitry Andric   // error. Otherwise it returns true to give the generic parser a
86320b57cec5SDimitry Andric   // chance at recognizing it.
86330b57cec5SDimitry Andric 
86340b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
86350b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getString();
86360b57cec5SDimitry Andric 
86375ffd83dbSDimitry Andric   if (IDVal == ".cpadd") {
86385ffd83dbSDimitry Andric     parseDirectiveCpAdd(DirectiveID.getLoc());
86395ffd83dbSDimitry Andric     return false;
86405ffd83dbSDimitry Andric   }
86410b57cec5SDimitry Andric   if (IDVal == ".cpload") {
86420b57cec5SDimitry Andric     parseDirectiveCpLoad(DirectiveID.getLoc());
86430b57cec5SDimitry Andric     return false;
86440b57cec5SDimitry Andric   }
86450b57cec5SDimitry Andric   if (IDVal == ".cprestore") {
86460b57cec5SDimitry Andric     parseDirectiveCpRestore(DirectiveID.getLoc());
86470b57cec5SDimitry Andric     return false;
86480b57cec5SDimitry Andric   }
86490b57cec5SDimitry Andric   if (IDVal == ".cplocal") {
86500b57cec5SDimitry Andric     parseDirectiveCpLocal(DirectiveID.getLoc());
86510b57cec5SDimitry Andric     return false;
86520b57cec5SDimitry Andric   }
86530b57cec5SDimitry Andric   if (IDVal == ".ent") {
86540b57cec5SDimitry Andric     StringRef SymbolName;
86550b57cec5SDimitry Andric 
86560b57cec5SDimitry Andric     if (Parser.parseIdentifier(SymbolName)) {
86570b57cec5SDimitry Andric       reportParseError("expected identifier after .ent");
86580b57cec5SDimitry Andric       return false;
86590b57cec5SDimitry Andric     }
86600b57cec5SDimitry Andric 
86610b57cec5SDimitry Andric     // There's an undocumented extension that allows an integer to
86620b57cec5SDimitry Andric     // follow the name of the procedure which AFAICS is ignored by GAS.
86630b57cec5SDimitry Andric     // Example: .ent foo,2
86640b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
86650b57cec5SDimitry Andric       if (getLexer().isNot(AsmToken::Comma)) {
86660b57cec5SDimitry Andric         // Even though we accept this undocumented extension for compatibility
86670b57cec5SDimitry Andric         // reasons, the additional integer argument does not actually change
86680b57cec5SDimitry Andric         // the behaviour of the '.ent' directive, so we would like to discourage
86690b57cec5SDimitry Andric         // its use. We do this by not referring to the extended version in
86700b57cec5SDimitry Andric         // error messages which are not directly related to its use.
86710b57cec5SDimitry Andric         reportParseError("unexpected token, expected end of statement");
86720b57cec5SDimitry Andric         return false;
86730b57cec5SDimitry Andric       }
86740b57cec5SDimitry Andric       Parser.Lex(); // Eat the comma.
86750b57cec5SDimitry Andric       const MCExpr *DummyNumber;
86760b57cec5SDimitry Andric       int64_t DummyNumberVal;
86770b57cec5SDimitry Andric       // If the user was explicitly trying to use the extended version,
86780b57cec5SDimitry Andric       // we still give helpful extension-related error messages.
86790b57cec5SDimitry Andric       if (Parser.parseExpression(DummyNumber)) {
86800b57cec5SDimitry Andric         reportParseError("expected number after comma");
86810b57cec5SDimitry Andric         return false;
86820b57cec5SDimitry Andric       }
86830b57cec5SDimitry Andric       if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
86840b57cec5SDimitry Andric         reportParseError("expected an absolute expression after comma");
86850b57cec5SDimitry Andric         return false;
86860b57cec5SDimitry Andric       }
86870b57cec5SDimitry Andric     }
86880b57cec5SDimitry Andric 
86890b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
86900b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
86910b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
86920b57cec5SDimitry Andric       return false;
86930b57cec5SDimitry Andric     }
86940b57cec5SDimitry Andric 
86950b57cec5SDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
86960b57cec5SDimitry Andric 
86970b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveEnt(*Sym);
86980b57cec5SDimitry Andric     CurrentFn = Sym;
86990b57cec5SDimitry Andric     IsCpRestoreSet = false;
87000b57cec5SDimitry Andric     return false;
87010b57cec5SDimitry Andric   }
87020b57cec5SDimitry Andric 
87030b57cec5SDimitry Andric   if (IDVal == ".end") {
87040b57cec5SDimitry Andric     StringRef SymbolName;
87050b57cec5SDimitry Andric 
87060b57cec5SDimitry Andric     if (Parser.parseIdentifier(SymbolName)) {
87070b57cec5SDimitry Andric       reportParseError("expected identifier after .end");
87080b57cec5SDimitry Andric       return false;
87090b57cec5SDimitry Andric     }
87100b57cec5SDimitry Andric 
87110b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
87120b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
87130b57cec5SDimitry Andric       return false;
87140b57cec5SDimitry Andric     }
87150b57cec5SDimitry Andric 
87160b57cec5SDimitry Andric     if (CurrentFn == nullptr) {
87170b57cec5SDimitry Andric       reportParseError(".end used without .ent");
87180b57cec5SDimitry Andric       return false;
87190b57cec5SDimitry Andric     }
87200b57cec5SDimitry Andric 
87210b57cec5SDimitry Andric     if ((SymbolName != CurrentFn->getName())) {
87220b57cec5SDimitry Andric       reportParseError(".end symbol does not match .ent symbol");
87230b57cec5SDimitry Andric       return false;
87240b57cec5SDimitry Andric     }
87250b57cec5SDimitry Andric 
87260b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveEnd(SymbolName);
87270b57cec5SDimitry Andric     CurrentFn = nullptr;
87280b57cec5SDimitry Andric     IsCpRestoreSet = false;
87290b57cec5SDimitry Andric     return false;
87300b57cec5SDimitry Andric   }
87310b57cec5SDimitry Andric 
87320b57cec5SDimitry Andric   if (IDVal == ".frame") {
87330b57cec5SDimitry Andric     // .frame $stack_reg, frame_size_in_bytes, $return_reg
87340b57cec5SDimitry Andric     SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
873506c3fb27SDimitry Andric     ParseStatus Res = parseAnyRegister(TmpReg);
873606c3fb27SDimitry Andric     if (Res.isNoMatch() || Res.isFailure()) {
87370b57cec5SDimitry Andric       reportParseError("expected stack register");
87380b57cec5SDimitry Andric       return false;
87390b57cec5SDimitry Andric     }
87400b57cec5SDimitry Andric 
87410b57cec5SDimitry Andric     MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
87420b57cec5SDimitry Andric     if (!StackRegOpnd.isGPRAsmReg()) {
87430b57cec5SDimitry Andric       reportParseError(StackRegOpnd.getStartLoc(),
87440b57cec5SDimitry Andric                        "expected general purpose register");
87450b57cec5SDimitry Andric       return false;
87460b57cec5SDimitry Andric     }
87470b57cec5SDimitry Andric     unsigned StackReg = StackRegOpnd.getGPR32Reg();
87480b57cec5SDimitry Andric 
87490b57cec5SDimitry Andric     if (Parser.getTok().is(AsmToken::Comma))
87500b57cec5SDimitry Andric       Parser.Lex();
87510b57cec5SDimitry Andric     else {
87520b57cec5SDimitry Andric       reportParseError("unexpected token, expected comma");
87530b57cec5SDimitry Andric       return false;
87540b57cec5SDimitry Andric     }
87550b57cec5SDimitry Andric 
87560b57cec5SDimitry Andric     // Parse the frame size.
87570b57cec5SDimitry Andric     const MCExpr *FrameSize;
87580b57cec5SDimitry Andric     int64_t FrameSizeVal;
87590b57cec5SDimitry Andric 
87600b57cec5SDimitry Andric     if (Parser.parseExpression(FrameSize)) {
87610b57cec5SDimitry Andric       reportParseError("expected frame size value");
87620b57cec5SDimitry Andric       return false;
87630b57cec5SDimitry Andric     }
87640b57cec5SDimitry Andric 
87650b57cec5SDimitry Andric     if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
87660b57cec5SDimitry Andric       reportParseError("frame size not an absolute expression");
87670b57cec5SDimitry Andric       return false;
87680b57cec5SDimitry Andric     }
87690b57cec5SDimitry Andric 
87700b57cec5SDimitry Andric     if (Parser.getTok().is(AsmToken::Comma))
87710b57cec5SDimitry Andric       Parser.Lex();
87720b57cec5SDimitry Andric     else {
87730b57cec5SDimitry Andric       reportParseError("unexpected token, expected comma");
87740b57cec5SDimitry Andric       return false;
87750b57cec5SDimitry Andric     }
87760b57cec5SDimitry Andric 
87770b57cec5SDimitry Andric     // Parse the return register.
87780b57cec5SDimitry Andric     TmpReg.clear();
877906c3fb27SDimitry Andric     Res = parseAnyRegister(TmpReg);
878006c3fb27SDimitry Andric     if (Res.isNoMatch() || Res.isFailure()) {
87810b57cec5SDimitry Andric       reportParseError("expected return register");
87820b57cec5SDimitry Andric       return false;
87830b57cec5SDimitry Andric     }
87840b57cec5SDimitry Andric 
87850b57cec5SDimitry Andric     MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
87860b57cec5SDimitry Andric     if (!ReturnRegOpnd.isGPRAsmReg()) {
87870b57cec5SDimitry Andric       reportParseError(ReturnRegOpnd.getStartLoc(),
87880b57cec5SDimitry Andric                        "expected general purpose register");
87890b57cec5SDimitry Andric       return false;
87900b57cec5SDimitry Andric     }
87910b57cec5SDimitry Andric 
87920b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
87930b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
87940b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
87950b57cec5SDimitry Andric       return false;
87960b57cec5SDimitry Andric     }
87970b57cec5SDimitry Andric 
87980b57cec5SDimitry Andric     getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
87990b57cec5SDimitry Andric                                   ReturnRegOpnd.getGPR32Reg());
88000b57cec5SDimitry Andric     IsCpRestoreSet = false;
88010b57cec5SDimitry Andric     return false;
88020b57cec5SDimitry Andric   }
88030b57cec5SDimitry Andric 
88040b57cec5SDimitry Andric   if (IDVal == ".set") {
88050b57cec5SDimitry Andric     parseDirectiveSet();
88060b57cec5SDimitry Andric     return false;
88070b57cec5SDimitry Andric   }
88080b57cec5SDimitry Andric 
88090b57cec5SDimitry Andric   if (IDVal == ".mask" || IDVal == ".fmask") {
88100b57cec5SDimitry Andric     // .mask bitmask, frame_offset
88110b57cec5SDimitry Andric     // bitmask: One bit for each register used.
88120b57cec5SDimitry Andric     // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
88130b57cec5SDimitry Andric     //               first register is expected to be saved.
88140b57cec5SDimitry Andric     // Examples:
88150b57cec5SDimitry Andric     //   .mask 0x80000000, -4
88160b57cec5SDimitry Andric     //   .fmask 0x80000000, -4
88170b57cec5SDimitry Andric     //
88180b57cec5SDimitry Andric 
88190b57cec5SDimitry Andric     // Parse the bitmask
88200b57cec5SDimitry Andric     const MCExpr *BitMask;
88210b57cec5SDimitry Andric     int64_t BitMaskVal;
88220b57cec5SDimitry Andric 
88230b57cec5SDimitry Andric     if (Parser.parseExpression(BitMask)) {
88240b57cec5SDimitry Andric       reportParseError("expected bitmask value");
88250b57cec5SDimitry Andric       return false;
88260b57cec5SDimitry Andric     }
88270b57cec5SDimitry Andric 
88280b57cec5SDimitry Andric     if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
88290b57cec5SDimitry Andric       reportParseError("bitmask not an absolute expression");
88300b57cec5SDimitry Andric       return false;
88310b57cec5SDimitry Andric     }
88320b57cec5SDimitry Andric 
88330b57cec5SDimitry Andric     if (Parser.getTok().is(AsmToken::Comma))
88340b57cec5SDimitry Andric       Parser.Lex();
88350b57cec5SDimitry Andric     else {
88360b57cec5SDimitry Andric       reportParseError("unexpected token, expected comma");
88370b57cec5SDimitry Andric       return false;
88380b57cec5SDimitry Andric     }
88390b57cec5SDimitry Andric 
88400b57cec5SDimitry Andric     // Parse the frame_offset
88410b57cec5SDimitry Andric     const MCExpr *FrameOffset;
88420b57cec5SDimitry Andric     int64_t FrameOffsetVal;
88430b57cec5SDimitry Andric 
88440b57cec5SDimitry Andric     if (Parser.parseExpression(FrameOffset)) {
88450b57cec5SDimitry Andric       reportParseError("expected frame offset value");
88460b57cec5SDimitry Andric       return false;
88470b57cec5SDimitry Andric     }
88480b57cec5SDimitry Andric 
88490b57cec5SDimitry Andric     if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
88500b57cec5SDimitry Andric       reportParseError("frame offset not an absolute expression");
88510b57cec5SDimitry Andric       return false;
88520b57cec5SDimitry Andric     }
88530b57cec5SDimitry Andric 
88540b57cec5SDimitry Andric     // If this is not the end of the statement, report an error.
88550b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
88560b57cec5SDimitry Andric       reportParseError("unexpected token, expected end of statement");
88570b57cec5SDimitry Andric       return false;
88580b57cec5SDimitry Andric     }
88590b57cec5SDimitry Andric 
88600b57cec5SDimitry Andric     if (IDVal == ".mask")
88610b57cec5SDimitry Andric       getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
88620b57cec5SDimitry Andric     else
88630b57cec5SDimitry Andric       getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
88640b57cec5SDimitry Andric     return false;
88650b57cec5SDimitry Andric   }
88660b57cec5SDimitry Andric 
88670b57cec5SDimitry Andric   if (IDVal == ".nan")
88680b57cec5SDimitry Andric     return parseDirectiveNaN();
88690b57cec5SDimitry Andric 
88700b57cec5SDimitry Andric   if (IDVal == ".gpword") {
88710b57cec5SDimitry Andric     parseDirectiveGpWord();
88720b57cec5SDimitry Andric     return false;
88730b57cec5SDimitry Andric   }
88740b57cec5SDimitry Andric 
88750b57cec5SDimitry Andric   if (IDVal == ".gpdword") {
88760b57cec5SDimitry Andric     parseDirectiveGpDWord();
88770b57cec5SDimitry Andric     return false;
88780b57cec5SDimitry Andric   }
88790b57cec5SDimitry Andric 
88800b57cec5SDimitry Andric   if (IDVal == ".dtprelword") {
88810b57cec5SDimitry Andric     parseDirectiveDtpRelWord();
88820b57cec5SDimitry Andric     return false;
88830b57cec5SDimitry Andric   }
88840b57cec5SDimitry Andric 
88850b57cec5SDimitry Andric   if (IDVal == ".dtpreldword") {
88860b57cec5SDimitry Andric     parseDirectiveDtpRelDWord();
88870b57cec5SDimitry Andric     return false;
88880b57cec5SDimitry Andric   }
88890b57cec5SDimitry Andric 
88900b57cec5SDimitry Andric   if (IDVal == ".tprelword") {
88910b57cec5SDimitry Andric     parseDirectiveTpRelWord();
88920b57cec5SDimitry Andric     return false;
88930b57cec5SDimitry Andric   }
88940b57cec5SDimitry Andric 
88950b57cec5SDimitry Andric   if (IDVal == ".tpreldword") {
88960b57cec5SDimitry Andric     parseDirectiveTpRelDWord();
88970b57cec5SDimitry Andric     return false;
88980b57cec5SDimitry Andric   }
88990b57cec5SDimitry Andric 
89000b57cec5SDimitry Andric   if (IDVal == ".option") {
89010b57cec5SDimitry Andric     parseDirectiveOption();
89020b57cec5SDimitry Andric     return false;
89030b57cec5SDimitry Andric   }
89040b57cec5SDimitry Andric 
89050b57cec5SDimitry Andric   if (IDVal == ".abicalls") {
89060b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveAbiCalls();
89070b57cec5SDimitry Andric     if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
89080b57cec5SDimitry Andric       Error(Parser.getTok().getLoc(),
89090b57cec5SDimitry Andric             "unexpected token, expected end of statement");
89100b57cec5SDimitry Andric     }
89110b57cec5SDimitry Andric     return false;
89120b57cec5SDimitry Andric   }
89130b57cec5SDimitry Andric 
89140b57cec5SDimitry Andric   if (IDVal == ".cpsetup") {
89150b57cec5SDimitry Andric     parseDirectiveCPSetup();
89160b57cec5SDimitry Andric     return false;
89170b57cec5SDimitry Andric   }
89180b57cec5SDimitry Andric   if (IDVal == ".cpreturn") {
89190b57cec5SDimitry Andric     parseDirectiveCPReturn();
89200b57cec5SDimitry Andric     return false;
89210b57cec5SDimitry Andric   }
89220b57cec5SDimitry Andric   if (IDVal == ".module") {
89230b57cec5SDimitry Andric     parseDirectiveModule();
89240b57cec5SDimitry Andric     return false;
89250b57cec5SDimitry Andric   }
89260b57cec5SDimitry Andric   if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
89270b57cec5SDimitry Andric     parseInternalDirectiveReallowModule();
89280b57cec5SDimitry Andric     return false;
89290b57cec5SDimitry Andric   }
89300b57cec5SDimitry Andric   if (IDVal == ".insn") {
89310b57cec5SDimitry Andric     parseInsnDirective();
89320b57cec5SDimitry Andric     return false;
89330b57cec5SDimitry Andric   }
89340b57cec5SDimitry Andric   if (IDVal == ".rdata") {
89350b57cec5SDimitry Andric     parseRSectionDirective(".rodata");
89360b57cec5SDimitry Andric     return false;
89370b57cec5SDimitry Andric   }
89380b57cec5SDimitry Andric   if (IDVal == ".sbss") {
89390b57cec5SDimitry Andric     parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
89400b57cec5SDimitry Andric     return false;
89410b57cec5SDimitry Andric   }
89420b57cec5SDimitry Andric   if (IDVal == ".sdata") {
89430b57cec5SDimitry Andric     parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
89440b57cec5SDimitry Andric     return false;
89450b57cec5SDimitry Andric   }
89460b57cec5SDimitry Andric 
89470b57cec5SDimitry Andric   return true;
89480b57cec5SDimitry Andric }
89490b57cec5SDimitry Andric 
parseInternalDirectiveReallowModule()89500b57cec5SDimitry Andric bool MipsAsmParser::parseInternalDirectiveReallowModule() {
89510b57cec5SDimitry Andric   // If this is not the end of the statement, report an error.
89520b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
89530b57cec5SDimitry Andric     reportParseError("unexpected token, expected end of statement");
89540b57cec5SDimitry Andric     return false;
89550b57cec5SDimitry Andric   }
89560b57cec5SDimitry Andric 
89570b57cec5SDimitry Andric   getTargetStreamer().reallowModuleDirective();
89580b57cec5SDimitry Andric 
89590b57cec5SDimitry Andric   getParser().Lex(); // Eat EndOfStatement token.
89600b57cec5SDimitry Andric   return false;
89610b57cec5SDimitry Andric }
89620b57cec5SDimitry Andric 
LLVMInitializeMipsAsmParser()8963480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsAsmParser() {
89640b57cec5SDimitry Andric   RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
89650b57cec5SDimitry Andric   RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
89660b57cec5SDimitry Andric   RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
89670b57cec5SDimitry Andric   RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
89680b57cec5SDimitry Andric }
89690b57cec5SDimitry Andric 
89700b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
89710b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
89720b57cec5SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
89730b57cec5SDimitry Andric #include "MipsGenAsmMatcher.inc"
89740b57cec5SDimitry Andric 
mnemonicIsValid(StringRef Mnemonic,unsigned VariantID)89750b57cec5SDimitry Andric bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
89760b57cec5SDimitry Andric   // Find the appropriate table for this asm variant.
89770b57cec5SDimitry Andric   const MatchEntry *Start, *End;
89780b57cec5SDimitry Andric   switch (VariantID) {
89790b57cec5SDimitry Andric   default: llvm_unreachable("invalid variant!");
89800b57cec5SDimitry Andric   case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
89810b57cec5SDimitry Andric   }
89820b57cec5SDimitry Andric   // Search the table.
89830b57cec5SDimitry Andric   auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
89840b57cec5SDimitry Andric   return MnemonicRange.first != MnemonicRange.second;
89850b57cec5SDimitry Andric }
8986