blob: 1040bf7ffe60df641d806b1858595d0ca172100a [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 |
Daniel Sanders17793142015-02-18 16:24:50 +000079 Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
80 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
81 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
82 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000088 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
92namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000093class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000095 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000096 return static_cast<MipsTargetStreamer &>(TS);
97 }
98
Jack Carterb4dbc172012-09-05 23:34:03 +000099 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000100 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000101 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000102 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
103 // nullptr, which indicates that no function is currently
104 // selected. This usually happens after an '.end func'
105 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000106
Daniel Sandersef638fe2014-10-03 15:37:37 +0000107 // Print a warning along with its fix-it message at the given range.
108 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
109 SMRange Range, bool ShowColors = true);
110
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000111#define GET_ASSEMBLER_HEADER
112#include "MipsGenAsmMatcher.inc"
113
Matheus Almeida595fcab2014-06-11 15:05:56 +0000114 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
115
Chad Rosier49963552012-10-13 00:26:04 +0000116 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000117 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000118 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000121 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000122 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000123
Toma Tabacu13964452014-09-04 13:23:44 +0000124 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000125
Toma Tabacu13964452014-09-04 13:23:44 +0000126 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000127
David Blaikie960ea3f2014-06-08 16:18:35 +0000128 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
129 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Craig Topper56c590a2014-04-29 07:58:02 +0000131 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000132
David Blaikie960ea3f2014-06-08 16:18:35 +0000133 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000134
135 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000136 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000137 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000138
Jack Carter873c7242013-01-12 01:03:14 +0000139 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000140 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000145
Toma Tabacu13964452014-09-04 13:23:44 +0000146 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000147
David Blaikie960ea3f2014-06-08 16:18:35 +0000148 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000149
Toma Tabacu13964452014-09-04 13:23:44 +0000150 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000151
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000152 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000153 parseRegisterPair (OperandVector &Operands);
154
155 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000156 parseMovePRegPair(OperandVector &Operands);
157
158 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 parseRegisterList (OperandVector &Operands);
160
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 bool searchSymbolAlias(OperandVector &Operands);
162
Toma Tabacu13964452014-09-04 13:23:44 +0000163 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000164
Jack Carter30a59822012-10-04 04:03:53 +0000165 bool needsExpansion(MCInst &Inst);
166
Matheus Almeida3813d572014-06-19 14:39:14 +0000167 // Expands assembly pseudo instructions.
168 // Returns false on success, true otherwise.
169 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000172 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
173 SmallVectorImpl<MCInst> &Instructions);
174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000176 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000177
178 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000179 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000180
181 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000182 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000183 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000185
Toma Tabacu0d64b202014-08-14 10:29:17 +0000186 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
187 SmallVectorImpl<MCInst> &Instructions);
188
Jack Carter9e65aa32013-03-22 00:05:30 +0000189 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000190 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
191 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000192
193 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
195
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000196 bool reportParseError(Twine ErrorMsg);
197 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000198
Jack Carterb5cf5902013-04-17 00:18:04 +0000199 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000200 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000201
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000203
204 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000205 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000206 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000207 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000208 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000209 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000210 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000211 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000212 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000213
214 bool parseSetAtDirective();
215 bool parseSetNoAtDirective();
216 bool parseSetMacroDirective();
217 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000218 bool parseSetMsaDirective();
219 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000220 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000221 bool parseSetReorderDirective();
222 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000223 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000224 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000225 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000226 bool parseSetPopDirective();
227 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000228
Jack Carterd76b2372013-03-21 21:44:16 +0000229 bool parseSetAssignment();
230
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000231 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000232 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000233 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000234 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000235 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000236 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
237 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000238
Jack Carterdc1e35d2012-09-06 20:00:02 +0000239 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000240
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000241 bool eatComma(StringRef ErrorStr);
242
Jack Carter1ac53222013-02-20 23:11:17 +0000243 int matchCPURegisterName(StringRef Symbol);
244
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000245 int matchHWRegsRegisterName(StringRef Symbol);
246
Jack Carter873c7242013-01-12 01:03:14 +0000247 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000248
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000249 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000250
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000251 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000252
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000253 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000254
Jack Carter5dc8ac92013-09-25 23:50:44 +0000255 int matchMSA128RegisterName(StringRef Name);
256
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000257 int matchMSA128CtrlRegisterName(StringRef Name);
258
Jack Carterd0bd6422013-04-18 00:41:53 +0000259 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000260
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000261 unsigned getGPR(int RegNo);
262
Matheus Almeida7de68e72014-06-18 14:46:05 +0000263 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000264
265 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000266 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000267
268 // Helper function that checks if the value of a vector index is within the
269 // boundaries of accepted values for each RegisterKind
270 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
271 bool validateMSAIndex(int Val, int RegKind);
272
Daniel Sandersf0df2212014-08-04 12:20:00 +0000273 // Selects a new architecture by updating the FeatureBits with the necessary
274 // info including implied dependencies.
275 // Internally, it clears all the feature bits related to *any* architecture
276 // and selects the new one using the ToggleFeature functionality of the
277 // MCSubtargetInfo object that handles implied dependencies. The reason we
278 // clear all the arch related bits manually is because ToggleFeature only
279 // clears the features that imply the feature being cleared and not the
280 // features implied by the feature being cleared. This is easier to see
281 // with an example:
282 // --------------------------------------------------
283 // | Feature | Implies |
284 // | -------------------------------------------------|
285 // | FeatureMips1 | None |
286 // | FeatureMips2 | FeatureMips1 |
287 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
288 // | FeatureMips4 | FeatureMips3 |
289 // | ... | |
290 // --------------------------------------------------
291 //
292 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
293 // FeatureMipsGP64 | FeatureMips1)
294 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
295 void selectArch(StringRef ArchFeature) {
296 uint64_t FeatureBits = STI.getFeatureBits();
297 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
298 STI.setFeatureBits(FeatureBits);
299 setAvailableFeatures(
300 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000301 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000302 }
303
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000304 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000305 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000306 setAvailableFeatures(
307 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000308 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000309 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000310 }
311
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000312 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000313 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000314 setAvailableFeatures(
315 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000316 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000317 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000318 }
319
Rafael Espindola870c4e92012-01-11 03:56:41 +0000320public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000321 enum MipsMatchResultTy {
322 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
323#define GET_OPERAND_DIAGNOSTIC_TYPES
324#include "MipsGenAsmMatcher.inc"
325#undef GET_OPERAND_DIAGNOSTIC_TYPES
326
327 };
328
Joey Gouly0e76fa72013-09-12 10:28:05 +0000329 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000330 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000331 : MCTargetAsmParser(), STI(sti),
332 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
333 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000334 MCAsmParserExtension::Initialize(parser);
335
Jack Carterb4dbc172012-09-05 23:34:03 +0000336 // Initialize the set of available features.
337 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000338
339 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000340 AssemblerOptions.push_back(
341 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000342
343 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000344 AssemblerOptions.push_back(
345 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 getTargetStreamer().updateABIInfo(*this);
348
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000349 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000350 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000351
352 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000353 }
354
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000355 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
356 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
357
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000358 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
359 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000360 const MipsABIInfo &getABI() const { return ABI; }
361 bool isABI_N32() const { return ABI.IsN32(); }
362 bool isABI_N64() const { return ABI.IsN64(); }
363 bool isABI_O32() const { return ABI.IsO32(); }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000364 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000365
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000366 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000367 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
368 }
369
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000370 bool inMicroMipsMode() const {
371 return STI.getFeatureBits() & Mips::FeatureMicroMips;
372 }
373 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
374 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
375 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
376 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
377 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
378 bool hasMips32() const {
379 return (STI.getFeatureBits() & Mips::FeatureMips32);
380 }
381 bool hasMips64() const {
382 return (STI.getFeatureBits() & Mips::FeatureMips64);
383 }
384 bool hasMips32r2() const {
385 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
386 }
387 bool hasMips64r2() const {
388 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
389 }
Daniel Sanders17793142015-02-18 16:24:50 +0000390 bool hasMips32r3() const {
391 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
392 }
393 bool hasMips64r3() const {
394 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
395 }
396 bool hasMips32r5() const {
397 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
398 }
399 bool hasMips64r5() const {
400 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
401 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000402 bool hasMips32r6() const {
403 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
404 }
405 bool hasMips64r6() const {
406 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
407 }
Kai Nackee0245392015-01-27 19:11:28 +0000408 bool hasCnMips() const {
409 return (STI.getFeatureBits() & Mips::FeatureCnMips);
410 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000411 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
412 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
413 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
414
415 bool inMips16Mode() const {
416 return STI.getFeatureBits() & Mips::FeatureMips16;
417 }
418 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000419 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000421 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000422 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000423};
424}
425
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000426namespace {
427
428/// MipsOperand - Instances of this class represent a parsed Mips machine
429/// instruction.
430class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000431public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000432 /// Broad categories of register classes
433 /// The exact class is finalized by the render method.
434 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000435 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000436 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000437 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000438 RegKind_FCC = 4, /// FCC
439 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
440 RegKind_MSACtrl = 16, /// MSA control registers
441 RegKind_COP2 = 32, /// COP2
442 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
443 /// context).
444 RegKind_CCR = 128, /// CCR
445 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000446 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000447
448 /// Potentially any (e.g. $1)
449 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
450 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000451 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000452 };
453
454private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000455 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000456 k_Immediate, /// An immediate (possibly involving symbol references)
457 k_Memory, /// Base + Offset Memory Address
458 k_PhysRegister, /// A physical register from the Mips namespace
459 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000460 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000461 k_RegList, /// A physical register list
462 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000463 } Kind;
464
David Blaikie960ea3f2014-06-08 16:18:35 +0000465public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 MipsOperand(KindTy K, MipsAsmParser &Parser)
467 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
468
David Blaikie960ea3f2014-06-08 16:18:35 +0000469private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000470 /// For diagnostics, and checking the assembler temporary
471 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000472
Eric Christopher8996c5d2013-03-15 00:42:55 +0000473 struct Token {
474 const char *Data;
475 unsigned Length;
476 };
477
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000478 struct PhysRegOp {
479 unsigned Num; /// Register Number
480 };
481
482 struct RegIdxOp {
483 unsigned Index; /// Index into the register class
484 RegKind Kind; /// Bitfield of the kinds it could possibly be
485 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000486 };
487
488 struct ImmOp {
489 const MCExpr *Val;
490 };
491
492 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000493 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000494 const MCExpr *Off;
495 };
496
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000497 struct RegListOp {
498 SmallVector<unsigned, 10> *List;
499 };
500
Jack Carterb4dbc172012-09-05 23:34:03 +0000501 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000502 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000503 struct PhysRegOp PhysReg;
504 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000505 struct ImmOp Imm;
506 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000507 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000508 };
509
510 SMLoc StartLoc, EndLoc;
511
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000512 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000513 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
514 const MCRegisterInfo *RegInfo,
515 SMLoc S, SMLoc E,
516 MipsAsmParser &Parser) {
517 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000518 Op->RegIdx.Index = Index;
519 Op->RegIdx.RegInfo = RegInfo;
520 Op->RegIdx.Kind = RegKind;
521 Op->StartLoc = S;
522 Op->EndLoc = E;
523 return Op;
524 }
525
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000526public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527 /// Coerce the register to GPR32 and return the real register for the current
528 /// target.
529 unsigned getGPR32Reg() const {
530 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000531 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000532 unsigned ClassID = Mips::GPR32RegClassID;
533 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000534 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000535
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000536 /// Coerce the register to GPR32 and return the real register for the current
537 /// target.
538 unsigned getGPRMM16Reg() const {
539 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
540 unsigned ClassID = Mips::GPR32RegClassID;
541 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
542 }
543
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000544 /// Coerce the register to GPR64 and return the real register for the current
545 /// target.
546 unsigned getGPR64Reg() const {
547 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
548 unsigned ClassID = Mips::GPR64RegClassID;
549 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000550 }
551
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000552private:
553 /// Coerce the register to AFGR64 and return the real register for the current
554 /// target.
555 unsigned getAFGR64Reg() const {
556 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
557 if (RegIdx.Index % 2 != 0)
558 AsmParser.Warning(StartLoc, "Float register should be even.");
559 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
560 .getRegister(RegIdx.Index / 2);
561 }
562
563 /// Coerce the register to FGR64 and return the real register for the current
564 /// target.
565 unsigned getFGR64Reg() const {
566 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
567 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
568 .getRegister(RegIdx.Index);
569 }
570
571 /// Coerce the register to FGR32 and return the real register for the current
572 /// target.
573 unsigned getFGR32Reg() const {
574 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
575 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
576 .getRegister(RegIdx.Index);
577 }
578
579 /// Coerce the register to FGRH32 and return the real register for the current
580 /// target.
581 unsigned getFGRH32Reg() const {
582 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
583 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
584 .getRegister(RegIdx.Index);
585 }
586
587 /// Coerce the register to FCC and return the real register for the current
588 /// target.
589 unsigned getFCCReg() const {
590 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
591 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
592 .getRegister(RegIdx.Index);
593 }
594
595 /// Coerce the register to MSA128 and return the real register for the current
596 /// target.
597 unsigned getMSA128Reg() const {
598 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
599 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
600 // identical
601 unsigned ClassID = Mips::MSA128BRegClassID;
602 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
603 }
604
605 /// Coerce the register to MSACtrl and return the real register for the
606 /// current target.
607 unsigned getMSACtrlReg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
609 unsigned ClassID = Mips::MSACtrlRegClassID;
610 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to COP2 and return the real register for the
614 /// current target.
615 unsigned getCOP2Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
617 unsigned ClassID = Mips::COP2RegClassID;
618 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
619 }
620
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000621 /// Coerce the register to COP3 and return the real register for the
622 /// current target.
623 unsigned getCOP3Reg() const {
624 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
625 unsigned ClassID = Mips::COP3RegClassID;
626 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
627 }
628
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000629 /// Coerce the register to ACC64DSP and return the real register for the
630 /// current target.
631 unsigned getACC64DSPReg() const {
632 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
633 unsigned ClassID = Mips::ACC64DSPRegClassID;
634 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
635 }
636
637 /// Coerce the register to HI32DSP and return the real register for the
638 /// current target.
639 unsigned getHI32DSPReg() const {
640 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
641 unsigned ClassID = Mips::HI32DSPRegClassID;
642 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
643 }
644
645 /// Coerce the register to LO32DSP and return the real register for the
646 /// current target.
647 unsigned getLO32DSPReg() const {
648 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
649 unsigned ClassID = Mips::LO32DSPRegClassID;
650 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
651 }
652
653 /// Coerce the register to CCR and return the real register for the
654 /// current target.
655 unsigned getCCRReg() const {
656 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
657 unsigned ClassID = Mips::CCRRegClassID;
658 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
659 }
660
661 /// Coerce the register to HWRegs and return the real register for the
662 /// current target.
663 unsigned getHWRegsReg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
665 unsigned ClassID = Mips::HWRegsRegClassID;
666 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
667 }
668
669public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000670 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000671 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000672 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000673 Inst.addOperand(MCOperand::CreateImm(0));
674 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
675 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
676 else
677 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000678 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000679
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000680 void addRegOperands(MCInst &Inst, unsigned N) const {
681 llvm_unreachable("Use a custom parser instead");
682 }
683
Daniel Sanders21bce302014-04-01 12:35:23 +0000684 /// Render the operand to an MCInst as a GPR32
685 /// Asserts if the wrong number of operands are requested, or the operand
686 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000687 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
688 assert(N == 1 && "Invalid number of operands!");
689 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
690 }
691
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000692 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
693 assert(N == 1 && "Invalid number of operands!");
694 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
695 }
696
Jozef Kolek1904fa22014-11-24 14:25:53 +0000697 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
698 assert(N == 1 && "Invalid number of operands!");
699 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
700 }
701
Zoran Jovanovic41688672015-02-10 16:36:20 +0000702 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
703 assert(N == 1 && "Invalid number of operands!");
704 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
705 }
706
Daniel Sanders21bce302014-04-01 12:35:23 +0000707 /// Render the operand to an MCInst as a GPR64
708 /// Asserts if the wrong number of operands are requested, or the operand
709 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
711 assert(N == 1 && "Invalid number of operands!");
712 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
713 }
714
715 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
717 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
718 }
719
720 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
722 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
723 }
724
725 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
726 assert(N == 1 && "Invalid number of operands!");
727 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000728 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000729 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000730 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
731 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 }
733
734 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
735 assert(N == 1 && "Invalid number of operands!");
736 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
737 }
738
739 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
740 assert(N == 1 && "Invalid number of operands!");
741 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
742 }
743
744 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
746 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
747 }
748
749 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
750 assert(N == 1 && "Invalid number of operands!");
751 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
752 }
753
754 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
755 assert(N == 1 && "Invalid number of operands!");
756 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
757 }
758
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000759 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
760 assert(N == 1 && "Invalid number of operands!");
761 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
762 }
763
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000764 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
765 assert(N == 1 && "Invalid number of operands!");
766 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
767 }
768
769 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
770 assert(N == 1 && "Invalid number of operands!");
771 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
772 }
773
774 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
775 assert(N == 1 && "Invalid number of operands!");
776 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
777 }
778
779 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
780 assert(N == 1 && "Invalid number of operands!");
781 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
782 }
783
784 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
785 assert(N == 1 && "Invalid number of operands!");
786 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
787 }
788
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000789 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000790 assert(N == 1 && "Invalid number of operands!");
791 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000792 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000793 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000794
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000795 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000796 assert(N == 2 && "Invalid number of operands!");
797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000799
800 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000801 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000802 }
803
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000804 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
805 assert(N == 2 && "Invalid number of operands!");
806
807 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
808
809 const MCExpr *Expr = getMemOff();
810 addExpr(Inst, Expr);
811 }
812
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000813 void addRegListOperands(MCInst &Inst, unsigned N) const {
814 assert(N == 1 && "Invalid number of operands!");
815
816 for (auto RegNo : getRegList())
817 Inst.addOperand(MCOperand::CreateReg(RegNo));
818 }
819
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000820 void addRegPairOperands(MCInst &Inst, unsigned N) const {
821 assert(N == 2 && "Invalid number of operands!");
822 unsigned RegNo = getRegPair();
823 Inst.addOperand(MCOperand::CreateReg(RegNo++));
824 Inst.addOperand(MCOperand::CreateReg(RegNo));
825 }
826
Zoran Jovanovic41688672015-02-10 16:36:20 +0000827 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 2 && "Invalid number of operands!");
829 for (auto RegNo : getRegList())
830 Inst.addOperand(MCOperand::CreateReg(RegNo));
831 }
832
Craig Topper56c590a2014-04-29 07:58:02 +0000833 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000834 // As a special case until we sort out the definition of div/divu, pretend
835 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
836 if (isGPRAsmReg() && RegIdx.Index == 0)
837 return true;
838
839 return Kind == k_PhysRegister;
840 }
841 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000842 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 bool isConstantImm() const {
844 return isImm() && dyn_cast<MCConstantExpr>(getImm());
845 }
Craig Topper56c590a2014-04-29 07:58:02 +0000846 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 // Note: It's not possible to pretend that other operand kinds are tokens.
848 // The matcher emitter checks tokens first.
849 return Kind == k_Token;
850 }
Craig Topper56c590a2014-04-29 07:58:02 +0000851 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000852 bool isConstantMemOff() const {
853 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
854 }
855 template <unsigned Bits> bool isMemWithSimmOffset() const {
856 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
857 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000858 bool isMemWithGRPMM16Base() const {
859 return isMem() && getMemBase()->isMM16AsmReg();
860 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000861 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
862 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
863 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
864 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000865 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
866 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
867 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
868 && (getMemBase()->getGPR32Reg() == Mips::SP);
869 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000870 bool isRegList16() const {
871 if (!isRegList())
872 return false;
873
874 int Size = RegList.List->size();
875 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
876 RegList.List->back() != Mips::RA)
877 return false;
878
879 int PrevReg = *RegList.List->begin();
880 for (int i = 1; i < Size - 1; i++) {
881 int Reg = (*(RegList.List))[i];
882 if ( Reg != PrevReg + 1)
883 return false;
884 PrevReg = Reg;
885 }
886
887 return true;
888 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000889 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 bool isLSAImm() const {
891 if (!isConstantImm())
892 return false;
893 int64_t Val = getConstantImm();
894 return 1 <= Val && Val <= 4;
895 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000896 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000897 bool isMovePRegPair() const {
898 if (Kind != k_RegList || RegList.List->size() != 2)
899 return false;
900
901 unsigned R0 = RegList.List->front();
902 unsigned R1 = RegList.List->back();
903
904 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
905 (R0 == Mips::A1 && R1 == Mips::A3) ||
906 (R0 == Mips::A2 && R1 == Mips::A3) ||
907 (R0 == Mips::A0 && R1 == Mips::S5) ||
908 (R0 == Mips::A0 && R1 == Mips::S6) ||
909 (R0 == Mips::A0 && R1 == Mips::A1) ||
910 (R0 == Mips::A0 && R1 == Mips::A2) ||
911 (R0 == Mips::A0 && R1 == Mips::A3))
912 return true;
913
914 return false;
915 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000916
917 StringRef getToken() const {
918 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000919 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000920 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000921 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000922
Craig Topper56c590a2014-04-29 07:58:02 +0000923 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 // As a special case until we sort out the definition of div/divu, pretend
925 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
926 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
927 RegIdx.Kind & RegKind_GPR)
928 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000929
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 assert(Kind == k_PhysRegister && "Invalid access!");
931 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000932 }
933
Jack Carterb4dbc172012-09-05 23:34:03 +0000934 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000936 return Imm.Val;
937 }
938
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 int64_t getConstantImm() const {
940 const MCExpr *Val = getImm();
941 return static_cast<const MCConstantExpr *>(Val)->getValue();
942 }
943
944 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000945 assert((Kind == k_Memory) && "Invalid access!");
946 return Mem.Base;
947 }
948
949 const MCExpr *getMemOff() const {
950 assert((Kind == k_Memory) && "Invalid access!");
951 return Mem.Off;
952 }
953
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000954 int64_t getConstantMemOff() const {
955 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
956 }
957
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000958 const SmallVectorImpl<unsigned> &getRegList() const {
959 assert((Kind == k_RegList) && "Invalid access!");
960 return *(RegList.List);
961 }
962
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000963 unsigned getRegPair() const {
964 assert((Kind == k_RegPair) && "Invalid access!");
965 return RegIdx.Index;
966 }
967
David Blaikie960ea3f2014-06-08 16:18:35 +0000968 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
969 MipsAsmParser &Parser) {
970 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000971 Op->Tok.Data = Str.data();
972 Op->Tok.Length = Str.size();
973 Op->StartLoc = S;
974 Op->EndLoc = S;
975 return Op;
976 }
977
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000978 /// Create a numeric register (e.g. $1). The exact register remains
979 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000980 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000981 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000982 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000983 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000985 }
986
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 /// Create a register that is definitely a GPR.
988 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000989 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000990 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000991 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000993 }
994
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000995 /// Create a register that is definitely a FGR.
996 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000997 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000998 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000999 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1001 }
1002
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001003 /// Create a register that is definitely a HWReg.
1004 /// This is typically only used for named registers such as $hwr_cpunum.
1005 static std::unique_ptr<MipsOperand>
1006 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1007 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1008 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1009 }
1010
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 /// Create a register that is definitely an FCC.
1012 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001013 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001014 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001015 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1017 }
1018
1019 /// Create a register that is definitely an ACC.
1020 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001021 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001022 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001023 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1025 }
1026
1027 /// Create a register that is definitely an MSA128.
1028 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001029 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001030 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001031 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1033 }
1034
1035 /// Create a register that is definitely an MSACtrl.
1036 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001037 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001038 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1041 }
1042
David Blaikie960ea3f2014-06-08 16:18:35 +00001043 static std::unique_ptr<MipsOperand>
1044 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1045 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001046 Op->Imm.Val = Val;
1047 Op->StartLoc = S;
1048 Op->EndLoc = E;
1049 return Op;
1050 }
1051
David Blaikie960ea3f2014-06-08 16:18:35 +00001052 static std::unique_ptr<MipsOperand>
1053 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1054 SMLoc E, MipsAsmParser &Parser) {
1055 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1056 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001057 Op->Mem.Off = Off;
1058 Op->StartLoc = S;
1059 Op->EndLoc = E;
1060 return Op;
1061 }
1062
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001063 static std::unique_ptr<MipsOperand>
1064 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1065 MipsAsmParser &Parser) {
1066 assert (Regs.size() > 0 && "Empty list not allowed");
1067
1068 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001069 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001070 Op->StartLoc = StartLoc;
1071 Op->EndLoc = EndLoc;
1072 return Op;
1073 }
1074
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001075 static std::unique_ptr<MipsOperand>
1076 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1077 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1078 Op->RegIdx.Index = RegNo;
1079 Op->StartLoc = S;
1080 Op->EndLoc = E;
1081 return Op;
1082 }
1083
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 bool isGPRAsmReg() const {
1085 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001086 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001087 bool isMM16AsmReg() const {
1088 if (!(isRegIdx() && RegIdx.Kind))
1089 return false;
1090 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1091 || RegIdx.Index == 16 || RegIdx.Index == 17);
1092 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001093 bool isMM16AsmRegZero() const {
1094 if (!(isRegIdx() && RegIdx.Kind))
1095 return false;
1096 return (RegIdx.Index == 0 ||
1097 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1098 RegIdx.Index == 17);
1099 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001100 bool isMM16AsmRegMoveP() const {
1101 if (!(isRegIdx() && RegIdx.Kind))
1102 return false;
1103 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1104 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1105 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 bool isFGRAsmReg() const {
1107 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1108 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001109 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 bool isHWRegsAsmReg() const {
1111 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001112 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 bool isCCRAsmReg() const {
1114 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001115 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001117 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1118 return false;
1119 if (!AsmParser.hasEightFccRegisters())
1120 return RegIdx.Index == 0;
1121 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001122 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001123 bool isACCAsmReg() const {
1124 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001125 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 bool isCOP2AsmReg() const {
1127 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001128 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001129 bool isCOP3AsmReg() const {
1130 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1131 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 bool isMSA128AsmReg() const {
1133 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001134 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 bool isMSACtrlAsmReg() const {
1136 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001137 }
1138
Jack Carterb4dbc172012-09-05 23:34:03 +00001139 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001140 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001141 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001142 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001143
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001144 virtual ~MipsOperand() {
1145 switch (Kind) {
1146 case k_Immediate:
1147 break;
1148 case k_Memory:
1149 delete Mem.Base;
1150 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001151 case k_RegList:
1152 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001153 case k_PhysRegister:
1154 case k_RegisterIndex:
1155 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001156 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001157 break;
1158 }
1159 }
1160
Craig Topper56c590a2014-04-29 07:58:02 +00001161 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 switch (Kind) {
1163 case k_Immediate:
1164 OS << "Imm<";
1165 Imm.Val->print(OS);
1166 OS << ">";
1167 break;
1168 case k_Memory:
1169 OS << "Mem<";
1170 Mem.Base->print(OS);
1171 OS << ", ";
1172 Mem.Off->print(OS);
1173 OS << ">";
1174 break;
1175 case k_PhysRegister:
1176 OS << "PhysReg<" << PhysReg.Num << ">";
1177 break;
1178 case k_RegisterIndex:
1179 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1180 break;
1181 case k_Token:
1182 OS << Tok.Data;
1183 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001184 case k_RegList:
1185 OS << "RegList< ";
1186 for (auto Reg : (*RegList.List))
1187 OS << Reg << " ";
1188 OS << ">";
1189 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001190 case k_RegPair:
1191 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1192 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001194 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001195}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001196} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001197
Jack Carter9e65aa32013-03-22 00:05:30 +00001198namespace llvm {
1199extern const MCInstrDesc MipsInsts[];
1200}
1201static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1202 return MipsInsts[Opcode];
1203}
1204
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001205static bool hasShortDelaySlot(unsigned Opcode) {
1206 switch (Opcode) {
1207 case Mips::JALS_MM:
1208 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001209 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001210 case Mips::BGEZALS_MM:
1211 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001212 return true;
1213 default:
1214 return false;
1215 }
1216}
1217
Jack Carter9e65aa32013-03-22 00:05:30 +00001218bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001219 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001220 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001221
Jack Carter9e65aa32013-03-22 00:05:30 +00001222 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001223
1224 if (MCID.isBranch() || MCID.isCall()) {
1225 const unsigned Opcode = Inst.getOpcode();
1226 MCOperand Offset;
1227
1228 switch (Opcode) {
1229 default:
1230 break;
Kai Nackee0245392015-01-27 19:11:28 +00001231 case Mips::BBIT0:
1232 case Mips::BBIT032:
1233 case Mips::BBIT1:
1234 case Mips::BBIT132:
1235 assert(hasCnMips() && "instruction only valid for octeon cpus");
1236 // Fall through
1237
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001238 case Mips::BEQ:
1239 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 case Mips::BEQ_MM:
1241 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001242 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001243 Offset = Inst.getOperand(2);
1244 if (!Offset.isImm())
1245 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001246 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001247 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001248 if (OffsetToAlignment(Offset.getImm(),
1249 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001250 return Error(IDLoc, "branch to misaligned address");
1251 break;
1252 case Mips::BGEZ:
1253 case Mips::BGTZ:
1254 case Mips::BLEZ:
1255 case Mips::BLTZ:
1256 case Mips::BGEZAL:
1257 case Mips::BLTZAL:
1258 case Mips::BC1F:
1259 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001260 case Mips::BGEZ_MM:
1261 case Mips::BGTZ_MM:
1262 case Mips::BLEZ_MM:
1263 case Mips::BLTZ_MM:
1264 case Mips::BGEZAL_MM:
1265 case Mips::BLTZAL_MM:
1266 case Mips::BC1F_MM:
1267 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001268 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001269 Offset = Inst.getOperand(1);
1270 if (!Offset.isImm())
1271 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001272 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001273 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001274 if (OffsetToAlignment(Offset.getImm(),
1275 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001276 return Error(IDLoc, "branch to misaligned address");
1277 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001278 case Mips::BEQZ16_MM:
1279 case Mips::BNEZ16_MM:
1280 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1281 Offset = Inst.getOperand(1);
1282 if (!Offset.isImm())
1283 break; // We'll deal with this situation later on when applying fixups.
1284 if (!isIntN(8, Offset.getImm()))
1285 return Error(IDLoc, "branch target out of range");
1286 if (OffsetToAlignment(Offset.getImm(), 2LL))
1287 return Error(IDLoc, "branch to misaligned address");
1288 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001289 }
1290 }
1291
Daniel Sandersa84989a2014-06-16 13:25:35 +00001292 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1293 // We still accept it but it is a normal nop.
1294 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1295 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1296 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1297 "nop instruction");
1298 }
1299
Kai Nackee0245392015-01-27 19:11:28 +00001300 if (hasCnMips()) {
1301 const unsigned Opcode = Inst.getOpcode();
1302 MCOperand Opnd;
1303 int Imm;
1304
1305 switch (Opcode) {
1306 default:
1307 break;
1308
1309 case Mips::BBIT0:
1310 case Mips::BBIT032:
1311 case Mips::BBIT1:
1312 case Mips::BBIT132:
1313 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1314 // The offset is handled above
1315 Opnd = Inst.getOperand(1);
1316 if (!Opnd.isImm())
1317 return Error(IDLoc, "expected immediate operand kind");
1318 Imm = Opnd.getImm();
1319 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1320 Opcode == Mips::BBIT1 ? 63 : 31))
1321 return Error(IDLoc, "immediate operand value out of range");
1322 if (Imm > 31) {
1323 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1324 : Mips::BBIT132);
1325 Inst.getOperand(1).setImm(Imm - 32);
1326 }
1327 break;
1328
1329 case Mips::CINS:
1330 case Mips::CINS32:
1331 case Mips::EXTS:
1332 case Mips::EXTS32:
1333 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1334 // Check length
1335 Opnd = Inst.getOperand(3);
1336 if (!Opnd.isImm())
1337 return Error(IDLoc, "expected immediate operand kind");
1338 Imm = Opnd.getImm();
1339 if (Imm < 0 || Imm > 31)
1340 return Error(IDLoc, "immediate operand value out of range");
1341 // Check position
1342 Opnd = Inst.getOperand(2);
1343 if (!Opnd.isImm())
1344 return Error(IDLoc, "expected immediate operand kind");
1345 Imm = Opnd.getImm();
1346 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1347 Opcode == Mips::EXTS ? 63 : 31))
1348 return Error(IDLoc, "immediate operand value out of range");
1349 if (Imm > 31) {
1350 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1351 Inst.getOperand(2).setImm(Imm - 32);
1352 }
1353 break;
1354
1355 case Mips::SEQi:
1356 case Mips::SNEi:
1357 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1358 Opnd = Inst.getOperand(2);
1359 if (!Opnd.isImm())
1360 return Error(IDLoc, "expected immediate operand kind");
1361 Imm = Opnd.getImm();
1362 if (!isInt<10>(Imm))
1363 return Error(IDLoc, "immediate operand value out of range");
1364 break;
1365 }
1366 }
1367
Toma Tabacu9db22db2014-09-09 10:15:38 +00001368 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001369 // If this instruction has a delay slot and .set reorder is active,
1370 // emit a NOP after it.
1371 Instructions.push_back(Inst);
1372 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001373 if (hasShortDelaySlot(Inst.getOpcode())) {
1374 NopInst.setOpcode(Mips::MOVE16_MM);
1375 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1376 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1377 } else {
1378 NopInst.setOpcode(Mips::SLL);
1379 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1380 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1381 NopInst.addOperand(MCOperand::CreateImm(0));
1382 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001383 Instructions.push_back(NopInst);
1384 return false;
1385 }
1386
Jack Carter9e65aa32013-03-22 00:05:30 +00001387 if (MCID.mayLoad() || MCID.mayStore()) {
1388 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001389 // reference or immediate we may have to expand instructions.
1390 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001391 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001392 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1393 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001394 MCOperand &Op = Inst.getOperand(i);
1395 if (Op.isImm()) {
1396 int MemOffset = Op.getImm();
1397 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 // Offset can't exceed 16bit value.
1399 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001400 return false;
1401 }
1402 } else if (Op.isExpr()) {
1403 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001404 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001405 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001406 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001407 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001408 // Expand symbol.
1409 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001410 return false;
1411 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001412 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001414 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001415 }
1416 }
1417 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001418 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001419 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001420
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001421 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001422 if (MCID.mayLoad()) {
1423 // Try to create 16-bit GP relative load instruction.
1424 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1425 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1426 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1427 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1428 MCOperand &Op = Inst.getOperand(i);
1429 if (Op.isImm()) {
1430 int MemOffset = Op.getImm();
1431 MCOperand &DstReg = Inst.getOperand(0);
1432 MCOperand &BaseReg = Inst.getOperand(1);
1433 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1434 getContext().getRegisterInfo()->getRegClass(
1435 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1436 BaseReg.getReg() == Mips::GP) {
1437 MCInst TmpInst;
1438 TmpInst.setLoc(IDLoc);
1439 TmpInst.setOpcode(Mips::LWGP_MM);
1440 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1441 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1442 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1443 Instructions.push_back(TmpInst);
1444 return false;
1445 }
1446 }
1447 }
1448 } // for
1449 } // if load
1450
1451 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1452
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001453 MCOperand Opnd;
1454 int Imm;
1455
1456 switch (Inst.getOpcode()) {
1457 default:
1458 break;
1459 case Mips::ADDIUS5_MM:
1460 Opnd = Inst.getOperand(2);
1461 if (!Opnd.isImm())
1462 return Error(IDLoc, "expected immediate operand kind");
1463 Imm = Opnd.getImm();
1464 if (Imm < -8 || Imm > 7)
1465 return Error(IDLoc, "immediate operand value out of range");
1466 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001467 case Mips::ADDIUSP_MM:
1468 Opnd = Inst.getOperand(0);
1469 if (!Opnd.isImm())
1470 return Error(IDLoc, "expected immediate operand kind");
1471 Imm = Opnd.getImm();
1472 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1473 Imm % 4 != 0)
1474 return Error(IDLoc, "immediate operand value out of range");
1475 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001476 case Mips::SLL16_MM:
1477 case Mips::SRL16_MM:
1478 Opnd = Inst.getOperand(2);
1479 if (!Opnd.isImm())
1480 return Error(IDLoc, "expected immediate operand kind");
1481 Imm = Opnd.getImm();
1482 if (Imm < 1 || Imm > 8)
1483 return Error(IDLoc, "immediate operand value out of range");
1484 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001485 case Mips::LI16_MM:
1486 Opnd = Inst.getOperand(1);
1487 if (!Opnd.isImm())
1488 return Error(IDLoc, "expected immediate operand kind");
1489 Imm = Opnd.getImm();
1490 if (Imm < -1 || Imm > 126)
1491 return Error(IDLoc, "immediate operand value out of range");
1492 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001493 case Mips::ADDIUR2_MM:
1494 Opnd = Inst.getOperand(2);
1495 if (!Opnd.isImm())
1496 return Error(IDLoc, "expected immediate operand kind");
1497 Imm = Opnd.getImm();
1498 if (!(Imm == 1 || Imm == -1 ||
1499 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1500 return Error(IDLoc, "immediate operand value out of range");
1501 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001502 case Mips::ADDIUR1SP_MM:
1503 Opnd = Inst.getOperand(1);
1504 if (!Opnd.isImm())
1505 return Error(IDLoc, "expected immediate operand kind");
1506 Imm = Opnd.getImm();
1507 if (OffsetToAlignment(Imm, 4LL))
1508 return Error(IDLoc, "misaligned immediate operand value");
1509 if (Imm < 0 || Imm > 255)
1510 return Error(IDLoc, "immediate operand value out of range");
1511 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001512 case Mips::ANDI16_MM:
1513 Opnd = Inst.getOperand(2);
1514 if (!Opnd.isImm())
1515 return Error(IDLoc, "expected immediate operand kind");
1516 Imm = Opnd.getImm();
1517 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1518 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1519 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1520 return Error(IDLoc, "immediate operand value out of range");
1521 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001522 case Mips::LBU16_MM:
1523 Opnd = Inst.getOperand(2);
1524 if (!Opnd.isImm())
1525 return Error(IDLoc, "expected immediate operand kind");
1526 Imm = Opnd.getImm();
1527 if (Imm < -1 || Imm > 14)
1528 return Error(IDLoc, "immediate operand value out of range");
1529 break;
1530 case Mips::SB16_MM:
1531 Opnd = Inst.getOperand(2);
1532 if (!Opnd.isImm())
1533 return Error(IDLoc, "expected immediate operand kind");
1534 Imm = Opnd.getImm();
1535 if (Imm < 0 || Imm > 15)
1536 return Error(IDLoc, "immediate operand value out of range");
1537 break;
1538 case Mips::LHU16_MM:
1539 case Mips::SH16_MM:
1540 Opnd = Inst.getOperand(2);
1541 if (!Opnd.isImm())
1542 return Error(IDLoc, "expected immediate operand kind");
1543 Imm = Opnd.getImm();
1544 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1545 return Error(IDLoc, "immediate operand value out of range");
1546 break;
1547 case Mips::LW16_MM:
1548 case Mips::SW16_MM:
1549 Opnd = Inst.getOperand(2);
1550 if (!Opnd.isImm())
1551 return Error(IDLoc, "expected immediate operand kind");
1552 Imm = Opnd.getImm();
1553 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1554 return Error(IDLoc, "immediate operand value out of range");
1555 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001556 case Mips::CACHE:
1557 case Mips::PREF:
1558 Opnd = Inst.getOperand(2);
1559 if (!Opnd.isImm())
1560 return Error(IDLoc, "expected immediate operand kind");
1561 Imm = Opnd.getImm();
1562 if (!isUInt<5>(Imm))
1563 return Error(IDLoc, "immediate operand value out of range");
1564 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001565 case Mips::ADDIUPC_MM:
1566 MCOperand Opnd = Inst.getOperand(1);
1567 if (!Opnd.isImm())
1568 return Error(IDLoc, "expected immediate operand kind");
1569 int Imm = Opnd.getImm();
1570 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1571 return Error(IDLoc, "immediate operand value out of range");
1572 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001573 }
1574 }
1575
Jack Carter9e65aa32013-03-22 00:05:30 +00001576 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001577 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001578 else
1579 Instructions.push_back(Inst);
1580
1581 return false;
1582}
1583
Jack Carter30a59822012-10-04 04:03:53 +00001584bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1585
Jack Carterd0bd6422013-04-18 00:41:53 +00001586 switch (Inst.getOpcode()) {
1587 case Mips::LoadImm32Reg:
1588 case Mips::LoadAddr32Imm:
1589 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001590 case Mips::LoadImm64Reg:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001591 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001592 case Mips::LWM_MM:
1593 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001594 case Mips::JalOneReg:
1595 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001596 return true;
1597 default:
1598 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001599 }
1600}
Jack Carter92995f12012-10-06 00:53:28 +00001601
Matheus Almeida3813d572014-06-19 14:39:14 +00001602bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001603 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001604 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001605 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001606 case Mips::LoadImm32Reg:
1607 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001608 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001609 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001610 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001611 return true;
1612 }
1613 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001614 case Mips::LoadAddr32Imm:
1615 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1616 case Mips::LoadAddr32Reg:
1617 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001618 case Mips::B_MM_Pseudo:
1619 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001620 case Mips::SWM_MM:
1621 case Mips::LWM_MM:
1622 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001623 case Mips::JalOneReg:
1624 case Mips::JalTwoReg:
1625 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001626 }
Jack Carter30a59822012-10-04 04:03:53 +00001627}
Jack Carter92995f12012-10-06 00:53:28 +00001628
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001629namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001630template <bool PerformShift>
1631void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001632 SmallVectorImpl<MCInst> &Instructions) {
1633 MCInst tmpInst;
1634 if (PerformShift) {
1635 tmpInst.setOpcode(Mips::DSLL);
1636 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1637 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1638 tmpInst.addOperand(MCOperand::CreateImm(16));
1639 tmpInst.setLoc(IDLoc);
1640 Instructions.push_back(tmpInst);
1641 tmpInst.clear();
1642 }
1643 tmpInst.setOpcode(Mips::ORi);
1644 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1645 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001646 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001647 tmpInst.setLoc(IDLoc);
1648 Instructions.push_back(tmpInst);
1649}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001650
1651template <int Shift, bool PerformShift>
1652void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1653 SmallVectorImpl<MCInst> &Instructions) {
1654 createShiftOr<PerformShift>(
1655 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1656 IDLoc, Instructions);
1657}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001658}
1659
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001660bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1661 SmallVectorImpl<MCInst> &Instructions) {
1662 // Create a JALR instruction which is going to replace the pseudo-JAL.
1663 MCInst JalrInst;
1664 JalrInst.setLoc(IDLoc);
1665 const MCOperand FirstRegOp = Inst.getOperand(0);
1666 const unsigned Opcode = Inst.getOpcode();
1667
1668 if (Opcode == Mips::JalOneReg) {
1669 // jal $rs => jalr $rs
1670 if (inMicroMipsMode()) {
1671 JalrInst.setOpcode(Mips::JALR16_MM);
1672 JalrInst.addOperand(FirstRegOp);
1673 } else {
1674 JalrInst.setOpcode(Mips::JALR);
1675 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1676 JalrInst.addOperand(FirstRegOp);
1677 }
1678 } else if (Opcode == Mips::JalTwoReg) {
1679 // jal $rd, $rs => jalr $rd, $rs
1680 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1681 JalrInst.addOperand(FirstRegOp);
1682 const MCOperand SecondRegOp = Inst.getOperand(1);
1683 JalrInst.addOperand(SecondRegOp);
1684 }
1685 Instructions.push_back(JalrInst);
1686
1687 // If .set reorder is active, emit a NOP after it.
1688 if (AssemblerOptions.back()->isReorder()) {
1689 // This is a 32-bit NOP because these 2 pseudo-instructions
1690 // do not have a short delay slot.
1691 MCInst NopInst;
1692 NopInst.setOpcode(Mips::SLL);
1693 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1694 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1695 NopInst.addOperand(MCOperand::CreateImm(0));
1696 Instructions.push_back(NopInst);
1697 }
1698
1699 return false;
1700}
1701
Matheus Almeida3813d572014-06-19 14:39:14 +00001702bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001703 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001704 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001705 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001706 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001707 const MCOperand &RegOp = Inst.getOperand(0);
1708 assert(RegOp.isReg() && "expected register operand kind");
1709
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001710 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001711 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001712 // FIXME: gas has a special case for values that are 000...1111, which
1713 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 if (0 <= ImmValue && ImmValue <= 65535) {
1715 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001716 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001717 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001718 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001720 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001721 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001722 } else if (ImmValue < 0 && ImmValue >= -32768) {
1723 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001724 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001725 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001726 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001727 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001728 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001729 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001730 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1731 // For any value of j that is representable as a 32-bit integer, create
1732 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001733 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001734 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001735 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001736 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1737 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001738 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001739 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1740 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001741 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001742 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001743 return true;
1744 }
1745
1746 // <------- lo32 ------>
1747 // <------- hi32 ------>
1748 // <- hi16 -> <- lo16 ->
1749 // _________________________________
1750 // | | | |
1751 // | 16-bytes | 16-bytes | 16-bytes |
1752 // |__________|__________|__________|
1753 //
1754 // For any value of j that is representable as a 48-bit integer, create
1755 // a sequence of:
1756 // li d,j => lui d,hi16(j)
1757 // ori d,d,hi16(lo32(j))
1758 // dsll d,d,16
1759 // ori d,d,lo16(lo32(j))
1760 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001761 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001762 tmpInst.addOperand(
1763 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001764 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001765 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1766 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1767 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001768 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001769 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001770 return true;
1771 }
1772
1773 // <------- hi32 ------> <------- lo32 ------>
1774 // <- hi16 -> <- lo16 ->
1775 // ___________________________________________
1776 // | | | | |
1777 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1778 // |__________|__________|__________|__________|
1779 //
1780 // For any value of j that isn't representable as a 48-bit integer.
1781 // li d,j => lui d,hi16(j)
1782 // ori d,d,lo16(hi32(j))
1783 // dsll d,d,16
1784 // ori d,d,hi16(lo32(j))
1785 // dsll d,d,16
1786 // ori d,d,lo16(lo32(j))
1787 tmpInst.setOpcode(Mips::LUi);
1788 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1789 tmpInst.addOperand(
1790 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1791 Instructions.push_back(tmpInst);
1792 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1793 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1794 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001795 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001796 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001797}
Jack Carter92995f12012-10-06 00:53:28 +00001798
Matheus Almeida3813d572014-06-19 14:39:14 +00001799bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001800MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1801 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001802 MCInst tmpInst;
1803 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001804 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1805 "expected immediate operand kind");
1806 if (!ImmOp.isImm()) {
1807 expandLoadAddressSym(Inst, IDLoc, Instructions);
1808 return false;
1809 }
Jack Carter543fdf82012-10-09 23:29:45 +00001810 const MCOperand &SrcRegOp = Inst.getOperand(1);
1811 assert(SrcRegOp.isReg() && "expected register operand kind");
1812 const MCOperand &DstRegOp = Inst.getOperand(0);
1813 assert(DstRegOp.isReg() && "expected register operand kind");
1814 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001815 if (-32768 <= ImmValue && ImmValue <= 65535) {
1816 // For -32768 <= j <= 65535.
1817 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001818 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001819 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1820 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1821 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1822 Instructions.push_back(tmpInst);
1823 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001824 // For any other value of j that is representable as a 32-bit integer.
1825 // la d,j(s) => lui d,hi16(j)
1826 // ori d,d,lo16(j)
1827 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001828 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001829 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1830 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1831 Instructions.push_back(tmpInst);
1832 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001833 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001834 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1835 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1836 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1837 Instructions.push_back(tmpInst);
1838 tmpInst.clear();
1839 tmpInst.setOpcode(Mips::ADDu);
1840 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1841 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1842 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1843 Instructions.push_back(tmpInst);
1844 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001845 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001846}
1847
Matheus Almeida3813d572014-06-19 14:39:14 +00001848bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001849MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1850 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001851 MCInst tmpInst;
1852 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001853 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1854 "expected immediate operand kind");
1855 if (!ImmOp.isImm()) {
1856 expandLoadAddressSym(Inst, IDLoc, Instructions);
1857 return false;
1858 }
Jack Carter543fdf82012-10-09 23:29:45 +00001859 const MCOperand &RegOp = Inst.getOperand(0);
1860 assert(RegOp.isReg() && "expected register operand kind");
1861 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001862 if (-32768 <= ImmValue && ImmValue <= 65535) {
1863 // For -32768 <= j <= 65535.
1864 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001865 tmpInst.setOpcode(Mips::ADDiu);
1866 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001867 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001868 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1869 Instructions.push_back(tmpInst);
1870 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001871 // For any other value of j that is representable as a 32-bit integer.
1872 // la d,j => lui d,hi16(j)
1873 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001874 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001875 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1876 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1877 Instructions.push_back(tmpInst);
1878 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001879 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001880 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1881 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1882 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1883 Instructions.push_back(tmpInst);
1884 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001885 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001886}
1887
Toma Tabacu0d64b202014-08-14 10:29:17 +00001888void
1889MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1890 SmallVectorImpl<MCInst> &Instructions) {
1891 // FIXME: If we do have a valid at register to use, we should generate a
1892 // slightly shorter sequence here.
1893 MCInst tmpInst;
1894 int ExprOperandNo = 1;
1895 // Sometimes the assembly parser will get the immediate expression as
1896 // a $zero + an immediate.
1897 if (Inst.getNumOperands() == 3) {
1898 assert(Inst.getOperand(1).getReg() ==
1899 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1900 ExprOperandNo = 2;
1901 }
1902 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1903 assert(SymOp.isExpr() && "expected symbol operand kind");
1904 const MCOperand &RegOp = Inst.getOperand(0);
1905 unsigned RegNo = RegOp.getReg();
1906 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1907 const MCSymbolRefExpr *HiExpr =
1908 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1909 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1910 const MCSymbolRefExpr *LoExpr =
1911 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1912 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1913 if (isGP64bit()) {
1914 // If it's a 64-bit architecture, expand to:
1915 // la d,sym => lui d,highest(sym)
1916 // ori d,d,higher(sym)
1917 // dsll d,d,16
1918 // ori d,d,hi16(sym)
1919 // dsll d,d,16
1920 // ori d,d,lo16(sym)
1921 const MCSymbolRefExpr *HighestExpr =
1922 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1923 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1924 const MCSymbolRefExpr *HigherExpr =
1925 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1926 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1927
1928 tmpInst.setOpcode(Mips::LUi);
1929 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1930 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1931 Instructions.push_back(tmpInst);
1932
1933 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1934 Instructions);
1935 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1936 Instructions);
1937 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1938 Instructions);
1939 } else {
1940 // Otherwise, expand to:
1941 // la d,sym => lui d,hi16(sym)
1942 // ori d,d,lo16(sym)
1943 tmpInst.setOpcode(Mips::LUi);
1944 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1945 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1946 Instructions.push_back(tmpInst);
1947
1948 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1949 Instructions);
1950 }
1951}
1952
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001953bool MipsAsmParser::expandUncondBranchMMPseudo(
1954 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001955 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1956 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001957
1958 MCOperand Offset = Inst.getOperand(0);
1959 if (Offset.isExpr()) {
1960 Inst.clear();
1961 Inst.setOpcode(Mips::BEQ_MM);
1962 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1963 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1964 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1965 } else {
1966 assert(Offset.isImm() && "expected immediate operand kind");
1967 if (isIntN(11, Offset.getImm())) {
1968 // If offset fits into 11 bits then this instruction becomes microMIPS
1969 // 16-bit unconditional branch instruction.
1970 Inst.setOpcode(Mips::B16_MM);
1971 } else {
1972 if (!isIntN(17, Offset.getImm()))
1973 Error(IDLoc, "branch target out of range");
1974 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1975 Error(IDLoc, "branch to misaligned address");
1976 Inst.clear();
1977 Inst.setOpcode(Mips::BEQ_MM);
1978 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1979 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1980 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1981 }
1982 }
1983 Instructions.push_back(Inst);
1984
1985 if (AssemblerOptions.back()->isReorder()) {
1986 // If .set reorder is active, emit a NOP after the branch instruction.
1987 MCInst NopInst;
1988 NopInst.setOpcode(Mips::MOVE16_MM);
1989 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1990 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1991 Instructions.push_back(NopInst);
1992 }
1993 return false;
1994}
1995
Jack Carter9e65aa32013-03-22 00:05:30 +00001996void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001997 SmallVectorImpl<MCInst> &Instructions,
1998 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001999 const MCSymbolRefExpr *SR;
2000 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002001 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002002 const MCExpr *ExprOffset;
2003 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002004 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002005 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2006 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002007 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002008 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2009 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002010 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002011 if (isImmOpnd) {
2012 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2013 ImmOffset = Inst.getOperand(2).getImm();
2014 LoOffset = ImmOffset & 0x0000ffff;
2015 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002016 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002017 if (LoOffset & 0x8000)
2018 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002019 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002020 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002021 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002022 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002023 // These are some of the types of expansions we perform here:
2024 // 1) lw $8, sym => lui $8, %hi(sym)
2025 // lw $8, %lo(sym)($8)
2026 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2027 // add $8, $8, $9
2028 // lw $8, %lo(offset)($9)
2029 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2030 // add $at, $at, $8
2031 // lw $8, %lo(offset)($at)
2032 // 4) sw $8, sym => lui $at, %hi(sym)
2033 // sw $8, %lo(sym)($at)
2034 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2035 // add $at, $at, $8
2036 // sw $8, %lo(offset)($at)
2037 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2038 // ldc1 $f0, %lo(sym)($at)
2039 //
2040 // For load instructions we can use the destination register as a temporary
2041 // if base and dst are different (examples 1 and 2) and if the base register
2042 // is general purpose otherwise we must use $at (example 6) and error if it's
2043 // not available. For stores we must use $at (examples 4 and 5) because we
2044 // must not clobber the source register setting up the offset.
2045 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2046 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2047 unsigned RegClassIDOp0 =
2048 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2049 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2050 (RegClassIDOp0 == Mips::GPR64RegClassID);
2051 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002052 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002053 else {
2054 int AT = getATReg(IDLoc);
2055 // At this point we need AT to perform the expansions and we exit if it is
2056 // not available.
2057 if (!AT)
2058 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002059 TmpRegNum = getReg(
2060 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002061 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002062
Jack Carter9e65aa32013-03-22 00:05:30 +00002063 TempInst.setOpcode(Mips::LUi);
2064 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2065 if (isImmOpnd)
2066 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2067 else {
2068 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002069 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002070 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2071 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2072 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002073 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002074 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002075 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002076 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002077 }
2078 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002079 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002080 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002082 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002083 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002084 TempInst.setOpcode(Mips::ADDu);
2085 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2086 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2087 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2088 Instructions.push_back(TempInst);
2089 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00002090 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002092 TempInst.setOpcode(Inst.getOpcode());
2093 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2094 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2095 if (isImmOpnd)
2096 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2097 else {
2098 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2100 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2101 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002103 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002105 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 }
2107 }
2108 Instructions.push_back(TempInst);
2109 TempInst.clear();
2110}
2111
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002112bool
2113MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2114 SmallVectorImpl<MCInst> &Instructions) {
2115 unsigned OpNum = Inst.getNumOperands();
2116 unsigned Opcode = Inst.getOpcode();
2117 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2118
2119 assert (Inst.getOperand(OpNum - 1).isImm() &&
2120 Inst.getOperand(OpNum - 2).isReg() &&
2121 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2122
2123 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2124 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2125 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2126 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2127 // It can be implemented as SWM16 or LWM16 instruction.
2128 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2129
2130 Inst.setOpcode(NewOpcode);
2131 Instructions.push_back(Inst);
2132 return false;
2133}
2134
Matheus Almeida595fcab2014-06-11 15:05:56 +00002135unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2136 // As described by the Mips32r2 spec, the registers Rd and Rs for
2137 // jalr.hb must be different.
2138 unsigned Opcode = Inst.getOpcode();
2139
2140 if (Opcode == Mips::JALR_HB &&
2141 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2142 return Match_RequiresDifferentSrcAndDst;
2143
2144 return Match_Success;
2145}
2146
David Blaikie960ea3f2014-06-08 16:18:35 +00002147bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2148 OperandVector &Operands,
2149 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002150 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002151 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002152
Jack Carterb4dbc172012-09-05 23:34:03 +00002153 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002154 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002155 unsigned MatchResult =
2156 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002157
2158 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002159 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002160 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002161 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002163 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002164 return false;
2165 }
2166 case Match_MissingFeature:
2167 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2168 return true;
2169 case Match_InvalidOperand: {
2170 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002171 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002172 if (ErrorInfo >= Operands.size())
2173 return Error(IDLoc, "too few operands for instruction");
2174
David Blaikie960ea3f2014-06-08 16:18:35 +00002175 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 if (ErrorLoc == SMLoc())
2177 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002178 }
2179
2180 return Error(ErrorLoc, "invalid operand for instruction");
2181 }
2182 case Match_MnemonicFail:
2183 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002184 case Match_RequiresDifferentSrcAndDst:
2185 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002186 }
Craig Topper589ceee2015-01-03 08:16:34 +00002187
2188 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002189}
2190
Toma Tabacu13964452014-09-04 13:23:44 +00002191void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002192 if ((RegIndex != 0) &&
2193 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002194 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002195 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002196 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002197 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002198 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002199 }
2200}
2201
Daniel Sandersef638fe2014-10-03 15:37:37 +00002202void
2203MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2204 SMRange Range, bool ShowColors) {
2205 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002206 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002207 ShowColors);
2208}
2209
Jack Carter1ac53222013-02-20 23:11:17 +00002210int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002211 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002212
Vladimir Medic4c299852013-11-06 11:27:05 +00002213 CC = StringSwitch<unsigned>(Name)
2214 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002215 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002216 .Case("a0", 4)
2217 .Case("a1", 5)
2218 .Case("a2", 6)
2219 .Case("a3", 7)
2220 .Case("v0", 2)
2221 .Case("v1", 3)
2222 .Case("s0", 16)
2223 .Case("s1", 17)
2224 .Case("s2", 18)
2225 .Case("s3", 19)
2226 .Case("s4", 20)
2227 .Case("s5", 21)
2228 .Case("s6", 22)
2229 .Case("s7", 23)
2230 .Case("k0", 26)
2231 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002232 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002233 .Case("sp", 29)
2234 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002235 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002236 .Case("ra", 31)
2237 .Case("t0", 8)
2238 .Case("t1", 9)
2239 .Case("t2", 10)
2240 .Case("t3", 11)
2241 .Case("t4", 12)
2242 .Case("t5", 13)
2243 .Case("t6", 14)
2244 .Case("t7", 15)
2245 .Case("t8", 24)
2246 .Case("t9", 25)
2247 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002248
Toma Tabacufda445c2014-09-15 15:33:01 +00002249 if (!(isABI_N32() || isABI_N64()))
2250 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002251
Daniel Sandersef638fe2014-10-03 15:37:37 +00002252 if (12 <= CC && CC <= 15) {
2253 // Name is one of t4-t7
2254 AsmToken RegTok = getLexer().peekTok();
2255 SMRange RegRange = RegTok.getLocRange();
2256
2257 StringRef FixedName = StringSwitch<StringRef>(Name)
2258 .Case("t4", "t0")
2259 .Case("t5", "t1")
2260 .Case("t6", "t2")
2261 .Case("t7", "t3")
2262 .Default("");
2263 assert(FixedName != "" && "Register name is not one of t4-t7.");
2264
2265 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2266 "Did you mean $" + FixedName + "?", RegRange);
2267 }
2268
Toma Tabacufda445c2014-09-15 15:33:01 +00002269 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2270 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2271 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2272 if (8 <= CC && CC <= 11)
2273 CC += 4;
2274
2275 if (CC == -1)
2276 CC = StringSwitch<unsigned>(Name)
2277 .Case("a4", 8)
2278 .Case("a5", 9)
2279 .Case("a6", 10)
2280 .Case("a7", 11)
2281 .Case("kt0", 26)
2282 .Case("kt1", 27)
2283 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002284
2285 return CC;
2286}
Jack Carterd0bd6422013-04-18 00:41:53 +00002287
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002288int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2289 int CC;
2290
2291 CC = StringSwitch<unsigned>(Name)
2292 .Case("hwr_cpunum", 0)
2293 .Case("hwr_synci_step", 1)
2294 .Case("hwr_cc", 2)
2295 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002296 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002297 .Default(-1);
2298
2299 return CC;
2300}
2301
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002302int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002303
Jack Cartera63b16a2012-09-07 00:23:42 +00002304 if (Name[0] == 'f') {
2305 StringRef NumString = Name.substr(1);
2306 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002307 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002308 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002309 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002310 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002311 return IntVal;
2312 }
2313 return -1;
2314}
Jack Cartera63b16a2012-09-07 00:23:42 +00002315
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002316int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2317
2318 if (Name.startswith("fcc")) {
2319 StringRef NumString = Name.substr(3);
2320 unsigned IntVal;
2321 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002322 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002323 if (IntVal > 7) // There are only 8 fcc registers.
2324 return -1;
2325 return IntVal;
2326 }
2327 return -1;
2328}
2329
2330int MipsAsmParser::matchACRegisterName(StringRef Name) {
2331
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002332 if (Name.startswith("ac")) {
2333 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002334 unsigned IntVal;
2335 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002336 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002337 if (IntVal > 3) // There are only 3 acc registers.
2338 return -1;
2339 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002340 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002341 return -1;
2342}
Jack Carterd0bd6422013-04-18 00:41:53 +00002343
Jack Carter5dc8ac92013-09-25 23:50:44 +00002344int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2345 unsigned IntVal;
2346
2347 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2348 return -1;
2349
2350 if (IntVal > 31)
2351 return -1;
2352
2353 return IntVal;
2354}
2355
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002356int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2357 int CC;
2358
2359 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002360 .Case("msair", 0)
2361 .Case("msacsr", 1)
2362 .Case("msaaccess", 2)
2363 .Case("msasave", 3)
2364 .Case("msamodify", 4)
2365 .Case("msarequest", 5)
2366 .Case("msamap", 6)
2367 .Case("msaunmap", 7)
2368 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002369
2370 return CC;
2371}
2372
Jack Carter0b744b32012-10-04 02:29:46 +00002373bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2374 if (Reg > 31)
2375 return false;
2376
Toma Tabacu3c24b042014-09-05 15:43:21 +00002377 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002378 return true;
2379}
2380
Matheus Almeida7de68e72014-06-18 14:46:05 +00002381int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002382 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002383 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002384 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002385 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002386 return AT;
2387}
Jack Carter0b744b32012-10-04 02:29:46 +00002388
Jack Carterd0bd6422013-04-18 00:41:53 +00002389unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002390 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002391}
2392
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002393unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002394 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002395 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002396}
2397
Jack Carter873c7242013-01-12 01:03:14 +00002398int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002399 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002400 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002401 return -1;
2402
Jack Carter873c7242013-01-12 01:03:14 +00002403 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002404}
2405
Toma Tabacu13964452014-09-04 13:23:44 +00002406bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002407 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002408 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002409
Jack Carter30a59822012-10-04 04:03:53 +00002410 // Check if the current operand has a custom associated parser, if so, try to
2411 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002412 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2413 if (ResTy == MatchOperand_Success)
2414 return false;
2415 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2416 // there was a match, but an error occurred, in which case, just return that
2417 // the operand parsing failed.
2418 if (ResTy == MatchOperand_ParseFail)
2419 return true;
2420
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002421 DEBUG(dbgs() << ".. Generic Parser\n");
2422
Jack Carterb4dbc172012-09-05 23:34:03 +00002423 switch (getLexer().getKind()) {
2424 default:
2425 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2426 return true;
2427 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002428 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002429 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002430
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002431 // Almost all registers have been parsed by custom parsers. There is only
2432 // one exception to this. $zero (and it's alias $0) will reach this point
2433 // for div, divu, and similar instructions because it is not an operand
2434 // to the instruction definition but an explicit register. Special case
2435 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002436 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002437 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002438
Jack Carterd0bd6422013-04-18 00:41:53 +00002439 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002440 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002441 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002442 return true;
2443
Jack Carter873c7242013-01-12 01:03:14 +00002444 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002445 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002446 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002447 const MCExpr *Res =
2448 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002449
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002450 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002451 return false;
2452 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002453 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 case AsmToken::LParen:
2455 case AsmToken::Minus:
2456 case AsmToken::Plus:
2457 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002458 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002459 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002460 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002461 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002463 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002464 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002465 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002466 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002467 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002468 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002469 return true;
2470
Jack Carter873c7242013-01-12 01:03:14 +00002471 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2472
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002474 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002475 } // case AsmToken::Percent
2476 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002477 return true;
2478}
2479
Vladimir Medic4c299852013-11-06 11:27:05 +00002480const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002481 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002482 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002483 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002484 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002485 // It's a constant, evaluate reloc value.
2486 int16_t Val;
2487 switch (getVariantKind(RelocStr)) {
2488 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2489 // Get the 1st 16-bits.
2490 Val = MCE->getValue() & 0xffff;
2491 break;
2492 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2493 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2494 // 16 bits being negative.
2495 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2496 break;
2497 case MCSymbolRefExpr::VK_Mips_HIGHER:
2498 // Get the 3rd 16-bits.
2499 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2500 break;
2501 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2502 // Get the 4th 16-bits.
2503 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2504 break;
2505 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002506 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002507 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002508 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002509 }
2510
Jack Carterb5cf5902013-04-17 00:18:04 +00002511 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002512 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002513 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002514 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002515 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002516 return Res;
2517 }
2518
2519 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002520 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2521
Sasa Stankovic06c47802014-04-03 10:37:45 +00002522 // Try to create target expression.
2523 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2524 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002525
Jack Carterd0bd6422013-04-18 00:41:53 +00002526 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2527 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002528 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2529 return Res;
2530 }
2531
2532 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2534 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2535 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002536 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002537 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002538 return Expr;
2539}
2540
2541bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2542
2543 switch (Expr->getKind()) {
2544 case MCExpr::Constant:
2545 return true;
2546 case MCExpr::SymbolRef:
2547 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2548 case MCExpr::Binary:
2549 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2550 if (!isEvaluated(BE->getLHS()))
2551 return false;
2552 return isEvaluated(BE->getRHS());
2553 }
2554 case MCExpr::Unary:
2555 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002556 case MCExpr::Target:
2557 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002558 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002559 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002560}
Jack Carterd0bd6422013-04-18 00:41:53 +00002561
Jack Carterb5cf5902013-04-17 00:18:04 +00002562bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002563 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002564 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002566 if (Tok.isNot(AsmToken::Identifier))
2567 return true;
2568
2569 std::string Str = Tok.getIdentifier().str();
2570
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 Parser.Lex(); // Eat the identifier.
2572 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002573 const MCExpr *IdVal;
2574 SMLoc EndLoc;
2575
2576 if (getLexer().getKind() == AsmToken::LParen) {
2577 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002579 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002581 const AsmToken &nextTok = Parser.getTok();
2582 if (nextTok.isNot(AsmToken::Identifier))
2583 return true;
2584 Str += "(%";
2585 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002587 if (getLexer().getKind() != AsmToken::LParen)
2588 return true;
2589 } else
2590 break;
2591 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002592 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002593 return true;
2594
2595 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002597
2598 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002600
Jack Carterd0bd6422013-04-18 00:41:53 +00002601 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002602 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002603}
2604
Jack Carterb4dbc172012-09-05 23:34:03 +00002605bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2606 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002607 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002608 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002609 if (ResTy == MatchOperand_Success) {
2610 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002611 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002612 StartLoc = Operand.getStartLoc();
2613 EndLoc = Operand.getEndLoc();
2614
2615 // AFAIK, we only support numeric registers and named GPR's in CFI
2616 // directives.
2617 // Don't worry about eating tokens before failing. Using an unrecognised
2618 // register is a parse error.
2619 if (Operand.isGPRAsmReg()) {
2620 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002621 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002622 }
2623
2624 return (RegNo == (unsigned)-1);
2625 }
2626
2627 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002628 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002629}
2630
Jack Carterb5cf5902013-04-17 00:18:04 +00002631bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002632 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002633 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002634 bool Result = true;
2635
2636 while (getLexer().getKind() == AsmToken::LParen)
2637 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002638
Jack Carterd0bd6422013-04-18 00:41:53 +00002639 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002640 default:
2641 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002642 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002643 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002644 case AsmToken::Integer:
2645 case AsmToken::Minus:
2646 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002647 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002648 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002649 else
2650 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002651 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002652 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002653 break;
Jack Carter873c7242013-01-12 01:03:14 +00002654 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002655 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002656 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002657 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002658}
2659
David Blaikie960ea3f2014-06-08 16:18:35 +00002660MipsAsmParser::OperandMatchResultTy
2661MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002662 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002663 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002664 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002665 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002666 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002667 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002668 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002669 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002670
Jack Carterb5cf5902013-04-17 00:18:04 +00002671 if (getLexer().getKind() == AsmToken::LParen) {
2672 Parser.Lex();
2673 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002674 }
2675
Jack Carterb5cf5902013-04-17 00:18:04 +00002676 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002677 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002678 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002679
Jack Carterd0bd6422013-04-18 00:41:53 +00002680 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002681 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002682 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2683 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002684 SMLoc E =
2685 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002686 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 return MatchOperand_Success;
2688 }
2689 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002690 SMLoc E =
2691 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002692
Jack Carterd0bd6422013-04-18 00:41:53 +00002693 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002694 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002695 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002696 S, E, *this);
2697 Operands.push_back(
2698 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002699 return MatchOperand_Success;
2700 }
2701 Error(Parser.getTok().getLoc(), "'(' expected");
2702 return MatchOperand_ParseFail;
2703 }
2704
Jack Carterd0bd6422013-04-18 00:41:53 +00002705 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002706 }
2707
Toma Tabacu13964452014-09-04 13:23:44 +00002708 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002709 if (Res != MatchOperand_Success)
2710 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002711
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002712 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002713 Error(Parser.getTok().getLoc(), "')' expected");
2714 return MatchOperand_ParseFail;
2715 }
2716
Jack Carter873c7242013-01-12 01:03:14 +00002717 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2718
Jack Carterd0bd6422013-04-18 00:41:53 +00002719 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002720
Craig Topper062a2ba2014-04-25 05:30:21 +00002721 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002722 IdVal = MCConstantExpr::Create(0, getContext());
2723
Jack Carterd0bd6422013-04-18 00:41:53 +00002724 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002725 std::unique_ptr<MipsOperand> op(
2726 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002727 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002728 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002729 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002730 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002731 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2732 int64_t Imm;
2733 if (IdVal->EvaluateAsAbsolute(Imm))
2734 IdVal = MCConstantExpr::Create(Imm, getContext());
2735 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2736 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2737 getContext());
2738 }
2739
David Blaikie960ea3f2014-06-08 16:18:35 +00002740 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002741 return MatchOperand_Success;
2742}
2743
David Blaikie960ea3f2014-06-08 16:18:35 +00002744bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002745 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002746 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2747 if (Sym) {
2748 SMLoc S = Parser.getTok().getLoc();
2749 const MCExpr *Expr;
2750 if (Sym->isVariable())
2751 Expr = Sym->getVariableValue();
2752 else
2753 return false;
2754 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002755 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002756 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002757 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002758 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002759 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002760 if (ResTy == MatchOperand_Success) {
2761 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002762 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002763 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002764 llvm_unreachable("Should never ParseFail");
2765 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002766 }
2767 } else if (Expr->getKind() == MCExpr::Constant) {
2768 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002769 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002770 Operands.push_back(
2771 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002772 return true;
2773 }
2774 }
2775 return false;
2776}
Jack Carterd0bd6422013-04-18 00:41:53 +00002777
Jack Carter873c7242013-01-12 01:03:14 +00002778MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002779MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002780 StringRef Identifier,
2781 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002782 int Index = matchCPURegisterName(Identifier);
2783 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002784 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002785 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2786 return MatchOperand_Success;
2787 }
2788
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002789 Index = matchHWRegsRegisterName(Identifier);
2790 if (Index != -1) {
2791 Operands.push_back(MipsOperand::createHWRegsReg(
2792 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2793 return MatchOperand_Success;
2794 }
2795
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002796 Index = matchFPURegisterName(Identifier);
2797 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002798 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002799 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2800 return MatchOperand_Success;
2801 }
2802
2803 Index = matchFCCRegisterName(Identifier);
2804 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002805 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002806 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2807 return MatchOperand_Success;
2808 }
2809
2810 Index = matchACRegisterName(Identifier);
2811 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002812 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002813 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2814 return MatchOperand_Success;
2815 }
2816
2817 Index = matchMSA128RegisterName(Identifier);
2818 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002819 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2821 return MatchOperand_Success;
2822 }
2823
2824 Index = matchMSA128CtrlRegisterName(Identifier);
2825 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002826 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002827 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2828 return MatchOperand_Success;
2829 }
2830
2831 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002832}
2833
2834MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002835MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002836 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002837 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002838
2839 if (Token.is(AsmToken::Identifier)) {
2840 DEBUG(dbgs() << ".. identifier\n");
2841 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002842 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002843 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002844 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845 } else if (Token.is(AsmToken::Integer)) {
2846 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002847 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002848 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2849 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 return MatchOperand_Success;
2851 }
2852
2853 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2854
2855 return MatchOperand_NoMatch;
2856}
2857
David Blaikie960ea3f2014-06-08 16:18:35 +00002858MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002859MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002860 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002861 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002862
2863 auto Token = Parser.getTok();
2864
2865 SMLoc S = Token.getLoc();
2866
2867 if (Token.isNot(AsmToken::Dollar)) {
2868 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2869 if (Token.is(AsmToken::Identifier)) {
2870 if (searchSymbolAlias(Operands))
2871 return MatchOperand_Success;
2872 }
2873 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2874 return MatchOperand_NoMatch;
2875 }
2876 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002877
Toma Tabacu13964452014-09-04 13:23:44 +00002878 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002879 if (ResTy == MatchOperand_Success) {
2880 Parser.Lex(); // $
2881 Parser.Lex(); // identifier
2882 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883 return ResTy;
2884}
2885
2886MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002887MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002888 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002889 switch (getLexer().getKind()) {
2890 default:
2891 return MatchOperand_NoMatch;
2892 case AsmToken::LParen:
2893 case AsmToken::Minus:
2894 case AsmToken::Plus:
2895 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002896 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002897 case AsmToken::String:
2898 break;
2899 }
2900
2901 const MCExpr *IdVal;
2902 SMLoc S = Parser.getTok().getLoc();
2903 if (getParser().parseExpression(IdVal))
2904 return MatchOperand_ParseFail;
2905
2906 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2907 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2908 return MatchOperand_Success;
2909}
2910
David Blaikie960ea3f2014-06-08 16:18:35 +00002911MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002912MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002913 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002914 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002915
2916 SMLoc S = getLexer().getLoc();
2917
2918 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002919 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002920 if (ResTy != MatchOperand_NoMatch)
2921 return ResTy;
2922
Daniel Sanders315386c2014-04-01 10:40:14 +00002923 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002924 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002925 if (ResTy != MatchOperand_NoMatch)
2926 return ResTy;
2927
Daniel Sandersffd84362014-04-01 10:41:48 +00002928 const MCExpr *Expr = nullptr;
2929 if (Parser.parseExpression(Expr)) {
2930 // We have no way of knowing if a symbol was consumed so we must ParseFail
2931 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002932 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002933 Operands.push_back(
2934 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002935 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002936}
2937
Vladimir Medic2b953d02013-10-01 09:48:56 +00002938MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002939MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002940 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002941 const MCExpr *IdVal;
2942 // If the first token is '$' we may have register operand.
2943 if (Parser.getTok().is(AsmToken::Dollar))
2944 return MatchOperand_NoMatch;
2945 SMLoc S = Parser.getTok().getLoc();
2946 if (getParser().parseExpression(IdVal))
2947 return MatchOperand_ParseFail;
2948 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002949 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002950 int64_t Val = MCE->getValue();
2951 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2952 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002953 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002954 return MatchOperand_Success;
2955}
2956
Matheus Almeida779c5932013-11-18 12:32:49 +00002957MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002958MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002959 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002960 switch (getLexer().getKind()) {
2961 default:
2962 return MatchOperand_NoMatch;
2963 case AsmToken::LParen:
2964 case AsmToken::Plus:
2965 case AsmToken::Minus:
2966 case AsmToken::Integer:
2967 break;
2968 }
2969
2970 const MCExpr *Expr;
2971 SMLoc S = Parser.getTok().getLoc();
2972
2973 if (getParser().parseExpression(Expr))
2974 return MatchOperand_ParseFail;
2975
2976 int64_t Val;
2977 if (!Expr->EvaluateAsAbsolute(Val)) {
2978 Error(S, "expected immediate value");
2979 return MatchOperand_ParseFail;
2980 }
2981
2982 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2983 // and because the CPU always adds one to the immediate field, the allowed
2984 // range becomes 1..4. We'll only check the range here and will deal
2985 // with the addition/subtraction when actually decoding/encoding
2986 // the instruction.
2987 if (Val < 1 || Val > 4) {
2988 Error(S, "immediate not in range (1..4)");
2989 return MatchOperand_ParseFail;
2990 }
2991
Jack Carter3b2c96e2014-01-22 23:31:38 +00002992 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002993 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002994 return MatchOperand_Success;
2995}
2996
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002997MipsAsmParser::OperandMatchResultTy
2998MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2999 MCAsmParser &Parser = getParser();
3000 SmallVector<unsigned, 10> Regs;
3001 unsigned RegNo;
3002 unsigned PrevReg = Mips::NoRegister;
3003 bool RegRange = false;
3004 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3005
3006 if (Parser.getTok().isNot(AsmToken::Dollar))
3007 return MatchOperand_ParseFail;
3008
3009 SMLoc S = Parser.getTok().getLoc();
3010 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3011 SMLoc E = getLexer().getLoc();
3012 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3013 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3014 if (RegRange) {
3015 // Remove last register operand because registers from register range
3016 // should be inserted first.
3017 if (RegNo == Mips::RA) {
3018 Regs.push_back(RegNo);
3019 } else {
3020 unsigned TmpReg = PrevReg + 1;
3021 while (TmpReg <= RegNo) {
3022 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3023 Error(E, "invalid register operand");
3024 return MatchOperand_ParseFail;
3025 }
3026
3027 PrevReg = TmpReg;
3028 Regs.push_back(TmpReg++);
3029 }
3030 }
3031
3032 RegRange = false;
3033 } else {
3034 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3035 (RegNo != Mips::RA)) {
3036 Error(E, "$16 or $31 expected");
3037 return MatchOperand_ParseFail;
3038 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3039 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3040 Error(E, "invalid register operand");
3041 return MatchOperand_ParseFail;
3042 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3043 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3044 Error(E, "consecutive register numbers expected");
3045 return MatchOperand_ParseFail;
3046 }
3047
3048 Regs.push_back(RegNo);
3049 }
3050
3051 if (Parser.getTok().is(AsmToken::Minus))
3052 RegRange = true;
3053
3054 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3055 !Parser.getTok().isNot(AsmToken::Comma)) {
3056 Error(E, "',' or '-' expected");
3057 return MatchOperand_ParseFail;
3058 }
3059
3060 Lex(); // Consume comma or minus
3061 if (Parser.getTok().isNot(AsmToken::Dollar))
3062 break;
3063
3064 PrevReg = RegNo;
3065 }
3066
3067 SMLoc E = Parser.getTok().getLoc();
3068 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3069 parseMemOperand(Operands);
3070 return MatchOperand_Success;
3071}
3072
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003073MipsAsmParser::OperandMatchResultTy
3074MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3075 MCAsmParser &Parser = getParser();
3076
3077 SMLoc S = Parser.getTok().getLoc();
3078 if (parseAnyRegister(Operands) != MatchOperand_Success)
3079 return MatchOperand_ParseFail;
3080
3081 SMLoc E = Parser.getTok().getLoc();
3082 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3083 unsigned Reg = Op.getGPR32Reg();
3084 Operands.pop_back();
3085 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3086 return MatchOperand_Success;
3087}
3088
Zoran Jovanovic41688672015-02-10 16:36:20 +00003089MipsAsmParser::OperandMatchResultTy
3090MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3091 MCAsmParser &Parser = getParser();
3092 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3093 SmallVector<unsigned, 10> Regs;
3094
3095 if (Parser.getTok().isNot(AsmToken::Dollar))
3096 return MatchOperand_ParseFail;
3097
3098 SMLoc S = Parser.getTok().getLoc();
3099
3100 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3101 return MatchOperand_ParseFail;
3102
3103 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3104 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3105 Regs.push_back(RegNo);
3106
3107 SMLoc E = Parser.getTok().getLoc();
3108 if (Parser.getTok().isNot(AsmToken::Comma)) {
3109 Error(E, "',' expected");
3110 return MatchOperand_ParseFail;
3111 }
3112
3113 // Remove comma.
3114 Parser.Lex();
3115
3116 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3117 return MatchOperand_ParseFail;
3118
3119 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3120 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3121 Regs.push_back(RegNo);
3122
3123 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3124
3125 return MatchOperand_Success;
3126}
3127
Jack Carterdc1e35d2012-09-06 20:00:02 +00003128MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3129
Vladimir Medic4c299852013-11-06 11:27:05 +00003130 MCSymbolRefExpr::VariantKind VK =
3131 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3132 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3133 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3134 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3135 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3136 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3137 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3138 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3139 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3140 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3141 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3142 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3143 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3144 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3145 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3146 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3147 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3148 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003149 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3150 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3151 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3152 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3153 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3154 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003155 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3156 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003157 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003158
Matheus Almeida2852af82014-04-22 10:15:54 +00003159 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003160
Jack Carterdc1e35d2012-09-06 20:00:02 +00003161 return VK;
3162}
Jack Cartera63b16a2012-09-07 00:23:42 +00003163
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003164/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3165/// either this.
3166/// ::= '(', register, ')'
3167/// handle it before we iterate so we don't get tripped up by the lack of
3168/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003169bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003170 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003171 if (getLexer().is(AsmToken::LParen)) {
3172 Operands.push_back(
3173 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3174 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003175 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003176 SMLoc Loc = getLexer().getLoc();
3177 Parser.eatToEndOfStatement();
3178 return Error(Loc, "unexpected token in argument list");
3179 }
3180 if (Parser.getTok().isNot(AsmToken::RParen)) {
3181 SMLoc Loc = getLexer().getLoc();
3182 Parser.eatToEndOfStatement();
3183 return Error(Loc, "unexpected token, expected ')'");
3184 }
3185 Operands.push_back(
3186 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3187 Parser.Lex();
3188 }
3189 return false;
3190}
3191
3192/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3193/// either one of these.
3194/// ::= '[', register, ']'
3195/// ::= '[', integer, ']'
3196/// handle it before we iterate so we don't get tripped up by the lack of
3197/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003198bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003199 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003200 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003201 if (getLexer().is(AsmToken::LBrac)) {
3202 Operands.push_back(
3203 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3204 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003205 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003206 SMLoc Loc = getLexer().getLoc();
3207 Parser.eatToEndOfStatement();
3208 return Error(Loc, "unexpected token in argument list");
3209 }
3210 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3211 SMLoc Loc = getLexer().getLoc();
3212 Parser.eatToEndOfStatement();
3213 return Error(Loc, "unexpected token, expected ']'");
3214 }
3215 Operands.push_back(
3216 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3217 Parser.Lex();
3218 }
3219 return false;
3220}
3221
David Blaikie960ea3f2014-06-08 16:18:35 +00003222bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3223 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003224 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003225 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003226
3227 // We have reached first instruction, module directive are now forbidden.
3228 getTargetStreamer().forbidModuleDirective();
3229
Vladimir Medic74593e62013-07-17 15:00:42 +00003230 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003231 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003232 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003233 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003234 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003235 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003237
3238 // Read the remaining operands.
3239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3240 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003241 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003242 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003243 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003244 return Error(Loc, "unexpected token in argument list");
3245 }
Toma Tabacu13964452014-09-04 13:23:44 +00003246 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003247 return true;
3248 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003249
Jack Carterd0bd6422013-04-18 00:41:53 +00003250 while (getLexer().is(AsmToken::Comma)) {
3251 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003252 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003253 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003254 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003255 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003256 return Error(Loc, "unexpected token in argument list");
3257 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003258 // Parse bracket and parenthesis suffixes before we iterate
3259 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003260 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003261 return true;
3262 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003263 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003264 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003265 }
3266 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003267 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3268 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003269 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003270 return Error(Loc, "unexpected token in argument list");
3271 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003272 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003273 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003274}
3275
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003276bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003277 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003278 SMLoc Loc = getLexer().getLoc();
3279 Parser.eatToEndOfStatement();
3280 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003281}
3282
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003283bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003284 return Error(Loc, ErrorMsg);
3285}
3286
Jack Carter0b744b32012-10-04 02:29:46 +00003287bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003288 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003289 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003290
3291 // Set the $at register to $0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003292 AssemblerOptions.back()->setATReg(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003293
3294 Parser.Lex(); // Eat "noat".
3295
Jack Carterd0bd6422013-04-18 00:41:53 +00003296 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003298 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003299 return false;
3300 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003301
3302 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003304 return false;
3305}
Jack Carterd0bd6422013-04-18 00:41:53 +00003306
Jack Carter0b744b32012-10-04 02:29:46 +00003307bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003308 // Line can be: ".set at", which sets $at to $1
3309 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003310 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003311 Parser.Lex(); // Eat "at".
3312
Jack Carter0b744b32012-10-04 02:29:46 +00003313 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003314 // No register was specified, so we set $at to $1.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003315 AssemblerOptions.back()->setATReg(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003316
3317 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003318 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003319 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003320 }
3321
3322 if (getLexer().isNot(AsmToken::Equal)) {
3323 reportParseError("unexpected token, expected equals sign");
3324 return false;
3325 }
3326 Parser.Lex(); // Eat "=".
3327
3328 if (getLexer().isNot(AsmToken::Dollar)) {
3329 if (getLexer().is(AsmToken::EndOfStatement)) {
3330 reportParseError("no register specified");
3331 return false;
3332 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003333 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003334 return false;
3335 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003336 }
3337 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003338
Toma Tabacu16a74492015-02-13 10:30:57 +00003339 // Find out what "reg" is.
3340 unsigned AtRegNo;
3341 const AsmToken &Reg = Parser.getTok();
3342 if (Reg.is(AsmToken::Identifier)) {
3343 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3344 } else if (Reg.is(AsmToken::Integer)) {
3345 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003346 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003347 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003348 return false;
3349 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003350
3351 // Check if $reg is a valid register. If it is, set $at to $reg.
3352 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3353 reportParseError("invalid register");
3354 return false;
3355 }
3356 Parser.Lex(); // Eat "reg".
3357
3358 // If this is not the end of the statement, report an error.
3359 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3360 reportParseError("unexpected token, expected end of statement");
3361 return false;
3362 }
3363
3364 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3365
3366 Parser.Lex(); // Consume the EndOfStatement.
3367 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003368}
3369
3370bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003371 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003372 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003373 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003375 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003376 return false;
3377 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003378 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003379 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003380 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003381 return false;
3382}
3383
3384bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003385 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003386 Parser.Lex();
3387 // If this is not the end of the statement, report an error.
3388 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003389 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003390 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003391 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003392 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003393 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003394 Parser.Lex(); // Consume the EndOfStatement.
3395 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003396}
3397
3398bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003399 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003400 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003401 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003402 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003403 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003404 return false;
3405 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003406 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003407 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003408 return false;
3409}
3410
3411bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003412 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003413 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003414 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003416 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003417 return false;
3418 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003419 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003420 reportParseError("`noreorder' must be set before `nomacro'");
3421 return false;
3422 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003423 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003424 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003425 return false;
3426}
Jack Carterd76b2372013-03-21 21:44:16 +00003427
Daniel Sanders44934432014-08-07 12:03:36 +00003428bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003429 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003430 Parser.Lex();
3431
3432 // If this is not the end of the statement, report an error.
3433 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003434 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003435
3436 setFeatureBits(Mips::FeatureMSA, "msa");
3437 getTargetStreamer().emitDirectiveSetMsa();
3438 return false;
3439}
3440
3441bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003442 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003443 Parser.Lex();
3444
3445 // If this is not the end of the statement, report an error.
3446 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003447 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003448
3449 clearFeatureBits(Mips::FeatureMSA, "msa");
3450 getTargetStreamer().emitDirectiveSetNoMsa();
3451 return false;
3452}
3453
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003454bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003455 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003456 Parser.Lex(); // Eat "nodsp".
3457
3458 // If this is not the end of the statement, report an error.
3459 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3460 reportParseError("unexpected token, expected end of statement");
3461 return false;
3462 }
3463
3464 clearFeatureBits(Mips::FeatureDSP, "dsp");
3465 getTargetStreamer().emitDirectiveSetNoDsp();
3466 return false;
3467}
3468
Toma Tabacucc2502d2014-11-04 17:18:07 +00003469bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003470 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003471 Parser.Lex(); // Eat "mips16".
3472
Jack Carter39536722014-01-22 23:08:42 +00003473 // If this is not the end of the statement, report an error.
3474 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003475 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003476 return false;
3477 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003478
3479 setFeatureBits(Mips::FeatureMips16, "mips16");
3480 getTargetStreamer().emitDirectiveSetMips16();
3481 Parser.Lex(); // Consume the EndOfStatement.
3482 return false;
3483}
3484
3485bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003486 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003487 Parser.Lex(); // Eat "nomips16".
3488
3489 // If this is not the end of the statement, report an error.
3490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3491 reportParseError("unexpected token, expected end of statement");
3492 return false;
3493 }
3494
3495 clearFeatureBits(Mips::FeatureMips16, "mips16");
3496 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003497 Parser.Lex(); // Consume the EndOfStatement.
3498 return false;
3499}
3500
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003501bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003502 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003503 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003504 // Line can be: .set fp=32
3505 // .set fp=xx
3506 // .set fp=64
3507 Parser.Lex(); // Eat fp token
3508 AsmToken Tok = Parser.getTok();
3509 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003510 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003511 return false;
3512 }
3513 Parser.Lex(); // Eat '=' token.
3514 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003515
3516 if (!parseFpABIValue(FpAbiVal, ".set"))
3517 return false;
3518
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003520 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003521 return false;
3522 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003523 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003524 Parser.Lex(); // Consume the EndOfStatement.
3525 return false;
3526}
3527
Toma Tabacu9db22db2014-09-09 10:15:38 +00003528bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003529 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003530 SMLoc Loc = getLexer().getLoc();
3531
3532 Parser.Lex();
3533 if (getLexer().isNot(AsmToken::EndOfStatement))
3534 return reportParseError("unexpected token, expected end of statement");
3535
3536 // Always keep an element on the options "stack" to prevent the user
3537 // from changing the initial options. This is how we remember them.
3538 if (AssemblerOptions.size() == 2)
3539 return reportParseError(Loc, ".set pop with no .set push");
3540
3541 AssemblerOptions.pop_back();
3542 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3543
3544 getTargetStreamer().emitDirectiveSetPop();
3545 return false;
3546}
3547
3548bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003549 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003550 Parser.Lex();
3551 if (getLexer().isNot(AsmToken::EndOfStatement))
3552 return reportParseError("unexpected token, expected end of statement");
3553
3554 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003555 AssemblerOptions.push_back(
3556 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003557
3558 getTargetStreamer().emitDirectiveSetPush();
3559 return false;
3560}
3561
Jack Carterd76b2372013-03-21 21:44:16 +00003562bool MipsAsmParser::parseSetAssignment() {
3563 StringRef Name;
3564 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003565 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003566
3567 if (Parser.parseIdentifier(Name))
3568 reportParseError("expected identifier after .set");
3569
3570 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003571 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003572 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003573
Jack Carter3b2c96e2014-01-22 23:31:38 +00003574 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003575 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003576
Jack Carterd0bd6422013-04-18 00:41:53 +00003577 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003578 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003579 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003580 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003581 Sym = getContext().GetOrCreateSymbol(Name);
3582 Sym->setVariableValue(Value);
3583
3584 return false;
3585}
Jack Carterd0bd6422013-04-18 00:41:53 +00003586
Toma Tabacu26647792014-09-09 12:52:14 +00003587bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003588 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003589 Parser.Lex();
3590 if (getLexer().isNot(AsmToken::EndOfStatement))
3591 return reportParseError("unexpected token, expected end of statement");
3592
3593 // Reset assembler options to their initial values.
3594 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3595 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3596
3597 getTargetStreamer().emitDirectiveSetMips0();
3598 return false;
3599}
3600
Toma Tabacu85618b32014-08-19 14:22:52 +00003601bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003602 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003603 Parser.Lex();
3604 if (getLexer().isNot(AsmToken::Equal))
3605 return reportParseError("unexpected token, expected equals sign");
3606
3607 Parser.Lex();
3608 StringRef Arch;
3609 if (Parser.parseIdentifier(Arch))
3610 return reportParseError("expected arch identifier");
3611
3612 StringRef ArchFeatureName =
3613 StringSwitch<StringRef>(Arch)
3614 .Case("mips1", "mips1")
3615 .Case("mips2", "mips2")
3616 .Case("mips3", "mips3")
3617 .Case("mips4", "mips4")
3618 .Case("mips5", "mips5")
3619 .Case("mips32", "mips32")
3620 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003621 .Case("mips32r3", "mips32r3")
3622 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003623 .Case("mips32r6", "mips32r6")
3624 .Case("mips64", "mips64")
3625 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003626 .Case("mips64r3", "mips64r3")
3627 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003628 .Case("mips64r6", "mips64r6")
3629 .Case("cnmips", "cnmips")
3630 .Case("r4000", "mips3") // This is an implementation of Mips3.
3631 .Default("");
3632
3633 if (ArchFeatureName.empty())
3634 return reportParseError("unsupported architecture");
3635
3636 selectArch(ArchFeatureName);
3637 getTargetStreamer().emitDirectiveSetArch(Arch);
3638 return false;
3639}
3640
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003641bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003642 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003643 Parser.Lex();
3644 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003645 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003646
Matheus Almeida2852af82014-04-22 10:15:54 +00003647 switch (Feature) {
3648 default:
3649 llvm_unreachable("Unimplemented feature");
3650 case Mips::FeatureDSP:
3651 setFeatureBits(Mips::FeatureDSP, "dsp");
3652 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003653 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003654 case Mips::FeatureMicroMips:
3655 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003656 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003657 case Mips::FeatureMips1:
3658 selectArch("mips1");
3659 getTargetStreamer().emitDirectiveSetMips1();
3660 break;
3661 case Mips::FeatureMips2:
3662 selectArch("mips2");
3663 getTargetStreamer().emitDirectiveSetMips2();
3664 break;
3665 case Mips::FeatureMips3:
3666 selectArch("mips3");
3667 getTargetStreamer().emitDirectiveSetMips3();
3668 break;
3669 case Mips::FeatureMips4:
3670 selectArch("mips4");
3671 getTargetStreamer().emitDirectiveSetMips4();
3672 break;
3673 case Mips::FeatureMips5:
3674 selectArch("mips5");
3675 getTargetStreamer().emitDirectiveSetMips5();
3676 break;
3677 case Mips::FeatureMips32:
3678 selectArch("mips32");
3679 getTargetStreamer().emitDirectiveSetMips32();
3680 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003681 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003682 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003683 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003684 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003685 case Mips::FeatureMips32r3:
3686 selectArch("mips32r3");
3687 getTargetStreamer().emitDirectiveSetMips32R3();
3688 break;
3689 case Mips::FeatureMips32r5:
3690 selectArch("mips32r5");
3691 getTargetStreamer().emitDirectiveSetMips32R5();
3692 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003693 case Mips::FeatureMips32r6:
3694 selectArch("mips32r6");
3695 getTargetStreamer().emitDirectiveSetMips32R6();
3696 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003697 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003698 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003699 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003700 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003701 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003702 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003703 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003704 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003705 case Mips::FeatureMips64r3:
3706 selectArch("mips64r3");
3707 getTargetStreamer().emitDirectiveSetMips64R3();
3708 break;
3709 case Mips::FeatureMips64r5:
3710 selectArch("mips64r5");
3711 getTargetStreamer().emitDirectiveSetMips64R5();
3712 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003713 case Mips::FeatureMips64r6:
3714 selectArch("mips64r6");
3715 getTargetStreamer().emitDirectiveSetMips64R6();
3716 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003717 }
3718 return false;
3719}
3720
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003721bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003722 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003723 if (getLexer().isNot(AsmToken::Comma)) {
3724 SMLoc Loc = getLexer().getLoc();
3725 Parser.eatToEndOfStatement();
3726 return Error(Loc, ErrorStr);
3727 }
3728
Matheus Almeida2852af82014-04-22 10:15:54 +00003729 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003730 return true;
3731}
3732
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003733bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003734 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003735 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003736
Toma Tabacudde4c462014-11-06 10:02:45 +00003737 if (inMips16Mode()) {
3738 reportParseError(".cpload is not supported in Mips16 mode");
3739 return false;
3740 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003741
David Blaikie960ea3f2014-06-08 16:18:35 +00003742 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003743 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003744 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3745 reportParseError("expected register containing function address");
3746 return false;
3747 }
3748
David Blaikie960ea3f2014-06-08 16:18:35 +00003749 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3750 if (!RegOpnd.isGPRAsmReg()) {
3751 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003752 return false;
3753 }
3754
Toma Tabacudde4c462014-11-06 10:02:45 +00003755 // If this is not the end of the statement, report an error.
3756 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3757 reportParseError("unexpected token, expected end of statement");
3758 return false;
3759 }
3760
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003761 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003762 return false;
3763}
3764
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003765bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003766 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003767 unsigned FuncReg;
3768 unsigned Save;
3769 bool SaveIsReg = true;
3770
Matheus Almeida7e815762014-06-18 13:08:59 +00003771 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003772 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003773 if (ResTy == MatchOperand_NoMatch) {
3774 reportParseError("expected register containing function address");
3775 Parser.eatToEndOfStatement();
3776 return false;
3777 }
3778
3779 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3780 if (!FuncRegOpnd.isGPRAsmReg()) {
3781 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3782 Parser.eatToEndOfStatement();
3783 return false;
3784 }
3785
3786 FuncReg = FuncRegOpnd.getGPR32Reg();
3787 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003788
Toma Tabacu65f10572014-09-16 15:00:52 +00003789 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003790 return true;
3791
Toma Tabacu13964452014-09-04 13:23:44 +00003792 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003793 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003794 const AsmToken &Tok = Parser.getTok();
3795 if (Tok.is(AsmToken::Integer)) {
3796 Save = Tok.getIntVal();
3797 SaveIsReg = false;
3798 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003799 } else {
3800 reportParseError("expected save register or stack offset");
3801 Parser.eatToEndOfStatement();
3802 return false;
3803 }
3804 } else {
3805 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3806 if (!SaveOpnd.isGPRAsmReg()) {
3807 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3808 Parser.eatToEndOfStatement();
3809 return false;
3810 }
3811 Save = SaveOpnd.getGPR32Reg();
3812 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003813
Toma Tabacu65f10572014-09-16 15:00:52 +00003814 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003815 return true;
3816
Toma Tabacu8874eac2015-02-18 13:46:53 +00003817 const MCExpr *Expr;
3818 if (Parser.parseExpression(Expr)) {
3819 reportParseError("expected expression");
3820 return false;
3821 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003822
Toma Tabacu8874eac2015-02-18 13:46:53 +00003823 if (Expr->getKind() != MCExpr::SymbolRef) {
3824 reportParseError("expected symbol");
3825 return false;
3826 }
3827 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3828
3829 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3830 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003831 return false;
3832}
3833
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003834bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003835 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003836 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3837 const AsmToken &Tok = Parser.getTok();
3838
3839 if (Tok.getString() == "2008") {
3840 Parser.Lex();
3841 getTargetStreamer().emitDirectiveNaN2008();
3842 return false;
3843 } else if (Tok.getString() == "legacy") {
3844 Parser.Lex();
3845 getTargetStreamer().emitDirectiveNaNLegacy();
3846 return false;
3847 }
3848 }
3849 // If we don't recognize the option passed to the .nan
3850 // directive (e.g. no option or unknown option), emit an error.
3851 reportParseError("invalid option in .nan directive");
3852 return false;
3853}
3854
Jack Carter0b744b32012-10-04 02:29:46 +00003855bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003856 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003857 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003858 const AsmToken &Tok = Parser.getTok();
3859
3860 if (Tok.getString() == "noat") {
3861 return parseSetNoAtDirective();
3862 } else if (Tok.getString() == "at") {
3863 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003864 } else if (Tok.getString() == "arch") {
3865 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003866 } else if (Tok.getString() == "fp") {
3867 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003868 } else if (Tok.getString() == "pop") {
3869 return parseSetPopDirective();
3870 } else if (Tok.getString() == "push") {
3871 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003872 } else if (Tok.getString() == "reorder") {
3873 return parseSetReorderDirective();
3874 } else if (Tok.getString() == "noreorder") {
3875 return parseSetNoReorderDirective();
3876 } else if (Tok.getString() == "macro") {
3877 return parseSetMacroDirective();
3878 } else if (Tok.getString() == "nomacro") {
3879 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003880 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003881 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003882 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003883 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003884 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003885 getTargetStreamer().emitDirectiveSetNoMicroMips();
3886 Parser.eatToEndOfStatement();
3887 return false;
3888 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003889 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003890 } else if (Tok.getString() == "mips0") {
3891 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003892 } else if (Tok.getString() == "mips1") {
3893 return parseSetFeature(Mips::FeatureMips1);
3894 } else if (Tok.getString() == "mips2") {
3895 return parseSetFeature(Mips::FeatureMips2);
3896 } else if (Tok.getString() == "mips3") {
3897 return parseSetFeature(Mips::FeatureMips3);
3898 } else if (Tok.getString() == "mips4") {
3899 return parseSetFeature(Mips::FeatureMips4);
3900 } else if (Tok.getString() == "mips5") {
3901 return parseSetFeature(Mips::FeatureMips5);
3902 } else if (Tok.getString() == "mips32") {
3903 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003904 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003905 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003906 } else if (Tok.getString() == "mips32r3") {
3907 return parseSetFeature(Mips::FeatureMips32r3);
3908 } else if (Tok.getString() == "mips32r5") {
3909 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003910 } else if (Tok.getString() == "mips32r6") {
3911 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003912 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003913 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003914 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003915 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003916 } else if (Tok.getString() == "mips64r3") {
3917 return parseSetFeature(Mips::FeatureMips64r3);
3918 } else if (Tok.getString() == "mips64r5") {
3919 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003920 } else if (Tok.getString() == "mips64r6") {
3921 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003922 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003923 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003924 } else if (Tok.getString() == "nodsp") {
3925 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003926 } else if (Tok.getString() == "msa") {
3927 return parseSetMsaDirective();
3928 } else if (Tok.getString() == "nomsa") {
3929 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003930 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003931 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003932 parseSetAssignment();
3933 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003934 }
Jack Carter07c818d2013-01-25 01:31:34 +00003935
Jack Carter0b744b32012-10-04 02:29:46 +00003936 return true;
3937}
3938
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003939/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003940/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003941bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003942 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003943 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3944 for (;;) {
3945 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003946 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003947 return true;
3948
3949 getParser().getStreamer().EmitValue(Value, Size);
3950
3951 if (getLexer().is(AsmToken::EndOfStatement))
3952 break;
3953
Jack Carter07c818d2013-01-25 01:31:34 +00003954 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003955 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003956 Parser.Lex();
3957 }
3958 }
3959
3960 Parser.Lex();
3961 return false;
3962}
3963
Vladimir Medic4c299852013-11-06 11:27:05 +00003964/// parseDirectiveGpWord
3965/// ::= .gpword local_sym
3966bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003967 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003968 const MCExpr *Value;
3969 // EmitGPRel32Value requires an expression, so we are using base class
3970 // method to evaluate the expression.
3971 if (getParser().parseExpression(Value))
3972 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003973 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003974
Vladimir Medice10c1122013-11-13 13:18:04 +00003975 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003976 return Error(getLexer().getLoc(),
3977 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003978 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003979 return false;
3980}
3981
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003982/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003983/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003984bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003985 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003986 const MCExpr *Value;
3987 // EmitGPRel64Value requires an expression, so we are using base class
3988 // method to evaluate the expression.
3989 if (getParser().parseExpression(Value))
3990 return true;
3991 getParser().getStreamer().EmitGPRel64Value(Value);
3992
3993 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003994 return Error(getLexer().getLoc(),
3995 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003996 Parser.Lex(); // Eat EndOfStatement token.
3997 return false;
3998}
3999
Jack Carter0cd3c192014-01-06 23:27:31 +00004000bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004001 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004002 // Get the option token.
4003 AsmToken Tok = Parser.getTok();
4004 // At the moment only identifiers are supported.
4005 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004006 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004007 Parser.eatToEndOfStatement();
4008 return false;
4009 }
4010
4011 StringRef Option = Tok.getIdentifier();
4012
4013 if (Option == "pic0") {
4014 getTargetStreamer().emitDirectiveOptionPic0();
4015 Parser.Lex();
4016 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4017 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004018 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004019 Parser.eatToEndOfStatement();
4020 }
4021 return false;
4022 }
4023
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004024 if (Option == "pic2") {
4025 getTargetStreamer().emitDirectiveOptionPic2();
4026 Parser.Lex();
4027 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4028 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004029 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004030 Parser.eatToEndOfStatement();
4031 }
4032 return false;
4033 }
4034
Jack Carter0cd3c192014-01-06 23:27:31 +00004035 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004036 Warning(Parser.getTok().getLoc(),
4037 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004038 Parser.eatToEndOfStatement();
4039 return false;
4040}
4041
Daniel Sanders7e527422014-07-10 13:38:23 +00004042/// parseDirectiveModule
4043/// ::= .module oddspreg
4044/// ::= .module nooddspreg
4045/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004046bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004047 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004048 MCAsmLexer &Lexer = getLexer();
4049 SMLoc L = Lexer.getLoc();
4050
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004051 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004052 // TODO : get a better message.
4053 reportParseError(".module directive must appear before any code");
4054 return false;
4055 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004056
Toma Tabacuc405c822015-01-23 10:40:19 +00004057 StringRef Option;
4058 if (Parser.parseIdentifier(Option)) {
4059 reportParseError("expected .module option identifier");
4060 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004061 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004062
Toma Tabacuc405c822015-01-23 10:40:19 +00004063 if (Option == "oddspreg") {
4064 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4065 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
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 return false; // parseDirectiveModule has finished successfully.
4074 } else if (Option == "nooddspreg") {
4075 if (!isABI_O32()) {
4076 Error(L, "'.module nooddspreg' requires the O32 ABI");
4077 return false;
4078 }
4079
4080 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4081 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4082
4083 // If this is not the end of the statement, report an error.
4084 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4085 reportParseError("unexpected token, expected end of statement");
4086 return false;
4087 }
4088
4089 return false; // parseDirectiveModule has finished successfully.
4090 } else if (Option == "fp") {
4091 return parseDirectiveModuleFP();
4092 } else {
4093 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4094 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004095}
4096
4097/// parseDirectiveModuleFP
4098/// ::= =32
4099/// ::= =xx
4100/// ::= =64
4101bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004102 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004103 MCAsmLexer &Lexer = getLexer();
4104
4105 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004106 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004107 return false;
4108 }
4109 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004110
Daniel Sanders7e527422014-07-10 13:38:23 +00004111 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004112 if (!parseFpABIValue(FpABI, ".module"))
4113 return false;
4114
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004116 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004117 return false;
4118 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004119
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004120 // Emit appropriate flags.
4121 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004122 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004123 return false;
4124}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004125
Daniel Sanders7e527422014-07-10 13:38:23 +00004126bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004127 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004128 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004129 MCAsmLexer &Lexer = getLexer();
4130
4131 if (Lexer.is(AsmToken::Identifier)) {
4132 StringRef Value = Parser.getTok().getString();
4133 Parser.Lex();
4134
4135 if (Value != "xx") {
4136 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4137 return false;
4138 }
4139
4140 if (!isABI_O32()) {
4141 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4142 return false;
4143 }
4144
Daniel Sanders7e527422014-07-10 13:38:23 +00004145 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004146 return true;
4147 }
4148
4149 if (Lexer.is(AsmToken::Integer)) {
4150 unsigned Value = Parser.getTok().getIntVal();
4151 Parser.Lex();
4152
4153 if (Value != 32 && Value != 64) {
4154 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4155 return false;
4156 }
4157
4158 if (Value == 32) {
4159 if (!isABI_O32()) {
4160 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4161 return false;
4162 }
4163
Daniel Sanders7e527422014-07-10 13:38:23 +00004164 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4165 } else
4166 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004167
Daniel Sanders7e527422014-07-10 13:38:23 +00004168 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004169 }
4170
4171 return false;
4172}
4173
Jack Carter0b744b32012-10-04 02:29:46 +00004174bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004175 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004176 StringRef IDVal = DirectiveID.getString();
4177
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004178 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004179 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004180 if (IDVal == ".dword") {
4181 parseDataDirective(8, DirectiveID.getLoc());
4182 return false;
4183 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004184 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004185 StringRef SymbolName;
4186
4187 if (Parser.parseIdentifier(SymbolName)) {
4188 reportParseError("expected identifier after .ent");
4189 return false;
4190 }
4191
4192 // There's an undocumented extension that allows an integer to
4193 // follow the name of the procedure which AFAICS is ignored by GAS.
4194 // Example: .ent foo,2
4195 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4196 if (getLexer().isNot(AsmToken::Comma)) {
4197 // Even though we accept this undocumented extension for compatibility
4198 // reasons, the additional integer argument does not actually change
4199 // the behaviour of the '.ent' directive, so we would like to discourage
4200 // its use. We do this by not referring to the extended version in
4201 // error messages which are not directly related to its use.
4202 reportParseError("unexpected token, expected end of statement");
4203 return false;
4204 }
4205 Parser.Lex(); // Eat the comma.
4206 const MCExpr *DummyNumber;
4207 int64_t DummyNumberVal;
4208 // If the user was explicitly trying to use the extended version,
4209 // we still give helpful extension-related error messages.
4210 if (Parser.parseExpression(DummyNumber)) {
4211 reportParseError("expected number after comma");
4212 return false;
4213 }
4214 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4215 reportParseError("expected an absolute expression after comma");
4216 return false;
4217 }
4218 }
4219
4220 // If this is not the end of the statement, report an error.
4221 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4222 reportParseError("unexpected token, expected end of statement");
4223 return false;
4224 }
4225
4226 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4227
4228 getTargetStreamer().emitDirectiveEnt(*Sym);
4229 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004230 return false;
4231 }
4232
Jack Carter07c818d2013-01-25 01:31:34 +00004233 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004234 StringRef SymbolName;
4235
4236 if (Parser.parseIdentifier(SymbolName)) {
4237 reportParseError("expected identifier after .end");
4238 return false;
4239 }
4240
4241 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4242 reportParseError("unexpected token, expected end of statement");
4243 return false;
4244 }
4245
4246 if (CurrentFn == nullptr) {
4247 reportParseError(".end used without .ent");
4248 return false;
4249 }
4250
4251 if ((SymbolName != CurrentFn->getName())) {
4252 reportParseError(".end symbol does not match .ent symbol");
4253 return false;
4254 }
4255
4256 getTargetStreamer().emitDirectiveEnd(SymbolName);
4257 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004258 return false;
4259 }
4260
Jack Carter07c818d2013-01-25 01:31:34 +00004261 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004262 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4263 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004264 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004265 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4266 reportParseError("expected stack register");
4267 return false;
4268 }
4269
4270 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4271 if (!StackRegOpnd.isGPRAsmReg()) {
4272 reportParseError(StackRegOpnd.getStartLoc(),
4273 "expected general purpose register");
4274 return false;
4275 }
4276 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4277
4278 if (Parser.getTok().is(AsmToken::Comma))
4279 Parser.Lex();
4280 else {
4281 reportParseError("unexpected token, expected comma");
4282 return false;
4283 }
4284
4285 // Parse the frame size.
4286 const MCExpr *FrameSize;
4287 int64_t FrameSizeVal;
4288
4289 if (Parser.parseExpression(FrameSize)) {
4290 reportParseError("expected frame size value");
4291 return false;
4292 }
4293
4294 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4295 reportParseError("frame size not an absolute expression");
4296 return false;
4297 }
4298
4299 if (Parser.getTok().is(AsmToken::Comma))
4300 Parser.Lex();
4301 else {
4302 reportParseError("unexpected token, expected comma");
4303 return false;
4304 }
4305
4306 // Parse the return register.
4307 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004308 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004309 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4310 reportParseError("expected return register");
4311 return false;
4312 }
4313
4314 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4315 if (!ReturnRegOpnd.isGPRAsmReg()) {
4316 reportParseError(ReturnRegOpnd.getStartLoc(),
4317 "expected general purpose register");
4318 return false;
4319 }
4320
4321 // If this is not the end of the statement, report an error.
4322 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4323 reportParseError("unexpected token, expected end of statement");
4324 return false;
4325 }
4326
4327 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4328 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004329 return false;
4330 }
4331
Jack Carter07c818d2013-01-25 01:31:34 +00004332 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004333 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004334 }
4335
Daniel Sandersd97a6342014-08-13 10:07:34 +00004336 if (IDVal == ".mask" || IDVal == ".fmask") {
4337 // .mask bitmask, frame_offset
4338 // bitmask: One bit for each register used.
4339 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4340 // first register is expected to be saved.
4341 // Examples:
4342 // .mask 0x80000000, -4
4343 // .fmask 0x80000000, -4
4344 //
Jack Carterbe332172012-09-07 00:48:02 +00004345
Daniel Sandersd97a6342014-08-13 10:07:34 +00004346 // Parse the bitmask
4347 const MCExpr *BitMask;
4348 int64_t BitMaskVal;
4349
4350 if (Parser.parseExpression(BitMask)) {
4351 reportParseError("expected bitmask value");
4352 return false;
4353 }
4354
4355 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4356 reportParseError("bitmask not an absolute expression");
4357 return false;
4358 }
4359
4360 if (Parser.getTok().is(AsmToken::Comma))
4361 Parser.Lex();
4362 else {
4363 reportParseError("unexpected token, expected comma");
4364 return false;
4365 }
4366
4367 // Parse the frame_offset
4368 const MCExpr *FrameOffset;
4369 int64_t FrameOffsetVal;
4370
4371 if (Parser.parseExpression(FrameOffset)) {
4372 reportParseError("expected frame offset value");
4373 return false;
4374 }
4375
4376 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4377 reportParseError("frame offset not an absolute expression");
4378 return false;
4379 }
4380
4381 // If this is not the end of the statement, report an error.
4382 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4383 reportParseError("unexpected token, expected end of statement");
4384 return false;
4385 }
4386
4387 if (IDVal == ".mask")
4388 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4389 else
4390 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004391 return false;
4392 }
4393
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004394 if (IDVal == ".nan")
4395 return parseDirectiveNaN();
4396
Jack Carter07c818d2013-01-25 01:31:34 +00004397 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004398 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004399 return false;
4400 }
4401
Rafael Espindolab59fb732014-03-28 18:50:26 +00004402 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004403 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004404 return false;
4405 }
4406
Jack Carter07c818d2013-01-25 01:31:34 +00004407 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004408 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004409 return false;
4410 }
4411
Jack Carter0cd3c192014-01-06 23:27:31 +00004412 if (IDVal == ".option")
4413 return parseDirectiveOption();
4414
4415 if (IDVal == ".abicalls") {
4416 getTargetStreamer().emitDirectiveAbiCalls();
4417 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004418 Error(Parser.getTok().getLoc(),
4419 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004420 // Clear line
4421 Parser.eatToEndOfStatement();
4422 }
4423 return false;
4424 }
4425
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004426 if (IDVal == ".cpsetup")
4427 return parseDirectiveCPSetup();
4428
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004429 if (IDVal == ".module")
4430 return parseDirectiveModule();
4431
Rafael Espindola870c4e92012-01-11 03:56:41 +00004432 return true;
4433}
4434
Rafael Espindola870c4e92012-01-11 03:56:41 +00004435extern "C" void LLVMInitializeMipsAsmParser() {
4436 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4437 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4438 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4439 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4440}
Jack Carterb4dbc172012-09-05 23:34:03 +00004441
4442#define GET_REGISTER_MATCHER
4443#define GET_MATCHER_IMPLEMENTATION
4444#include "MipsGenAsmMatcher.inc"