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