1f4a2713aSLionel Sambuc //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #include "MCTargetDesc/MipsMCExpr.h"
11f4a2713aSLionel Sambuc #include "MCTargetDesc/MipsMCTargetDesc.h"
12f4a2713aSLionel Sambuc #include "MipsRegisterInfo.h"
13f4a2713aSLionel Sambuc #include "MipsTargetStreamer.h"
14*0a6a1f1dSLionel Sambuc #include "llvm/ADT/APInt.h"
15*0a6a1f1dSLionel Sambuc #include "llvm/ADT/SmallVector.h"
16f4a2713aSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
17f4a2713aSLionel Sambuc #include "llvm/MC/MCContext.h"
18f4a2713aSLionel Sambuc #include "llvm/MC/MCExpr.h"
19f4a2713aSLionel Sambuc #include "llvm/MC/MCInst.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/MC/MCInstBuilder.h"
21f4a2713aSLionel Sambuc #include "llvm/MC/MCParser/MCAsmLexer.h"
22f4a2713aSLionel Sambuc #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23f4a2713aSLionel Sambuc #include "llvm/MC/MCStreamer.h"
24f4a2713aSLionel Sambuc #include "llvm/MC/MCSubtargetInfo.h"
25f4a2713aSLionel Sambuc #include "llvm/MC/MCSymbol.h"
26f4a2713aSLionel Sambuc #include "llvm/MC/MCTargetAsmParser.h"
27*0a6a1f1dSLionel Sambuc #include "llvm/Support/Debug.h"
28*0a6a1f1dSLionel Sambuc #include "llvm/Support/MathExtras.h"
29*0a6a1f1dSLionel Sambuc #include "llvm/Support/SourceMgr.h"
30f4a2713aSLionel Sambuc #include "llvm/Support/TargetRegistry.h"
31*0a6a1f1dSLionel Sambuc #include <memory>
32f4a2713aSLionel Sambuc 
33f4a2713aSLionel Sambuc using namespace llvm;
34f4a2713aSLionel Sambuc 
35*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "mips-asm-parser"
36*0a6a1f1dSLionel Sambuc 
37f4a2713aSLionel Sambuc namespace llvm {
38f4a2713aSLionel Sambuc class MCInstrInfo;
39f4a2713aSLionel Sambuc }
40f4a2713aSLionel Sambuc 
41f4a2713aSLionel Sambuc namespace {
42f4a2713aSLionel Sambuc class MipsAssemblerOptions {
43f4a2713aSLionel Sambuc public:
MipsAssemblerOptions(uint64_t Features_)44*0a6a1f1dSLionel Sambuc   MipsAssemblerOptions(uint64_t Features_) :
45*0a6a1f1dSLionel Sambuc     ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
46f4a2713aSLionel Sambuc 
MipsAssemblerOptions(const MipsAssemblerOptions * Opts)47*0a6a1f1dSLionel Sambuc   MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48*0a6a1f1dSLionel Sambuc     ATReg = Opts->getATRegNum();
49*0a6a1f1dSLionel Sambuc     Reorder = Opts->isReorder();
50*0a6a1f1dSLionel Sambuc     Macro = Opts->isMacro();
51*0a6a1f1dSLionel Sambuc     Features = Opts->getFeatures();
52*0a6a1f1dSLionel Sambuc   }
53*0a6a1f1dSLionel Sambuc 
getATRegNum() const54*0a6a1f1dSLionel Sambuc   unsigned getATRegNum() const { return ATReg; }
55f4a2713aSLionel Sambuc   bool setATReg(unsigned Reg);
56f4a2713aSLionel Sambuc 
isReorder() const57*0a6a1f1dSLionel Sambuc   bool isReorder() const { return Reorder; }
setReorder()58*0a6a1f1dSLionel Sambuc   void setReorder() { Reorder = true; }
setNoReorder()59*0a6a1f1dSLionel Sambuc   void setNoReorder() { Reorder = false; }
60f4a2713aSLionel Sambuc 
isMacro() const61*0a6a1f1dSLionel Sambuc   bool isMacro() const { return Macro; }
setMacro()62*0a6a1f1dSLionel Sambuc   void setMacro() { Macro = true; }
setNoMacro()63*0a6a1f1dSLionel Sambuc   void setNoMacro() { Macro = false; }
64*0a6a1f1dSLionel Sambuc 
getFeatures() const65*0a6a1f1dSLionel Sambuc   uint64_t getFeatures() const { return Features; }
setFeatures(uint64_t Features_)66*0a6a1f1dSLionel Sambuc   void setFeatures(uint64_t Features_) { Features = Features_; }
67*0a6a1f1dSLionel Sambuc 
68*0a6a1f1dSLionel Sambuc   // Set of features that are either architecture features or referenced
69*0a6a1f1dSLionel Sambuc   // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70*0a6a1f1dSLionel Sambuc   // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71*0a6a1f1dSLionel Sambuc   // The reason we need this mask is explained in the selectArch function.
72*0a6a1f1dSLionel Sambuc   // FIXME: Ideally we would like TableGen to generate this information.
73*0a6a1f1dSLionel Sambuc   static const uint64_t AllArchRelatedMask =
74*0a6a1f1dSLionel Sambuc       Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75*0a6a1f1dSLionel Sambuc       Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76*0a6a1f1dSLionel Sambuc       Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77*0a6a1f1dSLionel Sambuc       Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78*0a6a1f1dSLionel Sambuc       Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79*0a6a1f1dSLionel Sambuc       Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80*0a6a1f1dSLionel Sambuc       Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81f4a2713aSLionel Sambuc 
82f4a2713aSLionel Sambuc private:
83*0a6a1f1dSLionel Sambuc   unsigned ATReg;
84*0a6a1f1dSLionel Sambuc   bool Reorder;
85*0a6a1f1dSLionel Sambuc   bool Macro;
86*0a6a1f1dSLionel Sambuc   uint64_t Features;
87f4a2713aSLionel Sambuc };
88f4a2713aSLionel Sambuc }
89f4a2713aSLionel Sambuc 
90f4a2713aSLionel Sambuc namespace {
91f4a2713aSLionel Sambuc class MipsAsmParser : public MCTargetAsmParser {
getTargetStreamer()92f4a2713aSLionel Sambuc   MipsTargetStreamer &getTargetStreamer() {
93*0a6a1f1dSLionel Sambuc     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
94f4a2713aSLionel Sambuc     return static_cast<MipsTargetStreamer &>(TS);
95f4a2713aSLionel Sambuc   }
96f4a2713aSLionel Sambuc 
97f4a2713aSLionel Sambuc   MCSubtargetInfo &STI;
98*0a6a1f1dSLionel Sambuc   SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
99*0a6a1f1dSLionel Sambuc   MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100*0a6a1f1dSLionel Sambuc                        // nullptr, which indicates that no function is currently
101*0a6a1f1dSLionel Sambuc                        // selected. This usually happens after an '.end func'
102*0a6a1f1dSLionel Sambuc                        // directive.
103*0a6a1f1dSLionel Sambuc 
104*0a6a1f1dSLionel Sambuc   // Print a warning along with its fix-it message at the given range.
105*0a6a1f1dSLionel Sambuc   void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
106*0a6a1f1dSLionel Sambuc                              SMRange Range, bool ShowColors = true);
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc #define GET_ASSEMBLER_HEADER
109f4a2713aSLionel Sambuc #include "MipsGenAsmMatcher.inc"
110f4a2713aSLionel Sambuc 
111*0a6a1f1dSLionel Sambuc   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
112f4a2713aSLionel Sambuc 
113*0a6a1f1dSLionel Sambuc   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
114*0a6a1f1dSLionel Sambuc                                OperandVector &Operands, MCStreamer &Out,
115*0a6a1f1dSLionel Sambuc                                uint64_t &ErrorInfo,
116*0a6a1f1dSLionel Sambuc                                bool MatchingInlineAsm) override;
117*0a6a1f1dSLionel Sambuc 
118*0a6a1f1dSLionel Sambuc   /// Parse a register as used in CFI directives
119*0a6a1f1dSLionel Sambuc   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
120*0a6a1f1dSLionel Sambuc 
121*0a6a1f1dSLionel Sambuc   bool parseParenSuffix(StringRef Name, OperandVector &Operands);
122*0a6a1f1dSLionel Sambuc 
123*0a6a1f1dSLionel Sambuc   bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
124f4a2713aSLionel Sambuc 
125f4a2713aSLionel Sambuc   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
126*0a6a1f1dSLionel Sambuc                         SMLoc NameLoc, OperandVector &Operands) override;
127f4a2713aSLionel Sambuc 
128*0a6a1f1dSLionel Sambuc   bool ParseDirective(AsmToken DirectiveID) override;
129*0a6a1f1dSLionel Sambuc 
130*0a6a1f1dSLionel Sambuc   MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
131f4a2713aSLionel Sambuc 
132f4a2713aSLionel Sambuc   MipsAsmParser::OperandMatchResultTy
133*0a6a1f1dSLionel Sambuc   matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
134*0a6a1f1dSLionel Sambuc                                     StringRef Identifier, SMLoc S);
135f4a2713aSLionel Sambuc 
136f4a2713aSLionel Sambuc   MipsAsmParser::OperandMatchResultTy
137*0a6a1f1dSLionel Sambuc   matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
138*0a6a1f1dSLionel Sambuc 
139*0a6a1f1dSLionel Sambuc   MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
140*0a6a1f1dSLionel Sambuc 
141*0a6a1f1dSLionel Sambuc   MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
142*0a6a1f1dSLionel Sambuc 
143*0a6a1f1dSLionel Sambuc   MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
144*0a6a1f1dSLionel Sambuc 
145*0a6a1f1dSLionel Sambuc   MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
146*0a6a1f1dSLionel Sambuc 
147*0a6a1f1dSLionel Sambuc   MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
148f4a2713aSLionel Sambuc 
149f4a2713aSLionel Sambuc   MipsAsmParser::OperandMatchResultTy
150*0a6a1f1dSLionel Sambuc   parseRegisterPair (OperandVector &Operands);
151f4a2713aSLionel Sambuc 
152f4a2713aSLionel Sambuc   MipsAsmParser::OperandMatchResultTy
153*0a6a1f1dSLionel Sambuc   parseRegisterList (OperandVector  &Operands);
154f4a2713aSLionel Sambuc 
155*0a6a1f1dSLionel Sambuc   bool searchSymbolAlias(OperandVector &Operands);
156f4a2713aSLionel Sambuc 
157*0a6a1f1dSLionel Sambuc   bool parseOperand(OperandVector &, StringRef Mnemonic);
158f4a2713aSLionel Sambuc 
159f4a2713aSLionel Sambuc   bool needsExpansion(MCInst &Inst);
160f4a2713aSLionel Sambuc 
161*0a6a1f1dSLionel Sambuc   // Expands assembly pseudo instructions.
162*0a6a1f1dSLionel Sambuc   // Returns false on success, true otherwise.
163*0a6a1f1dSLionel Sambuc   bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
164f4a2713aSLionel Sambuc                          SmallVectorImpl<MCInst> &Instructions);
165*0a6a1f1dSLionel Sambuc 
166*0a6a1f1dSLionel Sambuc   bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
167f4a2713aSLionel Sambuc                      SmallVectorImpl<MCInst> &Instructions);
168*0a6a1f1dSLionel Sambuc 
169*0a6a1f1dSLionel Sambuc   bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
170f4a2713aSLionel Sambuc                             SmallVectorImpl<MCInst> &Instructions);
171*0a6a1f1dSLionel Sambuc 
172*0a6a1f1dSLionel Sambuc   bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
173f4a2713aSLionel Sambuc                             SmallVectorImpl<MCInst> &Instructions);
174*0a6a1f1dSLionel Sambuc 
175*0a6a1f1dSLionel Sambuc   void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
176*0a6a1f1dSLionel Sambuc                             SmallVectorImpl<MCInst> &Instructions);
177*0a6a1f1dSLionel Sambuc 
178f4a2713aSLionel Sambuc   void expandMemInst(MCInst &Inst, SMLoc IDLoc,
179f4a2713aSLionel Sambuc                      SmallVectorImpl<MCInst> &Instructions, bool isLoad,
180f4a2713aSLionel Sambuc                      bool isImmOpnd);
181*0a6a1f1dSLionel Sambuc   bool reportParseError(Twine ErrorMsg);
182*0a6a1f1dSLionel Sambuc   bool reportParseError(SMLoc Loc, Twine ErrorMsg);
183f4a2713aSLionel Sambuc 
184f4a2713aSLionel Sambuc   bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
185f4a2713aSLionel Sambuc   bool parseRelocOperand(const MCExpr *&Res);
186f4a2713aSLionel Sambuc 
187f4a2713aSLionel Sambuc   const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
188f4a2713aSLionel Sambuc 
189f4a2713aSLionel Sambuc   bool isEvaluated(const MCExpr *Expr);
190*0a6a1f1dSLionel Sambuc   bool parseSetMips0Directive();
191*0a6a1f1dSLionel Sambuc   bool parseSetArchDirective();
192*0a6a1f1dSLionel Sambuc   bool parseSetFeature(uint64_t Feature);
193*0a6a1f1dSLionel Sambuc   bool parseDirectiveCpLoad(SMLoc Loc);
194*0a6a1f1dSLionel Sambuc   bool parseDirectiveCPSetup();
195*0a6a1f1dSLionel Sambuc   bool parseDirectiveNaN();
196f4a2713aSLionel Sambuc   bool parseDirectiveSet();
197*0a6a1f1dSLionel Sambuc   bool parseDirectiveOption();
198f4a2713aSLionel Sambuc 
199f4a2713aSLionel Sambuc   bool parseSetAtDirective();
200f4a2713aSLionel Sambuc   bool parseSetNoAtDirective();
201f4a2713aSLionel Sambuc   bool parseSetMacroDirective();
202f4a2713aSLionel Sambuc   bool parseSetNoMacroDirective();
203*0a6a1f1dSLionel Sambuc   bool parseSetMsaDirective();
204*0a6a1f1dSLionel Sambuc   bool parseSetNoMsaDirective();
205*0a6a1f1dSLionel Sambuc   bool parseSetNoDspDirective();
206f4a2713aSLionel Sambuc   bool parseSetReorderDirective();
207f4a2713aSLionel Sambuc   bool parseSetNoReorderDirective();
208*0a6a1f1dSLionel Sambuc   bool parseSetMips16Directive();
209*0a6a1f1dSLionel Sambuc   bool parseSetNoMips16Directive();
210*0a6a1f1dSLionel Sambuc   bool parseSetFpDirective();
211*0a6a1f1dSLionel Sambuc   bool parseSetPopDirective();
212*0a6a1f1dSLionel Sambuc   bool parseSetPushDirective();
213f4a2713aSLionel Sambuc 
214f4a2713aSLionel Sambuc   bool parseSetAssignment();
215f4a2713aSLionel Sambuc 
216*0a6a1f1dSLionel Sambuc   bool parseDataDirective(unsigned Size, SMLoc L);
217f4a2713aSLionel Sambuc   bool parseDirectiveGpWord();
218*0a6a1f1dSLionel Sambuc   bool parseDirectiveGpDWord();
219*0a6a1f1dSLionel Sambuc   bool parseDirectiveModule();
220*0a6a1f1dSLionel Sambuc   bool parseDirectiveModuleFP();
221*0a6a1f1dSLionel Sambuc   bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
222*0a6a1f1dSLionel Sambuc                        StringRef Directive);
223f4a2713aSLionel Sambuc 
224f4a2713aSLionel Sambuc   MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
225f4a2713aSLionel Sambuc 
226*0a6a1f1dSLionel Sambuc   bool eatComma(StringRef ErrorStr);
227f4a2713aSLionel Sambuc 
228f4a2713aSLionel Sambuc   int matchCPURegisterName(StringRef Symbol);
229f4a2713aSLionel Sambuc 
230*0a6a1f1dSLionel Sambuc   int matchHWRegsRegisterName(StringRef Symbol);
231*0a6a1f1dSLionel Sambuc 
232f4a2713aSLionel Sambuc   int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
233f4a2713aSLionel Sambuc 
234f4a2713aSLionel Sambuc   int matchFPURegisterName(StringRef Name);
235f4a2713aSLionel Sambuc 
236f4a2713aSLionel Sambuc   int matchFCCRegisterName(StringRef Name);
237f4a2713aSLionel Sambuc 
238f4a2713aSLionel Sambuc   int matchACRegisterName(StringRef Name);
239f4a2713aSLionel Sambuc 
240f4a2713aSLionel Sambuc   int matchMSA128RegisterName(StringRef Name);
241f4a2713aSLionel Sambuc 
242f4a2713aSLionel Sambuc   int matchMSA128CtrlRegisterName(StringRef Name);
243f4a2713aSLionel Sambuc 
244f4a2713aSLionel Sambuc   unsigned getReg(int RC, int RegNo);
245f4a2713aSLionel Sambuc 
246*0a6a1f1dSLionel Sambuc   unsigned getGPR(int RegNo);
247*0a6a1f1dSLionel Sambuc 
248*0a6a1f1dSLionel Sambuc   int getATReg(SMLoc Loc);
249f4a2713aSLionel Sambuc 
250f4a2713aSLionel Sambuc   bool processInstruction(MCInst &Inst, SMLoc IDLoc,
251f4a2713aSLionel Sambuc                           SmallVectorImpl<MCInst> &Instructions);
252f4a2713aSLionel Sambuc 
253f4a2713aSLionel Sambuc   // Helper function that checks if the value of a vector index is within the
254f4a2713aSLionel Sambuc   // boundaries of accepted values for each RegisterKind
255f4a2713aSLionel Sambuc   // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
256f4a2713aSLionel Sambuc   bool validateMSAIndex(int Val, int RegKind);
257f4a2713aSLionel Sambuc 
258*0a6a1f1dSLionel Sambuc   // Selects a new architecture by updating the FeatureBits with the necessary
259*0a6a1f1dSLionel Sambuc   // info including implied dependencies.
260*0a6a1f1dSLionel Sambuc   // Internally, it clears all the feature bits related to *any* architecture
261*0a6a1f1dSLionel Sambuc   // and selects the new one using the ToggleFeature functionality of the
262*0a6a1f1dSLionel Sambuc   // MCSubtargetInfo object that handles implied dependencies. The reason we
263*0a6a1f1dSLionel Sambuc   // clear all the arch related bits manually is because ToggleFeature only
264*0a6a1f1dSLionel Sambuc   // clears the features that imply the feature being cleared and not the
265*0a6a1f1dSLionel Sambuc   // features implied by the feature being cleared. This is easier to see
266*0a6a1f1dSLionel Sambuc   // with an example:
267*0a6a1f1dSLionel Sambuc   //  --------------------------------------------------
268*0a6a1f1dSLionel Sambuc   // | Feature         | Implies                        |
269*0a6a1f1dSLionel Sambuc   // | -------------------------------------------------|
270*0a6a1f1dSLionel Sambuc   // | FeatureMips1    | None                           |
271*0a6a1f1dSLionel Sambuc   // | FeatureMips2    | FeatureMips1                   |
272*0a6a1f1dSLionel Sambuc   // | FeatureMips3    | FeatureMips2 | FeatureMipsGP64 |
273*0a6a1f1dSLionel Sambuc   // | FeatureMips4    | FeatureMips3                   |
274*0a6a1f1dSLionel Sambuc   // | ...             |                                |
275*0a6a1f1dSLionel Sambuc   //  --------------------------------------------------
276*0a6a1f1dSLionel Sambuc   //
277*0a6a1f1dSLionel Sambuc   // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
278*0a6a1f1dSLionel Sambuc   // FeatureMipsGP64 | FeatureMips1)
279*0a6a1f1dSLionel Sambuc   // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
selectArch(StringRef ArchFeature)280*0a6a1f1dSLionel Sambuc   void selectArch(StringRef ArchFeature) {
281*0a6a1f1dSLionel Sambuc     uint64_t FeatureBits = STI.getFeatureBits();
282*0a6a1f1dSLionel Sambuc     FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
283*0a6a1f1dSLionel Sambuc     STI.setFeatureBits(FeatureBits);
284*0a6a1f1dSLionel Sambuc     setAvailableFeatures(
285*0a6a1f1dSLionel Sambuc         ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
286*0a6a1f1dSLionel Sambuc     AssemblerOptions.back()->setFeatures(getAvailableFeatures());
287f4a2713aSLionel Sambuc   }
288f4a2713aSLionel Sambuc 
setFeatureBits(uint64_t Feature,StringRef FeatureString)289*0a6a1f1dSLionel Sambuc   void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
290*0a6a1f1dSLionel Sambuc     if (!(STI.getFeatureBits() & Feature)) {
291*0a6a1f1dSLionel Sambuc       setAvailableFeatures(
292*0a6a1f1dSLionel Sambuc           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
293*0a6a1f1dSLionel Sambuc     }
294*0a6a1f1dSLionel Sambuc     AssemblerOptions.back()->setFeatures(getAvailableFeatures());
295*0a6a1f1dSLionel Sambuc   }
296*0a6a1f1dSLionel Sambuc 
clearFeatureBits(uint64_t Feature,StringRef FeatureString)297*0a6a1f1dSLionel Sambuc   void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
298*0a6a1f1dSLionel Sambuc     if (STI.getFeatureBits() & Feature) {
299*0a6a1f1dSLionel Sambuc       setAvailableFeatures(
300*0a6a1f1dSLionel Sambuc           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
301*0a6a1f1dSLionel Sambuc     }
302*0a6a1f1dSLionel Sambuc     AssemblerOptions.back()->setFeatures(getAvailableFeatures());
303*0a6a1f1dSLionel Sambuc   }
304*0a6a1f1dSLionel Sambuc 
305*0a6a1f1dSLionel Sambuc public:
306*0a6a1f1dSLionel Sambuc   enum MipsMatchResultTy {
307*0a6a1f1dSLionel Sambuc     Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
308*0a6a1f1dSLionel Sambuc #define GET_OPERAND_DIAGNOSTIC_TYPES
309*0a6a1f1dSLionel Sambuc #include "MipsGenAsmMatcher.inc"
310*0a6a1f1dSLionel Sambuc #undef GET_OPERAND_DIAGNOSTIC_TYPES
311*0a6a1f1dSLionel Sambuc 
312*0a6a1f1dSLionel Sambuc   };
313*0a6a1f1dSLionel Sambuc 
MipsAsmParser(MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)314*0a6a1f1dSLionel Sambuc   MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
315*0a6a1f1dSLionel Sambuc                 const MCInstrInfo &MII, const MCTargetOptions &Options)
316*0a6a1f1dSLionel Sambuc       : MCTargetAsmParser(), STI(sti) {
317*0a6a1f1dSLionel Sambuc     MCAsmParserExtension::Initialize(parser);
318*0a6a1f1dSLionel Sambuc 
319*0a6a1f1dSLionel Sambuc     // Initialize the set of available features.
320*0a6a1f1dSLionel Sambuc     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
321*0a6a1f1dSLionel Sambuc 
322*0a6a1f1dSLionel Sambuc     // Remember the initial assembler options. The user can not modify these.
323*0a6a1f1dSLionel Sambuc     AssemblerOptions.push_back(
324*0a6a1f1dSLionel Sambuc                      make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
325*0a6a1f1dSLionel Sambuc 
326*0a6a1f1dSLionel Sambuc     // Create an assembler options environment for the user to modify.
327*0a6a1f1dSLionel Sambuc     AssemblerOptions.push_back(
328*0a6a1f1dSLionel Sambuc                      make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
329*0a6a1f1dSLionel Sambuc 
330*0a6a1f1dSLionel Sambuc     getTargetStreamer().updateABIInfo(*this);
331*0a6a1f1dSLionel Sambuc 
332*0a6a1f1dSLionel Sambuc     // Assert exactly one ABI was chosen.
333*0a6a1f1dSLionel Sambuc     assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
334*0a6a1f1dSLionel Sambuc             ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
335*0a6a1f1dSLionel Sambuc             ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
336*0a6a1f1dSLionel Sambuc             ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
337*0a6a1f1dSLionel Sambuc 
338*0a6a1f1dSLionel Sambuc     if (!isABI_O32() && !useOddSPReg() != 0)
339*0a6a1f1dSLionel Sambuc       report_fatal_error("-mno-odd-spreg requires the O32 ABI");
340*0a6a1f1dSLionel Sambuc 
341*0a6a1f1dSLionel Sambuc     CurrentFn = nullptr;
342*0a6a1f1dSLionel Sambuc   }
343*0a6a1f1dSLionel Sambuc 
344*0a6a1f1dSLionel Sambuc   /// True if all of $fcc0 - $fcc7 exist for the current ISA.
hasEightFccRegisters() const345*0a6a1f1dSLionel Sambuc   bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
346*0a6a1f1dSLionel Sambuc 
isGP64bit() const347*0a6a1f1dSLionel Sambuc   bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
isFP64bit() const348*0a6a1f1dSLionel Sambuc   bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
isABI_N32() const349*0a6a1f1dSLionel Sambuc   bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
isABI_N64() const350*0a6a1f1dSLionel Sambuc   bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
isABI_O32() const351*0a6a1f1dSLionel Sambuc   bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
isABI_FPXX() const352*0a6a1f1dSLionel Sambuc   bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
353*0a6a1f1dSLionel Sambuc 
useOddSPReg() const354*0a6a1f1dSLionel Sambuc   bool useOddSPReg() const {
355*0a6a1f1dSLionel Sambuc     return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
356*0a6a1f1dSLionel Sambuc   }
357*0a6a1f1dSLionel Sambuc 
inMicroMipsMode() const358*0a6a1f1dSLionel Sambuc   bool inMicroMipsMode() const {
359*0a6a1f1dSLionel Sambuc     return STI.getFeatureBits() & Mips::FeatureMicroMips;
360*0a6a1f1dSLionel Sambuc   }
hasMips1() const361*0a6a1f1dSLionel Sambuc   bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
hasMips2() const362*0a6a1f1dSLionel Sambuc   bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
hasMips3() const363*0a6a1f1dSLionel Sambuc   bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
hasMips4() const364*0a6a1f1dSLionel Sambuc   bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
hasMips5() const365*0a6a1f1dSLionel Sambuc   bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
hasMips32() const366*0a6a1f1dSLionel Sambuc   bool hasMips32() const {
367*0a6a1f1dSLionel Sambuc     return (STI.getFeatureBits() & Mips::FeatureMips32);
368*0a6a1f1dSLionel Sambuc   }
hasMips64() const369*0a6a1f1dSLionel Sambuc   bool hasMips64() const {
370*0a6a1f1dSLionel Sambuc     return (STI.getFeatureBits() & Mips::FeatureMips64);
371*0a6a1f1dSLionel Sambuc   }
hasMips32r2() const372*0a6a1f1dSLionel Sambuc   bool hasMips32r2() const {
373*0a6a1f1dSLionel Sambuc     return (STI.getFeatureBits() & Mips::FeatureMips32r2);
374*0a6a1f1dSLionel Sambuc   }
hasMips64r2() const375*0a6a1f1dSLionel Sambuc   bool hasMips64r2() const {
376*0a6a1f1dSLionel Sambuc     return (STI.getFeatureBits() & Mips::FeatureMips64r2);
377*0a6a1f1dSLionel Sambuc   }
hasMips32r6() const378*0a6a1f1dSLionel Sambuc   bool hasMips32r6() const {
379*0a6a1f1dSLionel Sambuc     return (STI.getFeatureBits() & Mips::FeatureMips32r6);
380*0a6a1f1dSLionel Sambuc   }
hasMips64r6() const381*0a6a1f1dSLionel Sambuc   bool hasMips64r6() const {
382*0a6a1f1dSLionel Sambuc     return (STI.getFeatureBits() & Mips::FeatureMips64r6);
383*0a6a1f1dSLionel Sambuc   }
hasDSP() const384*0a6a1f1dSLionel Sambuc   bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
hasDSPR2() const385*0a6a1f1dSLionel Sambuc   bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
hasMSA() const386*0a6a1f1dSLionel Sambuc   bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
387*0a6a1f1dSLionel Sambuc 
inMips16Mode() const388*0a6a1f1dSLionel Sambuc   bool inMips16Mode() const {
389*0a6a1f1dSLionel Sambuc     return STI.getFeatureBits() & Mips::FeatureMips16;
390*0a6a1f1dSLionel Sambuc   }
391*0a6a1f1dSLionel Sambuc   // TODO: see how can we get this info.
abiUsesSoftFloat() const392*0a6a1f1dSLionel Sambuc   bool abiUsesSoftFloat() const { return false; }
393*0a6a1f1dSLionel Sambuc 
394*0a6a1f1dSLionel Sambuc   /// Warn if RegNo is the current assembler temporary.
395*0a6a1f1dSLionel Sambuc   void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
396f4a2713aSLionel Sambuc };
397f4a2713aSLionel Sambuc }
398f4a2713aSLionel Sambuc 
399f4a2713aSLionel Sambuc namespace {
400f4a2713aSLionel Sambuc 
401f4a2713aSLionel Sambuc /// MipsOperand - Instances of this class represent a parsed Mips machine
402f4a2713aSLionel Sambuc /// instruction.
403f4a2713aSLionel Sambuc class MipsOperand : public MCParsedAsmOperand {
404f4a2713aSLionel Sambuc public:
405*0a6a1f1dSLionel Sambuc   /// Broad categories of register classes
406*0a6a1f1dSLionel Sambuc   /// The exact class is finalized by the render method.
407*0a6a1f1dSLionel Sambuc   enum RegKind {
408*0a6a1f1dSLionel Sambuc     RegKind_GPR = 1,      /// GPR32 and GPR64 (depending on isGP64bit())
409*0a6a1f1dSLionel Sambuc     RegKind_FGR = 2,      /// FGR32, FGR64, AFGR64 (depending on context and
410*0a6a1f1dSLionel Sambuc                           /// isFP64bit())
411*0a6a1f1dSLionel Sambuc     RegKind_FCC = 4,      /// FCC
412*0a6a1f1dSLionel Sambuc     RegKind_MSA128 = 8,   /// MSA128[BHWD] (makes no difference which)
413*0a6a1f1dSLionel Sambuc     RegKind_MSACtrl = 16, /// MSA control registers
414*0a6a1f1dSLionel Sambuc     RegKind_COP2 = 32,    /// COP2
415*0a6a1f1dSLionel Sambuc     RegKind_ACC = 64,     /// HI32DSP, LO32DSP, and ACC64DSP (depending on
416*0a6a1f1dSLionel Sambuc                           /// context).
417*0a6a1f1dSLionel Sambuc     RegKind_CCR = 128,    /// CCR
418*0a6a1f1dSLionel Sambuc     RegKind_HWRegs = 256, /// HWRegs
419*0a6a1f1dSLionel Sambuc     RegKind_COP3 = 512,   /// COP3
420*0a6a1f1dSLionel Sambuc 
421*0a6a1f1dSLionel Sambuc     /// Potentially any (e.g. $1)
422*0a6a1f1dSLionel Sambuc     RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
423*0a6a1f1dSLionel Sambuc                       RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
424*0a6a1f1dSLionel Sambuc                       RegKind_CCR | RegKind_HWRegs | RegKind_COP3
425f4a2713aSLionel Sambuc   };
426f4a2713aSLionel Sambuc 
427f4a2713aSLionel Sambuc private:
428f4a2713aSLionel Sambuc   enum KindTy {
429*0a6a1f1dSLionel Sambuc     k_Immediate,     /// An immediate (possibly involving symbol references)
430*0a6a1f1dSLionel Sambuc     k_Memory,        /// Base + Offset Memory Address
431*0a6a1f1dSLionel Sambuc     k_PhysRegister,  /// A physical register from the Mips namespace
432*0a6a1f1dSLionel Sambuc     k_RegisterIndex, /// A register index in one or more RegKind.
433*0a6a1f1dSLionel Sambuc     k_Token,         /// A simple token
434*0a6a1f1dSLionel Sambuc     k_RegList,       /// A physical register list
435*0a6a1f1dSLionel Sambuc     k_RegPair        /// A pair of physical register
436f4a2713aSLionel Sambuc   } Kind;
437f4a2713aSLionel Sambuc 
438*0a6a1f1dSLionel Sambuc public:
MipsOperand(KindTy K,MipsAsmParser & Parser)439*0a6a1f1dSLionel Sambuc   MipsOperand(KindTy K, MipsAsmParser &Parser)
440*0a6a1f1dSLionel Sambuc       : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
441*0a6a1f1dSLionel Sambuc 
442*0a6a1f1dSLionel Sambuc private:
443*0a6a1f1dSLionel Sambuc   /// For diagnostics, and checking the assembler temporary
444*0a6a1f1dSLionel Sambuc   MipsAsmParser &AsmParser;
445f4a2713aSLionel Sambuc 
446f4a2713aSLionel Sambuc   struct Token {
447f4a2713aSLionel Sambuc     const char *Data;
448f4a2713aSLionel Sambuc     unsigned Length;
449f4a2713aSLionel Sambuc   };
450f4a2713aSLionel Sambuc 
451*0a6a1f1dSLionel Sambuc   struct PhysRegOp {
452*0a6a1f1dSLionel Sambuc     unsigned Num; /// Register Number
453*0a6a1f1dSLionel Sambuc   };
454*0a6a1f1dSLionel Sambuc 
455*0a6a1f1dSLionel Sambuc   struct RegIdxOp {
456*0a6a1f1dSLionel Sambuc     unsigned Index; /// Index into the register class
457*0a6a1f1dSLionel Sambuc     RegKind Kind;   /// Bitfield of the kinds it could possibly be
458*0a6a1f1dSLionel Sambuc     const MCRegisterInfo *RegInfo;
459f4a2713aSLionel Sambuc   };
460f4a2713aSLionel Sambuc 
461f4a2713aSLionel Sambuc   struct ImmOp {
462f4a2713aSLionel Sambuc     const MCExpr *Val;
463f4a2713aSLionel Sambuc   };
464f4a2713aSLionel Sambuc 
465f4a2713aSLionel Sambuc   struct MemOp {
466*0a6a1f1dSLionel Sambuc     MipsOperand *Base;
467f4a2713aSLionel Sambuc     const MCExpr *Off;
468f4a2713aSLionel Sambuc   };
469f4a2713aSLionel Sambuc 
470*0a6a1f1dSLionel Sambuc   struct RegListOp {
471*0a6a1f1dSLionel Sambuc     SmallVector<unsigned, 10> *List;
472*0a6a1f1dSLionel Sambuc   };
473*0a6a1f1dSLionel Sambuc 
474f4a2713aSLionel Sambuc   union {
475f4a2713aSLionel Sambuc     struct Token Tok;
476*0a6a1f1dSLionel Sambuc     struct PhysRegOp PhysReg;
477*0a6a1f1dSLionel Sambuc     struct RegIdxOp RegIdx;
478f4a2713aSLionel Sambuc     struct ImmOp Imm;
479f4a2713aSLionel Sambuc     struct MemOp Mem;
480*0a6a1f1dSLionel Sambuc     struct RegListOp RegList;
481f4a2713aSLionel Sambuc   };
482f4a2713aSLionel Sambuc 
483f4a2713aSLionel Sambuc   SMLoc StartLoc, EndLoc;
484f4a2713aSLionel Sambuc 
485*0a6a1f1dSLionel Sambuc   /// Internal constructor for register kinds
CreateReg(unsigned Index,RegKind RegKind,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)486*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
487*0a6a1f1dSLionel Sambuc                                                 const MCRegisterInfo *RegInfo,
488*0a6a1f1dSLionel Sambuc                                                 SMLoc S, SMLoc E,
489*0a6a1f1dSLionel Sambuc                                                 MipsAsmParser &Parser) {
490*0a6a1f1dSLionel Sambuc     auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
491*0a6a1f1dSLionel Sambuc     Op->RegIdx.Index = Index;
492*0a6a1f1dSLionel Sambuc     Op->RegIdx.RegInfo = RegInfo;
493*0a6a1f1dSLionel Sambuc     Op->RegIdx.Kind = RegKind;
494*0a6a1f1dSLionel Sambuc     Op->StartLoc = S;
495*0a6a1f1dSLionel Sambuc     Op->EndLoc = E;
496*0a6a1f1dSLionel Sambuc     return Op;
497*0a6a1f1dSLionel Sambuc   }
498*0a6a1f1dSLionel Sambuc 
499f4a2713aSLionel Sambuc public:
500*0a6a1f1dSLionel Sambuc   /// Coerce the register to GPR32 and return the real register for the current
501*0a6a1f1dSLionel Sambuc   /// target.
getGPR32Reg() const502*0a6a1f1dSLionel Sambuc   unsigned getGPR32Reg() const {
503*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
504*0a6a1f1dSLionel Sambuc     AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
505*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::GPR32RegClassID;
506*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
507f4a2713aSLionel Sambuc   }
508f4a2713aSLionel Sambuc 
509*0a6a1f1dSLionel Sambuc   /// Coerce the register to GPR32 and return the real register for the current
510*0a6a1f1dSLionel Sambuc   /// target.
getGPRMM16Reg() const511*0a6a1f1dSLionel Sambuc   unsigned getGPRMM16Reg() const {
512*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
513*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::GPR32RegClassID;
514*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
515f4a2713aSLionel Sambuc   }
516f4a2713aSLionel Sambuc 
517*0a6a1f1dSLionel Sambuc   /// Coerce the register to GPR64 and return the real register for the current
518*0a6a1f1dSLionel Sambuc   /// target.
getGPR64Reg() const519*0a6a1f1dSLionel Sambuc   unsigned getGPR64Reg() const {
520*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
521*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::GPR64RegClassID;
522*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
523*0a6a1f1dSLionel Sambuc   }
524*0a6a1f1dSLionel Sambuc 
525*0a6a1f1dSLionel Sambuc private:
526*0a6a1f1dSLionel Sambuc   /// Coerce the register to AFGR64 and return the real register for the current
527*0a6a1f1dSLionel Sambuc   /// target.
getAFGR64Reg() const528*0a6a1f1dSLionel Sambuc   unsigned getAFGR64Reg() const {
529*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
530*0a6a1f1dSLionel Sambuc     if (RegIdx.Index % 2 != 0)
531*0a6a1f1dSLionel Sambuc       AsmParser.Warning(StartLoc, "Float register should be even.");
532*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
533*0a6a1f1dSLionel Sambuc         .getRegister(RegIdx.Index / 2);
534*0a6a1f1dSLionel Sambuc   }
535*0a6a1f1dSLionel Sambuc 
536*0a6a1f1dSLionel Sambuc   /// Coerce the register to FGR64 and return the real register for the current
537*0a6a1f1dSLionel Sambuc   /// target.
getFGR64Reg() const538*0a6a1f1dSLionel Sambuc   unsigned getFGR64Reg() const {
539*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
540*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
541*0a6a1f1dSLionel Sambuc         .getRegister(RegIdx.Index);
542*0a6a1f1dSLionel Sambuc   }
543*0a6a1f1dSLionel Sambuc 
544*0a6a1f1dSLionel Sambuc   /// Coerce the register to FGR32 and return the real register for the current
545*0a6a1f1dSLionel Sambuc   /// target.
getFGR32Reg() const546*0a6a1f1dSLionel Sambuc   unsigned getFGR32Reg() const {
547*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
548*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
549*0a6a1f1dSLionel Sambuc         .getRegister(RegIdx.Index);
550*0a6a1f1dSLionel Sambuc   }
551*0a6a1f1dSLionel Sambuc 
552*0a6a1f1dSLionel Sambuc   /// Coerce the register to FGRH32 and return the real register for the current
553*0a6a1f1dSLionel Sambuc   /// target.
getFGRH32Reg() const554*0a6a1f1dSLionel Sambuc   unsigned getFGRH32Reg() const {
555*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
556*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
557*0a6a1f1dSLionel Sambuc         .getRegister(RegIdx.Index);
558*0a6a1f1dSLionel Sambuc   }
559*0a6a1f1dSLionel Sambuc 
560*0a6a1f1dSLionel Sambuc   /// Coerce the register to FCC and return the real register for the current
561*0a6a1f1dSLionel Sambuc   /// target.
getFCCReg() const562*0a6a1f1dSLionel Sambuc   unsigned getFCCReg() const {
563*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
564*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
565*0a6a1f1dSLionel Sambuc         .getRegister(RegIdx.Index);
566*0a6a1f1dSLionel Sambuc   }
567*0a6a1f1dSLionel Sambuc 
568*0a6a1f1dSLionel Sambuc   /// Coerce the register to MSA128 and return the real register for the current
569*0a6a1f1dSLionel Sambuc   /// target.
getMSA128Reg() const570*0a6a1f1dSLionel Sambuc   unsigned getMSA128Reg() const {
571*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
572*0a6a1f1dSLionel Sambuc     // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
573*0a6a1f1dSLionel Sambuc     // identical
574*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::MSA128BRegClassID;
575*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
576*0a6a1f1dSLionel Sambuc   }
577*0a6a1f1dSLionel Sambuc 
578*0a6a1f1dSLionel Sambuc   /// Coerce the register to MSACtrl and return the real register for the
579*0a6a1f1dSLionel Sambuc   /// current target.
getMSACtrlReg() const580*0a6a1f1dSLionel Sambuc   unsigned getMSACtrlReg() const {
581*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
582*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::MSACtrlRegClassID;
583*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584*0a6a1f1dSLionel Sambuc   }
585*0a6a1f1dSLionel Sambuc 
586*0a6a1f1dSLionel Sambuc   /// Coerce the register to COP2 and return the real register for the
587*0a6a1f1dSLionel Sambuc   /// current target.
getCOP2Reg() const588*0a6a1f1dSLionel Sambuc   unsigned getCOP2Reg() const {
589*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
590*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::COP2RegClassID;
591*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
592*0a6a1f1dSLionel Sambuc   }
593*0a6a1f1dSLionel Sambuc 
594*0a6a1f1dSLionel Sambuc   /// Coerce the register to COP3 and return the real register for the
595*0a6a1f1dSLionel Sambuc   /// current target.
getCOP3Reg() const596*0a6a1f1dSLionel Sambuc   unsigned getCOP3Reg() const {
597*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
598*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::COP3RegClassID;
599*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
600*0a6a1f1dSLionel Sambuc   }
601*0a6a1f1dSLionel Sambuc 
602*0a6a1f1dSLionel Sambuc   /// Coerce the register to ACC64DSP and return the real register for the
603*0a6a1f1dSLionel Sambuc   /// current target.
getACC64DSPReg() const604*0a6a1f1dSLionel Sambuc   unsigned getACC64DSPReg() const {
605*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
606*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::ACC64DSPRegClassID;
607*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
608*0a6a1f1dSLionel Sambuc   }
609*0a6a1f1dSLionel Sambuc 
610*0a6a1f1dSLionel Sambuc   /// Coerce the register to HI32DSP and return the real register for the
611*0a6a1f1dSLionel Sambuc   /// current target.
getHI32DSPReg() const612*0a6a1f1dSLionel Sambuc   unsigned getHI32DSPReg() const {
613*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
614*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::HI32DSPRegClassID;
615*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
616*0a6a1f1dSLionel Sambuc   }
617*0a6a1f1dSLionel Sambuc 
618*0a6a1f1dSLionel Sambuc   /// Coerce the register to LO32DSP and return the real register for the
619*0a6a1f1dSLionel Sambuc   /// current target.
getLO32DSPReg() const620*0a6a1f1dSLionel Sambuc   unsigned getLO32DSPReg() const {
621*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
622*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::LO32DSPRegClassID;
623*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
624*0a6a1f1dSLionel Sambuc   }
625*0a6a1f1dSLionel Sambuc 
626*0a6a1f1dSLionel Sambuc   /// Coerce the register to CCR and return the real register for the
627*0a6a1f1dSLionel Sambuc   /// current target.
getCCRReg() const628*0a6a1f1dSLionel Sambuc   unsigned getCCRReg() const {
629*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
630*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::CCRRegClassID;
631*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632*0a6a1f1dSLionel Sambuc   }
633*0a6a1f1dSLionel Sambuc 
634*0a6a1f1dSLionel Sambuc   /// Coerce the register to HWRegs and return the real register for the
635*0a6a1f1dSLionel Sambuc   /// current target.
getHWRegsReg() const636*0a6a1f1dSLionel Sambuc   unsigned getHWRegsReg() const {
637*0a6a1f1dSLionel Sambuc     assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
638*0a6a1f1dSLionel Sambuc     unsigned ClassID = Mips::HWRegsRegClassID;
639*0a6a1f1dSLionel Sambuc     return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
640*0a6a1f1dSLionel Sambuc   }
641*0a6a1f1dSLionel Sambuc 
642*0a6a1f1dSLionel Sambuc public:
addExpr(MCInst & Inst,const MCExpr * Expr) const643f4a2713aSLionel Sambuc   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
644f4a2713aSLionel Sambuc     // Add as immediate when possible.  Null MCExpr = 0.
645*0a6a1f1dSLionel Sambuc     if (!Expr)
646f4a2713aSLionel Sambuc       Inst.addOperand(MCOperand::CreateImm(0));
647f4a2713aSLionel Sambuc     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
648f4a2713aSLionel Sambuc       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
649f4a2713aSLionel Sambuc     else
650f4a2713aSLionel Sambuc       Inst.addOperand(MCOperand::CreateExpr(Expr));
651f4a2713aSLionel Sambuc   }
652f4a2713aSLionel Sambuc 
addRegOperands(MCInst & Inst,unsigned N) const653*0a6a1f1dSLionel Sambuc   void addRegOperands(MCInst &Inst, unsigned N) const {
654*0a6a1f1dSLionel Sambuc     llvm_unreachable("Use a custom parser instead");
655*0a6a1f1dSLionel Sambuc   }
656*0a6a1f1dSLionel Sambuc 
657*0a6a1f1dSLionel Sambuc   /// Render the operand to an MCInst as a GPR32
658*0a6a1f1dSLionel Sambuc   /// Asserts if the wrong number of operands are requested, or the operand
659*0a6a1f1dSLionel Sambuc   /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR32AsmRegOperands(MCInst & Inst,unsigned N) const660*0a6a1f1dSLionel Sambuc   void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
661*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
662*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
663*0a6a1f1dSLionel Sambuc   }
664*0a6a1f1dSLionel Sambuc 
addGPRMM16AsmRegOperands(MCInst & Inst,unsigned N) const665*0a6a1f1dSLionel Sambuc   void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
666*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
667*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
668*0a6a1f1dSLionel Sambuc   }
669*0a6a1f1dSLionel Sambuc 
addGPRMM16AsmRegZeroOperands(MCInst & Inst,unsigned N) const670*0a6a1f1dSLionel Sambuc   void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
671*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
672*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
673*0a6a1f1dSLionel Sambuc   }
674*0a6a1f1dSLionel Sambuc 
675*0a6a1f1dSLionel Sambuc   /// Render the operand to an MCInst as a GPR64
676*0a6a1f1dSLionel Sambuc   /// Asserts if the wrong number of operands are requested, or the operand
677*0a6a1f1dSLionel Sambuc   /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR64AsmRegOperands(MCInst & Inst,unsigned N) const678*0a6a1f1dSLionel Sambuc   void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
679*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
680*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
681*0a6a1f1dSLionel Sambuc   }
682*0a6a1f1dSLionel Sambuc 
addAFGR64AsmRegOperands(MCInst & Inst,unsigned N) const683*0a6a1f1dSLionel Sambuc   void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
684*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
685*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
686*0a6a1f1dSLionel Sambuc   }
687*0a6a1f1dSLionel Sambuc 
addFGR64AsmRegOperands(MCInst & Inst,unsigned N) const688*0a6a1f1dSLionel Sambuc   void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
689*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
690*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
691*0a6a1f1dSLionel Sambuc   }
692*0a6a1f1dSLionel Sambuc 
addFGR32AsmRegOperands(MCInst & Inst,unsigned N) const693*0a6a1f1dSLionel Sambuc   void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
694*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
695*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
696*0a6a1f1dSLionel Sambuc     // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
697*0a6a1f1dSLionel Sambuc     if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
698*0a6a1f1dSLionel Sambuc       AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
699*0a6a1f1dSLionel Sambuc                                 "registers");
700*0a6a1f1dSLionel Sambuc   }
701*0a6a1f1dSLionel Sambuc 
addFGRH32AsmRegOperands(MCInst & Inst,unsigned N) const702*0a6a1f1dSLionel Sambuc   void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
703*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
704*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
705*0a6a1f1dSLionel Sambuc   }
706*0a6a1f1dSLionel Sambuc 
addFCCAsmRegOperands(MCInst & Inst,unsigned N) const707*0a6a1f1dSLionel Sambuc   void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
708*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
709*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
710*0a6a1f1dSLionel Sambuc   }
711*0a6a1f1dSLionel Sambuc 
addMSA128AsmRegOperands(MCInst & Inst,unsigned N) const712*0a6a1f1dSLionel Sambuc   void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
713*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
714*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
715*0a6a1f1dSLionel Sambuc   }
716*0a6a1f1dSLionel Sambuc 
addMSACtrlAsmRegOperands(MCInst & Inst,unsigned N) const717*0a6a1f1dSLionel Sambuc   void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
718*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
719*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
720*0a6a1f1dSLionel Sambuc   }
721*0a6a1f1dSLionel Sambuc 
addCOP2AsmRegOperands(MCInst & Inst,unsigned N) const722*0a6a1f1dSLionel Sambuc   void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
723*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
724*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
725*0a6a1f1dSLionel Sambuc   }
726*0a6a1f1dSLionel Sambuc 
addCOP3AsmRegOperands(MCInst & Inst,unsigned N) const727*0a6a1f1dSLionel Sambuc   void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
728*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
729*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
730*0a6a1f1dSLionel Sambuc   }
731*0a6a1f1dSLionel Sambuc 
addACC64DSPAsmRegOperands(MCInst & Inst,unsigned N) const732*0a6a1f1dSLionel Sambuc   void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
733*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
734*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
735*0a6a1f1dSLionel Sambuc   }
736*0a6a1f1dSLionel Sambuc 
addHI32DSPAsmRegOperands(MCInst & Inst,unsigned N) const737*0a6a1f1dSLionel Sambuc   void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
738*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
739*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
740*0a6a1f1dSLionel Sambuc   }
741*0a6a1f1dSLionel Sambuc 
addLO32DSPAsmRegOperands(MCInst & Inst,unsigned N) const742*0a6a1f1dSLionel Sambuc   void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
743*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
744*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
745*0a6a1f1dSLionel Sambuc   }
746*0a6a1f1dSLionel Sambuc 
addCCRAsmRegOperands(MCInst & Inst,unsigned N) const747*0a6a1f1dSLionel Sambuc   void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
748*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
749*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
750*0a6a1f1dSLionel Sambuc   }
751*0a6a1f1dSLionel Sambuc 
addHWRegsAsmRegOperands(MCInst & Inst,unsigned N) const752*0a6a1f1dSLionel Sambuc   void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
753*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
754*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
755*0a6a1f1dSLionel Sambuc   }
756*0a6a1f1dSLionel Sambuc 
addImmOperands(MCInst & Inst,unsigned N) const757f4a2713aSLionel Sambuc   void addImmOperands(MCInst &Inst, unsigned N) const {
758f4a2713aSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
759f4a2713aSLionel Sambuc     const MCExpr *Expr = getImm();
760f4a2713aSLionel Sambuc     addExpr(Inst, Expr);
761f4a2713aSLionel Sambuc   }
762f4a2713aSLionel Sambuc 
addMemOperands(MCInst & Inst,unsigned N) const763f4a2713aSLionel Sambuc   void addMemOperands(MCInst &Inst, unsigned N) const {
764f4a2713aSLionel Sambuc     assert(N == 2 && "Invalid number of operands!");
765f4a2713aSLionel Sambuc 
766*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
767f4a2713aSLionel Sambuc 
768f4a2713aSLionel Sambuc     const MCExpr *Expr = getMemOff();
769f4a2713aSLionel Sambuc     addExpr(Inst, Expr);
770f4a2713aSLionel Sambuc   }
771f4a2713aSLionel Sambuc 
addMicroMipsMemOperands(MCInst & Inst,unsigned N) const772*0a6a1f1dSLionel Sambuc   void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
773*0a6a1f1dSLionel Sambuc     assert(N == 2 && "Invalid number of operands!");
774*0a6a1f1dSLionel Sambuc 
775*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
776*0a6a1f1dSLionel Sambuc 
777*0a6a1f1dSLionel Sambuc     const MCExpr *Expr = getMemOff();
778*0a6a1f1dSLionel Sambuc     addExpr(Inst, Expr);
779*0a6a1f1dSLionel Sambuc   }
780*0a6a1f1dSLionel Sambuc 
addRegListOperands(MCInst & Inst,unsigned N) const781*0a6a1f1dSLionel Sambuc   void addRegListOperands(MCInst &Inst, unsigned N) const {
782*0a6a1f1dSLionel Sambuc     assert(N == 1 && "Invalid number of operands!");
783*0a6a1f1dSLionel Sambuc 
784*0a6a1f1dSLionel Sambuc     for (auto RegNo : getRegList())
785*0a6a1f1dSLionel Sambuc       Inst.addOperand(MCOperand::CreateReg(RegNo));
786*0a6a1f1dSLionel Sambuc   }
787*0a6a1f1dSLionel Sambuc 
addRegPairOperands(MCInst & Inst,unsigned N) const788*0a6a1f1dSLionel Sambuc   void addRegPairOperands(MCInst &Inst, unsigned N) const {
789*0a6a1f1dSLionel Sambuc     assert(N == 2 && "Invalid number of operands!");
790*0a6a1f1dSLionel Sambuc     unsigned RegNo = getRegPair();
791*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(RegNo++));
792*0a6a1f1dSLionel Sambuc     Inst.addOperand(MCOperand::CreateReg(RegNo));
793*0a6a1f1dSLionel Sambuc   }
794*0a6a1f1dSLionel Sambuc 
isReg() const795*0a6a1f1dSLionel Sambuc   bool isReg() const override {
796*0a6a1f1dSLionel Sambuc     // As a special case until we sort out the definition of div/divu, pretend
797*0a6a1f1dSLionel Sambuc     // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
798*0a6a1f1dSLionel Sambuc     if (isGPRAsmReg() && RegIdx.Index == 0)
799*0a6a1f1dSLionel Sambuc       return true;
800*0a6a1f1dSLionel Sambuc 
801*0a6a1f1dSLionel Sambuc     return Kind == k_PhysRegister;
802*0a6a1f1dSLionel Sambuc   }
isRegIdx() const803*0a6a1f1dSLionel Sambuc   bool isRegIdx() const { return Kind == k_RegisterIndex; }
isImm() const804*0a6a1f1dSLionel Sambuc   bool isImm() const override { return Kind == k_Immediate; }
isConstantImm() const805*0a6a1f1dSLionel Sambuc   bool isConstantImm() const {
806*0a6a1f1dSLionel Sambuc     return isImm() && dyn_cast<MCConstantExpr>(getImm());
807*0a6a1f1dSLionel Sambuc   }
isToken() const808*0a6a1f1dSLionel Sambuc   bool isToken() const override {
809*0a6a1f1dSLionel Sambuc     // Note: It's not possible to pretend that other operand kinds are tokens.
810*0a6a1f1dSLionel Sambuc     // The matcher emitter checks tokens first.
811*0a6a1f1dSLionel Sambuc     return Kind == k_Token;
812*0a6a1f1dSLionel Sambuc   }
isMem() const813*0a6a1f1dSLionel Sambuc   bool isMem() const override { return Kind == k_Memory; }
isConstantMemOff() const814*0a6a1f1dSLionel Sambuc   bool isConstantMemOff() const {
815*0a6a1f1dSLionel Sambuc     return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
816*0a6a1f1dSLionel Sambuc   }
isMemWithSimmOffset() const817*0a6a1f1dSLionel Sambuc   template <unsigned Bits> bool isMemWithSimmOffset() const {
818*0a6a1f1dSLionel Sambuc     return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
819*0a6a1f1dSLionel Sambuc   }
isMemWithGRPMM16Base() const820*0a6a1f1dSLionel Sambuc   bool isMemWithGRPMM16Base() const {
821*0a6a1f1dSLionel Sambuc     return isMem() && getMemBase()->isMM16AsmReg();
822*0a6a1f1dSLionel Sambuc   }
isMemWithUimmOffsetSP() const823*0a6a1f1dSLionel Sambuc   template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
824*0a6a1f1dSLionel Sambuc     return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
825*0a6a1f1dSLionel Sambuc       && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
826*0a6a1f1dSLionel Sambuc   }
isMemWithUimmWordAlignedOffsetSP() const827*0a6a1f1dSLionel Sambuc   template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
828*0a6a1f1dSLionel Sambuc     return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
829*0a6a1f1dSLionel Sambuc       && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
830*0a6a1f1dSLionel Sambuc       && (getMemBase()->getGPR32Reg() == Mips::SP);
831*0a6a1f1dSLionel Sambuc   }
isRegList16() const832*0a6a1f1dSLionel Sambuc   bool isRegList16() const {
833*0a6a1f1dSLionel Sambuc     if (!isRegList())
834*0a6a1f1dSLionel Sambuc       return false;
835*0a6a1f1dSLionel Sambuc 
836*0a6a1f1dSLionel Sambuc     int Size = RegList.List->size();
837*0a6a1f1dSLionel Sambuc     if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
838*0a6a1f1dSLionel Sambuc         RegList.List->back() != Mips::RA)
839*0a6a1f1dSLionel Sambuc       return false;
840*0a6a1f1dSLionel Sambuc 
841*0a6a1f1dSLionel Sambuc     int PrevReg = *RegList.List->begin();
842*0a6a1f1dSLionel Sambuc     for (int i = 1; i < Size - 1; i++) {
843*0a6a1f1dSLionel Sambuc       int Reg = (*(RegList.List))[i];
844*0a6a1f1dSLionel Sambuc       if ( Reg != PrevReg + 1)
845*0a6a1f1dSLionel Sambuc         return false;
846*0a6a1f1dSLionel Sambuc       PrevReg = Reg;
847*0a6a1f1dSLionel Sambuc     }
848*0a6a1f1dSLionel Sambuc 
849*0a6a1f1dSLionel Sambuc     return true;
850*0a6a1f1dSLionel Sambuc   }
isInvNum() const851f4a2713aSLionel Sambuc   bool isInvNum() const { return Kind == k_Immediate; }
isLSAImm() const852*0a6a1f1dSLionel Sambuc   bool isLSAImm() const {
853*0a6a1f1dSLionel Sambuc     if (!isConstantImm())
854*0a6a1f1dSLionel Sambuc       return false;
855*0a6a1f1dSLionel Sambuc     int64_t Val = getConstantImm();
856*0a6a1f1dSLionel Sambuc     return 1 <= Val && Val <= 4;
857*0a6a1f1dSLionel Sambuc   }
isRegList() const858*0a6a1f1dSLionel Sambuc   bool isRegList() const { return Kind == k_RegList; }
859f4a2713aSLionel Sambuc 
getToken() const860f4a2713aSLionel Sambuc   StringRef getToken() const {
861f4a2713aSLionel Sambuc     assert(Kind == k_Token && "Invalid access!");
862f4a2713aSLionel Sambuc     return StringRef(Tok.Data, Tok.Length);
863f4a2713aSLionel Sambuc   }
isRegPair() const864*0a6a1f1dSLionel Sambuc   bool isRegPair() const { return Kind == k_RegPair; }
865f4a2713aSLionel Sambuc 
getReg() const866*0a6a1f1dSLionel Sambuc   unsigned getReg() const override {
867*0a6a1f1dSLionel Sambuc     // As a special case until we sort out the definition of div/divu, pretend
868*0a6a1f1dSLionel Sambuc     // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
869*0a6a1f1dSLionel Sambuc     if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
870*0a6a1f1dSLionel Sambuc         RegIdx.Kind & RegKind_GPR)
871*0a6a1f1dSLionel Sambuc       return getGPR32Reg(); // FIXME: GPR64 too
872f4a2713aSLionel Sambuc 
873*0a6a1f1dSLionel Sambuc     assert(Kind == k_PhysRegister && "Invalid access!");
874*0a6a1f1dSLionel Sambuc     return PhysReg.Num;
875f4a2713aSLionel Sambuc   }
876f4a2713aSLionel Sambuc 
getImm() const877f4a2713aSLionel Sambuc   const MCExpr *getImm() const {
878*0a6a1f1dSLionel Sambuc     assert((Kind == k_Immediate) && "Invalid access!");
879f4a2713aSLionel Sambuc     return Imm.Val;
880f4a2713aSLionel Sambuc   }
881f4a2713aSLionel Sambuc 
getConstantImm() const882*0a6a1f1dSLionel Sambuc   int64_t getConstantImm() const {
883*0a6a1f1dSLionel Sambuc     const MCExpr *Val = getImm();
884*0a6a1f1dSLionel Sambuc     return static_cast<const MCConstantExpr *>(Val)->getValue();
885*0a6a1f1dSLionel Sambuc   }
886*0a6a1f1dSLionel Sambuc 
getMemBase() const887*0a6a1f1dSLionel Sambuc   MipsOperand *getMemBase() const {
888f4a2713aSLionel Sambuc     assert((Kind == k_Memory) && "Invalid access!");
889f4a2713aSLionel Sambuc     return Mem.Base;
890f4a2713aSLionel Sambuc   }
891f4a2713aSLionel Sambuc 
getMemOff() const892f4a2713aSLionel Sambuc   const MCExpr *getMemOff() const {
893f4a2713aSLionel Sambuc     assert((Kind == k_Memory) && "Invalid access!");
894f4a2713aSLionel Sambuc     return Mem.Off;
895f4a2713aSLionel Sambuc   }
896f4a2713aSLionel Sambuc 
getConstantMemOff() const897*0a6a1f1dSLionel Sambuc   int64_t getConstantMemOff() const {
898*0a6a1f1dSLionel Sambuc     return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
899*0a6a1f1dSLionel Sambuc   }
900*0a6a1f1dSLionel Sambuc 
getRegList() const901*0a6a1f1dSLionel Sambuc   const SmallVectorImpl<unsigned> &getRegList() const {
902*0a6a1f1dSLionel Sambuc     assert((Kind == k_RegList) && "Invalid access!");
903*0a6a1f1dSLionel Sambuc     return *(RegList.List);
904*0a6a1f1dSLionel Sambuc   }
905*0a6a1f1dSLionel Sambuc 
getRegPair() const906*0a6a1f1dSLionel Sambuc   unsigned getRegPair() const {
907*0a6a1f1dSLionel Sambuc     assert((Kind == k_RegPair) && "Invalid access!");
908*0a6a1f1dSLionel Sambuc     return RegIdx.Index;
909*0a6a1f1dSLionel Sambuc   }
910*0a6a1f1dSLionel Sambuc 
CreateToken(StringRef Str,SMLoc S,MipsAsmParser & Parser)911*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
912*0a6a1f1dSLionel Sambuc                                                   MipsAsmParser &Parser) {
913*0a6a1f1dSLionel Sambuc     auto Op = make_unique<MipsOperand>(k_Token, Parser);
914f4a2713aSLionel Sambuc     Op->Tok.Data = Str.data();
915f4a2713aSLionel Sambuc     Op->Tok.Length = Str.size();
916f4a2713aSLionel Sambuc     Op->StartLoc = S;
917f4a2713aSLionel Sambuc     Op->EndLoc = S;
918f4a2713aSLionel Sambuc     return Op;
919f4a2713aSLionel Sambuc   }
920f4a2713aSLionel Sambuc 
921*0a6a1f1dSLionel Sambuc   /// Create a numeric register (e.g. $1). The exact register remains
922*0a6a1f1dSLionel Sambuc   /// unresolved until an instruction successfully matches
923*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createNumericReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)924*0a6a1f1dSLionel Sambuc   createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
925*0a6a1f1dSLionel Sambuc                    SMLoc E, MipsAsmParser &Parser) {
926*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
927*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
928f4a2713aSLionel Sambuc   }
929f4a2713aSLionel Sambuc 
930*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely a GPR.
931*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $gp.
932*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createGPRReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)933*0a6a1f1dSLionel Sambuc   createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
934*0a6a1f1dSLionel Sambuc                MipsAsmParser &Parser) {
935*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
936f4a2713aSLionel Sambuc   }
937f4a2713aSLionel Sambuc 
938*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely a FGR.
939*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $f0.
940*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createFGRReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)941*0a6a1f1dSLionel Sambuc   createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
942*0a6a1f1dSLionel Sambuc                MipsAsmParser &Parser) {
943*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
944*0a6a1f1dSLionel Sambuc   }
945*0a6a1f1dSLionel Sambuc 
946*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely a HWReg.
947*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $hwr_cpunum.
948*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createHWRegsReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)949*0a6a1f1dSLionel Sambuc   createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
950*0a6a1f1dSLionel Sambuc                   SMLoc S, SMLoc E, MipsAsmParser &Parser) {
951*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
952*0a6a1f1dSLionel Sambuc   }
953*0a6a1f1dSLionel Sambuc 
954*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely an FCC.
955*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $fcc0.
956*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createFCCReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)957*0a6a1f1dSLionel Sambuc   createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
958*0a6a1f1dSLionel Sambuc                MipsAsmParser &Parser) {
959*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
960*0a6a1f1dSLionel Sambuc   }
961*0a6a1f1dSLionel Sambuc 
962*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely an ACC.
963*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $ac0.
964*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createACCReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)965*0a6a1f1dSLionel Sambuc   createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
966*0a6a1f1dSLionel Sambuc                MipsAsmParser &Parser) {
967*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
968*0a6a1f1dSLionel Sambuc   }
969*0a6a1f1dSLionel Sambuc 
970*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely an MSA128.
971*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $w0.
972*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createMSA128Reg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)973*0a6a1f1dSLionel Sambuc   createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
974*0a6a1f1dSLionel Sambuc                   SMLoc E, MipsAsmParser &Parser) {
975*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
976*0a6a1f1dSLionel Sambuc   }
977*0a6a1f1dSLionel Sambuc 
978*0a6a1f1dSLionel Sambuc   /// Create a register that is definitely an MSACtrl.
979*0a6a1f1dSLionel Sambuc   /// This is typically only used for named registers such as $msaaccess.
980*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
createMSACtrlReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)981*0a6a1f1dSLionel Sambuc   createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
982*0a6a1f1dSLionel Sambuc                    SMLoc E, MipsAsmParser &Parser) {
983*0a6a1f1dSLionel Sambuc     return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
984*0a6a1f1dSLionel Sambuc   }
985*0a6a1f1dSLionel Sambuc 
986*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E,MipsAsmParser & Parser)987*0a6a1f1dSLionel Sambuc   CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
988*0a6a1f1dSLionel Sambuc     auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
989f4a2713aSLionel Sambuc     Op->Imm.Val = Val;
990f4a2713aSLionel Sambuc     Op->StartLoc = S;
991f4a2713aSLionel Sambuc     Op->EndLoc = E;
992f4a2713aSLionel Sambuc     return Op;
993f4a2713aSLionel Sambuc   }
994f4a2713aSLionel Sambuc 
995*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base,const MCExpr * Off,SMLoc S,SMLoc E,MipsAsmParser & Parser)996*0a6a1f1dSLionel Sambuc   CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
997*0a6a1f1dSLionel Sambuc             SMLoc E, MipsAsmParser &Parser) {
998*0a6a1f1dSLionel Sambuc     auto Op = make_unique<MipsOperand>(k_Memory, Parser);
999*0a6a1f1dSLionel Sambuc     Op->Mem.Base = Base.release();
1000f4a2713aSLionel Sambuc     Op->Mem.Off = Off;
1001f4a2713aSLionel Sambuc     Op->StartLoc = S;
1002f4a2713aSLionel Sambuc     Op->EndLoc = E;
1003f4a2713aSLionel Sambuc     return Op;
1004f4a2713aSLionel Sambuc   }
1005f4a2713aSLionel Sambuc 
1006*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
CreateRegList(SmallVectorImpl<unsigned> & Regs,SMLoc StartLoc,SMLoc EndLoc,MipsAsmParser & Parser)1007*0a6a1f1dSLionel Sambuc   CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1008*0a6a1f1dSLionel Sambuc                 MipsAsmParser &Parser) {
1009*0a6a1f1dSLionel Sambuc     assert (Regs.size() > 0 && "Empty list not allowed");
1010*0a6a1f1dSLionel Sambuc 
1011*0a6a1f1dSLionel Sambuc     auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1012*0a6a1f1dSLionel Sambuc     Op->RegList.List = new SmallVector<unsigned, 10>();
1013*0a6a1f1dSLionel Sambuc     for (auto Reg : Regs)
1014*0a6a1f1dSLionel Sambuc       Op->RegList.List->push_back(Reg);
1015*0a6a1f1dSLionel Sambuc     Op->StartLoc = StartLoc;
1016*0a6a1f1dSLionel Sambuc     Op->EndLoc = EndLoc;
1017*0a6a1f1dSLionel Sambuc     return Op;
1018f4a2713aSLionel Sambuc   }
1019f4a2713aSLionel Sambuc 
1020*0a6a1f1dSLionel Sambuc   static std::unique_ptr<MipsOperand>
CreateRegPair(unsigned RegNo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1021*0a6a1f1dSLionel Sambuc   CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1022*0a6a1f1dSLionel Sambuc     auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1023*0a6a1f1dSLionel Sambuc     Op->RegIdx.Index = RegNo;
1024*0a6a1f1dSLionel Sambuc     Op->StartLoc = S;
1025*0a6a1f1dSLionel Sambuc     Op->EndLoc = E;
1026*0a6a1f1dSLionel Sambuc     return Op;
1027f4a2713aSLionel Sambuc   }
1028f4a2713aSLionel Sambuc 
isGPRAsmReg() const1029*0a6a1f1dSLionel Sambuc   bool isGPRAsmReg() const {
1030*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
1031f4a2713aSLionel Sambuc   }
isMM16AsmReg() const1032*0a6a1f1dSLionel Sambuc   bool isMM16AsmReg() const {
1033*0a6a1f1dSLionel Sambuc     if (!(isRegIdx() && RegIdx.Kind))
1034*0a6a1f1dSLionel Sambuc       return false;
1035*0a6a1f1dSLionel Sambuc     return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1036*0a6a1f1dSLionel Sambuc             || RegIdx.Index == 16 || RegIdx.Index == 17);
1037f4a2713aSLionel Sambuc   }
isMM16AsmRegZero() const1038*0a6a1f1dSLionel Sambuc   bool isMM16AsmRegZero() const {
1039*0a6a1f1dSLionel Sambuc     if (!(isRegIdx() && RegIdx.Kind))
1040*0a6a1f1dSLionel Sambuc       return false;
1041*0a6a1f1dSLionel Sambuc     return (RegIdx.Index == 0 ||
1042*0a6a1f1dSLionel Sambuc             (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1043*0a6a1f1dSLionel Sambuc             RegIdx.Index == 17);
1044f4a2713aSLionel Sambuc   }
isFGRAsmReg() const1045*0a6a1f1dSLionel Sambuc   bool isFGRAsmReg() const {
1046*0a6a1f1dSLionel Sambuc     // AFGR64 is $0-$15 but we handle this in getAFGR64()
1047*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
1048f4a2713aSLionel Sambuc   }
isHWRegsAsmReg() const1049*0a6a1f1dSLionel Sambuc   bool isHWRegsAsmReg() const {
1050*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
1051f4a2713aSLionel Sambuc   }
isCCRAsmReg() const1052*0a6a1f1dSLionel Sambuc   bool isCCRAsmReg() const {
1053*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
1054f4a2713aSLionel Sambuc   }
isFCCAsmReg() const1055*0a6a1f1dSLionel Sambuc   bool isFCCAsmReg() const {
1056*0a6a1f1dSLionel Sambuc     if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1057*0a6a1f1dSLionel Sambuc       return false;
1058*0a6a1f1dSLionel Sambuc     if (!AsmParser.hasEightFccRegisters())
1059*0a6a1f1dSLionel Sambuc       return RegIdx.Index == 0;
1060*0a6a1f1dSLionel Sambuc     return RegIdx.Index <= 7;
1061f4a2713aSLionel Sambuc   }
isACCAsmReg() const1062*0a6a1f1dSLionel Sambuc   bool isACCAsmReg() const {
1063*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
1064f4a2713aSLionel Sambuc   }
isCOP2AsmReg() const1065*0a6a1f1dSLionel Sambuc   bool isCOP2AsmReg() const {
1066*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
1067f4a2713aSLionel Sambuc   }
isCOP3AsmReg() const1068*0a6a1f1dSLionel Sambuc   bool isCOP3AsmReg() const {
1069*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1070f4a2713aSLionel Sambuc   }
isMSA128AsmReg() const1071*0a6a1f1dSLionel Sambuc   bool isMSA128AsmReg() const {
1072*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
1073f4a2713aSLionel Sambuc   }
isMSACtrlAsmReg() const1074*0a6a1f1dSLionel Sambuc   bool isMSACtrlAsmReg() const {
1075*0a6a1f1dSLionel Sambuc     return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
1076f4a2713aSLionel Sambuc   }
1077f4a2713aSLionel Sambuc 
1078f4a2713aSLionel Sambuc   /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const1079*0a6a1f1dSLionel Sambuc   SMLoc getStartLoc() const override { return StartLoc; }
1080f4a2713aSLionel Sambuc   /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const1081*0a6a1f1dSLionel Sambuc   SMLoc getEndLoc() const override { return EndLoc; }
1082f4a2713aSLionel Sambuc 
~MipsOperand()1083*0a6a1f1dSLionel Sambuc   virtual ~MipsOperand() {
1084*0a6a1f1dSLionel Sambuc     switch (Kind) {
1085*0a6a1f1dSLionel Sambuc     case k_Immediate:
1086*0a6a1f1dSLionel Sambuc       break;
1087*0a6a1f1dSLionel Sambuc     case k_Memory:
1088*0a6a1f1dSLionel Sambuc       delete Mem.Base;
1089*0a6a1f1dSLionel Sambuc       break;
1090*0a6a1f1dSLionel Sambuc     case k_RegList:
1091*0a6a1f1dSLionel Sambuc       delete RegList.List;
1092*0a6a1f1dSLionel Sambuc     case k_PhysRegister:
1093*0a6a1f1dSLionel Sambuc     case k_RegisterIndex:
1094*0a6a1f1dSLionel Sambuc     case k_Token:
1095*0a6a1f1dSLionel Sambuc     case k_RegPair:
1096*0a6a1f1dSLionel Sambuc       break;
1097*0a6a1f1dSLionel Sambuc     }
1098*0a6a1f1dSLionel Sambuc   }
1099*0a6a1f1dSLionel Sambuc 
print(raw_ostream & OS) const1100*0a6a1f1dSLionel Sambuc   void print(raw_ostream &OS) const override {
1101*0a6a1f1dSLionel Sambuc     switch (Kind) {
1102*0a6a1f1dSLionel Sambuc     case k_Immediate:
1103*0a6a1f1dSLionel Sambuc       OS << "Imm<";
1104*0a6a1f1dSLionel Sambuc       Imm.Val->print(OS);
1105*0a6a1f1dSLionel Sambuc       OS << ">";
1106*0a6a1f1dSLionel Sambuc       break;
1107*0a6a1f1dSLionel Sambuc     case k_Memory:
1108*0a6a1f1dSLionel Sambuc       OS << "Mem<";
1109*0a6a1f1dSLionel Sambuc       Mem.Base->print(OS);
1110*0a6a1f1dSLionel Sambuc       OS << ", ";
1111*0a6a1f1dSLionel Sambuc       Mem.Off->print(OS);
1112*0a6a1f1dSLionel Sambuc       OS << ">";
1113*0a6a1f1dSLionel Sambuc       break;
1114*0a6a1f1dSLionel Sambuc     case k_PhysRegister:
1115*0a6a1f1dSLionel Sambuc       OS << "PhysReg<" << PhysReg.Num << ">";
1116*0a6a1f1dSLionel Sambuc       break;
1117*0a6a1f1dSLionel Sambuc     case k_RegisterIndex:
1118*0a6a1f1dSLionel Sambuc       OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1119*0a6a1f1dSLionel Sambuc       break;
1120*0a6a1f1dSLionel Sambuc     case k_Token:
1121*0a6a1f1dSLionel Sambuc       OS << Tok.Data;
1122*0a6a1f1dSLionel Sambuc       break;
1123*0a6a1f1dSLionel Sambuc     case k_RegList:
1124*0a6a1f1dSLionel Sambuc       OS << "RegList< ";
1125*0a6a1f1dSLionel Sambuc       for (auto Reg : (*RegList.List))
1126*0a6a1f1dSLionel Sambuc         OS << Reg << " ";
1127*0a6a1f1dSLionel Sambuc       OS <<  ">";
1128*0a6a1f1dSLionel Sambuc       break;
1129*0a6a1f1dSLionel Sambuc     case k_RegPair:
1130*0a6a1f1dSLionel Sambuc       OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1131*0a6a1f1dSLionel Sambuc       break;
1132*0a6a1f1dSLionel Sambuc     }
1133f4a2713aSLionel Sambuc   }
1134f4a2713aSLionel Sambuc }; // class MipsOperand
1135f4a2713aSLionel Sambuc } // namespace
1136f4a2713aSLionel Sambuc 
1137f4a2713aSLionel Sambuc namespace llvm {
1138f4a2713aSLionel Sambuc extern const MCInstrDesc MipsInsts[];
1139f4a2713aSLionel Sambuc }
getInstDesc(unsigned Opcode)1140f4a2713aSLionel Sambuc static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1141f4a2713aSLionel Sambuc   return MipsInsts[Opcode];
1142f4a2713aSLionel Sambuc }
1143f4a2713aSLionel Sambuc 
hasShortDelaySlot(unsigned Opcode)1144*0a6a1f1dSLionel Sambuc static bool hasShortDelaySlot(unsigned Opcode) {
1145*0a6a1f1dSLionel Sambuc   switch (Opcode) {
1146*0a6a1f1dSLionel Sambuc     case Mips::JALS_MM:
1147*0a6a1f1dSLionel Sambuc     case Mips::JALRS_MM:
1148*0a6a1f1dSLionel Sambuc     case Mips::JALRS16_MM:
1149*0a6a1f1dSLionel Sambuc     case Mips::BGEZALS_MM:
1150*0a6a1f1dSLionel Sambuc     case Mips::BLTZALS_MM:
1151*0a6a1f1dSLionel Sambuc       return true;
1152*0a6a1f1dSLionel Sambuc     default:
1153*0a6a1f1dSLionel Sambuc       return false;
1154*0a6a1f1dSLionel Sambuc   }
1155*0a6a1f1dSLionel Sambuc }
1156*0a6a1f1dSLionel Sambuc 
processInstruction(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1157f4a2713aSLionel Sambuc bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1158f4a2713aSLionel Sambuc                                        SmallVectorImpl<MCInst> &Instructions) {
1159f4a2713aSLionel Sambuc   const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
1160*0a6a1f1dSLionel Sambuc 
1161f4a2713aSLionel Sambuc   Inst.setLoc(IDLoc);
1162*0a6a1f1dSLionel Sambuc 
1163*0a6a1f1dSLionel Sambuc   if (MCID.isBranch() || MCID.isCall()) {
1164*0a6a1f1dSLionel Sambuc     const unsigned Opcode = Inst.getOpcode();
1165*0a6a1f1dSLionel Sambuc     MCOperand Offset;
1166*0a6a1f1dSLionel Sambuc 
1167*0a6a1f1dSLionel Sambuc     switch (Opcode) {
1168*0a6a1f1dSLionel Sambuc     default:
1169*0a6a1f1dSLionel Sambuc       break;
1170*0a6a1f1dSLionel Sambuc     case Mips::BEQ:
1171*0a6a1f1dSLionel Sambuc     case Mips::BNE:
1172*0a6a1f1dSLionel Sambuc     case Mips::BEQ_MM:
1173*0a6a1f1dSLionel Sambuc     case Mips::BNE_MM:
1174*0a6a1f1dSLionel Sambuc       assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1175*0a6a1f1dSLionel Sambuc       Offset = Inst.getOperand(2);
1176*0a6a1f1dSLionel Sambuc       if (!Offset.isImm())
1177*0a6a1f1dSLionel Sambuc         break; // We'll deal with this situation later on when applying fixups.
1178*0a6a1f1dSLionel Sambuc       if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
1179*0a6a1f1dSLionel Sambuc         return Error(IDLoc, "branch target out of range");
1180*0a6a1f1dSLionel Sambuc       if (OffsetToAlignment(Offset.getImm(),
1181*0a6a1f1dSLionel Sambuc                             1LL << (inMicroMipsMode() ? 1 : 2)))
1182*0a6a1f1dSLionel Sambuc         return Error(IDLoc, "branch to misaligned address");
1183*0a6a1f1dSLionel Sambuc       break;
1184*0a6a1f1dSLionel Sambuc     case Mips::BGEZ:
1185*0a6a1f1dSLionel Sambuc     case Mips::BGTZ:
1186*0a6a1f1dSLionel Sambuc     case Mips::BLEZ:
1187*0a6a1f1dSLionel Sambuc     case Mips::BLTZ:
1188*0a6a1f1dSLionel Sambuc     case Mips::BGEZAL:
1189*0a6a1f1dSLionel Sambuc     case Mips::BLTZAL:
1190*0a6a1f1dSLionel Sambuc     case Mips::BC1F:
1191*0a6a1f1dSLionel Sambuc     case Mips::BC1T:
1192*0a6a1f1dSLionel Sambuc     case Mips::BGEZ_MM:
1193*0a6a1f1dSLionel Sambuc     case Mips::BGTZ_MM:
1194*0a6a1f1dSLionel Sambuc     case Mips::BLEZ_MM:
1195*0a6a1f1dSLionel Sambuc     case Mips::BLTZ_MM:
1196*0a6a1f1dSLionel Sambuc     case Mips::BGEZAL_MM:
1197*0a6a1f1dSLionel Sambuc     case Mips::BLTZAL_MM:
1198*0a6a1f1dSLionel Sambuc     case Mips::BC1F_MM:
1199*0a6a1f1dSLionel Sambuc     case Mips::BC1T_MM:
1200*0a6a1f1dSLionel Sambuc       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1201*0a6a1f1dSLionel Sambuc       Offset = Inst.getOperand(1);
1202*0a6a1f1dSLionel Sambuc       if (!Offset.isImm())
1203*0a6a1f1dSLionel Sambuc         break; // We'll deal with this situation later on when applying fixups.
1204*0a6a1f1dSLionel Sambuc       if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
1205*0a6a1f1dSLionel Sambuc         return Error(IDLoc, "branch target out of range");
1206*0a6a1f1dSLionel Sambuc       if (OffsetToAlignment(Offset.getImm(),
1207*0a6a1f1dSLionel Sambuc                             1LL << (inMicroMipsMode() ? 1 : 2)))
1208*0a6a1f1dSLionel Sambuc         return Error(IDLoc, "branch to misaligned address");
1209*0a6a1f1dSLionel Sambuc       break;
1210*0a6a1f1dSLionel Sambuc     case Mips::BEQZ16_MM:
1211*0a6a1f1dSLionel Sambuc     case Mips::BNEZ16_MM:
1212*0a6a1f1dSLionel Sambuc       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1213*0a6a1f1dSLionel Sambuc       Offset = Inst.getOperand(1);
1214*0a6a1f1dSLionel Sambuc       if (!Offset.isImm())
1215*0a6a1f1dSLionel Sambuc         break; // We'll deal with this situation later on when applying fixups.
1216*0a6a1f1dSLionel Sambuc       if (!isIntN(8, Offset.getImm()))
1217*0a6a1f1dSLionel Sambuc         return Error(IDLoc, "branch target out of range");
1218*0a6a1f1dSLionel Sambuc       if (OffsetToAlignment(Offset.getImm(), 2LL))
1219*0a6a1f1dSLionel Sambuc         return Error(IDLoc, "branch to misaligned address");
1220*0a6a1f1dSLionel Sambuc       break;
1221*0a6a1f1dSLionel Sambuc     }
1222*0a6a1f1dSLionel Sambuc   }
1223*0a6a1f1dSLionel Sambuc 
1224*0a6a1f1dSLionel Sambuc   // SSNOP is deprecated on MIPS32r6/MIPS64r6
1225*0a6a1f1dSLionel Sambuc   // We still accept it but it is a normal nop.
1226*0a6a1f1dSLionel Sambuc   if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1227*0a6a1f1dSLionel Sambuc     std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1228*0a6a1f1dSLionel Sambuc     Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1229*0a6a1f1dSLionel Sambuc                                                       "nop instruction");
1230*0a6a1f1dSLionel Sambuc   }
1231*0a6a1f1dSLionel Sambuc 
1232*0a6a1f1dSLionel Sambuc   if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
1233f4a2713aSLionel Sambuc     // If this instruction has a delay slot and .set reorder is active,
1234f4a2713aSLionel Sambuc     // emit a NOP after it.
1235f4a2713aSLionel Sambuc     Instructions.push_back(Inst);
1236f4a2713aSLionel Sambuc     MCInst NopInst;
1237*0a6a1f1dSLionel Sambuc     if (hasShortDelaySlot(Inst.getOpcode())) {
1238*0a6a1f1dSLionel Sambuc       NopInst.setOpcode(Mips::MOVE16_MM);
1239*0a6a1f1dSLionel Sambuc       NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1240*0a6a1f1dSLionel Sambuc       NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1241*0a6a1f1dSLionel Sambuc     } else {
1242f4a2713aSLionel Sambuc       NopInst.setOpcode(Mips::SLL);
1243f4a2713aSLionel Sambuc       NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1244f4a2713aSLionel Sambuc       NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1245f4a2713aSLionel Sambuc       NopInst.addOperand(MCOperand::CreateImm(0));
1246*0a6a1f1dSLionel Sambuc     }
1247f4a2713aSLionel Sambuc     Instructions.push_back(NopInst);
1248f4a2713aSLionel Sambuc     return false;
1249f4a2713aSLionel Sambuc   }
1250f4a2713aSLionel Sambuc 
1251f4a2713aSLionel Sambuc   if (MCID.mayLoad() || MCID.mayStore()) {
1252f4a2713aSLionel Sambuc     // Check the offset of memory operand, if it is a symbol
1253f4a2713aSLionel Sambuc     // reference or immediate we may have to expand instructions.
1254f4a2713aSLionel Sambuc     for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1255f4a2713aSLionel Sambuc       const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1256f4a2713aSLionel Sambuc       if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1257f4a2713aSLionel Sambuc           (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1258f4a2713aSLionel Sambuc         MCOperand &Op = Inst.getOperand(i);
1259f4a2713aSLionel Sambuc         if (Op.isImm()) {
1260f4a2713aSLionel Sambuc           int MemOffset = Op.getImm();
1261f4a2713aSLionel Sambuc           if (MemOffset < -32768 || MemOffset > 32767) {
1262f4a2713aSLionel Sambuc             // Offset can't exceed 16bit value.
1263f4a2713aSLionel Sambuc             expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
1264f4a2713aSLionel Sambuc             return false;
1265f4a2713aSLionel Sambuc           }
1266f4a2713aSLionel Sambuc         } else if (Op.isExpr()) {
1267f4a2713aSLionel Sambuc           const MCExpr *Expr = Op.getExpr();
1268f4a2713aSLionel Sambuc           if (Expr->getKind() == MCExpr::SymbolRef) {
1269f4a2713aSLionel Sambuc             const MCSymbolRefExpr *SR =
1270f4a2713aSLionel Sambuc                 static_cast<const MCSymbolRefExpr *>(Expr);
1271f4a2713aSLionel Sambuc             if (SR->getKind() == MCSymbolRefExpr::VK_None) {
1272f4a2713aSLionel Sambuc               // Expand symbol.
1273f4a2713aSLionel Sambuc               expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
1274f4a2713aSLionel Sambuc               return false;
1275f4a2713aSLionel Sambuc             }
1276f4a2713aSLionel Sambuc           } else if (!isEvaluated(Expr)) {
1277f4a2713aSLionel Sambuc             expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
1278f4a2713aSLionel Sambuc             return false;
1279f4a2713aSLionel Sambuc           }
1280f4a2713aSLionel Sambuc         }
1281f4a2713aSLionel Sambuc       }
1282f4a2713aSLionel Sambuc     } // for
1283f4a2713aSLionel Sambuc   }   // if load/store
1284f4a2713aSLionel Sambuc 
1285*0a6a1f1dSLionel Sambuc   // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1286*0a6a1f1dSLionel Sambuc   if (inMicroMipsMode()) {
1287*0a6a1f1dSLionel Sambuc     MCOperand Opnd;
1288*0a6a1f1dSLionel Sambuc     int Imm;
1289*0a6a1f1dSLionel Sambuc 
1290*0a6a1f1dSLionel Sambuc     switch (Inst.getOpcode()) {
1291*0a6a1f1dSLionel Sambuc       default:
1292*0a6a1f1dSLionel Sambuc         break;
1293*0a6a1f1dSLionel Sambuc       case Mips::ADDIUS5_MM:
1294*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1295*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1296*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1297*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1298*0a6a1f1dSLionel Sambuc         if (Imm < -8 || Imm > 7)
1299*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1300*0a6a1f1dSLionel Sambuc         break;
1301*0a6a1f1dSLionel Sambuc       case Mips::ADDIUSP_MM:
1302*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(0);
1303*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1304*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1305*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1306*0a6a1f1dSLionel Sambuc         if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1307*0a6a1f1dSLionel Sambuc             Imm % 4 != 0)
1308*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1309*0a6a1f1dSLionel Sambuc         break;
1310*0a6a1f1dSLionel Sambuc       case Mips::SLL16_MM:
1311*0a6a1f1dSLionel Sambuc       case Mips::SRL16_MM:
1312*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1313*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1314*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1315*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1316*0a6a1f1dSLionel Sambuc         if (Imm < 1 || Imm > 8)
1317*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1318*0a6a1f1dSLionel Sambuc         break;
1319*0a6a1f1dSLionel Sambuc       case Mips::LI16_MM:
1320*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(1);
1321*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1322*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1323*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1324*0a6a1f1dSLionel Sambuc         if (Imm < -1 || Imm > 126)
1325*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1326*0a6a1f1dSLionel Sambuc         break;
1327*0a6a1f1dSLionel Sambuc       case Mips::ADDIUR2_MM:
1328*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1329*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1330*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1331*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1332*0a6a1f1dSLionel Sambuc         if (!(Imm == 1 || Imm == -1 ||
1333*0a6a1f1dSLionel Sambuc               ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1334*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1335*0a6a1f1dSLionel Sambuc         break;
1336*0a6a1f1dSLionel Sambuc       case Mips::ADDIUR1SP_MM:
1337*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(1);
1338*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1339*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1340*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1341*0a6a1f1dSLionel Sambuc         if (OffsetToAlignment(Imm, 4LL))
1342*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "misaligned immediate operand value");
1343*0a6a1f1dSLionel Sambuc         if (Imm < 0 || Imm > 255)
1344*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1345*0a6a1f1dSLionel Sambuc         break;
1346*0a6a1f1dSLionel Sambuc       case Mips::ANDI16_MM:
1347*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1348*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1349*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1350*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1351*0a6a1f1dSLionel Sambuc         if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1352*0a6a1f1dSLionel Sambuc               Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1353*0a6a1f1dSLionel Sambuc               Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1354*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1355*0a6a1f1dSLionel Sambuc         break;
1356*0a6a1f1dSLionel Sambuc       case Mips::LBU16_MM:
1357*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1358*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1359*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1360*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1361*0a6a1f1dSLionel Sambuc         if (Imm < -1 || Imm > 14)
1362*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1363*0a6a1f1dSLionel Sambuc         break;
1364*0a6a1f1dSLionel Sambuc       case Mips::SB16_MM:
1365*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1366*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1367*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1368*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1369*0a6a1f1dSLionel Sambuc         if (Imm < 0 || Imm > 15)
1370*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1371*0a6a1f1dSLionel Sambuc         break;
1372*0a6a1f1dSLionel Sambuc       case Mips::LHU16_MM:
1373*0a6a1f1dSLionel Sambuc       case Mips::SH16_MM:
1374*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1375*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1376*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1377*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1378*0a6a1f1dSLionel Sambuc         if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1379*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1380*0a6a1f1dSLionel Sambuc         break;
1381*0a6a1f1dSLionel Sambuc       case Mips::LW16_MM:
1382*0a6a1f1dSLionel Sambuc       case Mips::SW16_MM:
1383*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1384*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1385*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1386*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1387*0a6a1f1dSLionel Sambuc         if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1388*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1389*0a6a1f1dSLionel Sambuc         break;
1390*0a6a1f1dSLionel Sambuc       case Mips::CACHE:
1391*0a6a1f1dSLionel Sambuc       case Mips::PREF:
1392*0a6a1f1dSLionel Sambuc         Opnd = Inst.getOperand(2);
1393*0a6a1f1dSLionel Sambuc         if (!Opnd.isImm())
1394*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "expected immediate operand kind");
1395*0a6a1f1dSLionel Sambuc         Imm = Opnd.getImm();
1396*0a6a1f1dSLionel Sambuc         if (!isUInt<5>(Imm))
1397*0a6a1f1dSLionel Sambuc           return Error(IDLoc, "immediate operand value out of range");
1398*0a6a1f1dSLionel Sambuc         break;
1399*0a6a1f1dSLionel Sambuc     }
1400*0a6a1f1dSLionel Sambuc   }
1401*0a6a1f1dSLionel Sambuc 
1402f4a2713aSLionel Sambuc   if (needsExpansion(Inst))
1403*0a6a1f1dSLionel Sambuc     return expandInstruction(Inst, IDLoc, Instructions);
1404f4a2713aSLionel Sambuc   else
1405f4a2713aSLionel Sambuc     Instructions.push_back(Inst);
1406f4a2713aSLionel Sambuc 
1407f4a2713aSLionel Sambuc   return false;
1408f4a2713aSLionel Sambuc }
1409f4a2713aSLionel Sambuc 
needsExpansion(MCInst & Inst)1410f4a2713aSLionel Sambuc bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1411f4a2713aSLionel Sambuc 
1412f4a2713aSLionel Sambuc   switch (Inst.getOpcode()) {
1413f4a2713aSLionel Sambuc   case Mips::LoadImm32Reg:
1414f4a2713aSLionel Sambuc   case Mips::LoadAddr32Imm:
1415f4a2713aSLionel Sambuc   case Mips::LoadAddr32Reg:
1416*0a6a1f1dSLionel Sambuc   case Mips::LoadImm64Reg:
1417f4a2713aSLionel Sambuc     return true;
1418f4a2713aSLionel Sambuc   default:
1419f4a2713aSLionel Sambuc     return false;
1420f4a2713aSLionel Sambuc   }
1421f4a2713aSLionel Sambuc }
1422f4a2713aSLionel Sambuc 
expandInstruction(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1423*0a6a1f1dSLionel Sambuc bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
1424f4a2713aSLionel Sambuc                                       SmallVectorImpl<MCInst> &Instructions) {
1425f4a2713aSLionel Sambuc   switch (Inst.getOpcode()) {
1426*0a6a1f1dSLionel Sambuc   default: llvm_unreachable("unimplemented expansion");
1427f4a2713aSLionel Sambuc   case Mips::LoadImm32Reg:
1428f4a2713aSLionel Sambuc     return expandLoadImm(Inst, IDLoc, Instructions);
1429*0a6a1f1dSLionel Sambuc   case Mips::LoadImm64Reg:
1430*0a6a1f1dSLionel Sambuc     if (!isGP64bit()) {
1431*0a6a1f1dSLionel Sambuc       Error(IDLoc, "instruction requires a 64-bit architecture");
1432*0a6a1f1dSLionel Sambuc       return true;
1433*0a6a1f1dSLionel Sambuc     }
1434*0a6a1f1dSLionel Sambuc     return expandLoadImm(Inst, IDLoc, Instructions);
1435f4a2713aSLionel Sambuc   case Mips::LoadAddr32Imm:
1436f4a2713aSLionel Sambuc     return expandLoadAddressImm(Inst, IDLoc, Instructions);
1437f4a2713aSLionel Sambuc   case Mips::LoadAddr32Reg:
1438f4a2713aSLionel Sambuc     return expandLoadAddressReg(Inst, IDLoc, Instructions);
1439f4a2713aSLionel Sambuc   }
1440f4a2713aSLionel Sambuc }
1441f4a2713aSLionel Sambuc 
1442*0a6a1f1dSLionel Sambuc namespace {
1443*0a6a1f1dSLionel Sambuc template <bool PerformShift>
createShiftOr(MCOperand Operand,unsigned RegNo,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1444*0a6a1f1dSLionel Sambuc void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
1445*0a6a1f1dSLionel Sambuc                    SmallVectorImpl<MCInst> &Instructions) {
1446*0a6a1f1dSLionel Sambuc   MCInst tmpInst;
1447*0a6a1f1dSLionel Sambuc   if (PerformShift) {
1448*0a6a1f1dSLionel Sambuc     tmpInst.setOpcode(Mips::DSLL);
1449*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1450*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1451*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(16));
1452*0a6a1f1dSLionel Sambuc     tmpInst.setLoc(IDLoc);
1453*0a6a1f1dSLionel Sambuc     Instructions.push_back(tmpInst);
1454*0a6a1f1dSLionel Sambuc     tmpInst.clear();
1455*0a6a1f1dSLionel Sambuc   }
1456*0a6a1f1dSLionel Sambuc   tmpInst.setOpcode(Mips::ORi);
1457*0a6a1f1dSLionel Sambuc   tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1458*0a6a1f1dSLionel Sambuc   tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1459*0a6a1f1dSLionel Sambuc   tmpInst.addOperand(Operand);
1460*0a6a1f1dSLionel Sambuc   tmpInst.setLoc(IDLoc);
1461*0a6a1f1dSLionel Sambuc   Instructions.push_back(tmpInst);
1462*0a6a1f1dSLionel Sambuc }
1463*0a6a1f1dSLionel Sambuc 
1464*0a6a1f1dSLionel Sambuc template <int Shift, bool PerformShift>
createShiftOr(int64_t Value,unsigned RegNo,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1465*0a6a1f1dSLionel Sambuc void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1466*0a6a1f1dSLionel Sambuc                    SmallVectorImpl<MCInst> &Instructions) {
1467*0a6a1f1dSLionel Sambuc   createShiftOr<PerformShift>(
1468*0a6a1f1dSLionel Sambuc       MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1469*0a6a1f1dSLionel Sambuc       IDLoc, Instructions);
1470*0a6a1f1dSLionel Sambuc }
1471*0a6a1f1dSLionel Sambuc }
1472*0a6a1f1dSLionel Sambuc 
expandLoadImm(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1473*0a6a1f1dSLionel Sambuc bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
1474f4a2713aSLionel Sambuc                                   SmallVectorImpl<MCInst> &Instructions) {
1475f4a2713aSLionel Sambuc   MCInst tmpInst;
1476f4a2713aSLionel Sambuc   const MCOperand &ImmOp = Inst.getOperand(1);
1477f4a2713aSLionel Sambuc   assert(ImmOp.isImm() && "expected immediate operand kind");
1478f4a2713aSLionel Sambuc   const MCOperand &RegOp = Inst.getOperand(0);
1479f4a2713aSLionel Sambuc   assert(RegOp.isReg() && "expected register operand kind");
1480f4a2713aSLionel Sambuc 
1481*0a6a1f1dSLionel Sambuc   int64_t ImmValue = ImmOp.getImm();
1482f4a2713aSLionel Sambuc   tmpInst.setLoc(IDLoc);
1483*0a6a1f1dSLionel Sambuc   // FIXME: gas has a special case for values that are 000...1111, which
1484*0a6a1f1dSLionel Sambuc   // becomes a li -1 and then a dsrl
1485f4a2713aSLionel Sambuc   if (0 <= ImmValue && ImmValue <= 65535) {
1486f4a2713aSLionel Sambuc     // For 0 <= j <= 65535.
1487f4a2713aSLionel Sambuc     // li d,j => ori d,$zero,j
1488f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ORi);
1489f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1490f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1491f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1492f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1493f4a2713aSLionel Sambuc   } else if (ImmValue < 0 && ImmValue >= -32768) {
1494f4a2713aSLionel Sambuc     // For -32768 <= j < 0.
1495f4a2713aSLionel Sambuc     // li d,j => addiu d,$zero,j
1496f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ADDiu);
1497f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1498f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1499f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1500f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1501*0a6a1f1dSLionel Sambuc   } else if ((ImmValue & 0xffffffff) == ImmValue) {
1502*0a6a1f1dSLionel Sambuc     // For any value of j that is representable as a 32-bit integer, create
1503*0a6a1f1dSLionel Sambuc     // a sequence of:
1504f4a2713aSLionel Sambuc     // li d,j => lui d,hi16(j)
1505f4a2713aSLionel Sambuc     //           ori d,d,lo16(j)
1506f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1507f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1508f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1509f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1510*0a6a1f1dSLionel Sambuc     createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1511*0a6a1f1dSLionel Sambuc   } else if ((ImmValue & (0xffffLL << 48)) == 0) {
1512*0a6a1f1dSLionel Sambuc     if (!isGP64bit()) {
1513*0a6a1f1dSLionel Sambuc       Error(IDLoc, "instruction requires a 64-bit architecture");
1514*0a6a1f1dSLionel Sambuc       return true;
1515f4a2713aSLionel Sambuc     }
1516f4a2713aSLionel Sambuc 
1517*0a6a1f1dSLionel Sambuc     //            <-------  lo32 ------>
1518*0a6a1f1dSLionel Sambuc     // <-------  hi32 ------>
1519*0a6a1f1dSLionel Sambuc     // <- hi16 ->             <- lo16 ->
1520*0a6a1f1dSLionel Sambuc     //  _________________________________
1521*0a6a1f1dSLionel Sambuc     // |          |          |          |
1522*0a6a1f1dSLionel Sambuc     // | 16-bytes | 16-bytes | 16-bytes |
1523*0a6a1f1dSLionel Sambuc     // |__________|__________|__________|
1524*0a6a1f1dSLionel Sambuc     //
1525*0a6a1f1dSLionel Sambuc     // For any value of j that is representable as a 48-bit integer, create
1526*0a6a1f1dSLionel Sambuc     // a sequence of:
1527*0a6a1f1dSLionel Sambuc     // li d,j => lui d,hi16(j)
1528*0a6a1f1dSLionel Sambuc     //           ori d,d,hi16(lo32(j))
1529*0a6a1f1dSLionel Sambuc     //           dsll d,d,16
1530*0a6a1f1dSLionel Sambuc     //           ori d,d,lo16(lo32(j))
1531*0a6a1f1dSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1532*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1533*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(
1534*0a6a1f1dSLionel Sambuc         MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
1535*0a6a1f1dSLionel Sambuc     Instructions.push_back(tmpInst);
1536*0a6a1f1dSLionel Sambuc     createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1537*0a6a1f1dSLionel Sambuc     createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1538*0a6a1f1dSLionel Sambuc   } else {
1539*0a6a1f1dSLionel Sambuc     if (!isGP64bit()) {
1540*0a6a1f1dSLionel Sambuc       Error(IDLoc, "instruction requires a 64-bit architecture");
1541*0a6a1f1dSLionel Sambuc       return true;
1542*0a6a1f1dSLionel Sambuc     }
1543*0a6a1f1dSLionel Sambuc 
1544*0a6a1f1dSLionel Sambuc     // <-------  hi32 ------> <-------  lo32 ------>
1545*0a6a1f1dSLionel Sambuc     // <- hi16 ->                        <- lo16 ->
1546*0a6a1f1dSLionel Sambuc     //  ___________________________________________
1547*0a6a1f1dSLionel Sambuc     // |          |          |          |          |
1548*0a6a1f1dSLionel Sambuc     // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1549*0a6a1f1dSLionel Sambuc     // |__________|__________|__________|__________|
1550*0a6a1f1dSLionel Sambuc     //
1551*0a6a1f1dSLionel Sambuc     // For any value of j that isn't representable as a 48-bit integer.
1552*0a6a1f1dSLionel Sambuc     // li d,j => lui d,hi16(j)
1553*0a6a1f1dSLionel Sambuc     //           ori d,d,lo16(hi32(j))
1554*0a6a1f1dSLionel Sambuc     //           dsll d,d,16
1555*0a6a1f1dSLionel Sambuc     //           ori d,d,hi16(lo32(j))
1556*0a6a1f1dSLionel Sambuc     //           dsll d,d,16
1557*0a6a1f1dSLionel Sambuc     //           ori d,d,lo16(lo32(j))
1558*0a6a1f1dSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1559*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1560*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(
1561*0a6a1f1dSLionel Sambuc         MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1562*0a6a1f1dSLionel Sambuc     Instructions.push_back(tmpInst);
1563*0a6a1f1dSLionel Sambuc     createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1564*0a6a1f1dSLionel Sambuc     createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1565*0a6a1f1dSLionel Sambuc     createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1566*0a6a1f1dSLionel Sambuc   }
1567*0a6a1f1dSLionel Sambuc   return false;
1568*0a6a1f1dSLionel Sambuc }
1569*0a6a1f1dSLionel Sambuc 
1570*0a6a1f1dSLionel Sambuc bool
expandLoadAddressReg(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1571f4a2713aSLionel Sambuc MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1572f4a2713aSLionel Sambuc                                     SmallVectorImpl<MCInst> &Instructions) {
1573f4a2713aSLionel Sambuc   MCInst tmpInst;
1574f4a2713aSLionel Sambuc   const MCOperand &ImmOp = Inst.getOperand(2);
1575*0a6a1f1dSLionel Sambuc   assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1576*0a6a1f1dSLionel Sambuc          "expected immediate operand kind");
1577*0a6a1f1dSLionel Sambuc   if (!ImmOp.isImm()) {
1578*0a6a1f1dSLionel Sambuc     expandLoadAddressSym(Inst, IDLoc, Instructions);
1579*0a6a1f1dSLionel Sambuc     return false;
1580*0a6a1f1dSLionel Sambuc   }
1581f4a2713aSLionel Sambuc   const MCOperand &SrcRegOp = Inst.getOperand(1);
1582f4a2713aSLionel Sambuc   assert(SrcRegOp.isReg() && "expected register operand kind");
1583f4a2713aSLionel Sambuc   const MCOperand &DstRegOp = Inst.getOperand(0);
1584f4a2713aSLionel Sambuc   assert(DstRegOp.isReg() && "expected register operand kind");
1585f4a2713aSLionel Sambuc   int ImmValue = ImmOp.getImm();
1586f4a2713aSLionel Sambuc   if (-32768 <= ImmValue && ImmValue <= 65535) {
1587f4a2713aSLionel Sambuc     // For -32768 <= j <= 65535.
1588f4a2713aSLionel Sambuc     // la d,j(s) => addiu d,s,j
1589f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ADDiu);
1590f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1591f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1592f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1593f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1594f4a2713aSLionel Sambuc   } else {
1595f4a2713aSLionel Sambuc     // For any other value of j that is representable as a 32-bit integer.
1596f4a2713aSLionel Sambuc     // la d,j(s) => lui d,hi16(j)
1597f4a2713aSLionel Sambuc     //              ori d,d,lo16(j)
1598f4a2713aSLionel Sambuc     //              addu d,d,s
1599f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1600f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1601f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1602f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1603f4a2713aSLionel Sambuc     tmpInst.clear();
1604f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ORi);
1605f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1606f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1607f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1608f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1609f4a2713aSLionel Sambuc     tmpInst.clear();
1610f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ADDu);
1611f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1612f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1613f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1614f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1615f4a2713aSLionel Sambuc   }
1616*0a6a1f1dSLionel Sambuc   return false;
1617f4a2713aSLionel Sambuc }
1618f4a2713aSLionel Sambuc 
1619*0a6a1f1dSLionel Sambuc bool
expandLoadAddressImm(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1620f4a2713aSLionel Sambuc MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1621f4a2713aSLionel Sambuc                                     SmallVectorImpl<MCInst> &Instructions) {
1622f4a2713aSLionel Sambuc   MCInst tmpInst;
1623f4a2713aSLionel Sambuc   const MCOperand &ImmOp = Inst.getOperand(1);
1624*0a6a1f1dSLionel Sambuc   assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1625*0a6a1f1dSLionel Sambuc          "expected immediate operand kind");
1626*0a6a1f1dSLionel Sambuc   if (!ImmOp.isImm()) {
1627*0a6a1f1dSLionel Sambuc     expandLoadAddressSym(Inst, IDLoc, Instructions);
1628*0a6a1f1dSLionel Sambuc     return false;
1629*0a6a1f1dSLionel Sambuc   }
1630f4a2713aSLionel Sambuc   const MCOperand &RegOp = Inst.getOperand(0);
1631f4a2713aSLionel Sambuc   assert(RegOp.isReg() && "expected register operand kind");
1632f4a2713aSLionel Sambuc   int ImmValue = ImmOp.getImm();
1633f4a2713aSLionel Sambuc   if (-32768 <= ImmValue && ImmValue <= 65535) {
1634f4a2713aSLionel Sambuc     // For -32768 <= j <= 65535.
1635f4a2713aSLionel Sambuc     // la d,j => addiu d,$zero,j
1636f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ADDiu);
1637f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1638f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1639f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1640f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1641f4a2713aSLionel Sambuc   } else {
1642f4a2713aSLionel Sambuc     // For any other value of j that is representable as a 32-bit integer.
1643f4a2713aSLionel Sambuc     // la d,j => lui d,hi16(j)
1644f4a2713aSLionel Sambuc     //           ori d,d,lo16(j)
1645f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1646f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1647f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1648f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1649f4a2713aSLionel Sambuc     tmpInst.clear();
1650f4a2713aSLionel Sambuc     tmpInst.setOpcode(Mips::ORi);
1651f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1652f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1653f4a2713aSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1654f4a2713aSLionel Sambuc     Instructions.push_back(tmpInst);
1655f4a2713aSLionel Sambuc   }
1656*0a6a1f1dSLionel Sambuc   return false;
1657*0a6a1f1dSLionel Sambuc }
1658*0a6a1f1dSLionel Sambuc 
1659*0a6a1f1dSLionel Sambuc void
expandLoadAddressSym(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)1660*0a6a1f1dSLionel Sambuc MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1661*0a6a1f1dSLionel Sambuc                                     SmallVectorImpl<MCInst> &Instructions) {
1662*0a6a1f1dSLionel Sambuc   // FIXME: If we do have a valid at register to use, we should generate a
1663*0a6a1f1dSLionel Sambuc   // slightly shorter sequence here.
1664*0a6a1f1dSLionel Sambuc   MCInst tmpInst;
1665*0a6a1f1dSLionel Sambuc   int ExprOperandNo = 1;
1666*0a6a1f1dSLionel Sambuc   // Sometimes the assembly parser will get the immediate expression as
1667*0a6a1f1dSLionel Sambuc   // a $zero + an immediate.
1668*0a6a1f1dSLionel Sambuc   if (Inst.getNumOperands() == 3) {
1669*0a6a1f1dSLionel Sambuc     assert(Inst.getOperand(1).getReg() ==
1670*0a6a1f1dSLionel Sambuc            (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1671*0a6a1f1dSLionel Sambuc     ExprOperandNo = 2;
1672*0a6a1f1dSLionel Sambuc   }
1673*0a6a1f1dSLionel Sambuc   const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1674*0a6a1f1dSLionel Sambuc   assert(SymOp.isExpr() && "expected symbol operand kind");
1675*0a6a1f1dSLionel Sambuc   const MCOperand &RegOp = Inst.getOperand(0);
1676*0a6a1f1dSLionel Sambuc   unsigned RegNo = RegOp.getReg();
1677*0a6a1f1dSLionel Sambuc   const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1678*0a6a1f1dSLionel Sambuc   const MCSymbolRefExpr *HiExpr =
1679*0a6a1f1dSLionel Sambuc       MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1680*0a6a1f1dSLionel Sambuc                               MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1681*0a6a1f1dSLionel Sambuc   const MCSymbolRefExpr *LoExpr =
1682*0a6a1f1dSLionel Sambuc       MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1683*0a6a1f1dSLionel Sambuc                               MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1684*0a6a1f1dSLionel Sambuc   if (isGP64bit()) {
1685*0a6a1f1dSLionel Sambuc     // If it's a 64-bit architecture, expand to:
1686*0a6a1f1dSLionel Sambuc     // la d,sym => lui  d,highest(sym)
1687*0a6a1f1dSLionel Sambuc     //             ori  d,d,higher(sym)
1688*0a6a1f1dSLionel Sambuc     //             dsll d,d,16
1689*0a6a1f1dSLionel Sambuc     //             ori  d,d,hi16(sym)
1690*0a6a1f1dSLionel Sambuc     //             dsll d,d,16
1691*0a6a1f1dSLionel Sambuc     //             ori  d,d,lo16(sym)
1692*0a6a1f1dSLionel Sambuc     const MCSymbolRefExpr *HighestExpr =
1693*0a6a1f1dSLionel Sambuc         MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1694*0a6a1f1dSLionel Sambuc                                 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1695*0a6a1f1dSLionel Sambuc     const MCSymbolRefExpr *HigherExpr =
1696*0a6a1f1dSLionel Sambuc         MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1697*0a6a1f1dSLionel Sambuc                                 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1698*0a6a1f1dSLionel Sambuc 
1699*0a6a1f1dSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1700*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1701*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1702*0a6a1f1dSLionel Sambuc     Instructions.push_back(tmpInst);
1703*0a6a1f1dSLionel Sambuc 
1704*0a6a1f1dSLionel Sambuc     createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1705*0a6a1f1dSLionel Sambuc                          Instructions);
1706*0a6a1f1dSLionel Sambuc     createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1707*0a6a1f1dSLionel Sambuc                         Instructions);
1708*0a6a1f1dSLionel Sambuc     createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1709*0a6a1f1dSLionel Sambuc                         Instructions);
1710*0a6a1f1dSLionel Sambuc   } else {
1711*0a6a1f1dSLionel Sambuc     // Otherwise, expand to:
1712*0a6a1f1dSLionel Sambuc     // la d,sym => lui  d,hi16(sym)
1713*0a6a1f1dSLionel Sambuc     //             ori  d,d,lo16(sym)
1714*0a6a1f1dSLionel Sambuc     tmpInst.setOpcode(Mips::LUi);
1715*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1716*0a6a1f1dSLionel Sambuc     tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1717*0a6a1f1dSLionel Sambuc     Instructions.push_back(tmpInst);
1718*0a6a1f1dSLionel Sambuc 
1719*0a6a1f1dSLionel Sambuc     createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1720*0a6a1f1dSLionel Sambuc                          Instructions);
1721*0a6a1f1dSLionel Sambuc   }
1722f4a2713aSLionel Sambuc }
1723f4a2713aSLionel Sambuc 
expandMemInst(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions,bool isLoad,bool isImmOpnd)1724f4a2713aSLionel Sambuc void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
1725f4a2713aSLionel Sambuc                                   SmallVectorImpl<MCInst> &Instructions,
1726f4a2713aSLionel Sambuc                                   bool isLoad, bool isImmOpnd) {
1727f4a2713aSLionel Sambuc   const MCSymbolRefExpr *SR;
1728f4a2713aSLionel Sambuc   MCInst TempInst;
1729f4a2713aSLionel Sambuc   unsigned ImmOffset, HiOffset, LoOffset;
1730f4a2713aSLionel Sambuc   const MCExpr *ExprOffset;
1731f4a2713aSLionel Sambuc   unsigned TmpRegNum;
1732f4a2713aSLionel Sambuc   // 1st operand is either the source or destination register.
1733f4a2713aSLionel Sambuc   assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1734f4a2713aSLionel Sambuc   unsigned RegOpNum = Inst.getOperand(0).getReg();
1735f4a2713aSLionel Sambuc   // 2nd operand is the base register.
1736f4a2713aSLionel Sambuc   assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1737f4a2713aSLionel Sambuc   unsigned BaseRegNum = Inst.getOperand(1).getReg();
1738f4a2713aSLionel Sambuc   // 3rd operand is either an immediate or expression.
1739f4a2713aSLionel Sambuc   if (isImmOpnd) {
1740f4a2713aSLionel Sambuc     assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1741f4a2713aSLionel Sambuc     ImmOffset = Inst.getOperand(2).getImm();
1742f4a2713aSLionel Sambuc     LoOffset = ImmOffset & 0x0000ffff;
1743f4a2713aSLionel Sambuc     HiOffset = (ImmOffset & 0xffff0000) >> 16;
1744f4a2713aSLionel Sambuc     // If msb of LoOffset is 1(negative number) we must increment HiOffset.
1745f4a2713aSLionel Sambuc     if (LoOffset & 0x8000)
1746f4a2713aSLionel Sambuc       HiOffset++;
1747f4a2713aSLionel Sambuc   } else
1748f4a2713aSLionel Sambuc     ExprOffset = Inst.getOperand(2).getExpr();
1749f4a2713aSLionel Sambuc   // All instructions will have the same location.
1750f4a2713aSLionel Sambuc   TempInst.setLoc(IDLoc);
1751*0a6a1f1dSLionel Sambuc   // These are some of the types of expansions we perform here:
1752*0a6a1f1dSLionel Sambuc   // 1) lw $8, sym        => lui $8, %hi(sym)
1753*0a6a1f1dSLionel Sambuc   //                         lw $8, %lo(sym)($8)
1754*0a6a1f1dSLionel Sambuc   // 2) lw $8, offset($9) => lui $8, %hi(offset)
1755*0a6a1f1dSLionel Sambuc   //                         add $8, $8, $9
1756*0a6a1f1dSLionel Sambuc   //                         lw $8, %lo(offset)($9)
1757*0a6a1f1dSLionel Sambuc   // 3) lw $8, offset($8) => lui $at, %hi(offset)
1758*0a6a1f1dSLionel Sambuc   //                         add $at, $at, $8
1759*0a6a1f1dSLionel Sambuc   //                         lw $8, %lo(offset)($at)
1760*0a6a1f1dSLionel Sambuc   // 4) sw $8, sym        => lui $at, %hi(sym)
1761*0a6a1f1dSLionel Sambuc   //                         sw $8, %lo(sym)($at)
1762*0a6a1f1dSLionel Sambuc   // 5) sw $8, offset($8) => lui $at, %hi(offset)
1763*0a6a1f1dSLionel Sambuc   //                         add $at, $at, $8
1764*0a6a1f1dSLionel Sambuc   //                         sw $8, %lo(offset)($at)
1765*0a6a1f1dSLionel Sambuc   // 6) ldc1 $f0, sym     => lui $at, %hi(sym)
1766*0a6a1f1dSLionel Sambuc   //                         ldc1 $f0, %lo(sym)($at)
1767*0a6a1f1dSLionel Sambuc   //
1768*0a6a1f1dSLionel Sambuc   // For load instructions we can use the destination register as a temporary
1769*0a6a1f1dSLionel Sambuc   // if base and dst are different (examples 1 and 2) and if the base register
1770*0a6a1f1dSLionel Sambuc   // is general purpose otherwise we must use $at (example 6) and error if it's
1771*0a6a1f1dSLionel Sambuc   // not available. For stores we must use $at (examples 4 and 5) because we
1772*0a6a1f1dSLionel Sambuc   // must not clobber the source register setting up the offset.
1773*0a6a1f1dSLionel Sambuc   const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1774*0a6a1f1dSLionel Sambuc   int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1775*0a6a1f1dSLionel Sambuc   unsigned RegClassIDOp0 =
1776*0a6a1f1dSLionel Sambuc       getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1777*0a6a1f1dSLionel Sambuc   bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1778*0a6a1f1dSLionel Sambuc                (RegClassIDOp0 == Mips::GPR64RegClassID);
1779*0a6a1f1dSLionel Sambuc   if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
1780*0a6a1f1dSLionel Sambuc     TmpRegNum = RegOpNum;
1781*0a6a1f1dSLionel Sambuc   else {
1782*0a6a1f1dSLionel Sambuc     int AT = getATReg(IDLoc);
1783*0a6a1f1dSLionel Sambuc     // At this point we need AT to perform the expansions and we exit if it is
1784*0a6a1f1dSLionel Sambuc     // not available.
1785*0a6a1f1dSLionel Sambuc     if (!AT)
1786*0a6a1f1dSLionel Sambuc       return;
1787*0a6a1f1dSLionel Sambuc     TmpRegNum = getReg(
1788*0a6a1f1dSLionel Sambuc         (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
1789*0a6a1f1dSLionel Sambuc   }
1790*0a6a1f1dSLionel Sambuc 
1791f4a2713aSLionel Sambuc   TempInst.setOpcode(Mips::LUi);
1792f4a2713aSLionel Sambuc   TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1793f4a2713aSLionel Sambuc   if (isImmOpnd)
1794f4a2713aSLionel Sambuc     TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1795f4a2713aSLionel Sambuc   else {
1796f4a2713aSLionel Sambuc     if (ExprOffset->getKind() == MCExpr::SymbolRef) {
1797f4a2713aSLionel Sambuc       SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
1798f4a2713aSLionel Sambuc       const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1799f4a2713aSLionel Sambuc           SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1800f4a2713aSLionel Sambuc           getContext());
1801f4a2713aSLionel Sambuc       TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
1802f4a2713aSLionel Sambuc     } else {
1803f4a2713aSLionel Sambuc       const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
1804f4a2713aSLionel Sambuc       TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
1805f4a2713aSLionel Sambuc     }
1806f4a2713aSLionel Sambuc   }
1807f4a2713aSLionel Sambuc   // Add the instruction to the list.
1808f4a2713aSLionel Sambuc   Instructions.push_back(TempInst);
1809f4a2713aSLionel Sambuc   // Prepare TempInst for next instruction.
1810f4a2713aSLionel Sambuc   TempInst.clear();
1811f4a2713aSLionel Sambuc   // Add temp register to base.
1812f4a2713aSLionel Sambuc   TempInst.setOpcode(Mips::ADDu);
1813f4a2713aSLionel Sambuc   TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1814f4a2713aSLionel Sambuc   TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1815f4a2713aSLionel Sambuc   TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1816f4a2713aSLionel Sambuc   Instructions.push_back(TempInst);
1817f4a2713aSLionel Sambuc   TempInst.clear();
1818*0a6a1f1dSLionel Sambuc   // And finally, create original instruction with low part
1819f4a2713aSLionel Sambuc   // of offset and new base.
1820f4a2713aSLionel Sambuc   TempInst.setOpcode(Inst.getOpcode());
1821f4a2713aSLionel Sambuc   TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1822f4a2713aSLionel Sambuc   TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1823f4a2713aSLionel Sambuc   if (isImmOpnd)
1824f4a2713aSLionel Sambuc     TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1825f4a2713aSLionel Sambuc   else {
1826f4a2713aSLionel Sambuc     if (ExprOffset->getKind() == MCExpr::SymbolRef) {
1827f4a2713aSLionel Sambuc       const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1828f4a2713aSLionel Sambuc           SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1829f4a2713aSLionel Sambuc           getContext());
1830f4a2713aSLionel Sambuc       TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
1831f4a2713aSLionel Sambuc     } else {
1832f4a2713aSLionel Sambuc       const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
1833f4a2713aSLionel Sambuc       TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
1834f4a2713aSLionel Sambuc     }
1835f4a2713aSLionel Sambuc   }
1836f4a2713aSLionel Sambuc   Instructions.push_back(TempInst);
1837f4a2713aSLionel Sambuc   TempInst.clear();
1838f4a2713aSLionel Sambuc }
1839f4a2713aSLionel Sambuc 
checkTargetMatchPredicate(MCInst & Inst)1840*0a6a1f1dSLionel Sambuc unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1841*0a6a1f1dSLionel Sambuc   // As described by the Mips32r2 spec, the registers Rd and Rs for
1842*0a6a1f1dSLionel Sambuc   // jalr.hb must be different.
1843*0a6a1f1dSLionel Sambuc   unsigned Opcode = Inst.getOpcode();
1844*0a6a1f1dSLionel Sambuc 
1845*0a6a1f1dSLionel Sambuc   if (Opcode == Mips::JALR_HB &&
1846*0a6a1f1dSLionel Sambuc       (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1847*0a6a1f1dSLionel Sambuc     return Match_RequiresDifferentSrcAndDst;
1848*0a6a1f1dSLionel Sambuc 
1849*0a6a1f1dSLionel Sambuc   return Match_Success;
1850*0a6a1f1dSLionel Sambuc }
1851*0a6a1f1dSLionel Sambuc 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)1852*0a6a1f1dSLionel Sambuc bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1853*0a6a1f1dSLionel Sambuc                                             OperandVector &Operands,
1854*0a6a1f1dSLionel Sambuc                                             MCStreamer &Out,
1855*0a6a1f1dSLionel Sambuc                                             uint64_t &ErrorInfo,
1856*0a6a1f1dSLionel Sambuc                                             bool MatchingInlineAsm) {
1857*0a6a1f1dSLionel Sambuc 
1858f4a2713aSLionel Sambuc   MCInst Inst;
1859f4a2713aSLionel Sambuc   SmallVector<MCInst, 8> Instructions;
1860f4a2713aSLionel Sambuc   unsigned MatchResult =
1861f4a2713aSLionel Sambuc       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
1862f4a2713aSLionel Sambuc 
1863f4a2713aSLionel Sambuc   switch (MatchResult) {
1864f4a2713aSLionel Sambuc   case Match_Success: {
1865f4a2713aSLionel Sambuc     if (processInstruction(Inst, IDLoc, Instructions))
1866f4a2713aSLionel Sambuc       return true;
1867f4a2713aSLionel Sambuc     for (unsigned i = 0; i < Instructions.size(); i++)
1868*0a6a1f1dSLionel Sambuc       Out.EmitInstruction(Instructions[i], STI);
1869f4a2713aSLionel Sambuc     return false;
1870f4a2713aSLionel Sambuc   }
1871f4a2713aSLionel Sambuc   case Match_MissingFeature:
1872f4a2713aSLionel Sambuc     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1873f4a2713aSLionel Sambuc     return true;
1874f4a2713aSLionel Sambuc   case Match_InvalidOperand: {
1875f4a2713aSLionel Sambuc     SMLoc ErrorLoc = IDLoc;
1876*0a6a1f1dSLionel Sambuc     if (ErrorInfo != ~0ULL) {
1877f4a2713aSLionel Sambuc       if (ErrorInfo >= Operands.size())
1878f4a2713aSLionel Sambuc         return Error(IDLoc, "too few operands for instruction");
1879f4a2713aSLionel Sambuc 
1880*0a6a1f1dSLionel Sambuc       ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
1881f4a2713aSLionel Sambuc       if (ErrorLoc == SMLoc())
1882f4a2713aSLionel Sambuc         ErrorLoc = IDLoc;
1883f4a2713aSLionel Sambuc     }
1884f4a2713aSLionel Sambuc 
1885f4a2713aSLionel Sambuc     return Error(ErrorLoc, "invalid operand for instruction");
1886f4a2713aSLionel Sambuc   }
1887f4a2713aSLionel Sambuc   case Match_MnemonicFail:
1888f4a2713aSLionel Sambuc     return Error(IDLoc, "invalid instruction");
1889*0a6a1f1dSLionel Sambuc   case Match_RequiresDifferentSrcAndDst:
1890*0a6a1f1dSLionel Sambuc     return Error(IDLoc, "source and destination must be different");
1891f4a2713aSLionel Sambuc   }
1892*0a6a1f1dSLionel Sambuc 
1893*0a6a1f1dSLionel Sambuc   llvm_unreachable("Implement any new match types added!");
1894*0a6a1f1dSLionel Sambuc }
1895*0a6a1f1dSLionel Sambuc 
warnIfAssemblerTemporary(int RegIndex,SMLoc Loc)1896*0a6a1f1dSLionel Sambuc void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1897*0a6a1f1dSLionel Sambuc   if ((RegIndex != 0) &&
1898*0a6a1f1dSLionel Sambuc       ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
1899*0a6a1f1dSLionel Sambuc     if (RegIndex == 1)
1900*0a6a1f1dSLionel Sambuc       Warning(Loc, "used $at without \".set noat\"");
1901*0a6a1f1dSLionel Sambuc     else
1902*0a6a1f1dSLionel Sambuc       Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
1903*0a6a1f1dSLionel Sambuc                        Twine(RegIndex) + "\"");
1904*0a6a1f1dSLionel Sambuc   }
1905*0a6a1f1dSLionel Sambuc }
1906*0a6a1f1dSLionel Sambuc 
1907*0a6a1f1dSLionel Sambuc void
printWarningWithFixIt(const Twine & Msg,const Twine & FixMsg,SMRange Range,bool ShowColors)1908*0a6a1f1dSLionel Sambuc MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1909*0a6a1f1dSLionel Sambuc                                      SMRange Range, bool ShowColors) {
1910*0a6a1f1dSLionel Sambuc   getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
1911*0a6a1f1dSLionel Sambuc                                   Range, SMFixIt(Range, FixMsg),
1912*0a6a1f1dSLionel Sambuc                                   ShowColors);
1913f4a2713aSLionel Sambuc }
1914f4a2713aSLionel Sambuc 
matchCPURegisterName(StringRef Name)1915f4a2713aSLionel Sambuc int MipsAsmParser::matchCPURegisterName(StringRef Name) {
1916f4a2713aSLionel Sambuc   int CC;
1917f4a2713aSLionel Sambuc 
1918f4a2713aSLionel Sambuc   CC = StringSwitch<unsigned>(Name)
1919f4a2713aSLionel Sambuc            .Case("zero", 0)
1920*0a6a1f1dSLionel Sambuc            .Case("at", 1)
1921f4a2713aSLionel Sambuc            .Case("a0", 4)
1922f4a2713aSLionel Sambuc            .Case("a1", 5)
1923f4a2713aSLionel Sambuc            .Case("a2", 6)
1924f4a2713aSLionel Sambuc            .Case("a3", 7)
1925f4a2713aSLionel Sambuc            .Case("v0", 2)
1926f4a2713aSLionel Sambuc            .Case("v1", 3)
1927f4a2713aSLionel Sambuc            .Case("s0", 16)
1928f4a2713aSLionel Sambuc            .Case("s1", 17)
1929f4a2713aSLionel Sambuc            .Case("s2", 18)
1930f4a2713aSLionel Sambuc            .Case("s3", 19)
1931f4a2713aSLionel Sambuc            .Case("s4", 20)
1932f4a2713aSLionel Sambuc            .Case("s5", 21)
1933f4a2713aSLionel Sambuc            .Case("s6", 22)
1934f4a2713aSLionel Sambuc            .Case("s7", 23)
1935f4a2713aSLionel Sambuc            .Case("k0", 26)
1936f4a2713aSLionel Sambuc            .Case("k1", 27)
1937*0a6a1f1dSLionel Sambuc            .Case("gp", 28)
1938f4a2713aSLionel Sambuc            .Case("sp", 29)
1939f4a2713aSLionel Sambuc            .Case("fp", 30)
1940*0a6a1f1dSLionel Sambuc            .Case("s8", 30)
1941f4a2713aSLionel Sambuc            .Case("ra", 31)
1942f4a2713aSLionel Sambuc            .Case("t0", 8)
1943f4a2713aSLionel Sambuc            .Case("t1", 9)
1944f4a2713aSLionel Sambuc            .Case("t2", 10)
1945f4a2713aSLionel Sambuc            .Case("t3", 11)
1946f4a2713aSLionel Sambuc            .Case("t4", 12)
1947f4a2713aSLionel Sambuc            .Case("t5", 13)
1948f4a2713aSLionel Sambuc            .Case("t6", 14)
1949f4a2713aSLionel Sambuc            .Case("t7", 15)
1950f4a2713aSLionel Sambuc            .Case("t8", 24)
1951f4a2713aSLionel Sambuc            .Case("t9", 25)
1952f4a2713aSLionel Sambuc            .Default(-1);
1953f4a2713aSLionel Sambuc 
1954*0a6a1f1dSLionel Sambuc   if (!(isABI_N32() || isABI_N64()))
1955*0a6a1f1dSLionel Sambuc     return CC;
1956*0a6a1f1dSLionel Sambuc 
1957*0a6a1f1dSLionel Sambuc   if (12 <= CC && CC <= 15) {
1958*0a6a1f1dSLionel Sambuc     // Name is one of t4-t7
1959*0a6a1f1dSLionel Sambuc     AsmToken RegTok = getLexer().peekTok();
1960*0a6a1f1dSLionel Sambuc     SMRange RegRange = RegTok.getLocRange();
1961*0a6a1f1dSLionel Sambuc 
1962*0a6a1f1dSLionel Sambuc     StringRef FixedName = StringSwitch<StringRef>(Name)
1963*0a6a1f1dSLionel Sambuc                               .Case("t4", "t0")
1964*0a6a1f1dSLionel Sambuc                               .Case("t5", "t1")
1965*0a6a1f1dSLionel Sambuc                               .Case("t6", "t2")
1966*0a6a1f1dSLionel Sambuc                               .Case("t7", "t3")
1967*0a6a1f1dSLionel Sambuc                               .Default("");
1968*0a6a1f1dSLionel Sambuc     assert(FixedName != "" &&  "Register name is not one of t4-t7.");
1969*0a6a1f1dSLionel Sambuc 
1970*0a6a1f1dSLionel Sambuc     printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1971*0a6a1f1dSLionel Sambuc                           "Did you mean $" + FixedName + "?", RegRange);
1972*0a6a1f1dSLionel Sambuc   }
1973*0a6a1f1dSLionel Sambuc 
1974f4a2713aSLionel Sambuc   // Although SGI documentation just cuts out t0-t3 for n32/n64,
1975f4a2713aSLionel Sambuc   // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1976f4a2713aSLionel Sambuc   // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1977*0a6a1f1dSLionel Sambuc   if (8 <= CC && CC <= 11)
1978f4a2713aSLionel Sambuc     CC += 4;
1979f4a2713aSLionel Sambuc 
1980*0a6a1f1dSLionel Sambuc   if (CC == -1)
1981f4a2713aSLionel Sambuc     CC = StringSwitch<unsigned>(Name)
1982f4a2713aSLionel Sambuc              .Case("a4", 8)
1983f4a2713aSLionel Sambuc              .Case("a5", 9)
1984f4a2713aSLionel Sambuc              .Case("a6", 10)
1985f4a2713aSLionel Sambuc              .Case("a7", 11)
1986f4a2713aSLionel Sambuc              .Case("kt0", 26)
1987f4a2713aSLionel Sambuc              .Case("kt1", 27)
1988*0a6a1f1dSLionel Sambuc              .Default(-1);
1989*0a6a1f1dSLionel Sambuc 
1990*0a6a1f1dSLionel Sambuc   return CC;
1991*0a6a1f1dSLionel Sambuc }
1992*0a6a1f1dSLionel Sambuc 
matchHWRegsRegisterName(StringRef Name)1993*0a6a1f1dSLionel Sambuc int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1994*0a6a1f1dSLionel Sambuc   int CC;
1995*0a6a1f1dSLionel Sambuc 
1996*0a6a1f1dSLionel Sambuc   CC = StringSwitch<unsigned>(Name)
1997*0a6a1f1dSLionel Sambuc             .Case("hwr_cpunum", 0)
1998*0a6a1f1dSLionel Sambuc             .Case("hwr_synci_step", 1)
1999*0a6a1f1dSLionel Sambuc             .Case("hwr_cc", 2)
2000*0a6a1f1dSLionel Sambuc             .Case("hwr_ccres", 3)
2001*0a6a1f1dSLionel Sambuc             .Case("hwr_ulr", 29)
2002f4a2713aSLionel Sambuc             .Default(-1);
2003f4a2713aSLionel Sambuc 
2004f4a2713aSLionel Sambuc   return CC;
2005f4a2713aSLionel Sambuc }
2006f4a2713aSLionel Sambuc 
matchFPURegisterName(StringRef Name)2007f4a2713aSLionel Sambuc int MipsAsmParser::matchFPURegisterName(StringRef Name) {
2008f4a2713aSLionel Sambuc 
2009f4a2713aSLionel Sambuc   if (Name[0] == 'f') {
2010f4a2713aSLionel Sambuc     StringRef NumString = Name.substr(1);
2011f4a2713aSLionel Sambuc     unsigned IntVal;
2012f4a2713aSLionel Sambuc     if (NumString.getAsInteger(10, IntVal))
2013f4a2713aSLionel Sambuc       return -1;     // This is not an integer.
2014f4a2713aSLionel Sambuc     if (IntVal > 31) // Maximum index for fpu register.
2015f4a2713aSLionel Sambuc       return -1;
2016f4a2713aSLionel Sambuc     return IntVal;
2017f4a2713aSLionel Sambuc   }
2018f4a2713aSLionel Sambuc   return -1;
2019f4a2713aSLionel Sambuc }
2020f4a2713aSLionel Sambuc 
matchFCCRegisterName(StringRef Name)2021f4a2713aSLionel Sambuc int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2022f4a2713aSLionel Sambuc 
2023f4a2713aSLionel Sambuc   if (Name.startswith("fcc")) {
2024f4a2713aSLionel Sambuc     StringRef NumString = Name.substr(3);
2025f4a2713aSLionel Sambuc     unsigned IntVal;
2026f4a2713aSLionel Sambuc     if (NumString.getAsInteger(10, IntVal))
2027f4a2713aSLionel Sambuc       return -1;    // This is not an integer.
2028f4a2713aSLionel Sambuc     if (IntVal > 7) // There are only 8 fcc registers.
2029f4a2713aSLionel Sambuc       return -1;
2030f4a2713aSLionel Sambuc     return IntVal;
2031f4a2713aSLionel Sambuc   }
2032f4a2713aSLionel Sambuc   return -1;
2033f4a2713aSLionel Sambuc }
2034f4a2713aSLionel Sambuc 
matchACRegisterName(StringRef Name)2035f4a2713aSLionel Sambuc int MipsAsmParser::matchACRegisterName(StringRef Name) {
2036f4a2713aSLionel Sambuc 
2037f4a2713aSLionel Sambuc   if (Name.startswith("ac")) {
2038f4a2713aSLionel Sambuc     StringRef NumString = Name.substr(2);
2039f4a2713aSLionel Sambuc     unsigned IntVal;
2040f4a2713aSLionel Sambuc     if (NumString.getAsInteger(10, IntVal))
2041f4a2713aSLionel Sambuc       return -1;    // This is not an integer.
2042f4a2713aSLionel Sambuc     if (IntVal > 3) // There are only 3 acc registers.
2043f4a2713aSLionel Sambuc       return -1;
2044f4a2713aSLionel Sambuc     return IntVal;
2045f4a2713aSLionel Sambuc   }
2046f4a2713aSLionel Sambuc   return -1;
2047f4a2713aSLionel Sambuc }
2048f4a2713aSLionel Sambuc 
matchMSA128RegisterName(StringRef Name)2049f4a2713aSLionel Sambuc int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2050f4a2713aSLionel Sambuc   unsigned IntVal;
2051f4a2713aSLionel Sambuc 
2052f4a2713aSLionel Sambuc   if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2053f4a2713aSLionel Sambuc     return -1;
2054f4a2713aSLionel Sambuc 
2055f4a2713aSLionel Sambuc   if (IntVal > 31)
2056f4a2713aSLionel Sambuc     return -1;
2057f4a2713aSLionel Sambuc 
2058f4a2713aSLionel Sambuc   return IntVal;
2059f4a2713aSLionel Sambuc }
2060f4a2713aSLionel Sambuc 
matchMSA128CtrlRegisterName(StringRef Name)2061f4a2713aSLionel Sambuc int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2062f4a2713aSLionel Sambuc   int CC;
2063f4a2713aSLionel Sambuc 
2064f4a2713aSLionel Sambuc   CC = StringSwitch<unsigned>(Name)
2065f4a2713aSLionel Sambuc            .Case("msair", 0)
2066f4a2713aSLionel Sambuc            .Case("msacsr", 1)
2067f4a2713aSLionel Sambuc            .Case("msaaccess", 2)
2068f4a2713aSLionel Sambuc            .Case("msasave", 3)
2069f4a2713aSLionel Sambuc            .Case("msamodify", 4)
2070f4a2713aSLionel Sambuc            .Case("msarequest", 5)
2071f4a2713aSLionel Sambuc            .Case("msamap", 6)
2072f4a2713aSLionel Sambuc            .Case("msaunmap", 7)
2073f4a2713aSLionel Sambuc            .Default(-1);
2074f4a2713aSLionel Sambuc 
2075f4a2713aSLionel Sambuc   return CC;
2076f4a2713aSLionel Sambuc }
2077f4a2713aSLionel Sambuc 
setATReg(unsigned Reg)2078f4a2713aSLionel Sambuc bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2079f4a2713aSLionel Sambuc   if (Reg > 31)
2080f4a2713aSLionel Sambuc     return false;
2081f4a2713aSLionel Sambuc 
2082*0a6a1f1dSLionel Sambuc   ATReg = Reg;
2083f4a2713aSLionel Sambuc   return true;
2084f4a2713aSLionel Sambuc }
2085f4a2713aSLionel Sambuc 
getATReg(SMLoc Loc)2086*0a6a1f1dSLionel Sambuc int MipsAsmParser::getATReg(SMLoc Loc) {
2087*0a6a1f1dSLionel Sambuc   int AT = AssemblerOptions.back()->getATRegNum();
2088*0a6a1f1dSLionel Sambuc   if (AT == 0)
2089*0a6a1f1dSLionel Sambuc     reportParseError(Loc,
2090*0a6a1f1dSLionel Sambuc                      "pseudo-instruction requires $at, which is not available");
2091*0a6a1f1dSLionel Sambuc   return AT;
2092*0a6a1f1dSLionel Sambuc }
2093f4a2713aSLionel Sambuc 
getReg(int RC,int RegNo)2094f4a2713aSLionel Sambuc unsigned MipsAsmParser::getReg(int RC, int RegNo) {
2095f4a2713aSLionel Sambuc   return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
2096f4a2713aSLionel Sambuc }
2097f4a2713aSLionel Sambuc 
getGPR(int RegNo)2098*0a6a1f1dSLionel Sambuc unsigned MipsAsmParser::getGPR(int RegNo) {
2099*0a6a1f1dSLionel Sambuc   return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
2100*0a6a1f1dSLionel Sambuc                 RegNo);
2101*0a6a1f1dSLionel Sambuc }
2102*0a6a1f1dSLionel Sambuc 
matchRegisterByNumber(unsigned RegNum,unsigned RegClass)2103f4a2713aSLionel Sambuc int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
2104f4a2713aSLionel Sambuc   if (RegNum >
2105*0a6a1f1dSLionel Sambuc       getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
2106f4a2713aSLionel Sambuc     return -1;
2107f4a2713aSLionel Sambuc 
2108f4a2713aSLionel Sambuc   return getReg(RegClass, RegNum);
2109f4a2713aSLionel Sambuc }
2110f4a2713aSLionel Sambuc 
parseOperand(OperandVector & Operands,StringRef Mnemonic)2111*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2112*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2113*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << "parseOperand\n");
2114f4a2713aSLionel Sambuc 
2115f4a2713aSLionel Sambuc   // Check if the current operand has a custom associated parser, if so, try to
2116f4a2713aSLionel Sambuc   // custom parse the operand, or fallback to the general approach.
2117f4a2713aSLionel Sambuc   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2118f4a2713aSLionel Sambuc   if (ResTy == MatchOperand_Success)
2119f4a2713aSLionel Sambuc     return false;
2120f4a2713aSLionel Sambuc   // If there wasn't a custom match, try the generic matcher below. Otherwise,
2121f4a2713aSLionel Sambuc   // there was a match, but an error occurred, in which case, just return that
2122f4a2713aSLionel Sambuc   // the operand parsing failed.
2123f4a2713aSLionel Sambuc   if (ResTy == MatchOperand_ParseFail)
2124f4a2713aSLionel Sambuc     return true;
2125f4a2713aSLionel Sambuc 
2126*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << ".. Generic Parser\n");
2127*0a6a1f1dSLionel Sambuc 
2128f4a2713aSLionel Sambuc   switch (getLexer().getKind()) {
2129f4a2713aSLionel Sambuc   default:
2130f4a2713aSLionel Sambuc     Error(Parser.getTok().getLoc(), "unexpected token in operand");
2131f4a2713aSLionel Sambuc     return true;
2132f4a2713aSLionel Sambuc   case AsmToken::Dollar: {
2133f4a2713aSLionel Sambuc     // Parse the register.
2134f4a2713aSLionel Sambuc     SMLoc S = Parser.getTok().getLoc();
2135f4a2713aSLionel Sambuc 
2136*0a6a1f1dSLionel Sambuc     // Almost all registers have been parsed by custom parsers. There is only
2137*0a6a1f1dSLionel Sambuc     // one exception to this. $zero (and it's alias $0) will reach this point
2138*0a6a1f1dSLionel Sambuc     // for div, divu, and similar instructions because it is not an operand
2139*0a6a1f1dSLionel Sambuc     // to the instruction definition but an explicit register. Special case
2140*0a6a1f1dSLionel Sambuc     // this situation for now.
2141*0a6a1f1dSLionel Sambuc     if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
2142f4a2713aSLionel Sambuc       return false;
2143*0a6a1f1dSLionel Sambuc 
2144f4a2713aSLionel Sambuc     // Maybe it is a symbol reference.
2145f4a2713aSLionel Sambuc     StringRef Identifier;
2146f4a2713aSLionel Sambuc     if (Parser.parseIdentifier(Identifier))
2147f4a2713aSLionel Sambuc       return true;
2148f4a2713aSLionel Sambuc 
2149f4a2713aSLionel Sambuc     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2150f4a2713aSLionel Sambuc     MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
2151f4a2713aSLionel Sambuc     // Otherwise create a symbol reference.
2152f4a2713aSLionel Sambuc     const MCExpr *Res =
2153f4a2713aSLionel Sambuc         MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
2154f4a2713aSLionel Sambuc 
2155*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
2156f4a2713aSLionel Sambuc     return false;
2157f4a2713aSLionel Sambuc   }
2158f4a2713aSLionel Sambuc   // Else drop to expression parsing.
2159f4a2713aSLionel Sambuc   case AsmToken::LParen:
2160f4a2713aSLionel Sambuc   case AsmToken::Minus:
2161f4a2713aSLionel Sambuc   case AsmToken::Plus:
2162f4a2713aSLionel Sambuc   case AsmToken::Integer:
2163*0a6a1f1dSLionel Sambuc   case AsmToken::Tilde:
2164f4a2713aSLionel Sambuc   case AsmToken::String: {
2165*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << ".. generic integer\n");
2166*0a6a1f1dSLionel Sambuc     OperandMatchResultTy ResTy = parseImm(Operands);
2167*0a6a1f1dSLionel Sambuc     return ResTy != MatchOperand_Success;
2168f4a2713aSLionel Sambuc   }
2169f4a2713aSLionel Sambuc   case AsmToken::Percent: {
2170f4a2713aSLionel Sambuc     // It is a symbol reference or constant expression.
2171f4a2713aSLionel Sambuc     const MCExpr *IdVal;
2172f4a2713aSLionel Sambuc     SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
2173f4a2713aSLionel Sambuc     if (parseRelocOperand(IdVal))
2174f4a2713aSLionel Sambuc       return true;
2175f4a2713aSLionel Sambuc 
2176f4a2713aSLionel Sambuc     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2177f4a2713aSLionel Sambuc 
2178*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2179f4a2713aSLionel Sambuc     return false;
2180f4a2713aSLionel Sambuc   } // case AsmToken::Percent
2181f4a2713aSLionel Sambuc   } // switch(getLexer().getKind())
2182f4a2713aSLionel Sambuc   return true;
2183f4a2713aSLionel Sambuc }
2184f4a2713aSLionel Sambuc 
evaluateRelocExpr(const MCExpr * Expr,StringRef RelocStr)2185f4a2713aSLionel Sambuc const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
2186f4a2713aSLionel Sambuc                                                StringRef RelocStr) {
2187f4a2713aSLionel Sambuc   const MCExpr *Res;
2188f4a2713aSLionel Sambuc   // Check the type of the expression.
2189f4a2713aSLionel Sambuc   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
2190*0a6a1f1dSLionel Sambuc     // It's a constant, evaluate reloc value.
2191*0a6a1f1dSLionel Sambuc     int16_t Val;
2192*0a6a1f1dSLionel Sambuc     switch (getVariantKind(RelocStr)) {
2193*0a6a1f1dSLionel Sambuc     case MCSymbolRefExpr::VK_Mips_ABS_LO:
2194*0a6a1f1dSLionel Sambuc       // Get the 1st 16-bits.
2195*0a6a1f1dSLionel Sambuc       Val = MCE->getValue() & 0xffff;
2196*0a6a1f1dSLionel Sambuc       break;
2197*0a6a1f1dSLionel Sambuc     case MCSymbolRefExpr::VK_Mips_ABS_HI:
2198*0a6a1f1dSLionel Sambuc       // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2199*0a6a1f1dSLionel Sambuc       // 16 bits being negative.
2200*0a6a1f1dSLionel Sambuc       Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2201*0a6a1f1dSLionel Sambuc       break;
2202*0a6a1f1dSLionel Sambuc     case MCSymbolRefExpr::VK_Mips_HIGHER:
2203*0a6a1f1dSLionel Sambuc       // Get the 3rd 16-bits.
2204*0a6a1f1dSLionel Sambuc       Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2205*0a6a1f1dSLionel Sambuc       break;
2206*0a6a1f1dSLionel Sambuc     case MCSymbolRefExpr::VK_Mips_HIGHEST:
2207*0a6a1f1dSLionel Sambuc       // Get the 4th 16-bits.
2208*0a6a1f1dSLionel Sambuc       Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2209*0a6a1f1dSLionel Sambuc       break;
2210*0a6a1f1dSLionel Sambuc     default:
2211*0a6a1f1dSLionel Sambuc       report_fatal_error("unsupported reloc value");
2212f4a2713aSLionel Sambuc     }
2213*0a6a1f1dSLionel Sambuc     return MCConstantExpr::Create(Val, getContext());
2214f4a2713aSLionel Sambuc   }
2215f4a2713aSLionel Sambuc 
2216f4a2713aSLionel Sambuc   if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
2217f4a2713aSLionel Sambuc     // It's a symbol, create a symbolic expression from the symbol.
2218f4a2713aSLionel Sambuc     StringRef Symbol = MSRE->getSymbol().getName();
2219f4a2713aSLionel Sambuc     MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2220f4a2713aSLionel Sambuc     Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
2221f4a2713aSLionel Sambuc     return Res;
2222f4a2713aSLionel Sambuc   }
2223f4a2713aSLionel Sambuc 
2224f4a2713aSLionel Sambuc   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2225*0a6a1f1dSLionel Sambuc     MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2226*0a6a1f1dSLionel Sambuc 
2227*0a6a1f1dSLionel Sambuc     // Try to create target expression.
2228*0a6a1f1dSLionel Sambuc     if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2229*0a6a1f1dSLionel Sambuc       return MipsMCExpr::Create(VK, Expr, getContext());
2230*0a6a1f1dSLionel Sambuc 
2231f4a2713aSLionel Sambuc     const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2232f4a2713aSLionel Sambuc     const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
2233f4a2713aSLionel Sambuc     Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2234f4a2713aSLionel Sambuc     return Res;
2235f4a2713aSLionel Sambuc   }
2236f4a2713aSLionel Sambuc 
2237f4a2713aSLionel Sambuc   if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
2238f4a2713aSLionel Sambuc     const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2239f4a2713aSLionel Sambuc     Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2240f4a2713aSLionel Sambuc     return Res;
2241f4a2713aSLionel Sambuc   }
2242f4a2713aSLionel Sambuc   // Just return the original expression.
2243f4a2713aSLionel Sambuc   return Expr;
2244f4a2713aSLionel Sambuc }
2245f4a2713aSLionel Sambuc 
isEvaluated(const MCExpr * Expr)2246f4a2713aSLionel Sambuc bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2247f4a2713aSLionel Sambuc 
2248f4a2713aSLionel Sambuc   switch (Expr->getKind()) {
2249f4a2713aSLionel Sambuc   case MCExpr::Constant:
2250f4a2713aSLionel Sambuc     return true;
2251f4a2713aSLionel Sambuc   case MCExpr::SymbolRef:
2252f4a2713aSLionel Sambuc     return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2253f4a2713aSLionel Sambuc   case MCExpr::Binary:
2254f4a2713aSLionel Sambuc     if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2255f4a2713aSLionel Sambuc       if (!isEvaluated(BE->getLHS()))
2256f4a2713aSLionel Sambuc         return false;
2257f4a2713aSLionel Sambuc       return isEvaluated(BE->getRHS());
2258f4a2713aSLionel Sambuc     }
2259f4a2713aSLionel Sambuc   case MCExpr::Unary:
2260f4a2713aSLionel Sambuc     return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
2261*0a6a1f1dSLionel Sambuc   case MCExpr::Target:
2262*0a6a1f1dSLionel Sambuc     return true;
2263f4a2713aSLionel Sambuc   }
2264f4a2713aSLionel Sambuc   return false;
2265f4a2713aSLionel Sambuc }
2266f4a2713aSLionel Sambuc 
parseRelocOperand(const MCExpr * & Res)2267f4a2713aSLionel Sambuc bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
2268*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2269f4a2713aSLionel Sambuc   Parser.Lex();                          // Eat the % token.
2270f4a2713aSLionel Sambuc   const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
2271f4a2713aSLionel Sambuc   if (Tok.isNot(AsmToken::Identifier))
2272f4a2713aSLionel Sambuc     return true;
2273f4a2713aSLionel Sambuc 
2274f4a2713aSLionel Sambuc   std::string Str = Tok.getIdentifier().str();
2275f4a2713aSLionel Sambuc 
2276f4a2713aSLionel Sambuc   Parser.Lex(); // Eat the identifier.
2277f4a2713aSLionel Sambuc   // Now make an expression from the rest of the operand.
2278f4a2713aSLionel Sambuc   const MCExpr *IdVal;
2279f4a2713aSLionel Sambuc   SMLoc EndLoc;
2280f4a2713aSLionel Sambuc 
2281f4a2713aSLionel Sambuc   if (getLexer().getKind() == AsmToken::LParen) {
2282f4a2713aSLionel Sambuc     while (1) {
2283f4a2713aSLionel Sambuc       Parser.Lex(); // Eat the '(' token.
2284f4a2713aSLionel Sambuc       if (getLexer().getKind() == AsmToken::Percent) {
2285f4a2713aSLionel Sambuc         Parser.Lex(); // Eat the % token.
2286f4a2713aSLionel Sambuc         const AsmToken &nextTok = Parser.getTok();
2287f4a2713aSLionel Sambuc         if (nextTok.isNot(AsmToken::Identifier))
2288f4a2713aSLionel Sambuc           return true;
2289f4a2713aSLionel Sambuc         Str += "(%";
2290f4a2713aSLionel Sambuc         Str += nextTok.getIdentifier();
2291f4a2713aSLionel Sambuc         Parser.Lex(); // Eat the identifier.
2292f4a2713aSLionel Sambuc         if (getLexer().getKind() != AsmToken::LParen)
2293f4a2713aSLionel Sambuc           return true;
2294f4a2713aSLionel Sambuc       } else
2295f4a2713aSLionel Sambuc         break;
2296f4a2713aSLionel Sambuc     }
2297f4a2713aSLionel Sambuc     if (getParser().parseParenExpression(IdVal, EndLoc))
2298f4a2713aSLionel Sambuc       return true;
2299f4a2713aSLionel Sambuc 
2300f4a2713aSLionel Sambuc     while (getLexer().getKind() == AsmToken::RParen)
2301f4a2713aSLionel Sambuc       Parser.Lex(); // Eat the ')' token.
2302f4a2713aSLionel Sambuc 
2303f4a2713aSLionel Sambuc   } else
2304f4a2713aSLionel Sambuc     return true; // Parenthesis must follow the relocation operand.
2305f4a2713aSLionel Sambuc 
2306f4a2713aSLionel Sambuc   Res = evaluateRelocExpr(IdVal, Str);
2307f4a2713aSLionel Sambuc   return false;
2308f4a2713aSLionel Sambuc }
2309f4a2713aSLionel Sambuc 
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)2310f4a2713aSLionel Sambuc bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2311f4a2713aSLionel Sambuc                                   SMLoc &EndLoc) {
2312*0a6a1f1dSLionel Sambuc   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
2313*0a6a1f1dSLionel Sambuc   OperandMatchResultTy ResTy = parseAnyRegister(Operands);
2314*0a6a1f1dSLionel Sambuc   if (ResTy == MatchOperand_Success) {
2315*0a6a1f1dSLionel Sambuc     assert(Operands.size() == 1);
2316*0a6a1f1dSLionel Sambuc     MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
2317*0a6a1f1dSLionel Sambuc     StartLoc = Operand.getStartLoc();
2318*0a6a1f1dSLionel Sambuc     EndLoc = Operand.getEndLoc();
2319*0a6a1f1dSLionel Sambuc 
2320*0a6a1f1dSLionel Sambuc     // AFAIK, we only support numeric registers and named GPR's in CFI
2321*0a6a1f1dSLionel Sambuc     // directives.
2322*0a6a1f1dSLionel Sambuc     // Don't worry about eating tokens before failing. Using an unrecognised
2323*0a6a1f1dSLionel Sambuc     // register is a parse error.
2324*0a6a1f1dSLionel Sambuc     if (Operand.isGPRAsmReg()) {
2325*0a6a1f1dSLionel Sambuc       // Resolve to GPR32 or GPR64 appropriately.
2326*0a6a1f1dSLionel Sambuc       RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
2327*0a6a1f1dSLionel Sambuc     }
2328*0a6a1f1dSLionel Sambuc 
2329*0a6a1f1dSLionel Sambuc     return (RegNo == (unsigned)-1);
2330*0a6a1f1dSLionel Sambuc   }
2331*0a6a1f1dSLionel Sambuc 
2332*0a6a1f1dSLionel Sambuc   assert(Operands.size() == 0);
2333f4a2713aSLionel Sambuc   return (RegNo == (unsigned)-1);
2334f4a2713aSLionel Sambuc }
2335f4a2713aSLionel Sambuc 
parseMemOffset(const MCExpr * & Res,bool isParenExpr)2336f4a2713aSLionel Sambuc bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
2337*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2338f4a2713aSLionel Sambuc   SMLoc S;
2339f4a2713aSLionel Sambuc   bool Result = true;
2340f4a2713aSLionel Sambuc 
2341f4a2713aSLionel Sambuc   while (getLexer().getKind() == AsmToken::LParen)
2342f4a2713aSLionel Sambuc     Parser.Lex();
2343f4a2713aSLionel Sambuc 
2344f4a2713aSLionel Sambuc   switch (getLexer().getKind()) {
2345f4a2713aSLionel Sambuc   default:
2346f4a2713aSLionel Sambuc     return true;
2347f4a2713aSLionel Sambuc   case AsmToken::Identifier:
2348f4a2713aSLionel Sambuc   case AsmToken::LParen:
2349f4a2713aSLionel Sambuc   case AsmToken::Integer:
2350f4a2713aSLionel Sambuc   case AsmToken::Minus:
2351f4a2713aSLionel Sambuc   case AsmToken::Plus:
2352f4a2713aSLionel Sambuc     if (isParenExpr)
2353f4a2713aSLionel Sambuc       Result = getParser().parseParenExpression(Res, S);
2354f4a2713aSLionel Sambuc     else
2355f4a2713aSLionel Sambuc       Result = (getParser().parseExpression(Res));
2356f4a2713aSLionel Sambuc     while (getLexer().getKind() == AsmToken::RParen)
2357f4a2713aSLionel Sambuc       Parser.Lex();
2358f4a2713aSLionel Sambuc     break;
2359f4a2713aSLionel Sambuc   case AsmToken::Percent:
2360f4a2713aSLionel Sambuc     Result = parseRelocOperand(Res);
2361f4a2713aSLionel Sambuc   }
2362f4a2713aSLionel Sambuc   return Result;
2363f4a2713aSLionel Sambuc }
2364f4a2713aSLionel Sambuc 
2365*0a6a1f1dSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseMemOperand(OperandVector & Operands)2366*0a6a1f1dSLionel Sambuc MipsAsmParser::parseMemOperand(OperandVector &Operands) {
2367*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2368*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << "parseMemOperand\n");
2369*0a6a1f1dSLionel Sambuc   const MCExpr *IdVal = nullptr;
2370f4a2713aSLionel Sambuc   SMLoc S;
2371f4a2713aSLionel Sambuc   bool isParenExpr = false;
2372f4a2713aSLionel Sambuc   MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
2373f4a2713aSLionel Sambuc   // First operand is the offset.
2374f4a2713aSLionel Sambuc   S = Parser.getTok().getLoc();
2375f4a2713aSLionel Sambuc 
2376f4a2713aSLionel Sambuc   if (getLexer().getKind() == AsmToken::LParen) {
2377f4a2713aSLionel Sambuc     Parser.Lex();
2378f4a2713aSLionel Sambuc     isParenExpr = true;
2379f4a2713aSLionel Sambuc   }
2380f4a2713aSLionel Sambuc 
2381f4a2713aSLionel Sambuc   if (getLexer().getKind() != AsmToken::Dollar) {
2382f4a2713aSLionel Sambuc     if (parseMemOffset(IdVal, isParenExpr))
2383f4a2713aSLionel Sambuc       return MatchOperand_ParseFail;
2384f4a2713aSLionel Sambuc 
2385f4a2713aSLionel Sambuc     const AsmToken &Tok = Parser.getTok(); // Get the next token.
2386f4a2713aSLionel Sambuc     if (Tok.isNot(AsmToken::LParen)) {
2387*0a6a1f1dSLionel Sambuc       MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2388*0a6a1f1dSLionel Sambuc       if (Mnemonic.getToken() == "la") {
2389f4a2713aSLionel Sambuc         SMLoc E =
2390f4a2713aSLionel Sambuc             SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2391*0a6a1f1dSLionel Sambuc         Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2392f4a2713aSLionel Sambuc         return MatchOperand_Success;
2393f4a2713aSLionel Sambuc       }
2394f4a2713aSLionel Sambuc       if (Tok.is(AsmToken::EndOfStatement)) {
2395f4a2713aSLionel Sambuc         SMLoc E =
2396f4a2713aSLionel Sambuc             SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2397f4a2713aSLionel Sambuc 
2398f4a2713aSLionel Sambuc         // Zero register assumed, add a memory operand with ZERO as its base.
2399*0a6a1f1dSLionel Sambuc         // "Base" will be managed by k_Memory.
2400*0a6a1f1dSLionel Sambuc         auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
2401*0a6a1f1dSLionel Sambuc                                               S, E, *this);
2402*0a6a1f1dSLionel Sambuc         Operands.push_back(
2403*0a6a1f1dSLionel Sambuc             MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
2404f4a2713aSLionel Sambuc         return MatchOperand_Success;
2405f4a2713aSLionel Sambuc       }
2406f4a2713aSLionel Sambuc       Error(Parser.getTok().getLoc(), "'(' expected");
2407f4a2713aSLionel Sambuc       return MatchOperand_ParseFail;
2408f4a2713aSLionel Sambuc     }
2409f4a2713aSLionel Sambuc 
2410f4a2713aSLionel Sambuc     Parser.Lex(); // Eat the '(' token.
2411f4a2713aSLionel Sambuc   }
2412f4a2713aSLionel Sambuc 
2413*0a6a1f1dSLionel Sambuc   Res = parseAnyRegister(Operands);
2414f4a2713aSLionel Sambuc   if (Res != MatchOperand_Success)
2415f4a2713aSLionel Sambuc     return Res;
2416f4a2713aSLionel Sambuc 
2417f4a2713aSLionel Sambuc   if (Parser.getTok().isNot(AsmToken::RParen)) {
2418f4a2713aSLionel Sambuc     Error(Parser.getTok().getLoc(), "')' expected");
2419f4a2713aSLionel Sambuc     return MatchOperand_ParseFail;
2420f4a2713aSLionel Sambuc   }
2421f4a2713aSLionel Sambuc 
2422f4a2713aSLionel Sambuc   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2423f4a2713aSLionel Sambuc 
2424f4a2713aSLionel Sambuc   Parser.Lex(); // Eat the ')' token.
2425f4a2713aSLionel Sambuc 
2426*0a6a1f1dSLionel Sambuc   if (!IdVal)
2427f4a2713aSLionel Sambuc     IdVal = MCConstantExpr::Create(0, getContext());
2428f4a2713aSLionel Sambuc 
2429f4a2713aSLionel Sambuc   // Replace the register operand with the memory operand.
2430*0a6a1f1dSLionel Sambuc   std::unique_ptr<MipsOperand> op(
2431*0a6a1f1dSLionel Sambuc       static_cast<MipsOperand *>(Operands.back().release()));
2432f4a2713aSLionel Sambuc   // Remove the register from the operands.
2433*0a6a1f1dSLionel Sambuc   // "op" will be managed by k_Memory.
2434f4a2713aSLionel Sambuc   Operands.pop_back();
2435f4a2713aSLionel Sambuc   // Add the memory operand.
2436f4a2713aSLionel Sambuc   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2437f4a2713aSLionel Sambuc     int64_t Imm;
2438f4a2713aSLionel Sambuc     if (IdVal->EvaluateAsAbsolute(Imm))
2439f4a2713aSLionel Sambuc       IdVal = MCConstantExpr::Create(Imm, getContext());
2440f4a2713aSLionel Sambuc     else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2441f4a2713aSLionel Sambuc       IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2442f4a2713aSLionel Sambuc                                    getContext());
2443f4a2713aSLionel Sambuc   }
2444f4a2713aSLionel Sambuc 
2445*0a6a1f1dSLionel Sambuc   Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
2446f4a2713aSLionel Sambuc   return MatchOperand_Success;
2447f4a2713aSLionel Sambuc }
2448f4a2713aSLionel Sambuc 
searchSymbolAlias(OperandVector & Operands)2449*0a6a1f1dSLionel Sambuc bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
2450*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2451f4a2713aSLionel Sambuc   MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2452f4a2713aSLionel Sambuc   if (Sym) {
2453f4a2713aSLionel Sambuc     SMLoc S = Parser.getTok().getLoc();
2454f4a2713aSLionel Sambuc     const MCExpr *Expr;
2455f4a2713aSLionel Sambuc     if (Sym->isVariable())
2456f4a2713aSLionel Sambuc       Expr = Sym->getVariableValue();
2457f4a2713aSLionel Sambuc     else
2458f4a2713aSLionel Sambuc       return false;
2459f4a2713aSLionel Sambuc     if (Expr->getKind() == MCExpr::SymbolRef) {
2460f4a2713aSLionel Sambuc       const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
2461*0a6a1f1dSLionel Sambuc       StringRef DefSymbol = Ref->getSymbol().getName();
2462f4a2713aSLionel Sambuc       if (DefSymbol.startswith("$")) {
2463*0a6a1f1dSLionel Sambuc         OperandMatchResultTy ResTy =
2464*0a6a1f1dSLionel Sambuc             matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
2465*0a6a1f1dSLionel Sambuc         if (ResTy == MatchOperand_Success) {
2466f4a2713aSLionel Sambuc           Parser.Lex();
2467f4a2713aSLionel Sambuc           return true;
2468*0a6a1f1dSLionel Sambuc         } else if (ResTy == MatchOperand_ParseFail)
2469*0a6a1f1dSLionel Sambuc           llvm_unreachable("Should never ParseFail");
2470*0a6a1f1dSLionel Sambuc         return false;
2471f4a2713aSLionel Sambuc       }
2472f4a2713aSLionel Sambuc     } else if (Expr->getKind() == MCExpr::Constant) {
2473f4a2713aSLionel Sambuc       Parser.Lex();
2474f4a2713aSLionel Sambuc       const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
2475*0a6a1f1dSLionel Sambuc       Operands.push_back(
2476*0a6a1f1dSLionel Sambuc           MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
2477f4a2713aSLionel Sambuc       return true;
2478f4a2713aSLionel Sambuc     }
2479f4a2713aSLionel Sambuc   }
2480f4a2713aSLionel Sambuc   return false;
2481f4a2713aSLionel Sambuc }
2482f4a2713aSLionel Sambuc 
2483f4a2713aSLionel Sambuc MipsAsmParser::OperandMatchResultTy
matchAnyRegisterNameWithoutDollar(OperandVector & Operands,StringRef Identifier,SMLoc S)2484*0a6a1f1dSLionel Sambuc MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
2485*0a6a1f1dSLionel Sambuc                                                  StringRef Identifier,
2486*0a6a1f1dSLionel Sambuc                                                  SMLoc S) {
2487*0a6a1f1dSLionel Sambuc   int Index = matchCPURegisterName(Identifier);
2488*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2489*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createGPRReg(
2490*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2491*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2492*0a6a1f1dSLionel Sambuc   }
2493*0a6a1f1dSLionel Sambuc 
2494*0a6a1f1dSLionel Sambuc   Index = matchHWRegsRegisterName(Identifier);
2495*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2496*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createHWRegsReg(
2497*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2498*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2499*0a6a1f1dSLionel Sambuc   }
2500*0a6a1f1dSLionel Sambuc 
2501*0a6a1f1dSLionel Sambuc   Index = matchFPURegisterName(Identifier);
2502*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2503*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createFGRReg(
2504*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2505*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2506*0a6a1f1dSLionel Sambuc   }
2507*0a6a1f1dSLionel Sambuc 
2508*0a6a1f1dSLionel Sambuc   Index = matchFCCRegisterName(Identifier);
2509*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2510*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createFCCReg(
2511*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2512*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2513*0a6a1f1dSLionel Sambuc   }
2514*0a6a1f1dSLionel Sambuc 
2515*0a6a1f1dSLionel Sambuc   Index = matchACRegisterName(Identifier);
2516*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2517*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createACCReg(
2518*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2519*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2520*0a6a1f1dSLionel Sambuc   }
2521*0a6a1f1dSLionel Sambuc 
2522*0a6a1f1dSLionel Sambuc   Index = matchMSA128RegisterName(Identifier);
2523*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2524*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createMSA128Reg(
2525*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2526*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2527*0a6a1f1dSLionel Sambuc   }
2528*0a6a1f1dSLionel Sambuc 
2529*0a6a1f1dSLionel Sambuc   Index = matchMSA128CtrlRegisterName(Identifier);
2530*0a6a1f1dSLionel Sambuc   if (Index != -1) {
2531*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createMSACtrlReg(
2532*0a6a1f1dSLionel Sambuc         Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2533*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2534*0a6a1f1dSLionel Sambuc   }
2535*0a6a1f1dSLionel Sambuc 
2536*0a6a1f1dSLionel Sambuc   return MatchOperand_NoMatch;
2537f4a2713aSLionel Sambuc }
2538f4a2713aSLionel Sambuc 
2539f4a2713aSLionel Sambuc MipsAsmParser::OperandMatchResultTy
matchAnyRegisterWithoutDollar(OperandVector & Operands,SMLoc S)2540*0a6a1f1dSLionel Sambuc MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
2541*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2542*0a6a1f1dSLionel Sambuc   auto Token = Parser.getLexer().peekTok(false);
2543*0a6a1f1dSLionel Sambuc 
2544*0a6a1f1dSLionel Sambuc   if (Token.is(AsmToken::Identifier)) {
2545*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << ".. identifier\n");
2546*0a6a1f1dSLionel Sambuc     StringRef Identifier = Token.getIdentifier();
2547*0a6a1f1dSLionel Sambuc     OperandMatchResultTy ResTy =
2548*0a6a1f1dSLionel Sambuc         matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
2549*0a6a1f1dSLionel Sambuc     return ResTy;
2550*0a6a1f1dSLionel Sambuc   } else if (Token.is(AsmToken::Integer)) {
2551*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << ".. integer\n");
2552*0a6a1f1dSLionel Sambuc     Operands.push_back(MipsOperand::createNumericReg(
2553*0a6a1f1dSLionel Sambuc         Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2554*0a6a1f1dSLionel Sambuc         *this));
2555*0a6a1f1dSLionel Sambuc     return MatchOperand_Success;
2556*0a6a1f1dSLionel Sambuc   }
2557*0a6a1f1dSLionel Sambuc 
2558*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2559*0a6a1f1dSLionel Sambuc 
2560*0a6a1f1dSLionel Sambuc   return MatchOperand_NoMatch;
2561f4a2713aSLionel Sambuc }
2562f4a2713aSLionel Sambuc 
2563f4a2713aSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseAnyRegister(OperandVector & Operands)2564*0a6a1f1dSLionel Sambuc MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2565*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2566*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << "parseAnyRegister\n");
2567*0a6a1f1dSLionel Sambuc 
2568*0a6a1f1dSLionel Sambuc   auto Token = Parser.getTok();
2569*0a6a1f1dSLionel Sambuc 
2570*0a6a1f1dSLionel Sambuc   SMLoc S = Token.getLoc();
2571*0a6a1f1dSLionel Sambuc 
2572*0a6a1f1dSLionel Sambuc   if (Token.isNot(AsmToken::Dollar)) {
2573*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2574*0a6a1f1dSLionel Sambuc     if (Token.is(AsmToken::Identifier)) {
2575*0a6a1f1dSLionel Sambuc       if (searchSymbolAlias(Operands))
2576*0a6a1f1dSLionel Sambuc         return MatchOperand_Success;
2577*0a6a1f1dSLionel Sambuc     }
2578*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2579*0a6a1f1dSLionel Sambuc     return MatchOperand_NoMatch;
2580*0a6a1f1dSLionel Sambuc   }
2581*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << ".. $\n");
2582*0a6a1f1dSLionel Sambuc 
2583*0a6a1f1dSLionel Sambuc   OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
2584*0a6a1f1dSLionel Sambuc   if (ResTy == MatchOperand_Success) {
2585*0a6a1f1dSLionel Sambuc     Parser.Lex(); // $
2586*0a6a1f1dSLionel Sambuc     Parser.Lex(); // identifier
2587*0a6a1f1dSLionel Sambuc   }
2588*0a6a1f1dSLionel Sambuc   return ResTy;
2589*0a6a1f1dSLionel Sambuc }
2590*0a6a1f1dSLionel Sambuc 
2591*0a6a1f1dSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseImm(OperandVector & Operands)2592*0a6a1f1dSLionel Sambuc MipsAsmParser::parseImm(OperandVector &Operands) {
2593*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2594*0a6a1f1dSLionel Sambuc   switch (getLexer().getKind()) {
2595*0a6a1f1dSLionel Sambuc   default:
2596*0a6a1f1dSLionel Sambuc     return MatchOperand_NoMatch;
2597*0a6a1f1dSLionel Sambuc   case AsmToken::LParen:
2598*0a6a1f1dSLionel Sambuc   case AsmToken::Minus:
2599*0a6a1f1dSLionel Sambuc   case AsmToken::Plus:
2600*0a6a1f1dSLionel Sambuc   case AsmToken::Integer:
2601*0a6a1f1dSLionel Sambuc   case AsmToken::Tilde:
2602*0a6a1f1dSLionel Sambuc   case AsmToken::String:
2603*0a6a1f1dSLionel Sambuc     break;
2604*0a6a1f1dSLionel Sambuc   }
2605*0a6a1f1dSLionel Sambuc 
2606*0a6a1f1dSLionel Sambuc   const MCExpr *IdVal;
2607*0a6a1f1dSLionel Sambuc   SMLoc S = Parser.getTok().getLoc();
2608*0a6a1f1dSLionel Sambuc   if (getParser().parseExpression(IdVal))
2609*0a6a1f1dSLionel Sambuc     return MatchOperand_ParseFail;
2610*0a6a1f1dSLionel Sambuc 
2611*0a6a1f1dSLionel Sambuc   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2612*0a6a1f1dSLionel Sambuc   Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2613*0a6a1f1dSLionel Sambuc   return MatchOperand_Success;
2614*0a6a1f1dSLionel Sambuc }
2615*0a6a1f1dSLionel Sambuc 
2616*0a6a1f1dSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseJumpTarget(OperandVector & Operands)2617*0a6a1f1dSLionel Sambuc MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2618*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2619*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << "parseJumpTarget\n");
2620*0a6a1f1dSLionel Sambuc 
2621*0a6a1f1dSLionel Sambuc   SMLoc S = getLexer().getLoc();
2622*0a6a1f1dSLionel Sambuc 
2623*0a6a1f1dSLionel Sambuc   // Integers and expressions are acceptable
2624*0a6a1f1dSLionel Sambuc   OperandMatchResultTy ResTy = parseImm(Operands);
2625*0a6a1f1dSLionel Sambuc   if (ResTy != MatchOperand_NoMatch)
2626*0a6a1f1dSLionel Sambuc     return ResTy;
2627*0a6a1f1dSLionel Sambuc 
2628*0a6a1f1dSLionel Sambuc   // Registers are a valid target and have priority over symbols.
2629*0a6a1f1dSLionel Sambuc   ResTy = parseAnyRegister(Operands);
2630*0a6a1f1dSLionel Sambuc   if (ResTy != MatchOperand_NoMatch)
2631*0a6a1f1dSLionel Sambuc     return ResTy;
2632*0a6a1f1dSLionel Sambuc 
2633*0a6a1f1dSLionel Sambuc   const MCExpr *Expr = nullptr;
2634*0a6a1f1dSLionel Sambuc   if (Parser.parseExpression(Expr)) {
2635*0a6a1f1dSLionel Sambuc     // We have no way of knowing if a symbol was consumed so we must ParseFail
2636*0a6a1f1dSLionel Sambuc     return MatchOperand_ParseFail;
2637*0a6a1f1dSLionel Sambuc   }
2638*0a6a1f1dSLionel Sambuc   Operands.push_back(
2639*0a6a1f1dSLionel Sambuc       MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
2640*0a6a1f1dSLionel Sambuc   return MatchOperand_Success;
2641*0a6a1f1dSLionel Sambuc }
2642*0a6a1f1dSLionel Sambuc 
2643*0a6a1f1dSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseInvNum(OperandVector & Operands)2644*0a6a1f1dSLionel Sambuc MipsAsmParser::parseInvNum(OperandVector &Operands) {
2645*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2646f4a2713aSLionel Sambuc   const MCExpr *IdVal;
2647f4a2713aSLionel Sambuc   // If the first token is '$' we may have register operand.
2648f4a2713aSLionel Sambuc   if (Parser.getTok().is(AsmToken::Dollar))
2649f4a2713aSLionel Sambuc     return MatchOperand_NoMatch;
2650f4a2713aSLionel Sambuc   SMLoc S = Parser.getTok().getLoc();
2651f4a2713aSLionel Sambuc   if (getParser().parseExpression(IdVal))
2652f4a2713aSLionel Sambuc     return MatchOperand_ParseFail;
2653f4a2713aSLionel Sambuc   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
2654f4a2713aSLionel Sambuc   assert(MCE && "Unexpected MCExpr type.");
2655f4a2713aSLionel Sambuc   int64_t Val = MCE->getValue();
2656f4a2713aSLionel Sambuc   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2657f4a2713aSLionel Sambuc   Operands.push_back(MipsOperand::CreateImm(
2658*0a6a1f1dSLionel Sambuc       MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
2659f4a2713aSLionel Sambuc   return MatchOperand_Success;
2660f4a2713aSLionel Sambuc }
2661f4a2713aSLionel Sambuc 
2662f4a2713aSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseLSAImm(OperandVector & Operands)2663*0a6a1f1dSLionel Sambuc MipsAsmParser::parseLSAImm(OperandVector &Operands) {
2664*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2665f4a2713aSLionel Sambuc   switch (getLexer().getKind()) {
2666f4a2713aSLionel Sambuc   default:
2667f4a2713aSLionel Sambuc     return MatchOperand_NoMatch;
2668f4a2713aSLionel Sambuc   case AsmToken::LParen:
2669f4a2713aSLionel Sambuc   case AsmToken::Plus:
2670f4a2713aSLionel Sambuc   case AsmToken::Minus:
2671f4a2713aSLionel Sambuc   case AsmToken::Integer:
2672f4a2713aSLionel Sambuc     break;
2673f4a2713aSLionel Sambuc   }
2674f4a2713aSLionel Sambuc 
2675f4a2713aSLionel Sambuc   const MCExpr *Expr;
2676f4a2713aSLionel Sambuc   SMLoc S = Parser.getTok().getLoc();
2677f4a2713aSLionel Sambuc 
2678f4a2713aSLionel Sambuc   if (getParser().parseExpression(Expr))
2679f4a2713aSLionel Sambuc     return MatchOperand_ParseFail;
2680f4a2713aSLionel Sambuc 
2681f4a2713aSLionel Sambuc   int64_t Val;
2682f4a2713aSLionel Sambuc   if (!Expr->EvaluateAsAbsolute(Val)) {
2683f4a2713aSLionel Sambuc     Error(S, "expected immediate value");
2684f4a2713aSLionel Sambuc     return MatchOperand_ParseFail;
2685f4a2713aSLionel Sambuc   }
2686f4a2713aSLionel Sambuc 
2687f4a2713aSLionel Sambuc   // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2688f4a2713aSLionel Sambuc   // and because the CPU always adds one to the immediate field, the allowed
2689f4a2713aSLionel Sambuc   // range becomes 1..4. We'll only check the range here and will deal
2690f4a2713aSLionel Sambuc   // with the addition/subtraction when actually decoding/encoding
2691f4a2713aSLionel Sambuc   // the instruction.
2692f4a2713aSLionel Sambuc   if (Val < 1 || Val > 4) {
2693f4a2713aSLionel Sambuc     Error(S, "immediate not in range (1..4)");
2694f4a2713aSLionel Sambuc     return MatchOperand_ParseFail;
2695f4a2713aSLionel Sambuc   }
2696f4a2713aSLionel Sambuc 
2697*0a6a1f1dSLionel Sambuc   Operands.push_back(
2698*0a6a1f1dSLionel Sambuc       MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
2699*0a6a1f1dSLionel Sambuc   return MatchOperand_Success;
2700*0a6a1f1dSLionel Sambuc }
2701*0a6a1f1dSLionel Sambuc 
2702*0a6a1f1dSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseRegisterList(OperandVector & Operands)2703*0a6a1f1dSLionel Sambuc MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2704*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2705*0a6a1f1dSLionel Sambuc   SmallVector<unsigned, 10> Regs;
2706*0a6a1f1dSLionel Sambuc   unsigned RegNo;
2707*0a6a1f1dSLionel Sambuc   unsigned PrevReg = Mips::NoRegister;
2708*0a6a1f1dSLionel Sambuc   bool RegRange = false;
2709*0a6a1f1dSLionel Sambuc   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2710*0a6a1f1dSLionel Sambuc 
2711*0a6a1f1dSLionel Sambuc   if (Parser.getTok().isNot(AsmToken::Dollar))
2712*0a6a1f1dSLionel Sambuc     return MatchOperand_ParseFail;
2713*0a6a1f1dSLionel Sambuc 
2714*0a6a1f1dSLionel Sambuc   SMLoc S = Parser.getTok().getLoc();
2715*0a6a1f1dSLionel Sambuc   while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2716*0a6a1f1dSLionel Sambuc     SMLoc E = getLexer().getLoc();
2717*0a6a1f1dSLionel Sambuc     MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2718*0a6a1f1dSLionel Sambuc     RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2719*0a6a1f1dSLionel Sambuc     if (RegRange) {
2720*0a6a1f1dSLionel Sambuc       // Remove last register operand because registers from register range
2721*0a6a1f1dSLionel Sambuc       // should be inserted first.
2722*0a6a1f1dSLionel Sambuc       if (RegNo == Mips::RA) {
2723*0a6a1f1dSLionel Sambuc         Regs.push_back(RegNo);
2724*0a6a1f1dSLionel Sambuc       } else {
2725*0a6a1f1dSLionel Sambuc         unsigned TmpReg = PrevReg + 1;
2726*0a6a1f1dSLionel Sambuc         while (TmpReg <= RegNo) {
2727*0a6a1f1dSLionel Sambuc           if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2728*0a6a1f1dSLionel Sambuc             Error(E, "invalid register operand");
2729*0a6a1f1dSLionel Sambuc             return MatchOperand_ParseFail;
2730*0a6a1f1dSLionel Sambuc           }
2731*0a6a1f1dSLionel Sambuc 
2732*0a6a1f1dSLionel Sambuc           PrevReg = TmpReg;
2733*0a6a1f1dSLionel Sambuc           Regs.push_back(TmpReg++);
2734*0a6a1f1dSLionel Sambuc         }
2735*0a6a1f1dSLionel Sambuc       }
2736*0a6a1f1dSLionel Sambuc 
2737*0a6a1f1dSLionel Sambuc       RegRange = false;
2738*0a6a1f1dSLionel Sambuc     } else {
2739*0a6a1f1dSLionel Sambuc       if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2740*0a6a1f1dSLionel Sambuc           (RegNo != Mips::RA)) {
2741*0a6a1f1dSLionel Sambuc         Error(E, "$16 or $31 expected");
2742*0a6a1f1dSLionel Sambuc         return MatchOperand_ParseFail;
2743*0a6a1f1dSLionel Sambuc       } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2744*0a6a1f1dSLionel Sambuc                  (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2745*0a6a1f1dSLionel Sambuc         Error(E, "invalid register operand");
2746*0a6a1f1dSLionel Sambuc         return MatchOperand_ParseFail;
2747*0a6a1f1dSLionel Sambuc       } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2748*0a6a1f1dSLionel Sambuc                  (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2749*0a6a1f1dSLionel Sambuc         Error(E, "consecutive register numbers expected");
2750*0a6a1f1dSLionel Sambuc         return MatchOperand_ParseFail;
2751*0a6a1f1dSLionel Sambuc       }
2752*0a6a1f1dSLionel Sambuc 
2753*0a6a1f1dSLionel Sambuc       Regs.push_back(RegNo);
2754*0a6a1f1dSLionel Sambuc     }
2755*0a6a1f1dSLionel Sambuc 
2756*0a6a1f1dSLionel Sambuc     if (Parser.getTok().is(AsmToken::Minus))
2757*0a6a1f1dSLionel Sambuc       RegRange = true;
2758*0a6a1f1dSLionel Sambuc 
2759*0a6a1f1dSLionel Sambuc     if (!Parser.getTok().isNot(AsmToken::Minus) &&
2760*0a6a1f1dSLionel Sambuc         !Parser.getTok().isNot(AsmToken::Comma)) {
2761*0a6a1f1dSLionel Sambuc       Error(E, "',' or '-' expected");
2762*0a6a1f1dSLionel Sambuc       return MatchOperand_ParseFail;
2763*0a6a1f1dSLionel Sambuc     }
2764*0a6a1f1dSLionel Sambuc 
2765*0a6a1f1dSLionel Sambuc     Lex(); // Consume comma or minus
2766*0a6a1f1dSLionel Sambuc     if (Parser.getTok().isNot(AsmToken::Dollar))
2767*0a6a1f1dSLionel Sambuc       break;
2768*0a6a1f1dSLionel Sambuc 
2769*0a6a1f1dSLionel Sambuc     PrevReg = RegNo;
2770*0a6a1f1dSLionel Sambuc   }
2771*0a6a1f1dSLionel Sambuc 
2772*0a6a1f1dSLionel Sambuc   SMLoc E = Parser.getTok().getLoc();
2773*0a6a1f1dSLionel Sambuc   Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2774*0a6a1f1dSLionel Sambuc   parseMemOperand(Operands);
2775*0a6a1f1dSLionel Sambuc   return MatchOperand_Success;
2776*0a6a1f1dSLionel Sambuc }
2777*0a6a1f1dSLionel Sambuc 
2778*0a6a1f1dSLionel Sambuc MipsAsmParser::OperandMatchResultTy
parseRegisterPair(OperandVector & Operands)2779*0a6a1f1dSLionel Sambuc MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2780*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2781*0a6a1f1dSLionel Sambuc 
2782*0a6a1f1dSLionel Sambuc   SMLoc S = Parser.getTok().getLoc();
2783*0a6a1f1dSLionel Sambuc   if (parseAnyRegister(Operands) != MatchOperand_Success)
2784*0a6a1f1dSLionel Sambuc     return MatchOperand_ParseFail;
2785*0a6a1f1dSLionel Sambuc 
2786*0a6a1f1dSLionel Sambuc   SMLoc E = Parser.getTok().getLoc();
2787*0a6a1f1dSLionel Sambuc   MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2788*0a6a1f1dSLionel Sambuc   unsigned Reg = Op.getGPR32Reg();
2789*0a6a1f1dSLionel Sambuc   Operands.pop_back();
2790*0a6a1f1dSLionel Sambuc   Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2791f4a2713aSLionel Sambuc   return MatchOperand_Success;
2792f4a2713aSLionel Sambuc }
2793f4a2713aSLionel Sambuc 
getVariantKind(StringRef Symbol)2794f4a2713aSLionel Sambuc MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2795f4a2713aSLionel Sambuc 
2796f4a2713aSLionel Sambuc   MCSymbolRefExpr::VariantKind VK =
2797f4a2713aSLionel Sambuc       StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2798f4a2713aSLionel Sambuc           .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2799f4a2713aSLionel Sambuc           .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2800f4a2713aSLionel Sambuc           .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2801f4a2713aSLionel Sambuc           .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2802f4a2713aSLionel Sambuc           .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2803f4a2713aSLionel Sambuc           .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2804f4a2713aSLionel Sambuc           .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2805f4a2713aSLionel Sambuc           .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2806f4a2713aSLionel Sambuc           .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2807f4a2713aSLionel Sambuc           .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2808f4a2713aSLionel Sambuc           .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2809f4a2713aSLionel Sambuc           .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2810f4a2713aSLionel Sambuc           .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2811f4a2713aSLionel Sambuc           .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2812f4a2713aSLionel Sambuc           .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2813f4a2713aSLionel Sambuc           .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2814f4a2713aSLionel Sambuc           .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
2815*0a6a1f1dSLionel Sambuc           .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2816*0a6a1f1dSLionel Sambuc           .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2817*0a6a1f1dSLionel Sambuc           .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2818*0a6a1f1dSLionel Sambuc           .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2819*0a6a1f1dSLionel Sambuc           .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2820*0a6a1f1dSLionel Sambuc           .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
2821*0a6a1f1dSLionel Sambuc           .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2822*0a6a1f1dSLionel Sambuc           .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
2823f4a2713aSLionel Sambuc           .Default(MCSymbolRefExpr::VK_None);
2824f4a2713aSLionel Sambuc 
2825*0a6a1f1dSLionel Sambuc   assert(VK != MCSymbolRefExpr::VK_None);
2826*0a6a1f1dSLionel Sambuc 
2827f4a2713aSLionel Sambuc   return VK;
2828f4a2713aSLionel Sambuc }
2829f4a2713aSLionel Sambuc 
2830*0a6a1f1dSLionel Sambuc /// Sometimes (i.e. load/stores) the operand may be followed immediately by
2831*0a6a1f1dSLionel Sambuc /// either this.
2832*0a6a1f1dSLionel Sambuc /// ::= '(', register, ')'
2833*0a6a1f1dSLionel Sambuc /// handle it before we iterate so we don't get tripped up by the lack of
2834*0a6a1f1dSLionel Sambuc /// a comma.
parseParenSuffix(StringRef Name,OperandVector & Operands)2835*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
2836*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2837*0a6a1f1dSLionel Sambuc   if (getLexer().is(AsmToken::LParen)) {
2838*0a6a1f1dSLionel Sambuc     Operands.push_back(
2839*0a6a1f1dSLionel Sambuc         MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2840*0a6a1f1dSLionel Sambuc     Parser.Lex();
2841*0a6a1f1dSLionel Sambuc     if (parseOperand(Operands, Name)) {
2842*0a6a1f1dSLionel Sambuc       SMLoc Loc = getLexer().getLoc();
2843*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
2844*0a6a1f1dSLionel Sambuc       return Error(Loc, "unexpected token in argument list");
2845*0a6a1f1dSLionel Sambuc     }
2846*0a6a1f1dSLionel Sambuc     if (Parser.getTok().isNot(AsmToken::RParen)) {
2847*0a6a1f1dSLionel Sambuc       SMLoc Loc = getLexer().getLoc();
2848*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
2849*0a6a1f1dSLionel Sambuc       return Error(Loc, "unexpected token, expected ')'");
2850*0a6a1f1dSLionel Sambuc     }
2851*0a6a1f1dSLionel Sambuc     Operands.push_back(
2852*0a6a1f1dSLionel Sambuc         MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2853*0a6a1f1dSLionel Sambuc     Parser.Lex();
2854*0a6a1f1dSLionel Sambuc   }
2855*0a6a1f1dSLionel Sambuc   return false;
2856*0a6a1f1dSLionel Sambuc }
2857*0a6a1f1dSLionel Sambuc 
2858*0a6a1f1dSLionel Sambuc /// Sometimes (i.e. in MSA) the operand may be followed immediately by
2859*0a6a1f1dSLionel Sambuc /// either one of these.
2860*0a6a1f1dSLionel Sambuc /// ::= '[', register, ']'
2861*0a6a1f1dSLionel Sambuc /// ::= '[', integer, ']'
2862*0a6a1f1dSLionel Sambuc /// handle it before we iterate so we don't get tripped up by the lack of
2863*0a6a1f1dSLionel Sambuc /// a comma.
parseBracketSuffix(StringRef Name,OperandVector & Operands)2864*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseBracketSuffix(StringRef Name,
2865*0a6a1f1dSLionel Sambuc                                        OperandVector &Operands) {
2866*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2867*0a6a1f1dSLionel Sambuc   if (getLexer().is(AsmToken::LBrac)) {
2868*0a6a1f1dSLionel Sambuc     Operands.push_back(
2869*0a6a1f1dSLionel Sambuc         MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2870*0a6a1f1dSLionel Sambuc     Parser.Lex();
2871*0a6a1f1dSLionel Sambuc     if (parseOperand(Operands, Name)) {
2872*0a6a1f1dSLionel Sambuc       SMLoc Loc = getLexer().getLoc();
2873*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
2874*0a6a1f1dSLionel Sambuc       return Error(Loc, "unexpected token in argument list");
2875*0a6a1f1dSLionel Sambuc     }
2876*0a6a1f1dSLionel Sambuc     if (Parser.getTok().isNot(AsmToken::RBrac)) {
2877*0a6a1f1dSLionel Sambuc       SMLoc Loc = getLexer().getLoc();
2878*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
2879*0a6a1f1dSLionel Sambuc       return Error(Loc, "unexpected token, expected ']'");
2880*0a6a1f1dSLionel Sambuc     }
2881*0a6a1f1dSLionel Sambuc     Operands.push_back(
2882*0a6a1f1dSLionel Sambuc         MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2883*0a6a1f1dSLionel Sambuc     Parser.Lex();
2884*0a6a1f1dSLionel Sambuc   }
2885*0a6a1f1dSLionel Sambuc   return false;
2886*0a6a1f1dSLionel Sambuc }
2887*0a6a1f1dSLionel Sambuc 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)2888*0a6a1f1dSLionel Sambuc bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2889*0a6a1f1dSLionel Sambuc                                      SMLoc NameLoc, OperandVector &Operands) {
2890*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2891*0a6a1f1dSLionel Sambuc   DEBUG(dbgs() << "ParseInstruction\n");
2892*0a6a1f1dSLionel Sambuc 
2893*0a6a1f1dSLionel Sambuc   // We have reached first instruction, module directive are now forbidden.
2894*0a6a1f1dSLionel Sambuc   getTargetStreamer().forbidModuleDirective();
2895*0a6a1f1dSLionel Sambuc 
2896f4a2713aSLionel Sambuc   // Check if we have valid mnemonic
2897f4a2713aSLionel Sambuc   if (!mnemonicIsValid(Name, 0)) {
2898f4a2713aSLionel Sambuc     Parser.eatToEndOfStatement();
2899*0a6a1f1dSLionel Sambuc     return Error(NameLoc, "unknown instruction");
2900f4a2713aSLionel Sambuc   }
2901f4a2713aSLionel Sambuc   // First operand in MCInst is instruction mnemonic.
2902*0a6a1f1dSLionel Sambuc   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
2903f4a2713aSLionel Sambuc 
2904f4a2713aSLionel Sambuc   // Read the remaining operands.
2905f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
2906f4a2713aSLionel Sambuc     // Read the first operand.
2907*0a6a1f1dSLionel Sambuc     if (parseOperand(Operands, Name)) {
2908f4a2713aSLionel Sambuc       SMLoc Loc = getLexer().getLoc();
2909f4a2713aSLionel Sambuc       Parser.eatToEndOfStatement();
2910f4a2713aSLionel Sambuc       return Error(Loc, "unexpected token in argument list");
2911f4a2713aSLionel Sambuc     }
2912*0a6a1f1dSLionel Sambuc     if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
2913*0a6a1f1dSLionel Sambuc       return true;
2914*0a6a1f1dSLionel Sambuc     // AFAIK, parenthesis suffixes are never on the first operand
2915f4a2713aSLionel Sambuc 
2916f4a2713aSLionel Sambuc     while (getLexer().is(AsmToken::Comma)) {
2917f4a2713aSLionel Sambuc       Parser.Lex(); // Eat the comma.
2918f4a2713aSLionel Sambuc       // Parse and remember the operand.
2919*0a6a1f1dSLionel Sambuc       if (parseOperand(Operands, Name)) {
2920f4a2713aSLionel Sambuc         SMLoc Loc = getLexer().getLoc();
2921f4a2713aSLionel Sambuc         Parser.eatToEndOfStatement();
2922f4a2713aSLionel Sambuc         return Error(Loc, "unexpected token in argument list");
2923f4a2713aSLionel Sambuc       }
2924*0a6a1f1dSLionel Sambuc       // Parse bracket and parenthesis suffixes before we iterate
2925*0a6a1f1dSLionel Sambuc       if (getLexer().is(AsmToken::LBrac)) {
2926*0a6a1f1dSLionel Sambuc         if (parseBracketSuffix(Name, Operands))
2927*0a6a1f1dSLionel Sambuc           return true;
2928*0a6a1f1dSLionel Sambuc       } else if (getLexer().is(AsmToken::LParen) &&
2929*0a6a1f1dSLionel Sambuc                  parseParenSuffix(Name, Operands))
2930*0a6a1f1dSLionel Sambuc         return true;
2931f4a2713aSLionel Sambuc     }
2932f4a2713aSLionel Sambuc   }
2933f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
2934f4a2713aSLionel Sambuc     SMLoc Loc = getLexer().getLoc();
2935f4a2713aSLionel Sambuc     Parser.eatToEndOfStatement();
2936f4a2713aSLionel Sambuc     return Error(Loc, "unexpected token in argument list");
2937f4a2713aSLionel Sambuc   }
2938f4a2713aSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
2939f4a2713aSLionel Sambuc   return false;
2940f4a2713aSLionel Sambuc }
2941f4a2713aSLionel Sambuc 
reportParseError(Twine ErrorMsg)2942*0a6a1f1dSLionel Sambuc bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
2943*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2944f4a2713aSLionel Sambuc   SMLoc Loc = getLexer().getLoc();
2945f4a2713aSLionel Sambuc   Parser.eatToEndOfStatement();
2946f4a2713aSLionel Sambuc   return Error(Loc, ErrorMsg);
2947f4a2713aSLionel Sambuc }
2948f4a2713aSLionel Sambuc 
reportParseError(SMLoc Loc,Twine ErrorMsg)2949*0a6a1f1dSLionel Sambuc bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
2950*0a6a1f1dSLionel Sambuc   return Error(Loc, ErrorMsg);
2951*0a6a1f1dSLionel Sambuc }
2952*0a6a1f1dSLionel Sambuc 
parseSetNoAtDirective()2953f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetNoAtDirective() {
2954*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2955f4a2713aSLionel Sambuc   // Line should look like: ".set noat".
2956f4a2713aSLionel Sambuc   // set at reg to 0.
2957*0a6a1f1dSLionel Sambuc   AssemblerOptions.back()->setATReg(0);
2958f4a2713aSLionel Sambuc   // eat noat
2959f4a2713aSLionel Sambuc   Parser.Lex();
2960f4a2713aSLionel Sambuc   // If this is not the end of the statement, report an error.
2961f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
2962*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
2963f4a2713aSLionel Sambuc     return false;
2964f4a2713aSLionel Sambuc   }
2965f4a2713aSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
2966f4a2713aSLionel Sambuc   return false;
2967f4a2713aSLionel Sambuc }
2968f4a2713aSLionel Sambuc 
parseSetAtDirective()2969f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetAtDirective() {
2970*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
2971f4a2713aSLionel Sambuc   // Line can be .set at - defaults to $1
2972f4a2713aSLionel Sambuc   // or .set at=$reg
2973f4a2713aSLionel Sambuc   int AtRegNo;
2974f4a2713aSLionel Sambuc   getParser().Lex();
2975f4a2713aSLionel Sambuc   if (getLexer().is(AsmToken::EndOfStatement)) {
2976*0a6a1f1dSLionel Sambuc     AssemblerOptions.back()->setATReg(1);
2977f4a2713aSLionel Sambuc     Parser.Lex(); // Consume the EndOfStatement.
2978f4a2713aSLionel Sambuc     return false;
2979f4a2713aSLionel Sambuc   } else if (getLexer().is(AsmToken::Equal)) {
2980f4a2713aSLionel Sambuc     getParser().Lex(); // Eat the '='.
2981f4a2713aSLionel Sambuc     if (getLexer().isNot(AsmToken::Dollar)) {
2982*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected dollar sign '$'");
2983f4a2713aSLionel Sambuc       return false;
2984f4a2713aSLionel Sambuc     }
2985f4a2713aSLionel Sambuc     Parser.Lex(); // Eat the '$'.
2986f4a2713aSLionel Sambuc     const AsmToken &Reg = Parser.getTok();
2987f4a2713aSLionel Sambuc     if (Reg.is(AsmToken::Identifier)) {
2988f4a2713aSLionel Sambuc       AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2989f4a2713aSLionel Sambuc     } else if (Reg.is(AsmToken::Integer)) {
2990f4a2713aSLionel Sambuc       AtRegNo = Reg.getIntVal();
2991f4a2713aSLionel Sambuc     } else {
2992*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected identifier or integer");
2993*0a6a1f1dSLionel Sambuc       return false;
2994*0a6a1f1dSLionel Sambuc     }
2995*0a6a1f1dSLionel Sambuc 
2996*0a6a1f1dSLionel Sambuc     if (AtRegNo < 0 || AtRegNo > 31) {
2997f4a2713aSLionel Sambuc       reportParseError("unexpected token in statement");
2998f4a2713aSLionel Sambuc       return false;
2999f4a2713aSLionel Sambuc     }
3000f4a2713aSLionel Sambuc 
3001*0a6a1f1dSLionel Sambuc     if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3002*0a6a1f1dSLionel Sambuc       reportParseError("invalid register");
3003f4a2713aSLionel Sambuc       return false;
3004f4a2713aSLionel Sambuc     }
3005f4a2713aSLionel Sambuc     getParser().Lex(); // Eat the register.
3006f4a2713aSLionel Sambuc 
3007f4a2713aSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3008*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3009f4a2713aSLionel Sambuc       return false;
3010f4a2713aSLionel Sambuc     }
3011f4a2713aSLionel Sambuc     Parser.Lex(); // Consume the EndOfStatement.
3012f4a2713aSLionel Sambuc     return false;
3013f4a2713aSLionel Sambuc   } else {
3014f4a2713aSLionel Sambuc     reportParseError("unexpected token in statement");
3015f4a2713aSLionel Sambuc     return false;
3016f4a2713aSLionel Sambuc   }
3017f4a2713aSLionel Sambuc }
3018f4a2713aSLionel Sambuc 
parseSetReorderDirective()3019f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetReorderDirective() {
3020*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3021f4a2713aSLionel Sambuc   Parser.Lex();
3022f4a2713aSLionel Sambuc   // If this is not the end of the statement, report an error.
3023f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3024*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3025f4a2713aSLionel Sambuc     return false;
3026f4a2713aSLionel Sambuc   }
3027*0a6a1f1dSLionel Sambuc   AssemblerOptions.back()->setReorder();
3028*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetReorder();
3029f4a2713aSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3030f4a2713aSLionel Sambuc   return false;
3031f4a2713aSLionel Sambuc }
3032f4a2713aSLionel Sambuc 
parseSetNoReorderDirective()3033f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetNoReorderDirective() {
3034*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3035f4a2713aSLionel Sambuc   Parser.Lex();
3036f4a2713aSLionel Sambuc   // If this is not the end of the statement, report an error.
3037f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3038*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3039f4a2713aSLionel Sambuc     return false;
3040f4a2713aSLionel Sambuc   }
3041*0a6a1f1dSLionel Sambuc   AssemblerOptions.back()->setNoReorder();
3042*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetNoReorder();
3043f4a2713aSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3044f4a2713aSLionel Sambuc   return false;
3045f4a2713aSLionel Sambuc }
3046f4a2713aSLionel Sambuc 
parseSetMacroDirective()3047f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetMacroDirective() {
3048*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3049f4a2713aSLionel Sambuc   Parser.Lex();
3050f4a2713aSLionel Sambuc   // If this is not the end of the statement, report an error.
3051f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3052*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3053f4a2713aSLionel Sambuc     return false;
3054f4a2713aSLionel Sambuc   }
3055*0a6a1f1dSLionel Sambuc   AssemblerOptions.back()->setMacro();
3056f4a2713aSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3057f4a2713aSLionel Sambuc   return false;
3058f4a2713aSLionel Sambuc }
3059f4a2713aSLionel Sambuc 
parseSetNoMacroDirective()3060f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetNoMacroDirective() {
3061*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3062f4a2713aSLionel Sambuc   Parser.Lex();
3063f4a2713aSLionel Sambuc   // If this is not the end of the statement, report an error.
3064f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3065*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3066*0a6a1f1dSLionel Sambuc     return false;
3067*0a6a1f1dSLionel Sambuc   }
3068*0a6a1f1dSLionel Sambuc   if (AssemblerOptions.back()->isReorder()) {
3069f4a2713aSLionel Sambuc     reportParseError("`noreorder' must be set before `nomacro'");
3070f4a2713aSLionel Sambuc     return false;
3071f4a2713aSLionel Sambuc   }
3072*0a6a1f1dSLionel Sambuc   AssemblerOptions.back()->setNoMacro();
3073f4a2713aSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3074f4a2713aSLionel Sambuc   return false;
3075f4a2713aSLionel Sambuc }
3076f4a2713aSLionel Sambuc 
parseSetMsaDirective()3077*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetMsaDirective() {
3078*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3079*0a6a1f1dSLionel Sambuc   Parser.Lex();
3080*0a6a1f1dSLionel Sambuc 
3081*0a6a1f1dSLionel Sambuc   // If this is not the end of the statement, report an error.
3082*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3083*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected end of statement");
3084*0a6a1f1dSLionel Sambuc 
3085*0a6a1f1dSLionel Sambuc   setFeatureBits(Mips::FeatureMSA, "msa");
3086*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetMsa();
3087*0a6a1f1dSLionel Sambuc   return false;
3088*0a6a1f1dSLionel Sambuc }
3089*0a6a1f1dSLionel Sambuc 
parseSetNoMsaDirective()3090*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetNoMsaDirective() {
3091*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3092*0a6a1f1dSLionel Sambuc   Parser.Lex();
3093*0a6a1f1dSLionel Sambuc 
3094*0a6a1f1dSLionel Sambuc   // If this is not the end of the statement, report an error.
3095*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3096*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected end of statement");
3097*0a6a1f1dSLionel Sambuc 
3098*0a6a1f1dSLionel Sambuc   clearFeatureBits(Mips::FeatureMSA, "msa");
3099*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetNoMsa();
3100*0a6a1f1dSLionel Sambuc   return false;
3101*0a6a1f1dSLionel Sambuc }
3102*0a6a1f1dSLionel Sambuc 
parseSetNoDspDirective()3103*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetNoDspDirective() {
3104*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3105*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat "nodsp".
3106*0a6a1f1dSLionel Sambuc 
3107*0a6a1f1dSLionel Sambuc   // If this is not the end of the statement, report an error.
3108*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3109*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3110*0a6a1f1dSLionel Sambuc     return false;
3111*0a6a1f1dSLionel Sambuc   }
3112*0a6a1f1dSLionel Sambuc 
3113*0a6a1f1dSLionel Sambuc   clearFeatureBits(Mips::FeatureDSP, "dsp");
3114*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetNoDsp();
3115*0a6a1f1dSLionel Sambuc   return false;
3116*0a6a1f1dSLionel Sambuc }
3117*0a6a1f1dSLionel Sambuc 
parseSetMips16Directive()3118*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetMips16Directive() {
3119*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3120*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat "mips16".
3121*0a6a1f1dSLionel Sambuc 
3122*0a6a1f1dSLionel Sambuc   // If this is not the end of the statement, report an error.
3123*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3124*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3125*0a6a1f1dSLionel Sambuc     return false;
3126*0a6a1f1dSLionel Sambuc   }
3127*0a6a1f1dSLionel Sambuc 
3128*0a6a1f1dSLionel Sambuc   setFeatureBits(Mips::FeatureMips16, "mips16");
3129*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetMips16();
3130*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3131*0a6a1f1dSLionel Sambuc   return false;
3132*0a6a1f1dSLionel Sambuc }
3133*0a6a1f1dSLionel Sambuc 
parseSetNoMips16Directive()3134*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetNoMips16Directive() {
3135*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3136*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat "nomips16".
3137*0a6a1f1dSLionel Sambuc 
3138*0a6a1f1dSLionel Sambuc   // If this is not the end of the statement, report an error.
3139*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3140*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3141*0a6a1f1dSLionel Sambuc     return false;
3142*0a6a1f1dSLionel Sambuc   }
3143*0a6a1f1dSLionel Sambuc 
3144*0a6a1f1dSLionel Sambuc   clearFeatureBits(Mips::FeatureMips16, "mips16");
3145*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetNoMips16();
3146*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3147*0a6a1f1dSLionel Sambuc   return false;
3148*0a6a1f1dSLionel Sambuc }
3149*0a6a1f1dSLionel Sambuc 
parseSetFpDirective()3150*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetFpDirective() {
3151*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3152*0a6a1f1dSLionel Sambuc   MipsABIFlagsSection::FpABIKind FpAbiVal;
3153*0a6a1f1dSLionel Sambuc   // Line can be: .set fp=32
3154*0a6a1f1dSLionel Sambuc   //              .set fp=xx
3155*0a6a1f1dSLionel Sambuc   //              .set fp=64
3156*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat fp token
3157*0a6a1f1dSLionel Sambuc   AsmToken Tok = Parser.getTok();
3158*0a6a1f1dSLionel Sambuc   if (Tok.isNot(AsmToken::Equal)) {
3159*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected equals sign '='");
3160*0a6a1f1dSLionel Sambuc     return false;
3161*0a6a1f1dSLionel Sambuc   }
3162*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat '=' token.
3163*0a6a1f1dSLionel Sambuc   Tok = Parser.getTok();
3164*0a6a1f1dSLionel Sambuc 
3165*0a6a1f1dSLionel Sambuc   if (!parseFpABIValue(FpAbiVal, ".set"))
3166*0a6a1f1dSLionel Sambuc     return false;
3167*0a6a1f1dSLionel Sambuc 
3168*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3169*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3170*0a6a1f1dSLionel Sambuc     return false;
3171*0a6a1f1dSLionel Sambuc   }
3172*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
3173*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3174*0a6a1f1dSLionel Sambuc   return false;
3175*0a6a1f1dSLionel Sambuc }
3176*0a6a1f1dSLionel Sambuc 
parseSetPopDirective()3177*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetPopDirective() {
3178*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3179*0a6a1f1dSLionel Sambuc   SMLoc Loc = getLexer().getLoc();
3180*0a6a1f1dSLionel Sambuc 
3181*0a6a1f1dSLionel Sambuc   Parser.Lex();
3182*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3183*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected end of statement");
3184*0a6a1f1dSLionel Sambuc 
3185*0a6a1f1dSLionel Sambuc   // Always keep an element on the options "stack" to prevent the user
3186*0a6a1f1dSLionel Sambuc   // from changing the initial options. This is how we remember them.
3187*0a6a1f1dSLionel Sambuc   if (AssemblerOptions.size() == 2)
3188*0a6a1f1dSLionel Sambuc     return reportParseError(Loc, ".set pop with no .set push");
3189*0a6a1f1dSLionel Sambuc 
3190*0a6a1f1dSLionel Sambuc   AssemblerOptions.pop_back();
3191*0a6a1f1dSLionel Sambuc   setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3192*0a6a1f1dSLionel Sambuc 
3193*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetPop();
3194*0a6a1f1dSLionel Sambuc   return false;
3195*0a6a1f1dSLionel Sambuc }
3196*0a6a1f1dSLionel Sambuc 
parseSetPushDirective()3197*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetPushDirective() {
3198*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3199*0a6a1f1dSLionel Sambuc   Parser.Lex();
3200*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3201*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected end of statement");
3202*0a6a1f1dSLionel Sambuc 
3203*0a6a1f1dSLionel Sambuc   // Create a copy of the current assembler options environment and push it.
3204*0a6a1f1dSLionel Sambuc   AssemblerOptions.push_back(
3205*0a6a1f1dSLionel Sambuc               make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
3206*0a6a1f1dSLionel Sambuc 
3207*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetPush();
3208*0a6a1f1dSLionel Sambuc   return false;
3209*0a6a1f1dSLionel Sambuc }
3210*0a6a1f1dSLionel Sambuc 
parseSetAssignment()3211f4a2713aSLionel Sambuc bool MipsAsmParser::parseSetAssignment() {
3212f4a2713aSLionel Sambuc   StringRef Name;
3213f4a2713aSLionel Sambuc   const MCExpr *Value;
3214*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3215f4a2713aSLionel Sambuc 
3216f4a2713aSLionel Sambuc   if (Parser.parseIdentifier(Name))
3217f4a2713aSLionel Sambuc     reportParseError("expected identifier after .set");
3218f4a2713aSLionel Sambuc 
3219f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::Comma))
3220*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected comma");
3221f4a2713aSLionel Sambuc   Lex(); // Eat comma
3222f4a2713aSLionel Sambuc 
3223*0a6a1f1dSLionel Sambuc   if (Parser.parseExpression(Value))
3224f4a2713aSLionel Sambuc     return reportParseError("expected valid expression after comma");
3225f4a2713aSLionel Sambuc 
3226f4a2713aSLionel Sambuc   // Check if the Name already exists as a symbol.
3227f4a2713aSLionel Sambuc   MCSymbol *Sym = getContext().LookupSymbol(Name);
3228f4a2713aSLionel Sambuc   if (Sym)
3229f4a2713aSLionel Sambuc     return reportParseError("symbol already defined");
3230f4a2713aSLionel Sambuc   Sym = getContext().GetOrCreateSymbol(Name);
3231f4a2713aSLionel Sambuc   Sym->setVariableValue(Value);
3232f4a2713aSLionel Sambuc 
3233f4a2713aSLionel Sambuc   return false;
3234f4a2713aSLionel Sambuc }
3235f4a2713aSLionel Sambuc 
parseSetMips0Directive()3236*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetMips0Directive() {
3237*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3238*0a6a1f1dSLionel Sambuc   Parser.Lex();
3239*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3240*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected end of statement");
3241f4a2713aSLionel Sambuc 
3242*0a6a1f1dSLionel Sambuc   // Reset assembler options to their initial values.
3243*0a6a1f1dSLionel Sambuc   setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3244*0a6a1f1dSLionel Sambuc   AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3245*0a6a1f1dSLionel Sambuc 
3246*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetMips0();
3247*0a6a1f1dSLionel Sambuc   return false;
3248*0a6a1f1dSLionel Sambuc }
3249*0a6a1f1dSLionel Sambuc 
parseSetArchDirective()3250*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetArchDirective() {
3251*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3252*0a6a1f1dSLionel Sambuc   Parser.Lex();
3253*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::Equal))
3254*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected equals sign");
3255*0a6a1f1dSLionel Sambuc 
3256*0a6a1f1dSLionel Sambuc   Parser.Lex();
3257*0a6a1f1dSLionel Sambuc   StringRef Arch;
3258*0a6a1f1dSLionel Sambuc   if (Parser.parseIdentifier(Arch))
3259*0a6a1f1dSLionel Sambuc     return reportParseError("expected arch identifier");
3260*0a6a1f1dSLionel Sambuc 
3261*0a6a1f1dSLionel Sambuc   StringRef ArchFeatureName =
3262*0a6a1f1dSLionel Sambuc       StringSwitch<StringRef>(Arch)
3263*0a6a1f1dSLionel Sambuc           .Case("mips1", "mips1")
3264*0a6a1f1dSLionel Sambuc           .Case("mips2", "mips2")
3265*0a6a1f1dSLionel Sambuc           .Case("mips3", "mips3")
3266*0a6a1f1dSLionel Sambuc           .Case("mips4", "mips4")
3267*0a6a1f1dSLionel Sambuc           .Case("mips5", "mips5")
3268*0a6a1f1dSLionel Sambuc           .Case("mips32", "mips32")
3269*0a6a1f1dSLionel Sambuc           .Case("mips32r2", "mips32r2")
3270*0a6a1f1dSLionel Sambuc           .Case("mips32r6", "mips32r6")
3271*0a6a1f1dSLionel Sambuc           .Case("mips64", "mips64")
3272*0a6a1f1dSLionel Sambuc           .Case("mips64r2", "mips64r2")
3273*0a6a1f1dSLionel Sambuc           .Case("mips64r6", "mips64r6")
3274*0a6a1f1dSLionel Sambuc           .Case("cnmips", "cnmips")
3275*0a6a1f1dSLionel Sambuc           .Case("r4000", "mips3") // This is an implementation of Mips3.
3276*0a6a1f1dSLionel Sambuc           .Default("");
3277*0a6a1f1dSLionel Sambuc 
3278*0a6a1f1dSLionel Sambuc   if (ArchFeatureName.empty())
3279*0a6a1f1dSLionel Sambuc     return reportParseError("unsupported architecture");
3280*0a6a1f1dSLionel Sambuc 
3281*0a6a1f1dSLionel Sambuc   selectArch(ArchFeatureName);
3282*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveSetArch(Arch);
3283*0a6a1f1dSLionel Sambuc   return false;
3284*0a6a1f1dSLionel Sambuc }
3285*0a6a1f1dSLionel Sambuc 
parseSetFeature(uint64_t Feature)3286*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
3287*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3288*0a6a1f1dSLionel Sambuc   Parser.Lex();
3289*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3290*0a6a1f1dSLionel Sambuc     return reportParseError("unexpected token, expected end of statement");
3291*0a6a1f1dSLionel Sambuc 
3292*0a6a1f1dSLionel Sambuc   switch (Feature) {
3293*0a6a1f1dSLionel Sambuc   default:
3294*0a6a1f1dSLionel Sambuc     llvm_unreachable("Unimplemented feature");
3295*0a6a1f1dSLionel Sambuc   case Mips::FeatureDSP:
3296*0a6a1f1dSLionel Sambuc     setFeatureBits(Mips::FeatureDSP, "dsp");
3297*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetDsp();
3298*0a6a1f1dSLionel Sambuc     break;
3299*0a6a1f1dSLionel Sambuc   case Mips::FeatureMicroMips:
3300*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMicroMips();
3301*0a6a1f1dSLionel Sambuc     break;
3302*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips1:
3303*0a6a1f1dSLionel Sambuc     selectArch("mips1");
3304*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips1();
3305*0a6a1f1dSLionel Sambuc     break;
3306*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips2:
3307*0a6a1f1dSLionel Sambuc     selectArch("mips2");
3308*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips2();
3309*0a6a1f1dSLionel Sambuc     break;
3310*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips3:
3311*0a6a1f1dSLionel Sambuc     selectArch("mips3");
3312*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips3();
3313*0a6a1f1dSLionel Sambuc     break;
3314*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips4:
3315*0a6a1f1dSLionel Sambuc     selectArch("mips4");
3316*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips4();
3317*0a6a1f1dSLionel Sambuc     break;
3318*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips5:
3319*0a6a1f1dSLionel Sambuc     selectArch("mips5");
3320*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips5();
3321*0a6a1f1dSLionel Sambuc     break;
3322*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips32:
3323*0a6a1f1dSLionel Sambuc     selectArch("mips32");
3324*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips32();
3325*0a6a1f1dSLionel Sambuc     break;
3326*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips32r2:
3327*0a6a1f1dSLionel Sambuc     selectArch("mips32r2");
3328*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips32R2();
3329*0a6a1f1dSLionel Sambuc     break;
3330*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips32r6:
3331*0a6a1f1dSLionel Sambuc     selectArch("mips32r6");
3332*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips32R6();
3333*0a6a1f1dSLionel Sambuc     break;
3334*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips64:
3335*0a6a1f1dSLionel Sambuc     selectArch("mips64");
3336*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips64();
3337*0a6a1f1dSLionel Sambuc     break;
3338*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips64r2:
3339*0a6a1f1dSLionel Sambuc     selectArch("mips64r2");
3340*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips64R2();
3341*0a6a1f1dSLionel Sambuc     break;
3342*0a6a1f1dSLionel Sambuc   case Mips::FeatureMips64r6:
3343*0a6a1f1dSLionel Sambuc     selectArch("mips64r6");
3344*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetMips64R6();
3345*0a6a1f1dSLionel Sambuc     break;
3346*0a6a1f1dSLionel Sambuc   }
3347*0a6a1f1dSLionel Sambuc   return false;
3348*0a6a1f1dSLionel Sambuc }
3349*0a6a1f1dSLionel Sambuc 
eatComma(StringRef ErrorStr)3350*0a6a1f1dSLionel Sambuc bool MipsAsmParser::eatComma(StringRef ErrorStr) {
3351*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3352*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::Comma)) {
3353*0a6a1f1dSLionel Sambuc     SMLoc Loc = getLexer().getLoc();
3354*0a6a1f1dSLionel Sambuc     Parser.eatToEndOfStatement();
3355*0a6a1f1dSLionel Sambuc     return Error(Loc, ErrorStr);
3356*0a6a1f1dSLionel Sambuc   }
3357*0a6a1f1dSLionel Sambuc 
3358*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat the comma.
3359*0a6a1f1dSLionel Sambuc   return true;
3360*0a6a1f1dSLionel Sambuc }
3361*0a6a1f1dSLionel Sambuc 
parseDirectiveCpLoad(SMLoc Loc)3362*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
3363*0a6a1f1dSLionel Sambuc   if (AssemblerOptions.back()->isReorder())
3364*0a6a1f1dSLionel Sambuc     Warning(Loc, ".cpload should be inside a noreorder section");
3365*0a6a1f1dSLionel Sambuc 
3366*0a6a1f1dSLionel Sambuc   if (inMips16Mode()) {
3367*0a6a1f1dSLionel Sambuc     reportParseError(".cpload is not supported in Mips16 mode");
3368*0a6a1f1dSLionel Sambuc     return false;
3369*0a6a1f1dSLionel Sambuc   }
3370*0a6a1f1dSLionel Sambuc 
3371*0a6a1f1dSLionel Sambuc   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
3372*0a6a1f1dSLionel Sambuc   OperandMatchResultTy ResTy = parseAnyRegister(Reg);
3373*0a6a1f1dSLionel Sambuc   if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3374*0a6a1f1dSLionel Sambuc     reportParseError("expected register containing function address");
3375*0a6a1f1dSLionel Sambuc     return false;
3376*0a6a1f1dSLionel Sambuc   }
3377*0a6a1f1dSLionel Sambuc 
3378*0a6a1f1dSLionel Sambuc   MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3379*0a6a1f1dSLionel Sambuc   if (!RegOpnd.isGPRAsmReg()) {
3380*0a6a1f1dSLionel Sambuc     reportParseError(RegOpnd.getStartLoc(), "invalid register");
3381*0a6a1f1dSLionel Sambuc     return false;
3382*0a6a1f1dSLionel Sambuc   }
3383*0a6a1f1dSLionel Sambuc 
3384*0a6a1f1dSLionel Sambuc   // If this is not the end of the statement, report an error.
3385*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3386*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3387*0a6a1f1dSLionel Sambuc     return false;
3388*0a6a1f1dSLionel Sambuc   }
3389*0a6a1f1dSLionel Sambuc 
3390*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
3391*0a6a1f1dSLionel Sambuc   return false;
3392*0a6a1f1dSLionel Sambuc }
3393*0a6a1f1dSLionel Sambuc 
parseDirectiveCPSetup()3394*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveCPSetup() {
3395*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3396*0a6a1f1dSLionel Sambuc   unsigned FuncReg;
3397*0a6a1f1dSLionel Sambuc   unsigned Save;
3398*0a6a1f1dSLionel Sambuc   bool SaveIsReg = true;
3399*0a6a1f1dSLionel Sambuc 
3400*0a6a1f1dSLionel Sambuc   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
3401*0a6a1f1dSLionel Sambuc   OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
3402*0a6a1f1dSLionel Sambuc   if (ResTy == MatchOperand_NoMatch) {
3403*0a6a1f1dSLionel Sambuc     reportParseError("expected register containing function address");
3404*0a6a1f1dSLionel Sambuc     Parser.eatToEndOfStatement();
3405*0a6a1f1dSLionel Sambuc     return false;
3406*0a6a1f1dSLionel Sambuc   }
3407*0a6a1f1dSLionel Sambuc 
3408*0a6a1f1dSLionel Sambuc   MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3409*0a6a1f1dSLionel Sambuc   if (!FuncRegOpnd.isGPRAsmReg()) {
3410*0a6a1f1dSLionel Sambuc     reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3411*0a6a1f1dSLionel Sambuc     Parser.eatToEndOfStatement();
3412*0a6a1f1dSLionel Sambuc     return false;
3413*0a6a1f1dSLionel Sambuc   }
3414*0a6a1f1dSLionel Sambuc 
3415*0a6a1f1dSLionel Sambuc   FuncReg = FuncRegOpnd.getGPR32Reg();
3416*0a6a1f1dSLionel Sambuc   TmpReg.clear();
3417*0a6a1f1dSLionel Sambuc 
3418*0a6a1f1dSLionel Sambuc   if (!eatComma("unexpected token, expected comma"))
3419*0a6a1f1dSLionel Sambuc     return true;
3420*0a6a1f1dSLionel Sambuc 
3421*0a6a1f1dSLionel Sambuc   ResTy = parseAnyRegister(TmpReg);
3422*0a6a1f1dSLionel Sambuc   if (ResTy == MatchOperand_NoMatch) {
3423*0a6a1f1dSLionel Sambuc     const AsmToken &Tok = Parser.getTok();
3424*0a6a1f1dSLionel Sambuc     if (Tok.is(AsmToken::Integer)) {
3425*0a6a1f1dSLionel Sambuc       Save = Tok.getIntVal();
3426*0a6a1f1dSLionel Sambuc       SaveIsReg = false;
3427*0a6a1f1dSLionel Sambuc       Parser.Lex();
3428*0a6a1f1dSLionel Sambuc     } else {
3429*0a6a1f1dSLionel Sambuc       reportParseError("expected save register or stack offset");
3430*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
3431*0a6a1f1dSLionel Sambuc       return false;
3432*0a6a1f1dSLionel Sambuc     }
3433*0a6a1f1dSLionel Sambuc   } else {
3434*0a6a1f1dSLionel Sambuc     MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3435*0a6a1f1dSLionel Sambuc     if (!SaveOpnd.isGPRAsmReg()) {
3436*0a6a1f1dSLionel Sambuc       reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3437*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
3438*0a6a1f1dSLionel Sambuc       return false;
3439*0a6a1f1dSLionel Sambuc     }
3440*0a6a1f1dSLionel Sambuc     Save = SaveOpnd.getGPR32Reg();
3441*0a6a1f1dSLionel Sambuc   }
3442*0a6a1f1dSLionel Sambuc 
3443*0a6a1f1dSLionel Sambuc   if (!eatComma("unexpected token, expected comma"))
3444*0a6a1f1dSLionel Sambuc     return true;
3445*0a6a1f1dSLionel Sambuc 
3446*0a6a1f1dSLionel Sambuc   StringRef Name;
3447*0a6a1f1dSLionel Sambuc   if (Parser.parseIdentifier(Name))
3448*0a6a1f1dSLionel Sambuc     reportParseError("expected identifier");
3449*0a6a1f1dSLionel Sambuc   MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
3450*0a6a1f1dSLionel Sambuc 
3451*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
3452*0a6a1f1dSLionel Sambuc   return false;
3453*0a6a1f1dSLionel Sambuc }
3454*0a6a1f1dSLionel Sambuc 
parseDirectiveNaN()3455*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveNaN() {
3456*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3457*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3458*0a6a1f1dSLionel Sambuc     const AsmToken &Tok = Parser.getTok();
3459*0a6a1f1dSLionel Sambuc 
3460*0a6a1f1dSLionel Sambuc     if (Tok.getString() == "2008") {
3461*0a6a1f1dSLionel Sambuc       Parser.Lex();
3462*0a6a1f1dSLionel Sambuc       getTargetStreamer().emitDirectiveNaN2008();
3463*0a6a1f1dSLionel Sambuc       return false;
3464*0a6a1f1dSLionel Sambuc     } else if (Tok.getString() == "legacy") {
3465*0a6a1f1dSLionel Sambuc       Parser.Lex();
3466*0a6a1f1dSLionel Sambuc       getTargetStreamer().emitDirectiveNaNLegacy();
3467*0a6a1f1dSLionel Sambuc       return false;
3468*0a6a1f1dSLionel Sambuc     }
3469*0a6a1f1dSLionel Sambuc   }
3470*0a6a1f1dSLionel Sambuc   // If we don't recognize the option passed to the .nan
3471*0a6a1f1dSLionel Sambuc   // directive (e.g. no option or unknown option), emit an error.
3472*0a6a1f1dSLionel Sambuc   reportParseError("invalid option in .nan directive");
3473*0a6a1f1dSLionel Sambuc   return false;
3474*0a6a1f1dSLionel Sambuc }
3475*0a6a1f1dSLionel Sambuc 
parseDirectiveSet()3476*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveSet() {
3477*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3478f4a2713aSLionel Sambuc   // Get the next token.
3479f4a2713aSLionel Sambuc   const AsmToken &Tok = Parser.getTok();
3480f4a2713aSLionel Sambuc 
3481f4a2713aSLionel Sambuc   if (Tok.getString() == "noat") {
3482f4a2713aSLionel Sambuc     return parseSetNoAtDirective();
3483f4a2713aSLionel Sambuc   } else if (Tok.getString() == "at") {
3484f4a2713aSLionel Sambuc     return parseSetAtDirective();
3485*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "arch") {
3486*0a6a1f1dSLionel Sambuc     return parseSetArchDirective();
3487*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "fp") {
3488*0a6a1f1dSLionel Sambuc     return parseSetFpDirective();
3489*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "pop") {
3490*0a6a1f1dSLionel Sambuc     return parseSetPopDirective();
3491*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "push") {
3492*0a6a1f1dSLionel Sambuc     return parseSetPushDirective();
3493f4a2713aSLionel Sambuc   } else if (Tok.getString() == "reorder") {
3494f4a2713aSLionel Sambuc     return parseSetReorderDirective();
3495f4a2713aSLionel Sambuc   } else if (Tok.getString() == "noreorder") {
3496f4a2713aSLionel Sambuc     return parseSetNoReorderDirective();
3497f4a2713aSLionel Sambuc   } else if (Tok.getString() == "macro") {
3498f4a2713aSLionel Sambuc     return parseSetMacroDirective();
3499f4a2713aSLionel Sambuc   } else if (Tok.getString() == "nomacro") {
3500f4a2713aSLionel Sambuc     return parseSetNoMacroDirective();
3501*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips16") {
3502*0a6a1f1dSLionel Sambuc     return parseSetMips16Directive();
3503f4a2713aSLionel Sambuc   } else if (Tok.getString() == "nomips16") {
3504*0a6a1f1dSLionel Sambuc     return parseSetNoMips16Directive();
3505f4a2713aSLionel Sambuc   } else if (Tok.getString() == "nomicromips") {
3506*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveSetNoMicroMips();
3507f4a2713aSLionel Sambuc     Parser.eatToEndOfStatement();
3508f4a2713aSLionel Sambuc     return false;
3509*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "micromips") {
3510*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMicroMips);
3511*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips0") {
3512*0a6a1f1dSLionel Sambuc     return parseSetMips0Directive();
3513*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips1") {
3514*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips1);
3515*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips2") {
3516*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips2);
3517*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips3") {
3518*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips3);
3519*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips4") {
3520*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips4);
3521*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips5") {
3522*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips5);
3523*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips32") {
3524*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips32);
3525*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips32r2") {
3526*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips32r2);
3527*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips32r6") {
3528*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips32r6);
3529*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips64") {
3530*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips64);
3531*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips64r2") {
3532*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips64r2);
3533*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "mips64r6") {
3534*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureMips64r6);
3535*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "dsp") {
3536*0a6a1f1dSLionel Sambuc     return parseSetFeature(Mips::FeatureDSP);
3537*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "nodsp") {
3538*0a6a1f1dSLionel Sambuc     return parseSetNoDspDirective();
3539*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "msa") {
3540*0a6a1f1dSLionel Sambuc     return parseSetMsaDirective();
3541*0a6a1f1dSLionel Sambuc   } else if (Tok.getString() == "nomsa") {
3542*0a6a1f1dSLionel Sambuc     return parseSetNoMsaDirective();
3543f4a2713aSLionel Sambuc   } else {
3544f4a2713aSLionel Sambuc     // It is just an identifier, look for an assignment.
3545f4a2713aSLionel Sambuc     parseSetAssignment();
3546f4a2713aSLionel Sambuc     return false;
3547f4a2713aSLionel Sambuc   }
3548f4a2713aSLionel Sambuc 
3549f4a2713aSLionel Sambuc   return true;
3550f4a2713aSLionel Sambuc }
3551f4a2713aSLionel Sambuc 
3552*0a6a1f1dSLionel Sambuc /// parseDataDirective
3553f4a2713aSLionel Sambuc ///  ::= .word [ expression (, expression)* ]
parseDataDirective(unsigned Size,SMLoc L)3554*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
3555*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3556f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3557f4a2713aSLionel Sambuc     for (;;) {
3558f4a2713aSLionel Sambuc       const MCExpr *Value;
3559f4a2713aSLionel Sambuc       if (getParser().parseExpression(Value))
3560f4a2713aSLionel Sambuc         return true;
3561f4a2713aSLionel Sambuc 
3562f4a2713aSLionel Sambuc       getParser().getStreamer().EmitValue(Value, Size);
3563f4a2713aSLionel Sambuc 
3564f4a2713aSLionel Sambuc       if (getLexer().is(AsmToken::EndOfStatement))
3565f4a2713aSLionel Sambuc         break;
3566f4a2713aSLionel Sambuc 
3567f4a2713aSLionel Sambuc       if (getLexer().isNot(AsmToken::Comma))
3568*0a6a1f1dSLionel Sambuc         return Error(L, "unexpected token, expected comma");
3569f4a2713aSLionel Sambuc       Parser.Lex();
3570f4a2713aSLionel Sambuc     }
3571f4a2713aSLionel Sambuc   }
3572f4a2713aSLionel Sambuc 
3573f4a2713aSLionel Sambuc   Parser.Lex();
3574f4a2713aSLionel Sambuc   return false;
3575f4a2713aSLionel Sambuc }
3576f4a2713aSLionel Sambuc 
3577f4a2713aSLionel Sambuc /// parseDirectiveGpWord
3578f4a2713aSLionel Sambuc ///  ::= .gpword local_sym
parseDirectiveGpWord()3579f4a2713aSLionel Sambuc bool MipsAsmParser::parseDirectiveGpWord() {
3580*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3581f4a2713aSLionel Sambuc   const MCExpr *Value;
3582f4a2713aSLionel Sambuc   // EmitGPRel32Value requires an expression, so we are using base class
3583f4a2713aSLionel Sambuc   // method to evaluate the expression.
3584f4a2713aSLionel Sambuc   if (getParser().parseExpression(Value))
3585f4a2713aSLionel Sambuc     return true;
3586f4a2713aSLionel Sambuc   getParser().getStreamer().EmitGPRel32Value(Value);
3587f4a2713aSLionel Sambuc 
3588f4a2713aSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3589*0a6a1f1dSLionel Sambuc     return Error(getLexer().getLoc(),
3590*0a6a1f1dSLionel Sambuc                 "unexpected token, expected end of statement");
3591f4a2713aSLionel Sambuc   Parser.Lex(); // Eat EndOfStatement token.
3592f4a2713aSLionel Sambuc   return false;
3593f4a2713aSLionel Sambuc }
3594f4a2713aSLionel Sambuc 
3595*0a6a1f1dSLionel Sambuc /// parseDirectiveGpDWord
3596*0a6a1f1dSLionel Sambuc ///  ::= .gpdword local_sym
parseDirectiveGpDWord()3597*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveGpDWord() {
3598*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3599*0a6a1f1dSLionel Sambuc   const MCExpr *Value;
3600*0a6a1f1dSLionel Sambuc   // EmitGPRel64Value requires an expression, so we are using base class
3601*0a6a1f1dSLionel Sambuc   // method to evaluate the expression.
3602*0a6a1f1dSLionel Sambuc   if (getParser().parseExpression(Value))
3603*0a6a1f1dSLionel Sambuc     return true;
3604*0a6a1f1dSLionel Sambuc   getParser().getStreamer().EmitGPRel64Value(Value);
3605f4a2713aSLionel Sambuc 
3606*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement))
3607*0a6a1f1dSLionel Sambuc     return Error(getLexer().getLoc(),
3608*0a6a1f1dSLionel Sambuc                 "unexpected token, expected end of statement");
3609*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat EndOfStatement token.
3610*0a6a1f1dSLionel Sambuc   return false;
3611*0a6a1f1dSLionel Sambuc }
3612*0a6a1f1dSLionel Sambuc 
parseDirectiveOption()3613*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveOption() {
3614*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3615*0a6a1f1dSLionel Sambuc   // Get the option token.
3616*0a6a1f1dSLionel Sambuc   AsmToken Tok = Parser.getTok();
3617*0a6a1f1dSLionel Sambuc   // At the moment only identifiers are supported.
3618*0a6a1f1dSLionel Sambuc   if (Tok.isNot(AsmToken::Identifier)) {
3619*0a6a1f1dSLionel Sambuc     Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
3620*0a6a1f1dSLionel Sambuc     Parser.eatToEndOfStatement();
3621*0a6a1f1dSLionel Sambuc     return false;
3622*0a6a1f1dSLionel Sambuc   }
3623*0a6a1f1dSLionel Sambuc 
3624*0a6a1f1dSLionel Sambuc   StringRef Option = Tok.getIdentifier();
3625*0a6a1f1dSLionel Sambuc 
3626*0a6a1f1dSLionel Sambuc   if (Option == "pic0") {
3627*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveOptionPic0();
3628*0a6a1f1dSLionel Sambuc     Parser.Lex();
3629*0a6a1f1dSLionel Sambuc     if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3630*0a6a1f1dSLionel Sambuc       Error(Parser.getTok().getLoc(),
3631*0a6a1f1dSLionel Sambuc             "unexpected token, expected end of statement");
3632*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
3633*0a6a1f1dSLionel Sambuc     }
3634*0a6a1f1dSLionel Sambuc     return false;
3635*0a6a1f1dSLionel Sambuc   }
3636*0a6a1f1dSLionel Sambuc 
3637*0a6a1f1dSLionel Sambuc   if (Option == "pic2") {
3638*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveOptionPic2();
3639*0a6a1f1dSLionel Sambuc     Parser.Lex();
3640*0a6a1f1dSLionel Sambuc     if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3641*0a6a1f1dSLionel Sambuc       Error(Parser.getTok().getLoc(),
3642*0a6a1f1dSLionel Sambuc             "unexpected token, expected end of statement");
3643*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
3644*0a6a1f1dSLionel Sambuc     }
3645*0a6a1f1dSLionel Sambuc     return false;
3646*0a6a1f1dSLionel Sambuc   }
3647*0a6a1f1dSLionel Sambuc 
3648*0a6a1f1dSLionel Sambuc   // Unknown option.
3649*0a6a1f1dSLionel Sambuc   Warning(Parser.getTok().getLoc(),
3650*0a6a1f1dSLionel Sambuc           "unknown option, expected 'pic0' or 'pic2'");
3651*0a6a1f1dSLionel Sambuc   Parser.eatToEndOfStatement();
3652*0a6a1f1dSLionel Sambuc   return false;
3653*0a6a1f1dSLionel Sambuc }
3654*0a6a1f1dSLionel Sambuc 
3655*0a6a1f1dSLionel Sambuc /// parseDirectiveModule
3656*0a6a1f1dSLionel Sambuc ///  ::= .module oddspreg
3657*0a6a1f1dSLionel Sambuc ///  ::= .module nooddspreg
3658*0a6a1f1dSLionel Sambuc ///  ::= .module fp=value
parseDirectiveModule()3659*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveModule() {
3660*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3661*0a6a1f1dSLionel Sambuc   MCAsmLexer &Lexer = getLexer();
3662*0a6a1f1dSLionel Sambuc   SMLoc L = Lexer.getLoc();
3663*0a6a1f1dSLionel Sambuc 
3664*0a6a1f1dSLionel Sambuc   if (!getTargetStreamer().isModuleDirectiveAllowed()) {
3665*0a6a1f1dSLionel Sambuc     // TODO : get a better message.
3666*0a6a1f1dSLionel Sambuc     reportParseError(".module directive must appear before any code");
3667*0a6a1f1dSLionel Sambuc     return false;
3668*0a6a1f1dSLionel Sambuc   }
3669*0a6a1f1dSLionel Sambuc 
3670*0a6a1f1dSLionel Sambuc   StringRef Option;
3671*0a6a1f1dSLionel Sambuc   if (Parser.parseIdentifier(Option)) {
3672*0a6a1f1dSLionel Sambuc     reportParseError("expected .module option identifier");
3673*0a6a1f1dSLionel Sambuc     return false;
3674*0a6a1f1dSLionel Sambuc   }
3675*0a6a1f1dSLionel Sambuc 
3676*0a6a1f1dSLionel Sambuc   if (Option == "oddspreg") {
3677*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3678*0a6a1f1dSLionel Sambuc     clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3679*0a6a1f1dSLionel Sambuc 
3680*0a6a1f1dSLionel Sambuc     // If this is not the end of the statement, report an error.
3681*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3682*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3683*0a6a1f1dSLionel Sambuc       return false;
3684*0a6a1f1dSLionel Sambuc     }
3685*0a6a1f1dSLionel Sambuc 
3686*0a6a1f1dSLionel Sambuc     return false; // parseDirectiveModule has finished successfully.
3687*0a6a1f1dSLionel Sambuc   } else if (Option == "nooddspreg") {
3688*0a6a1f1dSLionel Sambuc     if (!isABI_O32()) {
3689*0a6a1f1dSLionel Sambuc       Error(L, "'.module nooddspreg' requires the O32 ABI");
3690*0a6a1f1dSLionel Sambuc       return false;
3691*0a6a1f1dSLionel Sambuc     }
3692*0a6a1f1dSLionel Sambuc 
3693*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3694*0a6a1f1dSLionel Sambuc     setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3695*0a6a1f1dSLionel Sambuc 
3696*0a6a1f1dSLionel Sambuc     // If this is not the end of the statement, report an error.
3697*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3698*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3699*0a6a1f1dSLionel Sambuc       return false;
3700*0a6a1f1dSLionel Sambuc     }
3701*0a6a1f1dSLionel Sambuc 
3702*0a6a1f1dSLionel Sambuc     return false; // parseDirectiveModule has finished successfully.
3703*0a6a1f1dSLionel Sambuc   } else if (Option == "fp") {
3704*0a6a1f1dSLionel Sambuc     return parseDirectiveModuleFP();
3705*0a6a1f1dSLionel Sambuc   } else {
3706*0a6a1f1dSLionel Sambuc     return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
3707*0a6a1f1dSLionel Sambuc   }
3708*0a6a1f1dSLionel Sambuc }
3709*0a6a1f1dSLionel Sambuc 
3710*0a6a1f1dSLionel Sambuc /// parseDirectiveModuleFP
3711*0a6a1f1dSLionel Sambuc ///  ::= =32
3712*0a6a1f1dSLionel Sambuc ///  ::= =xx
3713*0a6a1f1dSLionel Sambuc ///  ::= =64
parseDirectiveModuleFP()3714*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseDirectiveModuleFP() {
3715*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3716*0a6a1f1dSLionel Sambuc   MCAsmLexer &Lexer = getLexer();
3717*0a6a1f1dSLionel Sambuc 
3718*0a6a1f1dSLionel Sambuc   if (Lexer.isNot(AsmToken::Equal)) {
3719*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected equals sign '='");
3720*0a6a1f1dSLionel Sambuc     return false;
3721*0a6a1f1dSLionel Sambuc   }
3722*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Eat '=' token.
3723*0a6a1f1dSLionel Sambuc 
3724*0a6a1f1dSLionel Sambuc   MipsABIFlagsSection::FpABIKind FpABI;
3725*0a6a1f1dSLionel Sambuc   if (!parseFpABIValue(FpABI, ".module"))
3726*0a6a1f1dSLionel Sambuc     return false;
3727*0a6a1f1dSLionel Sambuc 
3728*0a6a1f1dSLionel Sambuc   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3729*0a6a1f1dSLionel Sambuc     reportParseError("unexpected token, expected end of statement");
3730*0a6a1f1dSLionel Sambuc     return false;
3731*0a6a1f1dSLionel Sambuc   }
3732*0a6a1f1dSLionel Sambuc 
3733*0a6a1f1dSLionel Sambuc   // Emit appropriate flags.
3734*0a6a1f1dSLionel Sambuc   getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
3735*0a6a1f1dSLionel Sambuc   Parser.Lex(); // Consume the EndOfStatement.
3736*0a6a1f1dSLionel Sambuc   return false;
3737*0a6a1f1dSLionel Sambuc }
3738*0a6a1f1dSLionel Sambuc 
parseFpABIValue(MipsABIFlagsSection::FpABIKind & FpABI,StringRef Directive)3739*0a6a1f1dSLionel Sambuc bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
3740*0a6a1f1dSLionel Sambuc                                     StringRef Directive) {
3741*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3742*0a6a1f1dSLionel Sambuc   MCAsmLexer &Lexer = getLexer();
3743*0a6a1f1dSLionel Sambuc 
3744*0a6a1f1dSLionel Sambuc   if (Lexer.is(AsmToken::Identifier)) {
3745*0a6a1f1dSLionel Sambuc     StringRef Value = Parser.getTok().getString();
3746*0a6a1f1dSLionel Sambuc     Parser.Lex();
3747*0a6a1f1dSLionel Sambuc 
3748*0a6a1f1dSLionel Sambuc     if (Value != "xx") {
3749*0a6a1f1dSLionel Sambuc       reportParseError("unsupported value, expected 'xx', '32' or '64'");
3750*0a6a1f1dSLionel Sambuc       return false;
3751*0a6a1f1dSLionel Sambuc     }
3752*0a6a1f1dSLionel Sambuc 
3753*0a6a1f1dSLionel Sambuc     if (!isABI_O32()) {
3754*0a6a1f1dSLionel Sambuc       reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3755*0a6a1f1dSLionel Sambuc       return false;
3756*0a6a1f1dSLionel Sambuc     }
3757*0a6a1f1dSLionel Sambuc 
3758*0a6a1f1dSLionel Sambuc     FpABI = MipsABIFlagsSection::FpABIKind::XX;
3759*0a6a1f1dSLionel Sambuc     return true;
3760*0a6a1f1dSLionel Sambuc   }
3761*0a6a1f1dSLionel Sambuc 
3762*0a6a1f1dSLionel Sambuc   if (Lexer.is(AsmToken::Integer)) {
3763*0a6a1f1dSLionel Sambuc     unsigned Value = Parser.getTok().getIntVal();
3764*0a6a1f1dSLionel Sambuc     Parser.Lex();
3765*0a6a1f1dSLionel Sambuc 
3766*0a6a1f1dSLionel Sambuc     if (Value != 32 && Value != 64) {
3767*0a6a1f1dSLionel Sambuc       reportParseError("unsupported value, expected 'xx', '32' or '64'");
3768*0a6a1f1dSLionel Sambuc       return false;
3769*0a6a1f1dSLionel Sambuc     }
3770*0a6a1f1dSLionel Sambuc 
3771*0a6a1f1dSLionel Sambuc     if (Value == 32) {
3772*0a6a1f1dSLionel Sambuc       if (!isABI_O32()) {
3773*0a6a1f1dSLionel Sambuc         reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3774*0a6a1f1dSLionel Sambuc         return false;
3775*0a6a1f1dSLionel Sambuc       }
3776*0a6a1f1dSLionel Sambuc 
3777*0a6a1f1dSLionel Sambuc       FpABI = MipsABIFlagsSection::FpABIKind::S32;
3778*0a6a1f1dSLionel Sambuc     } else
3779*0a6a1f1dSLionel Sambuc       FpABI = MipsABIFlagsSection::FpABIKind::S64;
3780*0a6a1f1dSLionel Sambuc 
3781*0a6a1f1dSLionel Sambuc     return true;
3782*0a6a1f1dSLionel Sambuc   }
3783*0a6a1f1dSLionel Sambuc 
3784*0a6a1f1dSLionel Sambuc   return false;
3785*0a6a1f1dSLionel Sambuc }
3786*0a6a1f1dSLionel Sambuc 
ParseDirective(AsmToken DirectiveID)3787*0a6a1f1dSLionel Sambuc bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
3788*0a6a1f1dSLionel Sambuc   MCAsmParser &Parser = getParser();
3789f4a2713aSLionel Sambuc   StringRef IDVal = DirectiveID.getString();
3790f4a2713aSLionel Sambuc 
3791*0a6a1f1dSLionel Sambuc   if (IDVal == ".cpload")
3792*0a6a1f1dSLionel Sambuc     return parseDirectiveCpLoad(DirectiveID.getLoc());
3793*0a6a1f1dSLionel Sambuc   if (IDVal == ".dword") {
3794*0a6a1f1dSLionel Sambuc     parseDataDirective(8, DirectiveID.getLoc());
3795*0a6a1f1dSLionel Sambuc     return false;
3796*0a6a1f1dSLionel Sambuc   }
3797f4a2713aSLionel Sambuc   if (IDVal == ".ent") {
3798*0a6a1f1dSLionel Sambuc     StringRef SymbolName;
3799*0a6a1f1dSLionel Sambuc 
3800*0a6a1f1dSLionel Sambuc     if (Parser.parseIdentifier(SymbolName)) {
3801*0a6a1f1dSLionel Sambuc       reportParseError("expected identifier after .ent");
3802*0a6a1f1dSLionel Sambuc       return false;
3803*0a6a1f1dSLionel Sambuc     }
3804*0a6a1f1dSLionel Sambuc 
3805*0a6a1f1dSLionel Sambuc     // There's an undocumented extension that allows an integer to
3806*0a6a1f1dSLionel Sambuc     // follow the name of the procedure which AFAICS is ignored by GAS.
3807*0a6a1f1dSLionel Sambuc     // Example: .ent foo,2
3808*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3809*0a6a1f1dSLionel Sambuc       if (getLexer().isNot(AsmToken::Comma)) {
3810*0a6a1f1dSLionel Sambuc         // Even though we accept this undocumented extension for compatibility
3811*0a6a1f1dSLionel Sambuc         // reasons, the additional integer argument does not actually change
3812*0a6a1f1dSLionel Sambuc         // the behaviour of the '.ent' directive, so we would like to discourage
3813*0a6a1f1dSLionel Sambuc         // its use. We do this by not referring to the extended version in
3814*0a6a1f1dSLionel Sambuc         // error messages which are not directly related to its use.
3815*0a6a1f1dSLionel Sambuc         reportParseError("unexpected token, expected end of statement");
3816*0a6a1f1dSLionel Sambuc         return false;
3817*0a6a1f1dSLionel Sambuc       }
3818*0a6a1f1dSLionel Sambuc       Parser.Lex(); // Eat the comma.
3819*0a6a1f1dSLionel Sambuc       const MCExpr *DummyNumber;
3820*0a6a1f1dSLionel Sambuc       int64_t DummyNumberVal;
3821*0a6a1f1dSLionel Sambuc       // If the user was explicitly trying to use the extended version,
3822*0a6a1f1dSLionel Sambuc       // we still give helpful extension-related error messages.
3823*0a6a1f1dSLionel Sambuc       if (Parser.parseExpression(DummyNumber)) {
3824*0a6a1f1dSLionel Sambuc         reportParseError("expected number after comma");
3825*0a6a1f1dSLionel Sambuc         return false;
3826*0a6a1f1dSLionel Sambuc       }
3827*0a6a1f1dSLionel Sambuc       if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3828*0a6a1f1dSLionel Sambuc         reportParseError("expected an absolute expression after comma");
3829*0a6a1f1dSLionel Sambuc         return false;
3830*0a6a1f1dSLionel Sambuc       }
3831*0a6a1f1dSLionel Sambuc     }
3832*0a6a1f1dSLionel Sambuc 
3833*0a6a1f1dSLionel Sambuc     // If this is not the end of the statement, report an error.
3834*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3835*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3836*0a6a1f1dSLionel Sambuc       return false;
3837*0a6a1f1dSLionel Sambuc     }
3838*0a6a1f1dSLionel Sambuc 
3839*0a6a1f1dSLionel Sambuc     MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3840*0a6a1f1dSLionel Sambuc 
3841*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveEnt(*Sym);
3842*0a6a1f1dSLionel Sambuc     CurrentFn = Sym;
3843f4a2713aSLionel Sambuc     return false;
3844f4a2713aSLionel Sambuc   }
3845f4a2713aSLionel Sambuc 
3846f4a2713aSLionel Sambuc   if (IDVal == ".end") {
3847*0a6a1f1dSLionel Sambuc     StringRef SymbolName;
3848*0a6a1f1dSLionel Sambuc 
3849*0a6a1f1dSLionel Sambuc     if (Parser.parseIdentifier(SymbolName)) {
3850*0a6a1f1dSLionel Sambuc       reportParseError("expected identifier after .end");
3851*0a6a1f1dSLionel Sambuc       return false;
3852*0a6a1f1dSLionel Sambuc     }
3853*0a6a1f1dSLionel Sambuc 
3854*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3855*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3856*0a6a1f1dSLionel Sambuc       return false;
3857*0a6a1f1dSLionel Sambuc     }
3858*0a6a1f1dSLionel Sambuc 
3859*0a6a1f1dSLionel Sambuc     if (CurrentFn == nullptr) {
3860*0a6a1f1dSLionel Sambuc       reportParseError(".end used without .ent");
3861*0a6a1f1dSLionel Sambuc       return false;
3862*0a6a1f1dSLionel Sambuc     }
3863*0a6a1f1dSLionel Sambuc 
3864*0a6a1f1dSLionel Sambuc     if ((SymbolName != CurrentFn->getName())) {
3865*0a6a1f1dSLionel Sambuc       reportParseError(".end symbol does not match .ent symbol");
3866*0a6a1f1dSLionel Sambuc       return false;
3867*0a6a1f1dSLionel Sambuc     }
3868*0a6a1f1dSLionel Sambuc 
3869*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveEnd(SymbolName);
3870*0a6a1f1dSLionel Sambuc     CurrentFn = nullptr;
3871f4a2713aSLionel Sambuc     return false;
3872f4a2713aSLionel Sambuc   }
3873f4a2713aSLionel Sambuc 
3874f4a2713aSLionel Sambuc   if (IDVal == ".frame") {
3875*0a6a1f1dSLionel Sambuc     // .frame $stack_reg, frame_size_in_bytes, $return_reg
3876*0a6a1f1dSLionel Sambuc     SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
3877*0a6a1f1dSLionel Sambuc     OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
3878*0a6a1f1dSLionel Sambuc     if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3879*0a6a1f1dSLionel Sambuc       reportParseError("expected stack register");
3880*0a6a1f1dSLionel Sambuc       return false;
3881*0a6a1f1dSLionel Sambuc     }
3882*0a6a1f1dSLionel Sambuc 
3883*0a6a1f1dSLionel Sambuc     MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3884*0a6a1f1dSLionel Sambuc     if (!StackRegOpnd.isGPRAsmReg()) {
3885*0a6a1f1dSLionel Sambuc       reportParseError(StackRegOpnd.getStartLoc(),
3886*0a6a1f1dSLionel Sambuc                        "expected general purpose register");
3887*0a6a1f1dSLionel Sambuc       return false;
3888*0a6a1f1dSLionel Sambuc     }
3889*0a6a1f1dSLionel Sambuc     unsigned StackReg = StackRegOpnd.getGPR32Reg();
3890*0a6a1f1dSLionel Sambuc 
3891*0a6a1f1dSLionel Sambuc     if (Parser.getTok().is(AsmToken::Comma))
3892*0a6a1f1dSLionel Sambuc       Parser.Lex();
3893*0a6a1f1dSLionel Sambuc     else {
3894*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected comma");
3895*0a6a1f1dSLionel Sambuc       return false;
3896*0a6a1f1dSLionel Sambuc     }
3897*0a6a1f1dSLionel Sambuc 
3898*0a6a1f1dSLionel Sambuc     // Parse the frame size.
3899*0a6a1f1dSLionel Sambuc     const MCExpr *FrameSize;
3900*0a6a1f1dSLionel Sambuc     int64_t FrameSizeVal;
3901*0a6a1f1dSLionel Sambuc 
3902*0a6a1f1dSLionel Sambuc     if (Parser.parseExpression(FrameSize)) {
3903*0a6a1f1dSLionel Sambuc       reportParseError("expected frame size value");
3904*0a6a1f1dSLionel Sambuc       return false;
3905*0a6a1f1dSLionel Sambuc     }
3906*0a6a1f1dSLionel Sambuc 
3907*0a6a1f1dSLionel Sambuc     if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3908*0a6a1f1dSLionel Sambuc       reportParseError("frame size not an absolute expression");
3909*0a6a1f1dSLionel Sambuc       return false;
3910*0a6a1f1dSLionel Sambuc     }
3911*0a6a1f1dSLionel Sambuc 
3912*0a6a1f1dSLionel Sambuc     if (Parser.getTok().is(AsmToken::Comma))
3913*0a6a1f1dSLionel Sambuc       Parser.Lex();
3914*0a6a1f1dSLionel Sambuc     else {
3915*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected comma");
3916*0a6a1f1dSLionel Sambuc       return false;
3917*0a6a1f1dSLionel Sambuc     }
3918*0a6a1f1dSLionel Sambuc 
3919*0a6a1f1dSLionel Sambuc     // Parse the return register.
3920*0a6a1f1dSLionel Sambuc     TmpReg.clear();
3921*0a6a1f1dSLionel Sambuc     ResTy = parseAnyRegister(TmpReg);
3922*0a6a1f1dSLionel Sambuc     if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3923*0a6a1f1dSLionel Sambuc       reportParseError("expected return register");
3924*0a6a1f1dSLionel Sambuc       return false;
3925*0a6a1f1dSLionel Sambuc     }
3926*0a6a1f1dSLionel Sambuc 
3927*0a6a1f1dSLionel Sambuc     MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3928*0a6a1f1dSLionel Sambuc     if (!ReturnRegOpnd.isGPRAsmReg()) {
3929*0a6a1f1dSLionel Sambuc       reportParseError(ReturnRegOpnd.getStartLoc(),
3930*0a6a1f1dSLionel Sambuc                        "expected general purpose register");
3931*0a6a1f1dSLionel Sambuc       return false;
3932*0a6a1f1dSLionel Sambuc     }
3933*0a6a1f1dSLionel Sambuc 
3934*0a6a1f1dSLionel Sambuc     // If this is not the end of the statement, report an error.
3935*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3936*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3937*0a6a1f1dSLionel Sambuc       return false;
3938*0a6a1f1dSLionel Sambuc     }
3939*0a6a1f1dSLionel Sambuc 
3940*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3941*0a6a1f1dSLionel Sambuc                                   ReturnRegOpnd.getGPR32Reg());
3942f4a2713aSLionel Sambuc     return false;
3943f4a2713aSLionel Sambuc   }
3944f4a2713aSLionel Sambuc 
3945f4a2713aSLionel Sambuc   if (IDVal == ".set") {
3946f4a2713aSLionel Sambuc     return parseDirectiveSet();
3947f4a2713aSLionel Sambuc   }
3948f4a2713aSLionel Sambuc 
3949*0a6a1f1dSLionel Sambuc   if (IDVal == ".mask" || IDVal == ".fmask") {
3950*0a6a1f1dSLionel Sambuc     // .mask bitmask, frame_offset
3951*0a6a1f1dSLionel Sambuc     // bitmask: One bit for each register used.
3952*0a6a1f1dSLionel Sambuc     // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3953*0a6a1f1dSLionel Sambuc     //               first register is expected to be saved.
3954*0a6a1f1dSLionel Sambuc     // Examples:
3955*0a6a1f1dSLionel Sambuc     //   .mask 0x80000000, -4
3956*0a6a1f1dSLionel Sambuc     //   .fmask 0x80000000, -4
3957*0a6a1f1dSLionel Sambuc     //
3958*0a6a1f1dSLionel Sambuc 
3959*0a6a1f1dSLionel Sambuc     // Parse the bitmask
3960*0a6a1f1dSLionel Sambuc     const MCExpr *BitMask;
3961*0a6a1f1dSLionel Sambuc     int64_t BitMaskVal;
3962*0a6a1f1dSLionel Sambuc 
3963*0a6a1f1dSLionel Sambuc     if (Parser.parseExpression(BitMask)) {
3964*0a6a1f1dSLionel Sambuc       reportParseError("expected bitmask value");
3965f4a2713aSLionel Sambuc       return false;
3966f4a2713aSLionel Sambuc     }
3967f4a2713aSLionel Sambuc 
3968*0a6a1f1dSLionel Sambuc     if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3969*0a6a1f1dSLionel Sambuc       reportParseError("bitmask not an absolute expression");
3970f4a2713aSLionel Sambuc       return false;
3971f4a2713aSLionel Sambuc     }
3972f4a2713aSLionel Sambuc 
3973*0a6a1f1dSLionel Sambuc     if (Parser.getTok().is(AsmToken::Comma))
3974*0a6a1f1dSLionel Sambuc       Parser.Lex();
3975*0a6a1f1dSLionel Sambuc     else {
3976*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected comma");
3977*0a6a1f1dSLionel Sambuc       return false;
3978*0a6a1f1dSLionel Sambuc     }
3979*0a6a1f1dSLionel Sambuc 
3980*0a6a1f1dSLionel Sambuc     // Parse the frame_offset
3981*0a6a1f1dSLionel Sambuc     const MCExpr *FrameOffset;
3982*0a6a1f1dSLionel Sambuc     int64_t FrameOffsetVal;
3983*0a6a1f1dSLionel Sambuc 
3984*0a6a1f1dSLionel Sambuc     if (Parser.parseExpression(FrameOffset)) {
3985*0a6a1f1dSLionel Sambuc       reportParseError("expected frame offset value");
3986*0a6a1f1dSLionel Sambuc       return false;
3987*0a6a1f1dSLionel Sambuc     }
3988*0a6a1f1dSLionel Sambuc 
3989*0a6a1f1dSLionel Sambuc     if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3990*0a6a1f1dSLionel Sambuc       reportParseError("frame offset not an absolute expression");
3991*0a6a1f1dSLionel Sambuc       return false;
3992*0a6a1f1dSLionel Sambuc     }
3993*0a6a1f1dSLionel Sambuc 
3994*0a6a1f1dSLionel Sambuc     // If this is not the end of the statement, report an error.
3995*0a6a1f1dSLionel Sambuc     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3996*0a6a1f1dSLionel Sambuc       reportParseError("unexpected token, expected end of statement");
3997*0a6a1f1dSLionel Sambuc       return false;
3998*0a6a1f1dSLionel Sambuc     }
3999*0a6a1f1dSLionel Sambuc 
4000*0a6a1f1dSLionel Sambuc     if (IDVal == ".mask")
4001*0a6a1f1dSLionel Sambuc       getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4002*0a6a1f1dSLionel Sambuc     else
4003*0a6a1f1dSLionel Sambuc       getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
4004*0a6a1f1dSLionel Sambuc     return false;
4005*0a6a1f1dSLionel Sambuc   }
4006*0a6a1f1dSLionel Sambuc 
4007*0a6a1f1dSLionel Sambuc   if (IDVal == ".nan")
4008*0a6a1f1dSLionel Sambuc     return parseDirectiveNaN();
4009*0a6a1f1dSLionel Sambuc 
4010f4a2713aSLionel Sambuc   if (IDVal == ".gpword") {
4011f4a2713aSLionel Sambuc     parseDirectiveGpWord();
4012f4a2713aSLionel Sambuc     return false;
4013f4a2713aSLionel Sambuc   }
4014f4a2713aSLionel Sambuc 
4015*0a6a1f1dSLionel Sambuc   if (IDVal == ".gpdword") {
4016*0a6a1f1dSLionel Sambuc     parseDirectiveGpDWord();
4017f4a2713aSLionel Sambuc     return false;
4018f4a2713aSLionel Sambuc   }
4019f4a2713aSLionel Sambuc 
4020*0a6a1f1dSLionel Sambuc   if (IDVal == ".word") {
4021*0a6a1f1dSLionel Sambuc     parseDataDirective(4, DirectiveID.getLoc());
4022*0a6a1f1dSLionel Sambuc     return false;
4023*0a6a1f1dSLionel Sambuc   }
4024f4a2713aSLionel Sambuc 
4025*0a6a1f1dSLionel Sambuc   if (IDVal == ".option")
4026*0a6a1f1dSLionel Sambuc     return parseDirectiveOption();
4027*0a6a1f1dSLionel Sambuc 
4028*0a6a1f1dSLionel Sambuc   if (IDVal == ".abicalls") {
4029*0a6a1f1dSLionel Sambuc     getTargetStreamer().emitDirectiveAbiCalls();
4030*0a6a1f1dSLionel Sambuc     if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4031*0a6a1f1dSLionel Sambuc       Error(Parser.getTok().getLoc(),
4032*0a6a1f1dSLionel Sambuc             "unexpected token, expected end of statement");
4033*0a6a1f1dSLionel Sambuc       // Clear line
4034*0a6a1f1dSLionel Sambuc       Parser.eatToEndOfStatement();
4035*0a6a1f1dSLionel Sambuc     }
4036*0a6a1f1dSLionel Sambuc     return false;
4037*0a6a1f1dSLionel Sambuc   }
4038*0a6a1f1dSLionel Sambuc 
4039*0a6a1f1dSLionel Sambuc   if (IDVal == ".cpsetup")
4040*0a6a1f1dSLionel Sambuc     return parseDirectiveCPSetup();
4041*0a6a1f1dSLionel Sambuc 
4042*0a6a1f1dSLionel Sambuc   if (IDVal == ".module")
4043*0a6a1f1dSLionel Sambuc     return parseDirectiveModule();
4044f4a2713aSLionel Sambuc 
4045f4a2713aSLionel Sambuc   return true;
4046f4a2713aSLionel Sambuc }
4047f4a2713aSLionel Sambuc 
LLVMInitializeMipsAsmParser()4048f4a2713aSLionel Sambuc extern "C" void LLVMInitializeMipsAsmParser() {
4049f4a2713aSLionel Sambuc   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4050f4a2713aSLionel Sambuc   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4051f4a2713aSLionel Sambuc   RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4052f4a2713aSLionel Sambuc   RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4053f4a2713aSLionel Sambuc }
4054f4a2713aSLionel Sambuc 
4055f4a2713aSLionel Sambuc #define GET_REGISTER_MATCHER
4056f4a2713aSLionel Sambuc #define GET_MATCHER_IMPLEMENTATION
4057f4a2713aSLionel Sambuc #include "MipsGenAsmMatcher.inc"
4058