blob: 2e698dfbc9834f20485243cce702a8f7b788e169 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000032#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000033
34using namespace llvm;
35
Chandler Carruthe96dd892014-04-21 22:55:11 +000036#define DEBUG_TYPE "mips-asm-parser"
37
Joey Gouly0e76fa72013-09-12 10:28:05 +000038namespace llvm {
39class MCInstrInfo;
40}
41
Rafael Espindola870c4e92012-01-11 03:56:41 +000042namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000043class MipsAssemblerOptions {
44public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000045 MipsAssemblerOptions(uint64_t Features_) :
46 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000047
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
49 ATReg = Opts->getATRegNum();
50 Reorder = Opts->isReorder();
51 Macro = Opts->isMacro();
52 Features = Opts->getFeatures();
53 }
54
55 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000056 bool setATReg(unsigned Reg);
57
Toma Tabacu9db22db2014-09-09 10:15:38 +000058 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000059 void setReorder() { Reorder = true; }
60 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000061
Toma Tabacu9db22db2014-09-09 10:15:38 +000062 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000063 void setMacro() { Macro = true; }
64 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 uint64_t getFeatures() const { return Features; }
67 void setFeatures(uint64_t Features_) { Features = Features_; }
68
Daniel Sandersf0df2212014-08-04 12:20:00 +000069 // Set of features that are either architecture features or referenced
70 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
71 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
72 // The reason we need this mask is explained in the selectArch function.
73 // FIXME: Ideally we would like TableGen to generate this information.
74 static const uint64_t AllArchRelatedMask =
75 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
76 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
77 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
78 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
79 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
80 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
81 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
82
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000087 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
91namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000092class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000093 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000094 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000095 return static_cast<MipsTargetStreamer &>(TS);
96 }
97
Jack Carterb4dbc172012-09-05 23:34:03 +000098 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +000099 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000100 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000101 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
102 // nullptr, which indicates that no function is currently
103 // selected. This usually happens after an '.end func'
104 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000105
Daniel Sandersef638fe2014-10-03 15:37:37 +0000106 // Print a warning along with its fix-it message at the given range.
107 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
108 SMRange Range, bool ShowColors = true);
109
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000110#define GET_ASSEMBLER_HEADER
111#include "MipsGenAsmMatcher.inc"
112
Matheus Almeida595fcab2014-06-11 15:05:56 +0000113 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
114
Chad Rosier49963552012-10-13 00:26:04 +0000115 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000116 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000117 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000118 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000119
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000120 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000121 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
Toma Tabacu13964452014-09-04 13:23:44 +0000125 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000126
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
128 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
David Blaikie960ea3f2014-06-08 16:18:35 +0000132 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000133
134 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000135 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000137
Jack Carter873c7242013-01-12 01:03:14 +0000138 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000139 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000150
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000151 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000152 parseRegisterPair (OperandVector &Operands);
153
154 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000155 parseRegisterList (OperandVector &Operands);
156
David Blaikie960ea3f2014-06-08 16:18:35 +0000157 bool searchSymbolAlias(OperandVector &Operands);
158
Toma Tabacu13964452014-09-04 13:23:44 +0000159 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000160
Jack Carter30a59822012-10-04 04:03:53 +0000161 bool needsExpansion(MCInst &Inst);
162
Matheus Almeida3813d572014-06-19 14:39:14 +0000163 // Expands assembly pseudo instructions.
164 // Returns false on success, true otherwise.
165 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000166 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000167
168 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000169 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000170
171 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000172 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000173
174 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000175 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000176 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu0d64b202014-08-14 10:29:17 +0000179 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Jack Carter9e65aa32013-03-22 00:05:30 +0000182 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000183 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
184 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000185 bool reportParseError(Twine ErrorMsg);
186 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000187
Jack Carterb5cf5902013-04-17 00:18:04 +0000188 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000189 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000190
Vladimir Medic4c299852013-11-06 11:27:05 +0000191 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000192
193 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000194 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000195 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000196 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000197 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000198 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000199 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000200 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000201 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000202
203 bool parseSetAtDirective();
204 bool parseSetNoAtDirective();
205 bool parseSetMacroDirective();
206 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000207 bool parseSetMsaDirective();
208 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000209 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000210 bool parseSetReorderDirective();
211 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000212 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000213 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000214 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000215 bool parseSetPopDirective();
216 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000217
Jack Carterd76b2372013-03-21 21:44:16 +0000218 bool parseSetAssignment();
219
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000220 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000221 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000222 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000223 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000224 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000225 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
226 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000227
Jack Carterdc1e35d2012-09-06 20:00:02 +0000228 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000229
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000230 bool eatComma(StringRef ErrorStr);
231
Jack Carter1ac53222013-02-20 23:11:17 +0000232 int matchCPURegisterName(StringRef Symbol);
233
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000234 int matchHWRegsRegisterName(StringRef Symbol);
235
Jack Carter873c7242013-01-12 01:03:14 +0000236 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000237
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000238 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000239
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000240 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000241
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000242 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000243
Jack Carter5dc8ac92013-09-25 23:50:44 +0000244 int matchMSA128RegisterName(StringRef Name);
245
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000246 int matchMSA128CtrlRegisterName(StringRef Name);
247
Jack Carterd0bd6422013-04-18 00:41:53 +0000248 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000249
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000250 unsigned getGPR(int RegNo);
251
Matheus Almeida7de68e72014-06-18 14:46:05 +0000252 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000253
254 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000255 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000256
257 // Helper function that checks if the value of a vector index is within the
258 // boundaries of accepted values for each RegisterKind
259 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
260 bool validateMSAIndex(int Val, int RegKind);
261
Daniel Sandersf0df2212014-08-04 12:20:00 +0000262 // Selects a new architecture by updating the FeatureBits with the necessary
263 // info including implied dependencies.
264 // Internally, it clears all the feature bits related to *any* architecture
265 // and selects the new one using the ToggleFeature functionality of the
266 // MCSubtargetInfo object that handles implied dependencies. The reason we
267 // clear all the arch related bits manually is because ToggleFeature only
268 // clears the features that imply the feature being cleared and not the
269 // features implied by the feature being cleared. This is easier to see
270 // with an example:
271 // --------------------------------------------------
272 // | Feature | Implies |
273 // | -------------------------------------------------|
274 // | FeatureMips1 | None |
275 // | FeatureMips2 | FeatureMips1 |
276 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
277 // | FeatureMips4 | FeatureMips3 |
278 // | ... | |
279 // --------------------------------------------------
280 //
281 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
282 // FeatureMipsGP64 | FeatureMips1)
283 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
284 void selectArch(StringRef ArchFeature) {
285 uint64_t FeatureBits = STI.getFeatureBits();
286 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
287 STI.setFeatureBits(FeatureBits);
288 setAvailableFeatures(
289 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000290 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000291 }
292
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000293 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000294 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000295 setAvailableFeatures(
296 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000297 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000298 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000299 }
300
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000301 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000302 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000303 setAvailableFeatures(
304 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000305 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000306 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000307 }
308
Rafael Espindola870c4e92012-01-11 03:56:41 +0000309public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000310 enum MipsMatchResultTy {
311 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
312#define GET_OPERAND_DIAGNOSTIC_TYPES
313#include "MipsGenAsmMatcher.inc"
314#undef GET_OPERAND_DIAGNOSTIC_TYPES
315
316 };
317
Joey Gouly0e76fa72013-09-12 10:28:05 +0000318 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000319 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000320 : MCTargetAsmParser(), STI(sti),
321 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
322 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000323 MCAsmParserExtension::Initialize(parser);
324
Jack Carterb4dbc172012-09-05 23:34:03 +0000325 // Initialize the set of available features.
326 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000327
328 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000329 AssemblerOptions.push_back(
330 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000331
332 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000333 AssemblerOptions.push_back(
334 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000335
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000336 getTargetStreamer().updateABIInfo(*this);
337
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000338 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000339 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000340
341 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000342 }
343
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000344 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
345 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
348 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000349 const MipsABIInfo &getABI() const { return ABI; }
350 bool isABI_N32() const { return ABI.IsN32(); }
351 bool isABI_N64() const { return ABI.IsN64(); }
352 bool isABI_O32() const { return ABI.IsO32(); }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000353 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000354
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000355 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000356 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
357 }
358
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000359 bool inMicroMipsMode() const {
360 return STI.getFeatureBits() & Mips::FeatureMicroMips;
361 }
362 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
363 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
364 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
365 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
366 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
367 bool hasMips32() const {
368 return (STI.getFeatureBits() & Mips::FeatureMips32);
369 }
370 bool hasMips64() const {
371 return (STI.getFeatureBits() & Mips::FeatureMips64);
372 }
373 bool hasMips32r2() const {
374 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
375 }
376 bool hasMips64r2() const {
377 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
378 }
379 bool hasMips32r6() const {
380 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
381 }
382 bool hasMips64r6() const {
383 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
384 }
Kai Nackee0245392015-01-27 19:11:28 +0000385 bool hasCnMips() const {
386 return (STI.getFeatureBits() & Mips::FeatureCnMips);
387 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000388 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
389 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
390 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
391
392 bool inMips16Mode() const {
393 return STI.getFeatureBits() & Mips::FeatureMips16;
394 }
395 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000396 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000397
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000398 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000399 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000400};
401}
402
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000403namespace {
404
405/// MipsOperand - Instances of this class represent a parsed Mips machine
406/// instruction.
407class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000408public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000409 /// Broad categories of register classes
410 /// The exact class is finalized by the render method.
411 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000413 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000414 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000415 RegKind_FCC = 4, /// FCC
416 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
417 RegKind_MSACtrl = 16, /// MSA control registers
418 RegKind_COP2 = 32, /// COP2
419 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
420 /// context).
421 RegKind_CCR = 128, /// CCR
422 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000423 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000424
425 /// Potentially any (e.g. $1)
426 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
427 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000428 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000429 };
430
431private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000432 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000433 k_Immediate, /// An immediate (possibly involving symbol references)
434 k_Memory, /// Base + Offset Memory Address
435 k_PhysRegister, /// A physical register from the Mips namespace
436 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000437 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000438 k_RegList, /// A physical register list
439 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000440 } Kind;
441
David Blaikie960ea3f2014-06-08 16:18:35 +0000442public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 MipsOperand(KindTy K, MipsAsmParser &Parser)
444 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
445
David Blaikie960ea3f2014-06-08 16:18:35 +0000446private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000447 /// For diagnostics, and checking the assembler temporary
448 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000449
Eric Christopher8996c5d2013-03-15 00:42:55 +0000450 struct Token {
451 const char *Data;
452 unsigned Length;
453 };
454
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000455 struct PhysRegOp {
456 unsigned Num; /// Register Number
457 };
458
459 struct RegIdxOp {
460 unsigned Index; /// Index into the register class
461 RegKind Kind; /// Bitfield of the kinds it could possibly be
462 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000463 };
464
465 struct ImmOp {
466 const MCExpr *Val;
467 };
468
469 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000470 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000471 const MCExpr *Off;
472 };
473
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000474 struct RegListOp {
475 SmallVector<unsigned, 10> *List;
476 };
477
Jack Carterb4dbc172012-09-05 23:34:03 +0000478 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000479 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000480 struct PhysRegOp PhysReg;
481 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000482 struct ImmOp Imm;
483 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000484 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000485 };
486
487 SMLoc StartLoc, EndLoc;
488
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000489 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000490 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
491 const MCRegisterInfo *RegInfo,
492 SMLoc S, SMLoc E,
493 MipsAsmParser &Parser) {
494 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000495 Op->RegIdx.Index = Index;
496 Op->RegIdx.RegInfo = RegInfo;
497 Op->RegIdx.Kind = RegKind;
498 Op->StartLoc = S;
499 Op->EndLoc = E;
500 return Op;
501 }
502
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000503public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000504 /// Coerce the register to GPR32 and return the real register for the current
505 /// target.
506 unsigned getGPR32Reg() const {
507 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000508 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000509 unsigned ClassID = Mips::GPR32RegClassID;
510 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000511 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000512
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000513 /// Coerce the register to GPR32 and return the real register for the current
514 /// target.
515 unsigned getGPRMM16Reg() const {
516 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
517 unsigned ClassID = Mips::GPR32RegClassID;
518 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
519 }
520
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 /// Coerce the register to GPR64 and return the real register for the current
522 /// target.
523 unsigned getGPR64Reg() const {
524 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
525 unsigned ClassID = Mips::GPR64RegClassID;
526 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000527 }
528
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000529private:
530 /// Coerce the register to AFGR64 and return the real register for the current
531 /// target.
532 unsigned getAFGR64Reg() const {
533 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
534 if (RegIdx.Index % 2 != 0)
535 AsmParser.Warning(StartLoc, "Float register should be even.");
536 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
537 .getRegister(RegIdx.Index / 2);
538 }
539
540 /// Coerce the register to FGR64 and return the real register for the current
541 /// target.
542 unsigned getFGR64Reg() const {
543 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
544 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
545 .getRegister(RegIdx.Index);
546 }
547
548 /// Coerce the register to FGR32 and return the real register for the current
549 /// target.
550 unsigned getFGR32Reg() const {
551 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
552 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
553 .getRegister(RegIdx.Index);
554 }
555
556 /// Coerce the register to FGRH32 and return the real register for the current
557 /// target.
558 unsigned getFGRH32Reg() const {
559 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
560 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
561 .getRegister(RegIdx.Index);
562 }
563
564 /// Coerce the register to FCC and return the real register for the current
565 /// target.
566 unsigned getFCCReg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
568 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
569 .getRegister(RegIdx.Index);
570 }
571
572 /// Coerce the register to MSA128 and return the real register for the current
573 /// target.
574 unsigned getMSA128Reg() const {
575 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
576 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
577 // identical
578 unsigned ClassID = Mips::MSA128BRegClassID;
579 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
580 }
581
582 /// Coerce the register to MSACtrl and return the real register for the
583 /// current target.
584 unsigned getMSACtrlReg() const {
585 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
586 unsigned ClassID = Mips::MSACtrlRegClassID;
587 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
588 }
589
590 /// Coerce the register to COP2 and return the real register for the
591 /// current target.
592 unsigned getCOP2Reg() const {
593 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
594 unsigned ClassID = Mips::COP2RegClassID;
595 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
596 }
597
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000598 /// Coerce the register to COP3 and return the real register for the
599 /// current target.
600 unsigned getCOP3Reg() const {
601 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
602 unsigned ClassID = Mips::COP3RegClassID;
603 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
604 }
605
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000606 /// Coerce the register to ACC64DSP and return the real register for the
607 /// current target.
608 unsigned getACC64DSPReg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
610 unsigned ClassID = Mips::ACC64DSPRegClassID;
611 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
612 }
613
614 /// Coerce the register to HI32DSP and return the real register for the
615 /// current target.
616 unsigned getHI32DSPReg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
618 unsigned ClassID = Mips::HI32DSPRegClassID;
619 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
620 }
621
622 /// Coerce the register to LO32DSP and return the real register for the
623 /// current target.
624 unsigned getLO32DSPReg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
626 unsigned ClassID = Mips::LO32DSPRegClassID;
627 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
628 }
629
630 /// Coerce the register to CCR and return the real register for the
631 /// current target.
632 unsigned getCCRReg() const {
633 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
634 unsigned ClassID = Mips::CCRRegClassID;
635 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
636 }
637
638 /// Coerce the register to HWRegs and return the real register for the
639 /// current target.
640 unsigned getHWRegsReg() const {
641 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
642 unsigned ClassID = Mips::HWRegsRegClassID;
643 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
644 }
645
646public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000647 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000648 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000649 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000650 Inst.addOperand(MCOperand::CreateImm(0));
651 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
652 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
653 else
654 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000655 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000656
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000657 void addRegOperands(MCInst &Inst, unsigned N) const {
658 llvm_unreachable("Use a custom parser instead");
659 }
660
Daniel Sanders21bce302014-04-01 12:35:23 +0000661 /// Render the operand to an MCInst as a GPR32
662 /// Asserts if the wrong number of operands are requested, or the operand
663 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
665 assert(N == 1 && "Invalid number of operands!");
666 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
667 }
668
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000669 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
670 assert(N == 1 && "Invalid number of operands!");
671 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
672 }
673
Jozef Kolek1904fa22014-11-24 14:25:53 +0000674 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
675 assert(N == 1 && "Invalid number of operands!");
676 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
677 }
678
Daniel Sanders21bce302014-04-01 12:35:23 +0000679 /// Render the operand to an MCInst as a GPR64
680 /// Asserts if the wrong number of operands are requested, or the operand
681 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
683 assert(N == 1 && "Invalid number of operands!");
684 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
685 }
686
687 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
688 assert(N == 1 && "Invalid number of operands!");
689 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
690 }
691
692 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
693 assert(N == 1 && "Invalid number of operands!");
694 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
695 }
696
697 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
698 assert(N == 1 && "Invalid number of operands!");
699 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000700 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000701 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000702 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
703 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000704 }
705
706 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
707 assert(N == 1 && "Invalid number of operands!");
708 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
709 }
710
711 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
712 assert(N == 1 && "Invalid number of operands!");
713 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
714 }
715
716 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
717 assert(N == 1 && "Invalid number of operands!");
718 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
719 }
720
721 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
722 assert(N == 1 && "Invalid number of operands!");
723 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
724 }
725
726 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
727 assert(N == 1 && "Invalid number of operands!");
728 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
729 }
730
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000731 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
732 assert(N == 1 && "Invalid number of operands!");
733 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
734 }
735
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000736 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
737 assert(N == 1 && "Invalid number of operands!");
738 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
739 }
740
741 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
742 assert(N == 1 && "Invalid number of operands!");
743 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
744 }
745
746 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
747 assert(N == 1 && "Invalid number of operands!");
748 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
749 }
750
751 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
752 assert(N == 1 && "Invalid number of operands!");
753 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
754 }
755
756 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
757 assert(N == 1 && "Invalid number of operands!");
758 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
759 }
760
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000761 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000762 assert(N == 1 && "Invalid number of operands!");
763 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000764 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000765 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000766
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000767 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000768 assert(N == 2 && "Invalid number of operands!");
769
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000770 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000771
772 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000773 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000774 }
775
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000776 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
777 assert(N == 2 && "Invalid number of operands!");
778
779 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
780
781 const MCExpr *Expr = getMemOff();
782 addExpr(Inst, Expr);
783 }
784
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000785 void addRegListOperands(MCInst &Inst, unsigned N) const {
786 assert(N == 1 && "Invalid number of operands!");
787
788 for (auto RegNo : getRegList())
789 Inst.addOperand(MCOperand::CreateReg(RegNo));
790 }
791
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000792 void addRegPairOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 2 && "Invalid number of operands!");
794 unsigned RegNo = getRegPair();
795 Inst.addOperand(MCOperand::CreateReg(RegNo++));
796 Inst.addOperand(MCOperand::CreateReg(RegNo));
797 }
798
Craig Topper56c590a2014-04-29 07:58:02 +0000799 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 // As a special case until we sort out the definition of div/divu, pretend
801 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
802 if (isGPRAsmReg() && RegIdx.Index == 0)
803 return true;
804
805 return Kind == k_PhysRegister;
806 }
807 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000808 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 bool isConstantImm() const {
810 return isImm() && dyn_cast<MCConstantExpr>(getImm());
811 }
Craig Topper56c590a2014-04-29 07:58:02 +0000812 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 // Note: It's not possible to pretend that other operand kinds are tokens.
814 // The matcher emitter checks tokens first.
815 return Kind == k_Token;
816 }
Craig Topper56c590a2014-04-29 07:58:02 +0000817 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000818 bool isConstantMemOff() const {
819 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
820 }
821 template <unsigned Bits> bool isMemWithSimmOffset() const {
822 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
823 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000824 bool isMemWithGRPMM16Base() const {
825 return isMem() && getMemBase()->isMM16AsmReg();
826 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000827 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
828 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
829 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
830 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000831 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
832 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
833 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
834 && (getMemBase()->getGPR32Reg() == Mips::SP);
835 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000836 bool isRegList16() const {
837 if (!isRegList())
838 return false;
839
840 int Size = RegList.List->size();
841 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
842 RegList.List->back() != Mips::RA)
843 return false;
844
845 int PrevReg = *RegList.List->begin();
846 for (int i = 1; i < Size - 1; i++) {
847 int Reg = (*(RegList.List))[i];
848 if ( Reg != PrevReg + 1)
849 return false;
850 PrevReg = Reg;
851 }
852
853 return true;
854 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000855 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 bool isLSAImm() const {
857 if (!isConstantImm())
858 return false;
859 int64_t Val = getConstantImm();
860 return 1 <= Val && Val <= 4;
861 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000862 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000863
864 StringRef getToken() const {
865 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000866 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000867 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000868 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000869
Craig Topper56c590a2014-04-29 07:58:02 +0000870 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 // As a special case until we sort out the definition of div/divu, pretend
872 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
873 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
874 RegIdx.Kind & RegKind_GPR)
875 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000876
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 assert(Kind == k_PhysRegister && "Invalid access!");
878 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000879 }
880
Jack Carterb4dbc172012-09-05 23:34:03 +0000881 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000883 return Imm.Val;
884 }
885
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000886 int64_t getConstantImm() const {
887 const MCExpr *Val = getImm();
888 return static_cast<const MCConstantExpr *>(Val)->getValue();
889 }
890
891 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000892 assert((Kind == k_Memory) && "Invalid access!");
893 return Mem.Base;
894 }
895
896 const MCExpr *getMemOff() const {
897 assert((Kind == k_Memory) && "Invalid access!");
898 return Mem.Off;
899 }
900
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000901 int64_t getConstantMemOff() const {
902 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
903 }
904
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000905 const SmallVectorImpl<unsigned> &getRegList() const {
906 assert((Kind == k_RegList) && "Invalid access!");
907 return *(RegList.List);
908 }
909
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000910 unsigned getRegPair() const {
911 assert((Kind == k_RegPair) && "Invalid access!");
912 return RegIdx.Index;
913 }
914
David Blaikie960ea3f2014-06-08 16:18:35 +0000915 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
916 MipsAsmParser &Parser) {
917 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000918 Op->Tok.Data = Str.data();
919 Op->Tok.Length = Str.size();
920 Op->StartLoc = S;
921 Op->EndLoc = S;
922 return Op;
923 }
924
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 /// Create a numeric register (e.g. $1). The exact register remains
926 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000927 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000928 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000929 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000930 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000931 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000932 }
933
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000934 /// Create a register that is definitely a GPR.
935 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000936 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000937 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000938 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000940 }
941
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 /// Create a register that is definitely a FGR.
943 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000944 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000945 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000946 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000947 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
948 }
949
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000950 /// Create a register that is definitely a HWReg.
951 /// This is typically only used for named registers such as $hwr_cpunum.
952 static std::unique_ptr<MipsOperand>
953 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
954 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
955 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
956 }
957
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000958 /// Create a register that is definitely an FCC.
959 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000960 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000961 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000962 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000963 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
964 }
965
966 /// Create a register that is definitely an ACC.
967 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000968 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000969 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000970 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000971 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
972 }
973
974 /// Create a register that is definitely an MSA128.
975 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000976 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000977 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000978 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000979 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
980 }
981
982 /// Create a register that is definitely an MSACtrl.
983 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000984 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000985 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000986 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
988 }
989
David Blaikie960ea3f2014-06-08 16:18:35 +0000990 static std::unique_ptr<MipsOperand>
991 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
992 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000993 Op->Imm.Val = Val;
994 Op->StartLoc = S;
995 Op->EndLoc = E;
996 return Op;
997 }
998
David Blaikie960ea3f2014-06-08 16:18:35 +0000999 static std::unique_ptr<MipsOperand>
1000 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1001 SMLoc E, MipsAsmParser &Parser) {
1002 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1003 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001004 Op->Mem.Off = Off;
1005 Op->StartLoc = S;
1006 Op->EndLoc = E;
1007 return Op;
1008 }
1009
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001010 static std::unique_ptr<MipsOperand>
1011 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1012 MipsAsmParser &Parser) {
1013 assert (Regs.size() > 0 && "Empty list not allowed");
1014
1015 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1016 Op->RegList.List = new SmallVector<unsigned, 10>();
1017 for (auto Reg : Regs)
1018 Op->RegList.List->push_back(Reg);
1019 Op->StartLoc = StartLoc;
1020 Op->EndLoc = EndLoc;
1021 return Op;
1022 }
1023
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001024 static std::unique_ptr<MipsOperand>
1025 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1026 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1027 Op->RegIdx.Index = RegNo;
1028 Op->StartLoc = S;
1029 Op->EndLoc = E;
1030 return Op;
1031 }
1032
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001033 bool isGPRAsmReg() const {
1034 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001035 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001036 bool isMM16AsmReg() const {
1037 if (!(isRegIdx() && RegIdx.Kind))
1038 return false;
1039 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1040 || RegIdx.Index == 16 || RegIdx.Index == 17);
1041 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001042 bool isMM16AsmRegZero() const {
1043 if (!(isRegIdx() && RegIdx.Kind))
1044 return false;
1045 return (RegIdx.Index == 0 ||
1046 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1047 RegIdx.Index == 17);
1048 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 bool isFGRAsmReg() const {
1050 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1051 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001052 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001053 bool isHWRegsAsmReg() const {
1054 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001055 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 bool isCCRAsmReg() const {
1057 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001058 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001059 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001060 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1061 return false;
1062 if (!AsmParser.hasEightFccRegisters())
1063 return RegIdx.Index == 0;
1064 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001065 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 bool isACCAsmReg() const {
1067 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001068 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 bool isCOP2AsmReg() const {
1070 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001071 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001072 bool isCOP3AsmReg() const {
1073 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1074 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 bool isMSA128AsmReg() const {
1076 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001077 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 bool isMSACtrlAsmReg() const {
1079 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001080 }
1081
Jack Carterb4dbc172012-09-05 23:34:03 +00001082 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001083 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001084 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001085 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001086
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001087 virtual ~MipsOperand() {
1088 switch (Kind) {
1089 case k_Immediate:
1090 break;
1091 case k_Memory:
1092 delete Mem.Base;
1093 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001094 case k_RegList:
1095 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001096 case k_PhysRegister:
1097 case k_RegisterIndex:
1098 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001099 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001100 break;
1101 }
1102 }
1103
Craig Topper56c590a2014-04-29 07:58:02 +00001104 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 switch (Kind) {
1106 case k_Immediate:
1107 OS << "Imm<";
1108 Imm.Val->print(OS);
1109 OS << ">";
1110 break;
1111 case k_Memory:
1112 OS << "Mem<";
1113 Mem.Base->print(OS);
1114 OS << ", ";
1115 Mem.Off->print(OS);
1116 OS << ">";
1117 break;
1118 case k_PhysRegister:
1119 OS << "PhysReg<" << PhysReg.Num << ">";
1120 break;
1121 case k_RegisterIndex:
1122 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1123 break;
1124 case k_Token:
1125 OS << Tok.Data;
1126 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001127 case k_RegList:
1128 OS << "RegList< ";
1129 for (auto Reg : (*RegList.List))
1130 OS << Reg << " ";
1131 OS << ">";
1132 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001133 case k_RegPair:
1134 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1135 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001136 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001137 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001138}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001139} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001140
Jack Carter9e65aa32013-03-22 00:05:30 +00001141namespace llvm {
1142extern const MCInstrDesc MipsInsts[];
1143}
1144static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1145 return MipsInsts[Opcode];
1146}
1147
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001148static bool hasShortDelaySlot(unsigned Opcode) {
1149 switch (Opcode) {
1150 case Mips::JALS_MM:
1151 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001152 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001153 case Mips::BGEZALS_MM:
1154 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001155 return true;
1156 default:
1157 return false;
1158 }
1159}
1160
Jack Carter9e65aa32013-03-22 00:05:30 +00001161bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001162 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001163 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001164
Jack Carter9e65aa32013-03-22 00:05:30 +00001165 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001166
1167 if (MCID.isBranch() || MCID.isCall()) {
1168 const unsigned Opcode = Inst.getOpcode();
1169 MCOperand Offset;
1170
1171 switch (Opcode) {
1172 default:
1173 break;
Kai Nackee0245392015-01-27 19:11:28 +00001174 case Mips::BBIT0:
1175 case Mips::BBIT032:
1176 case Mips::BBIT1:
1177 case Mips::BBIT132:
1178 assert(hasCnMips() && "instruction only valid for octeon cpus");
1179 // Fall through
1180
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001181 case Mips::BEQ:
1182 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001183 case Mips::BEQ_MM:
1184 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001185 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001186 Offset = Inst.getOperand(2);
1187 if (!Offset.isImm())
1188 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001189 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001190 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001191 if (OffsetToAlignment(Offset.getImm(),
1192 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001193 return Error(IDLoc, "branch to misaligned address");
1194 break;
1195 case Mips::BGEZ:
1196 case Mips::BGTZ:
1197 case Mips::BLEZ:
1198 case Mips::BLTZ:
1199 case Mips::BGEZAL:
1200 case Mips::BLTZAL:
1201 case Mips::BC1F:
1202 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001203 case Mips::BGEZ_MM:
1204 case Mips::BGTZ_MM:
1205 case Mips::BLEZ_MM:
1206 case Mips::BLTZ_MM:
1207 case Mips::BGEZAL_MM:
1208 case Mips::BLTZAL_MM:
1209 case Mips::BC1F_MM:
1210 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001211 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001212 Offset = Inst.getOperand(1);
1213 if (!Offset.isImm())
1214 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001215 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001216 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001217 if (OffsetToAlignment(Offset.getImm(),
1218 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001219 return Error(IDLoc, "branch to misaligned address");
1220 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001221 case Mips::BEQZ16_MM:
1222 case Mips::BNEZ16_MM:
1223 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1224 Offset = Inst.getOperand(1);
1225 if (!Offset.isImm())
1226 break; // We'll deal with this situation later on when applying fixups.
1227 if (!isIntN(8, Offset.getImm()))
1228 return Error(IDLoc, "branch target out of range");
1229 if (OffsetToAlignment(Offset.getImm(), 2LL))
1230 return Error(IDLoc, "branch to misaligned address");
1231 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001232 }
1233 }
1234
Daniel Sandersa84989a2014-06-16 13:25:35 +00001235 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1236 // We still accept it but it is a normal nop.
1237 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1238 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1239 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1240 "nop instruction");
1241 }
1242
Kai Nackee0245392015-01-27 19:11:28 +00001243 if (hasCnMips()) {
1244 const unsigned Opcode = Inst.getOpcode();
1245 MCOperand Opnd;
1246 int Imm;
1247
1248 switch (Opcode) {
1249 default:
1250 break;
1251
1252 case Mips::BBIT0:
1253 case Mips::BBIT032:
1254 case Mips::BBIT1:
1255 case Mips::BBIT132:
1256 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1257 // The offset is handled above
1258 Opnd = Inst.getOperand(1);
1259 if (!Opnd.isImm())
1260 return Error(IDLoc, "expected immediate operand kind");
1261 Imm = Opnd.getImm();
1262 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1263 Opcode == Mips::BBIT1 ? 63 : 31))
1264 return Error(IDLoc, "immediate operand value out of range");
1265 if (Imm > 31) {
1266 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1267 : Mips::BBIT132);
1268 Inst.getOperand(1).setImm(Imm - 32);
1269 }
1270 break;
1271
1272 case Mips::CINS:
1273 case Mips::CINS32:
1274 case Mips::EXTS:
1275 case Mips::EXTS32:
1276 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1277 // Check length
1278 Opnd = Inst.getOperand(3);
1279 if (!Opnd.isImm())
1280 return Error(IDLoc, "expected immediate operand kind");
1281 Imm = Opnd.getImm();
1282 if (Imm < 0 || Imm > 31)
1283 return Error(IDLoc, "immediate operand value out of range");
1284 // Check position
1285 Opnd = Inst.getOperand(2);
1286 if (!Opnd.isImm())
1287 return Error(IDLoc, "expected immediate operand kind");
1288 Imm = Opnd.getImm();
1289 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1290 Opcode == Mips::EXTS ? 63 : 31))
1291 return Error(IDLoc, "immediate operand value out of range");
1292 if (Imm > 31) {
1293 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1294 Inst.getOperand(2).setImm(Imm - 32);
1295 }
1296 break;
1297
1298 case Mips::SEQi:
1299 case Mips::SNEi:
1300 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1301 Opnd = Inst.getOperand(2);
1302 if (!Opnd.isImm())
1303 return Error(IDLoc, "expected immediate operand kind");
1304 Imm = Opnd.getImm();
1305 if (!isInt<10>(Imm))
1306 return Error(IDLoc, "immediate operand value out of range");
1307 break;
1308 }
1309 }
1310
Toma Tabacu9db22db2014-09-09 10:15:38 +00001311 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001312 // If this instruction has a delay slot and .set reorder is active,
1313 // emit a NOP after it.
1314 Instructions.push_back(Inst);
1315 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001316 if (hasShortDelaySlot(Inst.getOpcode())) {
1317 NopInst.setOpcode(Mips::MOVE16_MM);
1318 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1319 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1320 } else {
1321 NopInst.setOpcode(Mips::SLL);
1322 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1323 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1324 NopInst.addOperand(MCOperand::CreateImm(0));
1325 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001326 Instructions.push_back(NopInst);
1327 return false;
1328 }
1329
Jack Carter9e65aa32013-03-22 00:05:30 +00001330 if (MCID.mayLoad() || MCID.mayStore()) {
1331 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001332 // reference or immediate we may have to expand instructions.
1333 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001334 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001335 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1336 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001337 MCOperand &Op = Inst.getOperand(i);
1338 if (Op.isImm()) {
1339 int MemOffset = Op.getImm();
1340 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001341 // Offset can't exceed 16bit value.
1342 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001343 return false;
1344 }
1345 } else if (Op.isExpr()) {
1346 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001347 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001348 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001349 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001350 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001351 // Expand symbol.
1352 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001353 return false;
1354 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001355 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001356 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001357 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001358 }
1359 }
1360 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001361 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001362 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001363
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001364 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1365 if (inMicroMipsMode()) {
1366 MCOperand Opnd;
1367 int Imm;
1368
1369 switch (Inst.getOpcode()) {
1370 default:
1371 break;
1372 case Mips::ADDIUS5_MM:
1373 Opnd = Inst.getOperand(2);
1374 if (!Opnd.isImm())
1375 return Error(IDLoc, "expected immediate operand kind");
1376 Imm = Opnd.getImm();
1377 if (Imm < -8 || Imm > 7)
1378 return Error(IDLoc, "immediate operand value out of range");
1379 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001380 case Mips::ADDIUSP_MM:
1381 Opnd = Inst.getOperand(0);
1382 if (!Opnd.isImm())
1383 return Error(IDLoc, "expected immediate operand kind");
1384 Imm = Opnd.getImm();
1385 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1386 Imm % 4 != 0)
1387 return Error(IDLoc, "immediate operand value out of range");
1388 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001389 case Mips::SLL16_MM:
1390 case Mips::SRL16_MM:
1391 Opnd = Inst.getOperand(2);
1392 if (!Opnd.isImm())
1393 return Error(IDLoc, "expected immediate operand kind");
1394 Imm = Opnd.getImm();
1395 if (Imm < 1 || Imm > 8)
1396 return Error(IDLoc, "immediate operand value out of range");
1397 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001398 case Mips::LI16_MM:
1399 Opnd = Inst.getOperand(1);
1400 if (!Opnd.isImm())
1401 return Error(IDLoc, "expected immediate operand kind");
1402 Imm = Opnd.getImm();
1403 if (Imm < -1 || Imm > 126)
1404 return Error(IDLoc, "immediate operand value out of range");
1405 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001406 case Mips::ADDIUR2_MM:
1407 Opnd = Inst.getOperand(2);
1408 if (!Opnd.isImm())
1409 return Error(IDLoc, "expected immediate operand kind");
1410 Imm = Opnd.getImm();
1411 if (!(Imm == 1 || Imm == -1 ||
1412 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1413 return Error(IDLoc, "immediate operand value out of range");
1414 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001415 case Mips::ADDIUR1SP_MM:
1416 Opnd = Inst.getOperand(1);
1417 if (!Opnd.isImm())
1418 return Error(IDLoc, "expected immediate operand kind");
1419 Imm = Opnd.getImm();
1420 if (OffsetToAlignment(Imm, 4LL))
1421 return Error(IDLoc, "misaligned immediate operand value");
1422 if (Imm < 0 || Imm > 255)
1423 return Error(IDLoc, "immediate operand value out of range");
1424 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001425 case Mips::ANDI16_MM:
1426 Opnd = Inst.getOperand(2);
1427 if (!Opnd.isImm())
1428 return Error(IDLoc, "expected immediate operand kind");
1429 Imm = Opnd.getImm();
1430 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1431 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1432 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1433 return Error(IDLoc, "immediate operand value out of range");
1434 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001435 case Mips::LBU16_MM:
1436 Opnd = Inst.getOperand(2);
1437 if (!Opnd.isImm())
1438 return Error(IDLoc, "expected immediate operand kind");
1439 Imm = Opnd.getImm();
1440 if (Imm < -1 || Imm > 14)
1441 return Error(IDLoc, "immediate operand value out of range");
1442 break;
1443 case Mips::SB16_MM:
1444 Opnd = Inst.getOperand(2);
1445 if (!Opnd.isImm())
1446 return Error(IDLoc, "expected immediate operand kind");
1447 Imm = Opnd.getImm();
1448 if (Imm < 0 || Imm > 15)
1449 return Error(IDLoc, "immediate operand value out of range");
1450 break;
1451 case Mips::LHU16_MM:
1452 case Mips::SH16_MM:
1453 Opnd = Inst.getOperand(2);
1454 if (!Opnd.isImm())
1455 return Error(IDLoc, "expected immediate operand kind");
1456 Imm = Opnd.getImm();
1457 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1458 return Error(IDLoc, "immediate operand value out of range");
1459 break;
1460 case Mips::LW16_MM:
1461 case Mips::SW16_MM:
1462 Opnd = Inst.getOperand(2);
1463 if (!Opnd.isImm())
1464 return Error(IDLoc, "expected immediate operand kind");
1465 Imm = Opnd.getImm();
1466 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1467 return Error(IDLoc, "immediate operand value out of range");
1468 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001469 case Mips::CACHE:
1470 case Mips::PREF:
1471 Opnd = Inst.getOperand(2);
1472 if (!Opnd.isImm())
1473 return Error(IDLoc, "expected immediate operand kind");
1474 Imm = Opnd.getImm();
1475 if (!isUInt<5>(Imm))
1476 return Error(IDLoc, "immediate operand value out of range");
1477 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001478 case Mips::ADDIUPC_MM:
1479 MCOperand Opnd = Inst.getOperand(1);
1480 if (!Opnd.isImm())
1481 return Error(IDLoc, "expected immediate operand kind");
1482 int Imm = Opnd.getImm();
1483 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1484 return Error(IDLoc, "immediate operand value out of range");
1485 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001486 }
1487 }
1488
Jack Carter9e65aa32013-03-22 00:05:30 +00001489 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001490 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001491 else
1492 Instructions.push_back(Inst);
1493
1494 return false;
1495}
1496
Jack Carter30a59822012-10-04 04:03:53 +00001497bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1498
Jack Carterd0bd6422013-04-18 00:41:53 +00001499 switch (Inst.getOpcode()) {
1500 case Mips::LoadImm32Reg:
1501 case Mips::LoadAddr32Imm:
1502 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001503 case Mips::LoadImm64Reg:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001504 case Mips::B_MM_Pseudo:
Jack Carterd0bd6422013-04-18 00:41:53 +00001505 return true;
1506 default:
1507 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001508 }
1509}
Jack Carter92995f12012-10-06 00:53:28 +00001510
Matheus Almeida3813d572014-06-19 14:39:14 +00001511bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001512 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001513 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001514 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001515 case Mips::LoadImm32Reg:
1516 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001517 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001518 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001519 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001520 return true;
1521 }
1522 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001523 case Mips::LoadAddr32Imm:
1524 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1525 case Mips::LoadAddr32Reg:
1526 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001527 case Mips::B_MM_Pseudo:
1528 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 }
Jack Carter30a59822012-10-04 04:03:53 +00001530}
Jack Carter92995f12012-10-06 00:53:28 +00001531
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001532namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001533template <bool PerformShift>
1534void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001535 SmallVectorImpl<MCInst> &Instructions) {
1536 MCInst tmpInst;
1537 if (PerformShift) {
1538 tmpInst.setOpcode(Mips::DSLL);
1539 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1540 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1541 tmpInst.addOperand(MCOperand::CreateImm(16));
1542 tmpInst.setLoc(IDLoc);
1543 Instructions.push_back(tmpInst);
1544 tmpInst.clear();
1545 }
1546 tmpInst.setOpcode(Mips::ORi);
1547 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1548 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001549 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001550 tmpInst.setLoc(IDLoc);
1551 Instructions.push_back(tmpInst);
1552}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001553
1554template <int Shift, bool PerformShift>
1555void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1556 SmallVectorImpl<MCInst> &Instructions) {
1557 createShiftOr<PerformShift>(
1558 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1559 IDLoc, Instructions);
1560}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001561}
1562
Matheus Almeida3813d572014-06-19 14:39:14 +00001563bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001564 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001565 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001566 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001567 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001568 const MCOperand &RegOp = Inst.getOperand(0);
1569 assert(RegOp.isReg() && "expected register operand kind");
1570
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001571 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001572 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001573 // FIXME: gas has a special case for values that are 000...1111, which
1574 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001575 if (0 <= ImmValue && ImmValue <= 65535) {
1576 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001577 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001578 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001579 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001581 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001582 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001583 } else if (ImmValue < 0 && ImmValue >= -32768) {
1584 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001585 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001586 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001587 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001588 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001589 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001590 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001591 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1592 // For any value of j that is representable as a 32-bit integer, create
1593 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001594 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001595 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001596 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001597 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1598 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001599 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001600 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1601 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001602 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001603 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001604 return true;
1605 }
1606
1607 // <------- lo32 ------>
1608 // <------- hi32 ------>
1609 // <- hi16 -> <- lo16 ->
1610 // _________________________________
1611 // | | | |
1612 // | 16-bytes | 16-bytes | 16-bytes |
1613 // |__________|__________|__________|
1614 //
1615 // For any value of j that is representable as a 48-bit integer, create
1616 // a sequence of:
1617 // li d,j => lui d,hi16(j)
1618 // ori d,d,hi16(lo32(j))
1619 // dsll d,d,16
1620 // ori d,d,lo16(lo32(j))
1621 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001622 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001623 tmpInst.addOperand(
1624 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001625 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001626 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1627 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1628 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001629 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001630 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001631 return true;
1632 }
1633
1634 // <------- hi32 ------> <------- lo32 ------>
1635 // <- hi16 -> <- lo16 ->
1636 // ___________________________________________
1637 // | | | | |
1638 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1639 // |__________|__________|__________|__________|
1640 //
1641 // For any value of j that isn't representable as a 48-bit integer.
1642 // li d,j => lui d,hi16(j)
1643 // ori d,d,lo16(hi32(j))
1644 // dsll d,d,16
1645 // ori d,d,hi16(lo32(j))
1646 // dsll d,d,16
1647 // ori d,d,lo16(lo32(j))
1648 tmpInst.setOpcode(Mips::LUi);
1649 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1650 tmpInst.addOperand(
1651 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1652 Instructions.push_back(tmpInst);
1653 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1654 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1655 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001656 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001657 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001658}
Jack Carter92995f12012-10-06 00:53:28 +00001659
Matheus Almeida3813d572014-06-19 14:39:14 +00001660bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001661MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1662 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001663 MCInst tmpInst;
1664 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001665 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1666 "expected immediate operand kind");
1667 if (!ImmOp.isImm()) {
1668 expandLoadAddressSym(Inst, IDLoc, Instructions);
1669 return false;
1670 }
Jack Carter543fdf82012-10-09 23:29:45 +00001671 const MCOperand &SrcRegOp = Inst.getOperand(1);
1672 assert(SrcRegOp.isReg() && "expected register operand kind");
1673 const MCOperand &DstRegOp = Inst.getOperand(0);
1674 assert(DstRegOp.isReg() && "expected register operand kind");
1675 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 if (-32768 <= ImmValue && ImmValue <= 65535) {
1677 // For -32768 <= j <= 65535.
1678 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001679 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001680 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1681 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1682 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1683 Instructions.push_back(tmpInst);
1684 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001685 // For any other value of j that is representable as a 32-bit integer.
1686 // la d,j(s) => lui d,hi16(j)
1687 // ori d,d,lo16(j)
1688 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001689 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001690 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1691 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1692 Instructions.push_back(tmpInst);
1693 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001694 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001695 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1696 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1697 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1698 Instructions.push_back(tmpInst);
1699 tmpInst.clear();
1700 tmpInst.setOpcode(Mips::ADDu);
1701 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1702 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1703 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1704 Instructions.push_back(tmpInst);
1705 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001706 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001707}
1708
Matheus Almeida3813d572014-06-19 14:39:14 +00001709bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001710MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1711 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001712 MCInst tmpInst;
1713 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001714 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1715 "expected immediate operand kind");
1716 if (!ImmOp.isImm()) {
1717 expandLoadAddressSym(Inst, IDLoc, Instructions);
1718 return false;
1719 }
Jack Carter543fdf82012-10-09 23:29:45 +00001720 const MCOperand &RegOp = Inst.getOperand(0);
1721 assert(RegOp.isReg() && "expected register operand kind");
1722 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001723 if (-32768 <= ImmValue && ImmValue <= 65535) {
1724 // For -32768 <= j <= 65535.
1725 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001726 tmpInst.setOpcode(Mips::ADDiu);
1727 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001729 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1730 Instructions.push_back(tmpInst);
1731 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 // For any other value of j that is representable as a 32-bit integer.
1733 // la d,j => lui d,hi16(j)
1734 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001735 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001736 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1737 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1738 Instructions.push_back(tmpInst);
1739 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001740 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001741 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1742 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1743 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1744 Instructions.push_back(tmpInst);
1745 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001746 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001747}
1748
Toma Tabacu0d64b202014-08-14 10:29:17 +00001749void
1750MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1751 SmallVectorImpl<MCInst> &Instructions) {
1752 // FIXME: If we do have a valid at register to use, we should generate a
1753 // slightly shorter sequence here.
1754 MCInst tmpInst;
1755 int ExprOperandNo = 1;
1756 // Sometimes the assembly parser will get the immediate expression as
1757 // a $zero + an immediate.
1758 if (Inst.getNumOperands() == 3) {
1759 assert(Inst.getOperand(1).getReg() ==
1760 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1761 ExprOperandNo = 2;
1762 }
1763 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1764 assert(SymOp.isExpr() && "expected symbol operand kind");
1765 const MCOperand &RegOp = Inst.getOperand(0);
1766 unsigned RegNo = RegOp.getReg();
1767 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1768 const MCSymbolRefExpr *HiExpr =
1769 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1770 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1771 const MCSymbolRefExpr *LoExpr =
1772 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1773 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1774 if (isGP64bit()) {
1775 // If it's a 64-bit architecture, expand to:
1776 // la d,sym => lui d,highest(sym)
1777 // ori d,d,higher(sym)
1778 // dsll d,d,16
1779 // ori d,d,hi16(sym)
1780 // dsll d,d,16
1781 // ori d,d,lo16(sym)
1782 const MCSymbolRefExpr *HighestExpr =
1783 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1784 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1785 const MCSymbolRefExpr *HigherExpr =
1786 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1787 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1788
1789 tmpInst.setOpcode(Mips::LUi);
1790 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1791 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1792 Instructions.push_back(tmpInst);
1793
1794 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1795 Instructions);
1796 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1797 Instructions);
1798 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1799 Instructions);
1800 } else {
1801 // Otherwise, expand to:
1802 // la d,sym => lui d,hi16(sym)
1803 // ori d,d,lo16(sym)
1804 tmpInst.setOpcode(Mips::LUi);
1805 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1806 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1807 Instructions.push_back(tmpInst);
1808
1809 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1810 Instructions);
1811 }
1812}
1813
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001814bool MipsAsmParser::expandUncondBranchMMPseudo(
1815 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001816 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1817 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001818
1819 MCOperand Offset = Inst.getOperand(0);
1820 if (Offset.isExpr()) {
1821 Inst.clear();
1822 Inst.setOpcode(Mips::BEQ_MM);
1823 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1824 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1825 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1826 } else {
1827 assert(Offset.isImm() && "expected immediate operand kind");
1828 if (isIntN(11, Offset.getImm())) {
1829 // If offset fits into 11 bits then this instruction becomes microMIPS
1830 // 16-bit unconditional branch instruction.
1831 Inst.setOpcode(Mips::B16_MM);
1832 } else {
1833 if (!isIntN(17, Offset.getImm()))
1834 Error(IDLoc, "branch target out of range");
1835 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1836 Error(IDLoc, "branch to misaligned address");
1837 Inst.clear();
1838 Inst.setOpcode(Mips::BEQ_MM);
1839 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1840 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1841 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1842 }
1843 }
1844 Instructions.push_back(Inst);
1845
1846 if (AssemblerOptions.back()->isReorder()) {
1847 // If .set reorder is active, emit a NOP after the branch instruction.
1848 MCInst NopInst;
1849 NopInst.setOpcode(Mips::MOVE16_MM);
1850 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1851 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1852 Instructions.push_back(NopInst);
1853 }
1854 return false;
1855}
1856
Jack Carter9e65aa32013-03-22 00:05:30 +00001857void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001858 SmallVectorImpl<MCInst> &Instructions,
1859 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001860 const MCSymbolRefExpr *SR;
1861 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001862 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001863 const MCExpr *ExprOffset;
1864 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001865 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001866 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1867 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001868 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001869 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1870 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001871 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001872 if (isImmOpnd) {
1873 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1874 ImmOffset = Inst.getOperand(2).getImm();
1875 LoOffset = ImmOffset & 0x0000ffff;
1876 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001877 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001878 if (LoOffset & 0x8000)
1879 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001880 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001881 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001882 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001883 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001884 // These are some of the types of expansions we perform here:
1885 // 1) lw $8, sym => lui $8, %hi(sym)
1886 // lw $8, %lo(sym)($8)
1887 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1888 // add $8, $8, $9
1889 // lw $8, %lo(offset)($9)
1890 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1891 // add $at, $at, $8
1892 // lw $8, %lo(offset)($at)
1893 // 4) sw $8, sym => lui $at, %hi(sym)
1894 // sw $8, %lo(sym)($at)
1895 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1896 // add $at, $at, $8
1897 // sw $8, %lo(offset)($at)
1898 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1899 // ldc1 $f0, %lo(sym)($at)
1900 //
1901 // For load instructions we can use the destination register as a temporary
1902 // if base and dst are different (examples 1 and 2) and if the base register
1903 // is general purpose otherwise we must use $at (example 6) and error if it's
1904 // not available. For stores we must use $at (examples 4 and 5) because we
1905 // must not clobber the source register setting up the offset.
1906 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1907 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1908 unsigned RegClassIDOp0 =
1909 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1910 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1911 (RegClassIDOp0 == Mips::GPR64RegClassID);
1912 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001913 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001914 else {
1915 int AT = getATReg(IDLoc);
1916 // At this point we need AT to perform the expansions and we exit if it is
1917 // not available.
1918 if (!AT)
1919 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001920 TmpRegNum = getReg(
1921 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001922 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001923
Jack Carter9e65aa32013-03-22 00:05:30 +00001924 TempInst.setOpcode(Mips::LUi);
1925 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1926 if (isImmOpnd)
1927 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1928 else {
1929 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001930 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001931 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1932 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1933 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001934 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001935 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001936 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001937 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001938 }
1939 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001940 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001941 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001942 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001943 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001944 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001945 TempInst.setOpcode(Mips::ADDu);
1946 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1947 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1948 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1949 Instructions.push_back(TempInst);
1950 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001951 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001952 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001953 TempInst.setOpcode(Inst.getOpcode());
1954 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1955 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1956 if (isImmOpnd)
1957 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1958 else {
1959 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001960 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1961 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1962 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001963 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001964 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001965 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001966 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001967 }
1968 }
1969 Instructions.push_back(TempInst);
1970 TempInst.clear();
1971}
1972
Matheus Almeida595fcab2014-06-11 15:05:56 +00001973unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1974 // As described by the Mips32r2 spec, the registers Rd and Rs for
1975 // jalr.hb must be different.
1976 unsigned Opcode = Inst.getOpcode();
1977
1978 if (Opcode == Mips::JALR_HB &&
1979 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1980 return Match_RequiresDifferentSrcAndDst;
1981
1982 return Match_Success;
1983}
1984
David Blaikie960ea3f2014-06-08 16:18:35 +00001985bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1986 OperandVector &Operands,
1987 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001988 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001989 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001990
Jack Carterb4dbc172012-09-05 23:34:03 +00001991 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001992 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001993 unsigned MatchResult =
1994 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001995
1996 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001997 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001998 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001999 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002000 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002001 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002002 return false;
2003 }
2004 case Match_MissingFeature:
2005 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2006 return true;
2007 case Match_InvalidOperand: {
2008 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002009 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002010 if (ErrorInfo >= Operands.size())
2011 return Error(IDLoc, "too few operands for instruction");
2012
David Blaikie960ea3f2014-06-08 16:18:35 +00002013 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002014 if (ErrorLoc == SMLoc())
2015 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002016 }
2017
2018 return Error(ErrorLoc, "invalid operand for instruction");
2019 }
2020 case Match_MnemonicFail:
2021 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002022 case Match_RequiresDifferentSrcAndDst:
2023 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002024 }
Craig Topper589ceee2015-01-03 08:16:34 +00002025
2026 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002027}
2028
Toma Tabacu13964452014-09-04 13:23:44 +00002029void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002030 if ((RegIndex != 0) &&
2031 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002032 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002033 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002034 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002035 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002036 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002037 }
2038}
2039
Daniel Sandersef638fe2014-10-03 15:37:37 +00002040void
2041MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2042 SMRange Range, bool ShowColors) {
2043 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002044 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002045 ShowColors);
2046}
2047
Jack Carter1ac53222013-02-20 23:11:17 +00002048int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002049 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002050
Vladimir Medic4c299852013-11-06 11:27:05 +00002051 CC = StringSwitch<unsigned>(Name)
2052 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002053 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002054 .Case("a0", 4)
2055 .Case("a1", 5)
2056 .Case("a2", 6)
2057 .Case("a3", 7)
2058 .Case("v0", 2)
2059 .Case("v1", 3)
2060 .Case("s0", 16)
2061 .Case("s1", 17)
2062 .Case("s2", 18)
2063 .Case("s3", 19)
2064 .Case("s4", 20)
2065 .Case("s5", 21)
2066 .Case("s6", 22)
2067 .Case("s7", 23)
2068 .Case("k0", 26)
2069 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002070 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002071 .Case("sp", 29)
2072 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002073 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002074 .Case("ra", 31)
2075 .Case("t0", 8)
2076 .Case("t1", 9)
2077 .Case("t2", 10)
2078 .Case("t3", 11)
2079 .Case("t4", 12)
2080 .Case("t5", 13)
2081 .Case("t6", 14)
2082 .Case("t7", 15)
2083 .Case("t8", 24)
2084 .Case("t9", 25)
2085 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002086
Toma Tabacufda445c2014-09-15 15:33:01 +00002087 if (!(isABI_N32() || isABI_N64()))
2088 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002089
Daniel Sandersef638fe2014-10-03 15:37:37 +00002090 if (12 <= CC && CC <= 15) {
2091 // Name is one of t4-t7
2092 AsmToken RegTok = getLexer().peekTok();
2093 SMRange RegRange = RegTok.getLocRange();
2094
2095 StringRef FixedName = StringSwitch<StringRef>(Name)
2096 .Case("t4", "t0")
2097 .Case("t5", "t1")
2098 .Case("t6", "t2")
2099 .Case("t7", "t3")
2100 .Default("");
2101 assert(FixedName != "" && "Register name is not one of t4-t7.");
2102
2103 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2104 "Did you mean $" + FixedName + "?", RegRange);
2105 }
2106
Toma Tabacufda445c2014-09-15 15:33:01 +00002107 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2108 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2109 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2110 if (8 <= CC && CC <= 11)
2111 CC += 4;
2112
2113 if (CC == -1)
2114 CC = StringSwitch<unsigned>(Name)
2115 .Case("a4", 8)
2116 .Case("a5", 9)
2117 .Case("a6", 10)
2118 .Case("a7", 11)
2119 .Case("kt0", 26)
2120 .Case("kt1", 27)
2121 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002122
2123 return CC;
2124}
Jack Carterd0bd6422013-04-18 00:41:53 +00002125
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002126int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2127 int CC;
2128
2129 CC = StringSwitch<unsigned>(Name)
2130 .Case("hwr_cpunum", 0)
2131 .Case("hwr_synci_step", 1)
2132 .Case("hwr_cc", 2)
2133 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002134 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002135 .Default(-1);
2136
2137 return CC;
2138}
2139
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002140int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002141
Jack Cartera63b16a2012-09-07 00:23:42 +00002142 if (Name[0] == 'f') {
2143 StringRef NumString = Name.substr(1);
2144 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002145 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002146 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002147 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002148 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002149 return IntVal;
2150 }
2151 return -1;
2152}
Jack Cartera63b16a2012-09-07 00:23:42 +00002153
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002154int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2155
2156 if (Name.startswith("fcc")) {
2157 StringRef NumString = Name.substr(3);
2158 unsigned IntVal;
2159 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002160 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002161 if (IntVal > 7) // There are only 8 fcc registers.
2162 return -1;
2163 return IntVal;
2164 }
2165 return -1;
2166}
2167
2168int MipsAsmParser::matchACRegisterName(StringRef Name) {
2169
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002170 if (Name.startswith("ac")) {
2171 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002172 unsigned IntVal;
2173 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002174 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002175 if (IntVal > 3) // There are only 3 acc registers.
2176 return -1;
2177 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002178 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002179 return -1;
2180}
Jack Carterd0bd6422013-04-18 00:41:53 +00002181
Jack Carter5dc8ac92013-09-25 23:50:44 +00002182int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2183 unsigned IntVal;
2184
2185 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2186 return -1;
2187
2188 if (IntVal > 31)
2189 return -1;
2190
2191 return IntVal;
2192}
2193
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002194int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2195 int CC;
2196
2197 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002198 .Case("msair", 0)
2199 .Case("msacsr", 1)
2200 .Case("msaaccess", 2)
2201 .Case("msasave", 3)
2202 .Case("msamodify", 4)
2203 .Case("msarequest", 5)
2204 .Case("msamap", 6)
2205 .Case("msaunmap", 7)
2206 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002207
2208 return CC;
2209}
2210
Jack Carter0b744b32012-10-04 02:29:46 +00002211bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2212 if (Reg > 31)
2213 return false;
2214
Toma Tabacu3c24b042014-09-05 15:43:21 +00002215 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002216 return true;
2217}
2218
Matheus Almeida7de68e72014-06-18 14:46:05 +00002219int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002220 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002221 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002222 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002223 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002224 return AT;
2225}
Jack Carter0b744b32012-10-04 02:29:46 +00002226
Jack Carterd0bd6422013-04-18 00:41:53 +00002227unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002228 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002229}
2230
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002231unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002232 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002233 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002234}
2235
Jack Carter873c7242013-01-12 01:03:14 +00002236int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002237 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002238 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002239 return -1;
2240
Jack Carter873c7242013-01-12 01:03:14 +00002241 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002242}
2243
Toma Tabacu13964452014-09-04 13:23:44 +00002244bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002245 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002246 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002247
Jack Carter30a59822012-10-04 04:03:53 +00002248 // Check if the current operand has a custom associated parser, if so, try to
2249 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002250 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2251 if (ResTy == MatchOperand_Success)
2252 return false;
2253 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2254 // there was a match, but an error occurred, in which case, just return that
2255 // the operand parsing failed.
2256 if (ResTy == MatchOperand_ParseFail)
2257 return true;
2258
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002259 DEBUG(dbgs() << ".. Generic Parser\n");
2260
Jack Carterb4dbc172012-09-05 23:34:03 +00002261 switch (getLexer().getKind()) {
2262 default:
2263 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2264 return true;
2265 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002266 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002267 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002268
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002269 // Almost all registers have been parsed by custom parsers. There is only
2270 // one exception to this. $zero (and it's alias $0) will reach this point
2271 // for div, divu, and similar instructions because it is not an operand
2272 // to the instruction definition but an explicit register. Special case
2273 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002274 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002275 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002276
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002278 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002279 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002280 return true;
2281
Jack Carter873c7242013-01-12 01:03:14 +00002282 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002283 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002284 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002285 const MCExpr *Res =
2286 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002287
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002288 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002289 return false;
2290 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002291 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002292 case AsmToken::LParen:
2293 case AsmToken::Minus:
2294 case AsmToken::Plus:
2295 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002296 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002297 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002298 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002299 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002300 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002301 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002302 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002303 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002304 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002305 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002306 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002307 return true;
2308
Jack Carter873c7242013-01-12 01:03:14 +00002309 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2310
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002311 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002312 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002313 } // case AsmToken::Percent
2314 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002315 return true;
2316}
2317
Vladimir Medic4c299852013-11-06 11:27:05 +00002318const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002319 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002320 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002321 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002322 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002323 // It's a constant, evaluate reloc value.
2324 int16_t Val;
2325 switch (getVariantKind(RelocStr)) {
2326 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2327 // Get the 1st 16-bits.
2328 Val = MCE->getValue() & 0xffff;
2329 break;
2330 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2331 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2332 // 16 bits being negative.
2333 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2334 break;
2335 case MCSymbolRefExpr::VK_Mips_HIGHER:
2336 // Get the 3rd 16-bits.
2337 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2338 break;
2339 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2340 // Get the 4th 16-bits.
2341 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2342 break;
2343 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002344 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002345 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002346 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002347 }
2348
Jack Carterb5cf5902013-04-17 00:18:04 +00002349 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002350 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002351 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002352 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002353 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002354 return Res;
2355 }
2356
2357 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002358 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2359
Sasa Stankovic06c47802014-04-03 10:37:45 +00002360 // Try to create target expression.
2361 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2362 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002363
Jack Carterd0bd6422013-04-18 00:41:53 +00002364 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2365 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002366 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2367 return Res;
2368 }
2369
2370 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002371 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2372 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2373 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002374 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002375 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002376 return Expr;
2377}
2378
2379bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2380
2381 switch (Expr->getKind()) {
2382 case MCExpr::Constant:
2383 return true;
2384 case MCExpr::SymbolRef:
2385 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2386 case MCExpr::Binary:
2387 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2388 if (!isEvaluated(BE->getLHS()))
2389 return false;
2390 return isEvaluated(BE->getRHS());
2391 }
2392 case MCExpr::Unary:
2393 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002394 case MCExpr::Target:
2395 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002396 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002397 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002398}
Jack Carterd0bd6422013-04-18 00:41:53 +00002399
Jack Carterb5cf5902013-04-17 00:18:04 +00002400bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002401 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002402 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002403 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002404 if (Tok.isNot(AsmToken::Identifier))
2405 return true;
2406
2407 std::string Str = Tok.getIdentifier().str();
2408
Jack Carterd0bd6422013-04-18 00:41:53 +00002409 Parser.Lex(); // Eat the identifier.
2410 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002411 const MCExpr *IdVal;
2412 SMLoc EndLoc;
2413
2414 if (getLexer().getKind() == AsmToken::LParen) {
2415 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002416 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002417 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002418 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002419 const AsmToken &nextTok = Parser.getTok();
2420 if (nextTok.isNot(AsmToken::Identifier))
2421 return true;
2422 Str += "(%";
2423 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002424 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002425 if (getLexer().getKind() != AsmToken::LParen)
2426 return true;
2427 } else
2428 break;
2429 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002431 return true;
2432
2433 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002434 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002435
2436 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002437 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002438
Jack Carterd0bd6422013-04-18 00:41:53 +00002439 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002440 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002441}
2442
Jack Carterb4dbc172012-09-05 23:34:03 +00002443bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2444 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002445 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002446 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447 if (ResTy == MatchOperand_Success) {
2448 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002449 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002450 StartLoc = Operand.getStartLoc();
2451 EndLoc = Operand.getEndLoc();
2452
2453 // AFAIK, we only support numeric registers and named GPR's in CFI
2454 // directives.
2455 // Don't worry about eating tokens before failing. Using an unrecognised
2456 // register is a parse error.
2457 if (Operand.isGPRAsmReg()) {
2458 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002459 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002460 }
2461
2462 return (RegNo == (unsigned)-1);
2463 }
2464
2465 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002466 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002467}
2468
Jack Carterb5cf5902013-04-17 00:18:04 +00002469bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002470 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002471 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002472 bool Result = true;
2473
2474 while (getLexer().getKind() == AsmToken::LParen)
2475 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002476
Jack Carterd0bd6422013-04-18 00:41:53 +00002477 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002478 default:
2479 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002480 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002481 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002482 case AsmToken::Integer:
2483 case AsmToken::Minus:
2484 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002485 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002486 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002487 else
2488 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002490 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002491 break;
Jack Carter873c7242013-01-12 01:03:14 +00002492 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002493 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002494 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002495 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002496}
2497
David Blaikie960ea3f2014-06-08 16:18:35 +00002498MipsAsmParser::OperandMatchResultTy
2499MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002500 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002501 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002502 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002503 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002504 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002505 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002506 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002507 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002508
Jack Carterb5cf5902013-04-17 00:18:04 +00002509 if (getLexer().getKind() == AsmToken::LParen) {
2510 Parser.Lex();
2511 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002512 }
2513
Jack Carterb5cf5902013-04-17 00:18:04 +00002514 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002515 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002516 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002517
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002519 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002520 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2521 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002522 SMLoc E =
2523 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002524 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002525 return MatchOperand_Success;
2526 }
2527 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002528 SMLoc E =
2529 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002530
Jack Carterd0bd6422013-04-18 00:41:53 +00002531 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002532 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002533 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002534 S, E, *this);
2535 Operands.push_back(
2536 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002537 return MatchOperand_Success;
2538 }
2539 Error(Parser.getTok().getLoc(), "'(' expected");
2540 return MatchOperand_ParseFail;
2541 }
2542
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002544 }
2545
Toma Tabacu13964452014-09-04 13:23:44 +00002546 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002547 if (Res != MatchOperand_Success)
2548 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002549
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002550 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002551 Error(Parser.getTok().getLoc(), "')' expected");
2552 return MatchOperand_ParseFail;
2553 }
2554
Jack Carter873c7242013-01-12 01:03:14 +00002555 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2556
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002558
Craig Topper062a2ba2014-04-25 05:30:21 +00002559 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002560 IdVal = MCConstantExpr::Create(0, getContext());
2561
Jack Carterd0bd6422013-04-18 00:41:53 +00002562 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002563 std::unique_ptr<MipsOperand> op(
2564 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002566 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002567 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002569 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2570 int64_t Imm;
2571 if (IdVal->EvaluateAsAbsolute(Imm))
2572 IdVal = MCConstantExpr::Create(Imm, getContext());
2573 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2574 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2575 getContext());
2576 }
2577
David Blaikie960ea3f2014-06-08 16:18:35 +00002578 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002579 return MatchOperand_Success;
2580}
2581
David Blaikie960ea3f2014-06-08 16:18:35 +00002582bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002583 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002584 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2585 if (Sym) {
2586 SMLoc S = Parser.getTok().getLoc();
2587 const MCExpr *Expr;
2588 if (Sym->isVariable())
2589 Expr = Sym->getVariableValue();
2590 else
2591 return false;
2592 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002593 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002594 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002595 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002596 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002597 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002598 if (ResTy == MatchOperand_Success) {
2599 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002600 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002601 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002602 llvm_unreachable("Should never ParseFail");
2603 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002604 }
2605 } else if (Expr->getKind() == MCExpr::Constant) {
2606 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002607 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002608 Operands.push_back(
2609 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002610 return true;
2611 }
2612 }
2613 return false;
2614}
Jack Carterd0bd6422013-04-18 00:41:53 +00002615
Jack Carter873c7242013-01-12 01:03:14 +00002616MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002617MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002618 StringRef Identifier,
2619 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002620 int Index = matchCPURegisterName(Identifier);
2621 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002622 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002623 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2624 return MatchOperand_Success;
2625 }
2626
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002627 Index = matchHWRegsRegisterName(Identifier);
2628 if (Index != -1) {
2629 Operands.push_back(MipsOperand::createHWRegsReg(
2630 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2631 return MatchOperand_Success;
2632 }
2633
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002634 Index = matchFPURegisterName(Identifier);
2635 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002636 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002637 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2638 return MatchOperand_Success;
2639 }
2640
2641 Index = matchFCCRegisterName(Identifier);
2642 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002643 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002644 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2645 return MatchOperand_Success;
2646 }
2647
2648 Index = matchACRegisterName(Identifier);
2649 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002650 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002651 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2652 return MatchOperand_Success;
2653 }
2654
2655 Index = matchMSA128RegisterName(Identifier);
2656 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002657 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002658 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2659 return MatchOperand_Success;
2660 }
2661
2662 Index = matchMSA128CtrlRegisterName(Identifier);
2663 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002664 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002665 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2666 return MatchOperand_Success;
2667 }
2668
2669 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002670}
2671
2672MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002673MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002674 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002675 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002676
2677 if (Token.is(AsmToken::Identifier)) {
2678 DEBUG(dbgs() << ".. identifier\n");
2679 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002680 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002681 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002682 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002683 } else if (Token.is(AsmToken::Integer)) {
2684 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002685 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002686 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2687 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002688 return MatchOperand_Success;
2689 }
2690
2691 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2692
2693 return MatchOperand_NoMatch;
2694}
2695
David Blaikie960ea3f2014-06-08 16:18:35 +00002696MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002697MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002698 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002699 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002700
2701 auto Token = Parser.getTok();
2702
2703 SMLoc S = Token.getLoc();
2704
2705 if (Token.isNot(AsmToken::Dollar)) {
2706 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2707 if (Token.is(AsmToken::Identifier)) {
2708 if (searchSymbolAlias(Operands))
2709 return MatchOperand_Success;
2710 }
2711 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2712 return MatchOperand_NoMatch;
2713 }
2714 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002715
Toma Tabacu13964452014-09-04 13:23:44 +00002716 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002717 if (ResTy == MatchOperand_Success) {
2718 Parser.Lex(); // $
2719 Parser.Lex(); // identifier
2720 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002721 return ResTy;
2722}
2723
2724MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002725MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002726 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002727 switch (getLexer().getKind()) {
2728 default:
2729 return MatchOperand_NoMatch;
2730 case AsmToken::LParen:
2731 case AsmToken::Minus:
2732 case AsmToken::Plus:
2733 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002734 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002735 case AsmToken::String:
2736 break;
2737 }
2738
2739 const MCExpr *IdVal;
2740 SMLoc S = Parser.getTok().getLoc();
2741 if (getParser().parseExpression(IdVal))
2742 return MatchOperand_ParseFail;
2743
2744 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2745 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2746 return MatchOperand_Success;
2747}
2748
David Blaikie960ea3f2014-06-08 16:18:35 +00002749MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002750MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002751 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002752 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002753
2754 SMLoc S = getLexer().getLoc();
2755
2756 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002757 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002758 if (ResTy != MatchOperand_NoMatch)
2759 return ResTy;
2760
Daniel Sanders315386c2014-04-01 10:40:14 +00002761 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002762 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002763 if (ResTy != MatchOperand_NoMatch)
2764 return ResTy;
2765
Daniel Sandersffd84362014-04-01 10:41:48 +00002766 const MCExpr *Expr = nullptr;
2767 if (Parser.parseExpression(Expr)) {
2768 // We have no way of knowing if a symbol was consumed so we must ParseFail
2769 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002770 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002771 Operands.push_back(
2772 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002773 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002774}
2775
Vladimir Medic2b953d02013-10-01 09:48:56 +00002776MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002777MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002778 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002779 const MCExpr *IdVal;
2780 // If the first token is '$' we may have register operand.
2781 if (Parser.getTok().is(AsmToken::Dollar))
2782 return MatchOperand_NoMatch;
2783 SMLoc S = Parser.getTok().getLoc();
2784 if (getParser().parseExpression(IdVal))
2785 return MatchOperand_ParseFail;
2786 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002787 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002788 int64_t Val = MCE->getValue();
2789 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2790 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002791 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002792 return MatchOperand_Success;
2793}
2794
Matheus Almeida779c5932013-11-18 12:32:49 +00002795MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002796MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002797 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002798 switch (getLexer().getKind()) {
2799 default:
2800 return MatchOperand_NoMatch;
2801 case AsmToken::LParen:
2802 case AsmToken::Plus:
2803 case AsmToken::Minus:
2804 case AsmToken::Integer:
2805 break;
2806 }
2807
2808 const MCExpr *Expr;
2809 SMLoc S = Parser.getTok().getLoc();
2810
2811 if (getParser().parseExpression(Expr))
2812 return MatchOperand_ParseFail;
2813
2814 int64_t Val;
2815 if (!Expr->EvaluateAsAbsolute(Val)) {
2816 Error(S, "expected immediate value");
2817 return MatchOperand_ParseFail;
2818 }
2819
2820 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2821 // and because the CPU always adds one to the immediate field, the allowed
2822 // range becomes 1..4. We'll only check the range here and will deal
2823 // with the addition/subtraction when actually decoding/encoding
2824 // the instruction.
2825 if (Val < 1 || Val > 4) {
2826 Error(S, "immediate not in range (1..4)");
2827 return MatchOperand_ParseFail;
2828 }
2829
Jack Carter3b2c96e2014-01-22 23:31:38 +00002830 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002831 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002832 return MatchOperand_Success;
2833}
2834
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002835MipsAsmParser::OperandMatchResultTy
2836MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2837 MCAsmParser &Parser = getParser();
2838 SmallVector<unsigned, 10> Regs;
2839 unsigned RegNo;
2840 unsigned PrevReg = Mips::NoRegister;
2841 bool RegRange = false;
2842 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2843
2844 if (Parser.getTok().isNot(AsmToken::Dollar))
2845 return MatchOperand_ParseFail;
2846
2847 SMLoc S = Parser.getTok().getLoc();
2848 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2849 SMLoc E = getLexer().getLoc();
2850 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2851 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2852 if (RegRange) {
2853 // Remove last register operand because registers from register range
2854 // should be inserted first.
2855 if (RegNo == Mips::RA) {
2856 Regs.push_back(RegNo);
2857 } else {
2858 unsigned TmpReg = PrevReg + 1;
2859 while (TmpReg <= RegNo) {
2860 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2861 Error(E, "invalid register operand");
2862 return MatchOperand_ParseFail;
2863 }
2864
2865 PrevReg = TmpReg;
2866 Regs.push_back(TmpReg++);
2867 }
2868 }
2869
2870 RegRange = false;
2871 } else {
2872 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2873 (RegNo != Mips::RA)) {
2874 Error(E, "$16 or $31 expected");
2875 return MatchOperand_ParseFail;
2876 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2877 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2878 Error(E, "invalid register operand");
2879 return MatchOperand_ParseFail;
2880 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2881 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2882 Error(E, "consecutive register numbers expected");
2883 return MatchOperand_ParseFail;
2884 }
2885
2886 Regs.push_back(RegNo);
2887 }
2888
2889 if (Parser.getTok().is(AsmToken::Minus))
2890 RegRange = true;
2891
2892 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2893 !Parser.getTok().isNot(AsmToken::Comma)) {
2894 Error(E, "',' or '-' expected");
2895 return MatchOperand_ParseFail;
2896 }
2897
2898 Lex(); // Consume comma or minus
2899 if (Parser.getTok().isNot(AsmToken::Dollar))
2900 break;
2901
2902 PrevReg = RegNo;
2903 }
2904
2905 SMLoc E = Parser.getTok().getLoc();
2906 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2907 parseMemOperand(Operands);
2908 return MatchOperand_Success;
2909}
2910
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002911MipsAsmParser::OperandMatchResultTy
2912MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2913 MCAsmParser &Parser = getParser();
2914
2915 SMLoc S = Parser.getTok().getLoc();
2916 if (parseAnyRegister(Operands) != MatchOperand_Success)
2917 return MatchOperand_ParseFail;
2918
2919 SMLoc E = Parser.getTok().getLoc();
2920 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2921 unsigned Reg = Op.getGPR32Reg();
2922 Operands.pop_back();
2923 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2924 return MatchOperand_Success;
2925}
2926
Jack Carterdc1e35d2012-09-06 20:00:02 +00002927MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2928
Vladimir Medic4c299852013-11-06 11:27:05 +00002929 MCSymbolRefExpr::VariantKind VK =
2930 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2931 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2932 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2933 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2934 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2935 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2936 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2937 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2938 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2939 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2940 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2941 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2942 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2943 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2944 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2945 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2946 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2947 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002948 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2949 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2950 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2951 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2952 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2953 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002954 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2955 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002956 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002957
Matheus Almeida2852af82014-04-22 10:15:54 +00002958 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002959
Jack Carterdc1e35d2012-09-06 20:00:02 +00002960 return VK;
2961}
Jack Cartera63b16a2012-09-07 00:23:42 +00002962
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002963/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2964/// either this.
2965/// ::= '(', register, ')'
2966/// handle it before we iterate so we don't get tripped up by the lack of
2967/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002968bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002969 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002970 if (getLexer().is(AsmToken::LParen)) {
2971 Operands.push_back(
2972 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2973 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002974 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002975 SMLoc Loc = getLexer().getLoc();
2976 Parser.eatToEndOfStatement();
2977 return Error(Loc, "unexpected token in argument list");
2978 }
2979 if (Parser.getTok().isNot(AsmToken::RParen)) {
2980 SMLoc Loc = getLexer().getLoc();
2981 Parser.eatToEndOfStatement();
2982 return Error(Loc, "unexpected token, expected ')'");
2983 }
2984 Operands.push_back(
2985 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2986 Parser.Lex();
2987 }
2988 return false;
2989}
2990
2991/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2992/// either one of these.
2993/// ::= '[', register, ']'
2994/// ::= '[', integer, ']'
2995/// handle it before we iterate so we don't get tripped up by the lack of
2996/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002997bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002998 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002999 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003000 if (getLexer().is(AsmToken::LBrac)) {
3001 Operands.push_back(
3002 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3003 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003004 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003005 SMLoc Loc = getLexer().getLoc();
3006 Parser.eatToEndOfStatement();
3007 return Error(Loc, "unexpected token in argument list");
3008 }
3009 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3010 SMLoc Loc = getLexer().getLoc();
3011 Parser.eatToEndOfStatement();
3012 return Error(Loc, "unexpected token, expected ']'");
3013 }
3014 Operands.push_back(
3015 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3016 Parser.Lex();
3017 }
3018 return false;
3019}
3020
David Blaikie960ea3f2014-06-08 16:18:35 +00003021bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3022 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003023 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003024 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003025
3026 // We have reached first instruction, module directive are now forbidden.
3027 getTargetStreamer().forbidModuleDirective();
3028
Vladimir Medic74593e62013-07-17 15:00:42 +00003029 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003030 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003031 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003032 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003033 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003034 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003035 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003036
3037 // Read the remaining operands.
3038 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3039 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003040 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003041 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003042 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003043 return Error(Loc, "unexpected token in argument list");
3044 }
Toma Tabacu13964452014-09-04 13:23:44 +00003045 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003046 return true;
3047 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003048
Jack Carterd0bd6422013-04-18 00:41:53 +00003049 while (getLexer().is(AsmToken::Comma)) {
3050 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003051 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003052 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003053 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003054 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003055 return Error(Loc, "unexpected token in argument list");
3056 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003057 // Parse bracket and parenthesis suffixes before we iterate
3058 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003059 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003060 return true;
3061 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003062 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003063 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003064 }
3065 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003066 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3067 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003068 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003069 return Error(Loc, "unexpected token in argument list");
3070 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003071 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003072 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003073}
3074
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003075bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003076 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003077 SMLoc Loc = getLexer().getLoc();
3078 Parser.eatToEndOfStatement();
3079 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003080}
3081
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003082bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003083 return Error(Loc, ErrorMsg);
3084}
3085
Jack Carter0b744b32012-10-04 02:29:46 +00003086bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003087 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003088 // Line should look like: ".set noat".
3089 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003090 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00003091 // eat noat
3092 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003093 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003095 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003096 return false;
3097 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003098 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003099 return false;
3100}
Jack Carterd0bd6422013-04-18 00:41:53 +00003101
Jack Carter0b744b32012-10-04 02:29:46 +00003102bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003103 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003104 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00003105 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00003106 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00003107 getParser().Lex();
3108 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003109 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00003110 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003111 return false;
3112 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003113 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00003114 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003115 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003116 return false;
3117 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003118 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00003119 const AsmToken &Reg = Parser.getTok();
3120 if (Reg.is(AsmToken::Identifier)) {
3121 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3122 } else if (Reg.is(AsmToken::Integer)) {
3123 AtRegNo = Reg.getIntVal();
3124 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003125 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003126 return false;
3127 }
Jack Carter1ac53222013-02-20 23:11:17 +00003128
Daniel Sanders71a89d922014-03-25 13:01:06 +00003129 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00003130 reportParseError("unexpected token in statement");
3131 return false;
3132 }
3133
Toma Tabacu9db22db2014-09-09 10:15:38 +00003134 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003135 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00003136 return false;
3137 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003138 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00003139
3140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003141 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003142 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003143 }
3144 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003145 return false;
3146 } else {
3147 reportParseError("unexpected token in statement");
3148 return false;
3149 }
3150}
3151
3152bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003153 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003154 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003155 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003156 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003157 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003158 return false;
3159 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003160 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003161 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003162 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003163 return false;
3164}
3165
3166bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003167 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003168 Parser.Lex();
3169 // If this is not the end of the statement, report an error.
3170 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003171 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003172 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003173 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003174 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003175 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003176 Parser.Lex(); // Consume the EndOfStatement.
3177 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003178}
3179
3180bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003181 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003182 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003183 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003184 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003185 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003186 return false;
3187 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003188 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003189 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003190 return false;
3191}
3192
3193bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003194 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003195 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003196 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003197 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003198 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003199 return false;
3200 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003201 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003202 reportParseError("`noreorder' must be set before `nomacro'");
3203 return false;
3204 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003205 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003206 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003207 return false;
3208}
Jack Carterd76b2372013-03-21 21:44:16 +00003209
Daniel Sanders44934432014-08-07 12:03:36 +00003210bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003211 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003212 Parser.Lex();
3213
3214 // If this is not the end of the statement, report an error.
3215 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003216 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003217
3218 setFeatureBits(Mips::FeatureMSA, "msa");
3219 getTargetStreamer().emitDirectiveSetMsa();
3220 return false;
3221}
3222
3223bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003224 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003225 Parser.Lex();
3226
3227 // If this is not the end of the statement, report an error.
3228 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003229 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003230
3231 clearFeatureBits(Mips::FeatureMSA, "msa");
3232 getTargetStreamer().emitDirectiveSetNoMsa();
3233 return false;
3234}
3235
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003236bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003237 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003238 Parser.Lex(); // Eat "nodsp".
3239
3240 // If this is not the end of the statement, report an error.
3241 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3242 reportParseError("unexpected token, expected end of statement");
3243 return false;
3244 }
3245
3246 clearFeatureBits(Mips::FeatureDSP, "dsp");
3247 getTargetStreamer().emitDirectiveSetNoDsp();
3248 return false;
3249}
3250
Toma Tabacucc2502d2014-11-04 17:18:07 +00003251bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003252 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003253 Parser.Lex(); // Eat "mips16".
3254
Jack Carter39536722014-01-22 23:08:42 +00003255 // If this is not the end of the statement, report an error.
3256 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003257 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003258 return false;
3259 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003260
3261 setFeatureBits(Mips::FeatureMips16, "mips16");
3262 getTargetStreamer().emitDirectiveSetMips16();
3263 Parser.Lex(); // Consume the EndOfStatement.
3264 return false;
3265}
3266
3267bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003268 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003269 Parser.Lex(); // Eat "nomips16".
3270
3271 // If this is not the end of the statement, report an error.
3272 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3273 reportParseError("unexpected token, expected end of statement");
3274 return false;
3275 }
3276
3277 clearFeatureBits(Mips::FeatureMips16, "mips16");
3278 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003279 Parser.Lex(); // Consume the EndOfStatement.
3280 return false;
3281}
3282
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003283bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003284 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003285 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003286 // Line can be: .set fp=32
3287 // .set fp=xx
3288 // .set fp=64
3289 Parser.Lex(); // Eat fp token
3290 AsmToken Tok = Parser.getTok();
3291 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003292 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003293 return false;
3294 }
3295 Parser.Lex(); // Eat '=' token.
3296 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003297
3298 if (!parseFpABIValue(FpAbiVal, ".set"))
3299 return false;
3300
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003301 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003302 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003303 return false;
3304 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003305 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003306 Parser.Lex(); // Consume the EndOfStatement.
3307 return false;
3308}
3309
Toma Tabacu9db22db2014-09-09 10:15:38 +00003310bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003311 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003312 SMLoc Loc = getLexer().getLoc();
3313
3314 Parser.Lex();
3315 if (getLexer().isNot(AsmToken::EndOfStatement))
3316 return reportParseError("unexpected token, expected end of statement");
3317
3318 // Always keep an element on the options "stack" to prevent the user
3319 // from changing the initial options. This is how we remember them.
3320 if (AssemblerOptions.size() == 2)
3321 return reportParseError(Loc, ".set pop with no .set push");
3322
3323 AssemblerOptions.pop_back();
3324 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3325
3326 getTargetStreamer().emitDirectiveSetPop();
3327 return false;
3328}
3329
3330bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003331 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003332 Parser.Lex();
3333 if (getLexer().isNot(AsmToken::EndOfStatement))
3334 return reportParseError("unexpected token, expected end of statement");
3335
3336 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003337 AssemblerOptions.push_back(
3338 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003339
3340 getTargetStreamer().emitDirectiveSetPush();
3341 return false;
3342}
3343
Jack Carterd76b2372013-03-21 21:44:16 +00003344bool MipsAsmParser::parseSetAssignment() {
3345 StringRef Name;
3346 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003347 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003348
3349 if (Parser.parseIdentifier(Name))
3350 reportParseError("expected identifier after .set");
3351
3352 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003353 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003354 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003355
Jack Carter3b2c96e2014-01-22 23:31:38 +00003356 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003357 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003358
Jack Carterd0bd6422013-04-18 00:41:53 +00003359 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003360 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003361 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003362 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003363 Sym = getContext().GetOrCreateSymbol(Name);
3364 Sym->setVariableValue(Value);
3365
3366 return false;
3367}
Jack Carterd0bd6422013-04-18 00:41:53 +00003368
Toma Tabacu26647792014-09-09 12:52:14 +00003369bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003370 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003371 Parser.Lex();
3372 if (getLexer().isNot(AsmToken::EndOfStatement))
3373 return reportParseError("unexpected token, expected end of statement");
3374
3375 // Reset assembler options to their initial values.
3376 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3377 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3378
3379 getTargetStreamer().emitDirectiveSetMips0();
3380 return false;
3381}
3382
Toma Tabacu85618b32014-08-19 14:22:52 +00003383bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003384 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003385 Parser.Lex();
3386 if (getLexer().isNot(AsmToken::Equal))
3387 return reportParseError("unexpected token, expected equals sign");
3388
3389 Parser.Lex();
3390 StringRef Arch;
3391 if (Parser.parseIdentifier(Arch))
3392 return reportParseError("expected arch identifier");
3393
3394 StringRef ArchFeatureName =
3395 StringSwitch<StringRef>(Arch)
3396 .Case("mips1", "mips1")
3397 .Case("mips2", "mips2")
3398 .Case("mips3", "mips3")
3399 .Case("mips4", "mips4")
3400 .Case("mips5", "mips5")
3401 .Case("mips32", "mips32")
3402 .Case("mips32r2", "mips32r2")
3403 .Case("mips32r6", "mips32r6")
3404 .Case("mips64", "mips64")
3405 .Case("mips64r2", "mips64r2")
3406 .Case("mips64r6", "mips64r6")
3407 .Case("cnmips", "cnmips")
3408 .Case("r4000", "mips3") // This is an implementation of Mips3.
3409 .Default("");
3410
3411 if (ArchFeatureName.empty())
3412 return reportParseError("unsupported architecture");
3413
3414 selectArch(ArchFeatureName);
3415 getTargetStreamer().emitDirectiveSetArch(Arch);
3416 return false;
3417}
3418
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003419bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003420 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003421 Parser.Lex();
3422 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003423 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003424
Matheus Almeida2852af82014-04-22 10:15:54 +00003425 switch (Feature) {
3426 default:
3427 llvm_unreachable("Unimplemented feature");
3428 case Mips::FeatureDSP:
3429 setFeatureBits(Mips::FeatureDSP, "dsp");
3430 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003431 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003432 case Mips::FeatureMicroMips:
3433 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003434 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003435 case Mips::FeatureMips1:
3436 selectArch("mips1");
3437 getTargetStreamer().emitDirectiveSetMips1();
3438 break;
3439 case Mips::FeatureMips2:
3440 selectArch("mips2");
3441 getTargetStreamer().emitDirectiveSetMips2();
3442 break;
3443 case Mips::FeatureMips3:
3444 selectArch("mips3");
3445 getTargetStreamer().emitDirectiveSetMips3();
3446 break;
3447 case Mips::FeatureMips4:
3448 selectArch("mips4");
3449 getTargetStreamer().emitDirectiveSetMips4();
3450 break;
3451 case Mips::FeatureMips5:
3452 selectArch("mips5");
3453 getTargetStreamer().emitDirectiveSetMips5();
3454 break;
3455 case Mips::FeatureMips32:
3456 selectArch("mips32");
3457 getTargetStreamer().emitDirectiveSetMips32();
3458 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003459 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003460 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003461 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003462 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003463 case Mips::FeatureMips32r6:
3464 selectArch("mips32r6");
3465 getTargetStreamer().emitDirectiveSetMips32R6();
3466 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003467 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003468 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003469 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003470 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003471 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003472 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003473 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003474 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003475 case Mips::FeatureMips64r6:
3476 selectArch("mips64r6");
3477 getTargetStreamer().emitDirectiveSetMips64R6();
3478 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003479 }
3480 return false;
3481}
3482
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003483bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003484 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003485 if (getLexer().isNot(AsmToken::Comma)) {
3486 SMLoc Loc = getLexer().getLoc();
3487 Parser.eatToEndOfStatement();
3488 return Error(Loc, ErrorStr);
3489 }
3490
Matheus Almeida2852af82014-04-22 10:15:54 +00003491 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003492 return true;
3493}
3494
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003495bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003496 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003497 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003498
Toma Tabacudde4c462014-11-06 10:02:45 +00003499 if (inMips16Mode()) {
3500 reportParseError(".cpload is not supported in Mips16 mode");
3501 return false;
3502 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003503
David Blaikie960ea3f2014-06-08 16:18:35 +00003504 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003505 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003506 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3507 reportParseError("expected register containing function address");
3508 return false;
3509 }
3510
David Blaikie960ea3f2014-06-08 16:18:35 +00003511 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3512 if (!RegOpnd.isGPRAsmReg()) {
3513 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003514 return false;
3515 }
3516
Toma Tabacudde4c462014-11-06 10:02:45 +00003517 // If this is not the end of the statement, report an error.
3518 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3519 reportParseError("unexpected token, expected end of statement");
3520 return false;
3521 }
3522
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003523 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003524 return false;
3525}
3526
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003527bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003528 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003529 unsigned FuncReg;
3530 unsigned Save;
3531 bool SaveIsReg = true;
3532
Matheus Almeida7e815762014-06-18 13:08:59 +00003533 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003534 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003535 if (ResTy == MatchOperand_NoMatch) {
3536 reportParseError("expected register containing function address");
3537 Parser.eatToEndOfStatement();
3538 return false;
3539 }
3540
3541 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3542 if (!FuncRegOpnd.isGPRAsmReg()) {
3543 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3544 Parser.eatToEndOfStatement();
3545 return false;
3546 }
3547
3548 FuncReg = FuncRegOpnd.getGPR32Reg();
3549 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003550
Toma Tabacu65f10572014-09-16 15:00:52 +00003551 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003552 return true;
3553
Toma Tabacu13964452014-09-04 13:23:44 +00003554 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003555 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003556 const AsmToken &Tok = Parser.getTok();
3557 if (Tok.is(AsmToken::Integer)) {
3558 Save = Tok.getIntVal();
3559 SaveIsReg = false;
3560 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003561 } else {
3562 reportParseError("expected save register or stack offset");
3563 Parser.eatToEndOfStatement();
3564 return false;
3565 }
3566 } else {
3567 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3568 if (!SaveOpnd.isGPRAsmReg()) {
3569 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3570 Parser.eatToEndOfStatement();
3571 return false;
3572 }
3573 Save = SaveOpnd.getGPR32Reg();
3574 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003575
Toma Tabacu65f10572014-09-16 15:00:52 +00003576 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003577 return true;
3578
3579 StringRef Name;
3580 if (Parser.parseIdentifier(Name))
3581 reportParseError("expected identifier");
3582 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003583
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003584 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003585 return false;
3586}
3587
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003588bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003589 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3591 const AsmToken &Tok = Parser.getTok();
3592
3593 if (Tok.getString() == "2008") {
3594 Parser.Lex();
3595 getTargetStreamer().emitDirectiveNaN2008();
3596 return false;
3597 } else if (Tok.getString() == "legacy") {
3598 Parser.Lex();
3599 getTargetStreamer().emitDirectiveNaNLegacy();
3600 return false;
3601 }
3602 }
3603 // If we don't recognize the option passed to the .nan
3604 // directive (e.g. no option or unknown option), emit an error.
3605 reportParseError("invalid option in .nan directive");
3606 return false;
3607}
3608
Jack Carter0b744b32012-10-04 02:29:46 +00003609bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003610 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003611 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003612 const AsmToken &Tok = Parser.getTok();
3613
3614 if (Tok.getString() == "noat") {
3615 return parseSetNoAtDirective();
3616 } else if (Tok.getString() == "at") {
3617 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003618 } else if (Tok.getString() == "arch") {
3619 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003620 } else if (Tok.getString() == "fp") {
3621 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003622 } else if (Tok.getString() == "pop") {
3623 return parseSetPopDirective();
3624 } else if (Tok.getString() == "push") {
3625 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003626 } else if (Tok.getString() == "reorder") {
3627 return parseSetReorderDirective();
3628 } else if (Tok.getString() == "noreorder") {
3629 return parseSetNoReorderDirective();
3630 } else if (Tok.getString() == "macro") {
3631 return parseSetMacroDirective();
3632 } else if (Tok.getString() == "nomacro") {
3633 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003634 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003635 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003636 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003637 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003638 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003639 getTargetStreamer().emitDirectiveSetNoMicroMips();
3640 Parser.eatToEndOfStatement();
3641 return false;
3642 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003643 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003644 } else if (Tok.getString() == "mips0") {
3645 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003646 } else if (Tok.getString() == "mips1") {
3647 return parseSetFeature(Mips::FeatureMips1);
3648 } else if (Tok.getString() == "mips2") {
3649 return parseSetFeature(Mips::FeatureMips2);
3650 } else if (Tok.getString() == "mips3") {
3651 return parseSetFeature(Mips::FeatureMips3);
3652 } else if (Tok.getString() == "mips4") {
3653 return parseSetFeature(Mips::FeatureMips4);
3654 } else if (Tok.getString() == "mips5") {
3655 return parseSetFeature(Mips::FeatureMips5);
3656 } else if (Tok.getString() == "mips32") {
3657 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003658 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003659 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003660 } else if (Tok.getString() == "mips32r6") {
3661 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003662 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003663 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003664 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003665 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003666 } else if (Tok.getString() == "mips64r6") {
3667 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003668 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003669 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003670 } else if (Tok.getString() == "nodsp") {
3671 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003672 } else if (Tok.getString() == "msa") {
3673 return parseSetMsaDirective();
3674 } else if (Tok.getString() == "nomsa") {
3675 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003676 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003677 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003678 parseSetAssignment();
3679 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003680 }
Jack Carter07c818d2013-01-25 01:31:34 +00003681
Jack Carter0b744b32012-10-04 02:29:46 +00003682 return true;
3683}
3684
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003685/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003686/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003687bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003688 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3690 for (;;) {
3691 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003692 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003693 return true;
3694
3695 getParser().getStreamer().EmitValue(Value, Size);
3696
3697 if (getLexer().is(AsmToken::EndOfStatement))
3698 break;
3699
Jack Carter07c818d2013-01-25 01:31:34 +00003700 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003701 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003702 Parser.Lex();
3703 }
3704 }
3705
3706 Parser.Lex();
3707 return false;
3708}
3709
Vladimir Medic4c299852013-11-06 11:27:05 +00003710/// parseDirectiveGpWord
3711/// ::= .gpword local_sym
3712bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003713 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003714 const MCExpr *Value;
3715 // EmitGPRel32Value requires an expression, so we are using base class
3716 // method to evaluate the expression.
3717 if (getParser().parseExpression(Value))
3718 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003719 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003720
Vladimir Medice10c1122013-11-13 13:18:04 +00003721 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003722 return Error(getLexer().getLoc(),
3723 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003724 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003725 return false;
3726}
3727
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003728/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003729/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003730bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003731 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003732 const MCExpr *Value;
3733 // EmitGPRel64Value requires an expression, so we are using base class
3734 // method to evaluate the expression.
3735 if (getParser().parseExpression(Value))
3736 return true;
3737 getParser().getStreamer().EmitGPRel64Value(Value);
3738
3739 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003740 return Error(getLexer().getLoc(),
3741 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003742 Parser.Lex(); // Eat EndOfStatement token.
3743 return false;
3744}
3745
Jack Carter0cd3c192014-01-06 23:27:31 +00003746bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003747 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003748 // Get the option token.
3749 AsmToken Tok = Parser.getTok();
3750 // At the moment only identifiers are supported.
3751 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003752 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003753 Parser.eatToEndOfStatement();
3754 return false;
3755 }
3756
3757 StringRef Option = Tok.getIdentifier();
3758
3759 if (Option == "pic0") {
3760 getTargetStreamer().emitDirectiveOptionPic0();
3761 Parser.Lex();
3762 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3763 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003764 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003765 Parser.eatToEndOfStatement();
3766 }
3767 return false;
3768 }
3769
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003770 if (Option == "pic2") {
3771 getTargetStreamer().emitDirectiveOptionPic2();
3772 Parser.Lex();
3773 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3774 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003775 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003776 Parser.eatToEndOfStatement();
3777 }
3778 return false;
3779 }
3780
Jack Carter0cd3c192014-01-06 23:27:31 +00003781 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003782 Warning(Parser.getTok().getLoc(),
3783 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003784 Parser.eatToEndOfStatement();
3785 return false;
3786}
3787
Daniel Sanders7e527422014-07-10 13:38:23 +00003788/// parseDirectiveModule
3789/// ::= .module oddspreg
3790/// ::= .module nooddspreg
3791/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003792bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003793 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003794 MCAsmLexer &Lexer = getLexer();
3795 SMLoc L = Lexer.getLoc();
3796
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003797 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003798 // TODO : get a better message.
3799 reportParseError(".module directive must appear before any code");
3800 return false;
3801 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003802
Toma Tabacuc405c822015-01-23 10:40:19 +00003803 StringRef Option;
3804 if (Parser.parseIdentifier(Option)) {
3805 reportParseError("expected .module option identifier");
3806 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003807 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003808
Toma Tabacuc405c822015-01-23 10:40:19 +00003809 if (Option == "oddspreg") {
3810 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3811 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3812
3813 // If this is not the end of the statement, report an error.
3814 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3815 reportParseError("unexpected token, expected end of statement");
3816 return false;
3817 }
3818
3819 return false; // parseDirectiveModule has finished successfully.
3820 } else if (Option == "nooddspreg") {
3821 if (!isABI_O32()) {
3822 Error(L, "'.module nooddspreg' requires the O32 ABI");
3823 return false;
3824 }
3825
3826 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3827 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3828
3829 // If this is not the end of the statement, report an error.
3830 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3831 reportParseError("unexpected token, expected end of statement");
3832 return false;
3833 }
3834
3835 return false; // parseDirectiveModule has finished successfully.
3836 } else if (Option == "fp") {
3837 return parseDirectiveModuleFP();
3838 } else {
3839 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
3840 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003841}
3842
3843/// parseDirectiveModuleFP
3844/// ::= =32
3845/// ::= =xx
3846/// ::= =64
3847bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003848 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003849 MCAsmLexer &Lexer = getLexer();
3850
3851 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003852 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003853 return false;
3854 }
3855 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003856
Daniel Sanders7e527422014-07-10 13:38:23 +00003857 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003858 if (!parseFpABIValue(FpABI, ".module"))
3859 return false;
3860
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003862 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003863 return false;
3864 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003865
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003866 // Emit appropriate flags.
3867 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003868 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003869 return false;
3870}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003871
Daniel Sanders7e527422014-07-10 13:38:23 +00003872bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003873 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003874 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003875 MCAsmLexer &Lexer = getLexer();
3876
3877 if (Lexer.is(AsmToken::Identifier)) {
3878 StringRef Value = Parser.getTok().getString();
3879 Parser.Lex();
3880
3881 if (Value != "xx") {
3882 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3883 return false;
3884 }
3885
3886 if (!isABI_O32()) {
3887 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3888 return false;
3889 }
3890
Daniel Sanders7e527422014-07-10 13:38:23 +00003891 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003892 return true;
3893 }
3894
3895 if (Lexer.is(AsmToken::Integer)) {
3896 unsigned Value = Parser.getTok().getIntVal();
3897 Parser.Lex();
3898
3899 if (Value != 32 && Value != 64) {
3900 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3901 return false;
3902 }
3903
3904 if (Value == 32) {
3905 if (!isABI_O32()) {
3906 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3907 return false;
3908 }
3909
Daniel Sanders7e527422014-07-10 13:38:23 +00003910 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3911 } else
3912 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003913
Daniel Sanders7e527422014-07-10 13:38:23 +00003914 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003915 }
3916
3917 return false;
3918}
3919
Jack Carter0b744b32012-10-04 02:29:46 +00003920bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003921 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003922 StringRef IDVal = DirectiveID.getString();
3923
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003924 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003925 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003926 if (IDVal == ".dword") {
3927 parseDataDirective(8, DirectiveID.getLoc());
3928 return false;
3929 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003930 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003931 StringRef SymbolName;
3932
3933 if (Parser.parseIdentifier(SymbolName)) {
3934 reportParseError("expected identifier after .ent");
3935 return false;
3936 }
3937
3938 // There's an undocumented extension that allows an integer to
3939 // follow the name of the procedure which AFAICS is ignored by GAS.
3940 // Example: .ent foo,2
3941 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3942 if (getLexer().isNot(AsmToken::Comma)) {
3943 // Even though we accept this undocumented extension for compatibility
3944 // reasons, the additional integer argument does not actually change
3945 // the behaviour of the '.ent' directive, so we would like to discourage
3946 // its use. We do this by not referring to the extended version in
3947 // error messages which are not directly related to its use.
3948 reportParseError("unexpected token, expected end of statement");
3949 return false;
3950 }
3951 Parser.Lex(); // Eat the comma.
3952 const MCExpr *DummyNumber;
3953 int64_t DummyNumberVal;
3954 // If the user was explicitly trying to use the extended version,
3955 // we still give helpful extension-related error messages.
3956 if (Parser.parseExpression(DummyNumber)) {
3957 reportParseError("expected number after comma");
3958 return false;
3959 }
3960 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3961 reportParseError("expected an absolute expression after comma");
3962 return false;
3963 }
3964 }
3965
3966 // If this is not the end of the statement, report an error.
3967 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3968 reportParseError("unexpected token, expected end of statement");
3969 return false;
3970 }
3971
3972 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3973
3974 getTargetStreamer().emitDirectiveEnt(*Sym);
3975 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003976 return false;
3977 }
3978
Jack Carter07c818d2013-01-25 01:31:34 +00003979 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003980 StringRef SymbolName;
3981
3982 if (Parser.parseIdentifier(SymbolName)) {
3983 reportParseError("expected identifier after .end");
3984 return false;
3985 }
3986
3987 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3988 reportParseError("unexpected token, expected end of statement");
3989 return false;
3990 }
3991
3992 if (CurrentFn == nullptr) {
3993 reportParseError(".end used without .ent");
3994 return false;
3995 }
3996
3997 if ((SymbolName != CurrentFn->getName())) {
3998 reportParseError(".end symbol does not match .ent symbol");
3999 return false;
4000 }
4001
4002 getTargetStreamer().emitDirectiveEnd(SymbolName);
4003 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004004 return false;
4005 }
4006
Jack Carter07c818d2013-01-25 01:31:34 +00004007 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004008 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4009 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004010 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004011 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4012 reportParseError("expected stack register");
4013 return false;
4014 }
4015
4016 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4017 if (!StackRegOpnd.isGPRAsmReg()) {
4018 reportParseError(StackRegOpnd.getStartLoc(),
4019 "expected general purpose register");
4020 return false;
4021 }
4022 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4023
4024 if (Parser.getTok().is(AsmToken::Comma))
4025 Parser.Lex();
4026 else {
4027 reportParseError("unexpected token, expected comma");
4028 return false;
4029 }
4030
4031 // Parse the frame size.
4032 const MCExpr *FrameSize;
4033 int64_t FrameSizeVal;
4034
4035 if (Parser.parseExpression(FrameSize)) {
4036 reportParseError("expected frame size value");
4037 return false;
4038 }
4039
4040 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4041 reportParseError("frame size not an absolute expression");
4042 return false;
4043 }
4044
4045 if (Parser.getTok().is(AsmToken::Comma))
4046 Parser.Lex();
4047 else {
4048 reportParseError("unexpected token, expected comma");
4049 return false;
4050 }
4051
4052 // Parse the return register.
4053 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004054 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004055 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4056 reportParseError("expected return register");
4057 return false;
4058 }
4059
4060 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4061 if (!ReturnRegOpnd.isGPRAsmReg()) {
4062 reportParseError(ReturnRegOpnd.getStartLoc(),
4063 "expected general purpose register");
4064 return false;
4065 }
4066
4067 // If this is not the end of the statement, report an error.
4068 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4069 reportParseError("unexpected token, expected end of statement");
4070 return false;
4071 }
4072
4073 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4074 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004075 return false;
4076 }
4077
Jack Carter07c818d2013-01-25 01:31:34 +00004078 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004079 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004080 }
4081
Daniel Sandersd97a6342014-08-13 10:07:34 +00004082 if (IDVal == ".mask" || IDVal == ".fmask") {
4083 // .mask bitmask, frame_offset
4084 // bitmask: One bit for each register used.
4085 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4086 // first register is expected to be saved.
4087 // Examples:
4088 // .mask 0x80000000, -4
4089 // .fmask 0x80000000, -4
4090 //
Jack Carterbe332172012-09-07 00:48:02 +00004091
Daniel Sandersd97a6342014-08-13 10:07:34 +00004092 // Parse the bitmask
4093 const MCExpr *BitMask;
4094 int64_t BitMaskVal;
4095
4096 if (Parser.parseExpression(BitMask)) {
4097 reportParseError("expected bitmask value");
4098 return false;
4099 }
4100
4101 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4102 reportParseError("bitmask not an absolute expression");
4103 return false;
4104 }
4105
4106 if (Parser.getTok().is(AsmToken::Comma))
4107 Parser.Lex();
4108 else {
4109 reportParseError("unexpected token, expected comma");
4110 return false;
4111 }
4112
4113 // Parse the frame_offset
4114 const MCExpr *FrameOffset;
4115 int64_t FrameOffsetVal;
4116
4117 if (Parser.parseExpression(FrameOffset)) {
4118 reportParseError("expected frame offset value");
4119 return false;
4120 }
4121
4122 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4123 reportParseError("frame offset not an absolute expression");
4124 return false;
4125 }
4126
4127 // If this is not the end of the statement, report an error.
4128 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4129 reportParseError("unexpected token, expected end of statement");
4130 return false;
4131 }
4132
4133 if (IDVal == ".mask")
4134 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4135 else
4136 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004137 return false;
4138 }
4139
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004140 if (IDVal == ".nan")
4141 return parseDirectiveNaN();
4142
Jack Carter07c818d2013-01-25 01:31:34 +00004143 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004144 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004145 return false;
4146 }
4147
Rafael Espindolab59fb732014-03-28 18:50:26 +00004148 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004149 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004150 return false;
4151 }
4152
Jack Carter07c818d2013-01-25 01:31:34 +00004153 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004154 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004155 return false;
4156 }
4157
Jack Carter0cd3c192014-01-06 23:27:31 +00004158 if (IDVal == ".option")
4159 return parseDirectiveOption();
4160
4161 if (IDVal == ".abicalls") {
4162 getTargetStreamer().emitDirectiveAbiCalls();
4163 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004164 Error(Parser.getTok().getLoc(),
4165 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004166 // Clear line
4167 Parser.eatToEndOfStatement();
4168 }
4169 return false;
4170 }
4171
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004172 if (IDVal == ".cpsetup")
4173 return parseDirectiveCPSetup();
4174
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004175 if (IDVal == ".module")
4176 return parseDirectiveModule();
4177
Rafael Espindola870c4e92012-01-11 03:56:41 +00004178 return true;
4179}
4180
Rafael Espindola870c4e92012-01-11 03:56:41 +00004181extern "C" void LLVMInitializeMipsAsmParser() {
4182 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4183 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4184 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4185 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4186}
Jack Carterb4dbc172012-09-05 23:34:03 +00004187
4188#define GET_REGISTER_MATCHER
4189#define GET_MATCHER_IMPLEMENTATION
4190#include "MipsGenAsmMatcher.inc"