blob: 51de707d949aa7ccecaef3b568a64d1bc499d5c3 [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.
Michael Kupersteinefd7a962015-02-19 11:38:11 +000074 static const uint64_t AllArchRelatedMask =
75 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
76 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
77 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
78 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
79 Mips::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
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000239 bool parseInternalDirectiveReallowModule();
240
Jack Carterdc1e35d2012-09-06 20:00:02 +0000241 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000242
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000243 bool eatComma(StringRef ErrorStr);
244
Jack Carter1ac53222013-02-20 23:11:17 +0000245 int matchCPURegisterName(StringRef Symbol);
246
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000247 int matchHWRegsRegisterName(StringRef Symbol);
248
Jack Carter873c7242013-01-12 01:03:14 +0000249 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000250
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000251 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000252
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000253 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000254
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000255 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000256
Jack Carter5dc8ac92013-09-25 23:50:44 +0000257 int matchMSA128RegisterName(StringRef Name);
258
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000259 int matchMSA128CtrlRegisterName(StringRef Name);
260
Jack Carterd0bd6422013-04-18 00:41:53 +0000261 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000262
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000263 unsigned getGPR(int RegNo);
264
Matheus Almeida7de68e72014-06-18 14:46:05 +0000265 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000266
267 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000268 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000269
270 // Helper function that checks if the value of a vector index is within the
271 // boundaries of accepted values for each RegisterKind
272 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
273 bool validateMSAIndex(int Val, int RegKind);
274
Daniel Sandersf0df2212014-08-04 12:20:00 +0000275 // Selects a new architecture by updating the FeatureBits with the necessary
276 // info including implied dependencies.
277 // Internally, it clears all the feature bits related to *any* architecture
278 // and selects the new one using the ToggleFeature functionality of the
279 // MCSubtargetInfo object that handles implied dependencies. The reason we
280 // clear all the arch related bits manually is because ToggleFeature only
281 // clears the features that imply the feature being cleared and not the
282 // features implied by the feature being cleared. This is easier to see
283 // with an example:
284 // --------------------------------------------------
285 // | Feature | Implies |
286 // | -------------------------------------------------|
287 // | FeatureMips1 | None |
288 // | FeatureMips2 | FeatureMips1 |
289 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
290 // | FeatureMips4 | FeatureMips3 |
291 // | ... | |
292 // --------------------------------------------------
293 //
294 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
295 // FeatureMipsGP64 | FeatureMips1)
296 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
297 void selectArch(StringRef ArchFeature) {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000298 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000299 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
300 STI.setFeatureBits(FeatureBits);
301 setAvailableFeatures(
302 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000303 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000304 }
305
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000306 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000307 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000308 setAvailableFeatures(
309 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000310 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000311 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000312 }
313
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000314 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000315 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000316 setAvailableFeatures(
317 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000318 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000319 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000320 }
321
Rafael Espindola870c4e92012-01-11 03:56:41 +0000322public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000323 enum MipsMatchResultTy {
324 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
325#define GET_OPERAND_DIAGNOSTIC_TYPES
326#include "MipsGenAsmMatcher.inc"
327#undef GET_OPERAND_DIAGNOSTIC_TYPES
328
329 };
330
Joey Gouly0e76fa72013-09-12 10:28:05 +0000331 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000332 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000333 : MCTargetAsmParser(), STI(sti),
334 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
335 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000336 MCAsmParserExtension::Initialize(parser);
337
Jack Carterb4dbc172012-09-05 23:34:03 +0000338 // Initialize the set of available features.
339 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000340
341 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000342 AssemblerOptions.push_back(
343 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000344
345 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000346 AssemblerOptions.push_back(
347 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000348
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000349 getTargetStreamer().updateABIInfo(*this);
350
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000351 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000352 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000353
354 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000355 }
356
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000357 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
358 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
359
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000360 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
361 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000362 const MipsABIInfo &getABI() const { return ABI; }
363 bool isABI_N32() const { return ABI.IsN32(); }
364 bool isABI_N64() const { return ABI.IsN64(); }
365 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000366 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000367
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000368 bool useOddSPReg() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000369 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000370 }
371
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000372 bool inMicroMipsMode() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000373 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000374 }
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000375 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
376 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
377 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
378 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
379 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000380 bool hasMips32() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000381 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000382 }
383 bool hasMips64() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000384 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000385 }
386 bool hasMips32r2() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000387 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000388 }
389 bool hasMips64r2() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000390 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000391 }
Daniel Sanders17793142015-02-18 16:24:50 +0000392 bool hasMips32r3() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000393 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000394 }
395 bool hasMips64r3() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000396 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000397 }
398 bool hasMips32r5() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000399 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000400 }
401 bool hasMips64r5() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000402 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000403 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 bool hasMips32r6() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000405 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000406 }
407 bool hasMips64r6() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000408 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
Kai Nackee0245392015-01-27 19:11:28 +0000410 bool hasCnMips() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000411 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000412 }
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000413 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
414 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
415 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000416
417 bool inMips16Mode() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000418 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000419 }
420 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000421 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000422
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000423 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000424 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000425};
426}
427
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000428namespace {
429
430/// MipsOperand - Instances of this class represent a parsed Mips machine
431/// instruction.
432class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000433public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000434 /// Broad categories of register classes
435 /// The exact class is finalized by the render method.
436 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000437 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000438 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000440 RegKind_FCC = 4, /// FCC
441 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
442 RegKind_MSACtrl = 16, /// MSA control registers
443 RegKind_COP2 = 32, /// COP2
444 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
445 /// context).
446 RegKind_CCR = 128, /// CCR
447 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000448 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000449
450 /// Potentially any (e.g. $1)
451 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
452 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000453 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000454 };
455
456private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000457 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000458 k_Immediate, /// An immediate (possibly involving symbol references)
459 k_Memory, /// Base + Offset Memory Address
460 k_PhysRegister, /// A physical register from the Mips namespace
461 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000462 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000463 k_RegList, /// A physical register list
464 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000465 } Kind;
466
David Blaikie960ea3f2014-06-08 16:18:35 +0000467public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000468 MipsOperand(KindTy K, MipsAsmParser &Parser)
469 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
470
David Blaikie960ea3f2014-06-08 16:18:35 +0000471private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000472 /// For diagnostics, and checking the assembler temporary
473 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000474
Eric Christopher8996c5d2013-03-15 00:42:55 +0000475 struct Token {
476 const char *Data;
477 unsigned Length;
478 };
479
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000480 struct PhysRegOp {
481 unsigned Num; /// Register Number
482 };
483
484 struct RegIdxOp {
485 unsigned Index; /// Index into the register class
486 RegKind Kind; /// Bitfield of the kinds it could possibly be
487 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000488 };
489
490 struct ImmOp {
491 const MCExpr *Val;
492 };
493
494 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000495 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000496 const MCExpr *Off;
497 };
498
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000499 struct RegListOp {
500 SmallVector<unsigned, 10> *List;
501 };
502
Jack Carterb4dbc172012-09-05 23:34:03 +0000503 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000504 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 struct PhysRegOp PhysReg;
506 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000507 struct ImmOp Imm;
508 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000509 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000510 };
511
512 SMLoc StartLoc, EndLoc;
513
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000514 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000515 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
516 const MCRegisterInfo *RegInfo,
517 SMLoc S, SMLoc E,
518 MipsAsmParser &Parser) {
519 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000520 Op->RegIdx.Index = Index;
521 Op->RegIdx.RegInfo = RegInfo;
522 Op->RegIdx.Kind = RegKind;
523 Op->StartLoc = S;
524 Op->EndLoc = E;
525 return Op;
526 }
527
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000528public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000529 /// Coerce the register to GPR32 and return the real register for the current
530 /// target.
531 unsigned getGPR32Reg() const {
532 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000533 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000534 unsigned ClassID = Mips::GPR32RegClassID;
535 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000536 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000537
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000538 /// Coerce the register to GPR32 and return the real register for the current
539 /// target.
540 unsigned getGPRMM16Reg() const {
541 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
542 unsigned ClassID = Mips::GPR32RegClassID;
543 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
544 }
545
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000546 /// Coerce the register to GPR64 and return the real register for the current
547 /// target.
548 unsigned getGPR64Reg() const {
549 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
550 unsigned ClassID = Mips::GPR64RegClassID;
551 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000552 }
553
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000554private:
555 /// Coerce the register to AFGR64 and return the real register for the current
556 /// target.
557 unsigned getAFGR64Reg() const {
558 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
559 if (RegIdx.Index % 2 != 0)
560 AsmParser.Warning(StartLoc, "Float register should be even.");
561 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
562 .getRegister(RegIdx.Index / 2);
563 }
564
565 /// Coerce the register to FGR64 and return the real register for the current
566 /// target.
567 unsigned getFGR64Reg() const {
568 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
569 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
570 .getRegister(RegIdx.Index);
571 }
572
573 /// Coerce the register to FGR32 and return the real register for the current
574 /// target.
575 unsigned getFGR32Reg() const {
576 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
577 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
578 .getRegister(RegIdx.Index);
579 }
580
581 /// Coerce the register to FGRH32 and return the real register for the current
582 /// target.
583 unsigned getFGRH32Reg() const {
584 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
585 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
586 .getRegister(RegIdx.Index);
587 }
588
589 /// Coerce the register to FCC and return the real register for the current
590 /// target.
591 unsigned getFCCReg() const {
592 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
593 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
594 .getRegister(RegIdx.Index);
595 }
596
597 /// Coerce the register to MSA128 and return the real register for the current
598 /// target.
599 unsigned getMSA128Reg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
601 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
602 // identical
603 unsigned ClassID = Mips::MSA128BRegClassID;
604 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
605 }
606
607 /// Coerce the register to MSACtrl and return the real register for the
608 /// current target.
609 unsigned getMSACtrlReg() const {
610 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
611 unsigned ClassID = Mips::MSACtrlRegClassID;
612 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
613 }
614
615 /// Coerce the register to COP2 and return the real register for the
616 /// current target.
617 unsigned getCOP2Reg() const {
618 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
619 unsigned ClassID = Mips::COP2RegClassID;
620 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
621 }
622
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000623 /// Coerce the register to COP3 and return the real register for the
624 /// current target.
625 unsigned getCOP3Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
627 unsigned ClassID = Mips::COP3RegClassID;
628 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
629 }
630
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 /// Coerce the register to ACC64DSP and return the real register for the
632 /// current target.
633 unsigned getACC64DSPReg() const {
634 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
635 unsigned ClassID = Mips::ACC64DSPRegClassID;
636 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
637 }
638
639 /// Coerce the register to HI32DSP and return the real register for the
640 /// current target.
641 unsigned getHI32DSPReg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
643 unsigned ClassID = Mips::HI32DSPRegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
645 }
646
647 /// Coerce the register to LO32DSP and return the real register for the
648 /// current target.
649 unsigned getLO32DSPReg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
651 unsigned ClassID = Mips::LO32DSPRegClassID;
652 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
653 }
654
655 /// Coerce the register to CCR and return the real register for the
656 /// current target.
657 unsigned getCCRReg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
659 unsigned ClassID = Mips::CCRRegClassID;
660 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
661 }
662
663 /// Coerce the register to HWRegs and return the real register for the
664 /// current target.
665 unsigned getHWRegsReg() const {
666 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
667 unsigned ClassID = Mips::HWRegsRegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
669 }
670
671public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000672 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000673 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000674 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000675 Inst.addOperand(MCOperand::CreateImm(0));
676 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
677 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
678 else
679 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000680 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000681
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 void addRegOperands(MCInst &Inst, unsigned N) const {
683 llvm_unreachable("Use a custom parser instead");
684 }
685
Daniel Sanders21bce302014-04-01 12:35:23 +0000686 /// Render the operand to an MCInst as a GPR32
687 /// Asserts if the wrong number of operands are requested, or the operand
688 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000689 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
692 }
693
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000694 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
695 assert(N == 1 && "Invalid number of operands!");
696 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
697 }
698
Jozef Kolek1904fa22014-11-24 14:25:53 +0000699 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
700 assert(N == 1 && "Invalid number of operands!");
701 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
702 }
703
Zoran Jovanovic41688672015-02-10 16:36:20 +0000704 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
705 assert(N == 1 && "Invalid number of operands!");
706 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
707 }
708
Daniel Sanders21bce302014-04-01 12:35:23 +0000709 /// Render the operand to an MCInst as a GPR64
710 /// Asserts if the wrong number of operands are requested, or the operand
711 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000712 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
713 assert(N == 1 && "Invalid number of operands!");
714 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
715 }
716
717 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
718 assert(N == 1 && "Invalid number of operands!");
719 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
720 }
721
722 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
724 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
725 }
726
727 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
728 assert(N == 1 && "Invalid number of operands!");
729 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000730 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000731 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000732 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
733 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 }
735
736 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
737 assert(N == 1 && "Invalid number of operands!");
738 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
739 }
740
741 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
742 assert(N == 1 && "Invalid number of operands!");
743 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
744 }
745
746 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
747 assert(N == 1 && "Invalid number of operands!");
748 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
749 }
750
751 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
752 assert(N == 1 && "Invalid number of operands!");
753 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
754 }
755
756 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
757 assert(N == 1 && "Invalid number of operands!");
758 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
759 }
760
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000761 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
762 assert(N == 1 && "Invalid number of operands!");
763 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
764 }
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
767 assert(N == 1 && "Invalid number of operands!");
768 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
769 }
770
771 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
772 assert(N == 1 && "Invalid number of operands!");
773 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
774 }
775
776 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
777 assert(N == 1 && "Invalid number of operands!");
778 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
779 }
780
781 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
783 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
784 }
785
786 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
788 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
789 }
790
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000791 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000792 assert(N == 1 && "Invalid number of operands!");
793 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000794 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000795 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000796
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000797 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000798 assert(N == 2 && "Invalid number of operands!");
799
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000801
802 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000803 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000804 }
805
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000806 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
807 assert(N == 2 && "Invalid number of operands!");
808
809 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
810
811 const MCExpr *Expr = getMemOff();
812 addExpr(Inst, Expr);
813 }
814
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000815 void addRegListOperands(MCInst &Inst, unsigned N) const {
816 assert(N == 1 && "Invalid number of operands!");
817
818 for (auto RegNo : getRegList())
819 Inst.addOperand(MCOperand::CreateReg(RegNo));
820 }
821
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000822 void addRegPairOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 2 && "Invalid number of operands!");
824 unsigned RegNo = getRegPair();
825 Inst.addOperand(MCOperand::CreateReg(RegNo++));
826 Inst.addOperand(MCOperand::CreateReg(RegNo));
827 }
828
Zoran Jovanovic41688672015-02-10 16:36:20 +0000829 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
830 assert(N == 2 && "Invalid number of operands!");
831 for (auto RegNo : getRegList())
832 Inst.addOperand(MCOperand::CreateReg(RegNo));
833 }
834
Craig Topper56c590a2014-04-29 07:58:02 +0000835 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 // As a special case until we sort out the definition of div/divu, pretend
837 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
838 if (isGPRAsmReg() && RegIdx.Index == 0)
839 return true;
840
841 return Kind == k_PhysRegister;
842 }
843 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000844 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 bool isConstantImm() const {
846 return isImm() && dyn_cast<MCConstantExpr>(getImm());
847 }
Craig Topper56c590a2014-04-29 07:58:02 +0000848 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000849 // Note: It's not possible to pretend that other operand kinds are tokens.
850 // The matcher emitter checks tokens first.
851 return Kind == k_Token;
852 }
Craig Topper56c590a2014-04-29 07:58:02 +0000853 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000854 bool isConstantMemOff() const {
855 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
856 }
857 template <unsigned Bits> bool isMemWithSimmOffset() const {
858 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
859 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000860 bool isMemWithGRPMM16Base() const {
861 return isMem() && getMemBase()->isMM16AsmReg();
862 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000863 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
864 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
865 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
866 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000867 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
868 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
869 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
870 && (getMemBase()->getGPR32Reg() == Mips::SP);
871 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000872 bool isRegList16() const {
873 if (!isRegList())
874 return false;
875
876 int Size = RegList.List->size();
877 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
878 RegList.List->back() != Mips::RA)
879 return false;
880
881 int PrevReg = *RegList.List->begin();
882 for (int i = 1; i < Size - 1; i++) {
883 int Reg = (*(RegList.List))[i];
884 if ( Reg != PrevReg + 1)
885 return false;
886 PrevReg = Reg;
887 }
888
889 return true;
890 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000891 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 bool isLSAImm() const {
893 if (!isConstantImm())
894 return false;
895 int64_t Val = getConstantImm();
896 return 1 <= Val && Val <= 4;
897 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000898 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000899 bool isMovePRegPair() const {
900 if (Kind != k_RegList || RegList.List->size() != 2)
901 return false;
902
903 unsigned R0 = RegList.List->front();
904 unsigned R1 = RegList.List->back();
905
906 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
907 (R0 == Mips::A1 && R1 == Mips::A3) ||
908 (R0 == Mips::A2 && R1 == Mips::A3) ||
909 (R0 == Mips::A0 && R1 == Mips::S5) ||
910 (R0 == Mips::A0 && R1 == Mips::S6) ||
911 (R0 == Mips::A0 && R1 == Mips::A1) ||
912 (R0 == Mips::A0 && R1 == Mips::A2) ||
913 (R0 == Mips::A0 && R1 == Mips::A3))
914 return true;
915
916 return false;
917 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000918
919 StringRef getToken() const {
920 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000921 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000922 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000923 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000924
Craig Topper56c590a2014-04-29 07:58:02 +0000925 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 // As a special case until we sort out the definition of div/divu, pretend
927 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
928 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
929 RegIdx.Kind & RegKind_GPR)
930 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000931
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 assert(Kind == k_PhysRegister && "Invalid access!");
933 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000934 }
935
Jack Carterb4dbc172012-09-05 23:34:03 +0000936 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000937 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000938 return Imm.Val;
939 }
940
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000941 int64_t getConstantImm() const {
942 const MCExpr *Val = getImm();
943 return static_cast<const MCConstantExpr *>(Val)->getValue();
944 }
945
946 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000947 assert((Kind == k_Memory) && "Invalid access!");
948 return Mem.Base;
949 }
950
951 const MCExpr *getMemOff() const {
952 assert((Kind == k_Memory) && "Invalid access!");
953 return Mem.Off;
954 }
955
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000956 int64_t getConstantMemOff() const {
957 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
958 }
959
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000960 const SmallVectorImpl<unsigned> &getRegList() const {
961 assert((Kind == k_RegList) && "Invalid access!");
962 return *(RegList.List);
963 }
964
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000965 unsigned getRegPair() const {
966 assert((Kind == k_RegPair) && "Invalid access!");
967 return RegIdx.Index;
968 }
969
David Blaikie960ea3f2014-06-08 16:18:35 +0000970 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
971 MipsAsmParser &Parser) {
972 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000973 Op->Tok.Data = Str.data();
974 Op->Tok.Length = Str.size();
975 Op->StartLoc = S;
976 Op->EndLoc = S;
977 return Op;
978 }
979
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000980 /// Create a numeric register (e.g. $1). The exact register remains
981 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000982 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000983 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000984 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000985 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000987 }
988
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000989 /// Create a register that is definitely a GPR.
990 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000991 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000992 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000993 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000994 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000995 }
996
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 /// Create a register that is definitely a FGR.
998 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000999 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001000 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001001 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1003 }
1004
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001005 /// Create a register that is definitely a HWReg.
1006 /// This is typically only used for named registers such as $hwr_cpunum.
1007 static std::unique_ptr<MipsOperand>
1008 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1009 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1010 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1011 }
1012
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001013 /// Create a register that is definitely an FCC.
1014 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001015 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001016 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001017 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1019 }
1020
1021 /// Create a register that is definitely an ACC.
1022 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001023 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001024 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1027 }
1028
1029 /// Create a register that is definitely an MSA128.
1030 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001031 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001032 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001033 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1035 }
1036
1037 /// Create a register that is definitely an MSACtrl.
1038 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001040 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1043 }
1044
David Blaikie960ea3f2014-06-08 16:18:35 +00001045 static std::unique_ptr<MipsOperand>
1046 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1047 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001048 Op->Imm.Val = Val;
1049 Op->StartLoc = S;
1050 Op->EndLoc = E;
1051 return Op;
1052 }
1053
David Blaikie960ea3f2014-06-08 16:18:35 +00001054 static std::unique_ptr<MipsOperand>
1055 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1056 SMLoc E, MipsAsmParser &Parser) {
1057 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1058 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001059 Op->Mem.Off = Off;
1060 Op->StartLoc = S;
1061 Op->EndLoc = E;
1062 return Op;
1063 }
1064
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001065 static std::unique_ptr<MipsOperand>
1066 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1067 MipsAsmParser &Parser) {
1068 assert (Regs.size() > 0 && "Empty list not allowed");
1069
1070 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001071 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001072 Op->StartLoc = StartLoc;
1073 Op->EndLoc = EndLoc;
1074 return Op;
1075 }
1076
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001077 static std::unique_ptr<MipsOperand>
1078 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1079 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1080 Op->RegIdx.Index = RegNo;
1081 Op->StartLoc = S;
1082 Op->EndLoc = E;
1083 return Op;
1084 }
1085
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001086 bool isGPRAsmReg() const {
1087 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001088 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001089 bool isMM16AsmReg() const {
1090 if (!(isRegIdx() && RegIdx.Kind))
1091 return false;
1092 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1093 || RegIdx.Index == 16 || RegIdx.Index == 17);
1094 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001095 bool isMM16AsmRegZero() const {
1096 if (!(isRegIdx() && RegIdx.Kind))
1097 return false;
1098 return (RegIdx.Index == 0 ||
1099 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1100 RegIdx.Index == 17);
1101 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001102 bool isMM16AsmRegMoveP() const {
1103 if (!(isRegIdx() && RegIdx.Kind))
1104 return false;
1105 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1106 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1107 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 bool isFGRAsmReg() const {
1109 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1110 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001111 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 bool isHWRegsAsmReg() const {
1113 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001114 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 bool isCCRAsmReg() const {
1116 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001117 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001119 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1120 return false;
1121 if (!AsmParser.hasEightFccRegisters())
1122 return RegIdx.Index == 0;
1123 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001124 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 bool isACCAsmReg() const {
1126 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001127 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 bool isCOP2AsmReg() const {
1129 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001130 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001131 bool isCOP3AsmReg() const {
1132 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1133 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isMSA128AsmReg() const {
1135 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001136 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 bool isMSACtrlAsmReg() const {
1138 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001139 }
1140
Jack Carterb4dbc172012-09-05 23:34:03 +00001141 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001142 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001143 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001144 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001145
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001146 virtual ~MipsOperand() {
1147 switch (Kind) {
1148 case k_Immediate:
1149 break;
1150 case k_Memory:
1151 delete Mem.Base;
1152 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001153 case k_RegList:
1154 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001155 case k_PhysRegister:
1156 case k_RegisterIndex:
1157 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001158 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001159 break;
1160 }
1161 }
1162
Craig Topper56c590a2014-04-29 07:58:02 +00001163 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001164 switch (Kind) {
1165 case k_Immediate:
1166 OS << "Imm<";
1167 Imm.Val->print(OS);
1168 OS << ">";
1169 break;
1170 case k_Memory:
1171 OS << "Mem<";
1172 Mem.Base->print(OS);
1173 OS << ", ";
1174 Mem.Off->print(OS);
1175 OS << ">";
1176 break;
1177 case k_PhysRegister:
1178 OS << "PhysReg<" << PhysReg.Num << ">";
1179 break;
1180 case k_RegisterIndex:
1181 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1182 break;
1183 case k_Token:
1184 OS << Tok.Data;
1185 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001186 case k_RegList:
1187 OS << "RegList< ";
1188 for (auto Reg : (*RegList.List))
1189 OS << Reg << " ";
1190 OS << ">";
1191 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001192 case k_RegPair:
1193 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1194 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001195 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001196 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001197}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001198} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001199
Jack Carter9e65aa32013-03-22 00:05:30 +00001200namespace llvm {
1201extern const MCInstrDesc MipsInsts[];
1202}
1203static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1204 return MipsInsts[Opcode];
1205}
1206
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001207static bool hasShortDelaySlot(unsigned Opcode) {
1208 switch (Opcode) {
1209 case Mips::JALS_MM:
1210 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001211 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001212 case Mips::BGEZALS_MM:
1213 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001214 return true;
1215 default:
1216 return false;
1217 }
1218}
1219
Jack Carter9e65aa32013-03-22 00:05:30 +00001220bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001221 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001222 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001223
Jack Carter9e65aa32013-03-22 00:05:30 +00001224 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001225
1226 if (MCID.isBranch() || MCID.isCall()) {
1227 const unsigned Opcode = Inst.getOpcode();
1228 MCOperand Offset;
1229
1230 switch (Opcode) {
1231 default:
1232 break;
Kai Nackee0245392015-01-27 19:11:28 +00001233 case Mips::BBIT0:
1234 case Mips::BBIT032:
1235 case Mips::BBIT1:
1236 case Mips::BBIT132:
1237 assert(hasCnMips() && "instruction only valid for octeon cpus");
1238 // Fall through
1239
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001240 case Mips::BEQ:
1241 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 case Mips::BEQ_MM:
1243 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001244 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001245 Offset = Inst.getOperand(2);
1246 if (!Offset.isImm())
1247 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001248 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001249 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001250 if (OffsetToAlignment(Offset.getImm(),
1251 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001252 return Error(IDLoc, "branch to misaligned address");
1253 break;
1254 case Mips::BGEZ:
1255 case Mips::BGTZ:
1256 case Mips::BLEZ:
1257 case Mips::BLTZ:
1258 case Mips::BGEZAL:
1259 case Mips::BLTZAL:
1260 case Mips::BC1F:
1261 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 case Mips::BGEZ_MM:
1263 case Mips::BGTZ_MM:
1264 case Mips::BLEZ_MM:
1265 case Mips::BLTZ_MM:
1266 case Mips::BGEZAL_MM:
1267 case Mips::BLTZAL_MM:
1268 case Mips::BC1F_MM:
1269 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001270 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001271 Offset = Inst.getOperand(1);
1272 if (!Offset.isImm())
1273 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001274 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001275 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001276 if (OffsetToAlignment(Offset.getImm(),
1277 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001278 return Error(IDLoc, "branch to misaligned address");
1279 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001280 case Mips::BEQZ16_MM:
1281 case Mips::BNEZ16_MM:
1282 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1283 Offset = Inst.getOperand(1);
1284 if (!Offset.isImm())
1285 break; // We'll deal with this situation later on when applying fixups.
1286 if (!isIntN(8, Offset.getImm()))
1287 return Error(IDLoc, "branch target out of range");
1288 if (OffsetToAlignment(Offset.getImm(), 2LL))
1289 return Error(IDLoc, "branch to misaligned address");
1290 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001291 }
1292 }
1293
Daniel Sandersa84989a2014-06-16 13:25:35 +00001294 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1295 // We still accept it but it is a normal nop.
1296 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1297 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1298 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1299 "nop instruction");
1300 }
1301
Kai Nackee0245392015-01-27 19:11:28 +00001302 if (hasCnMips()) {
1303 const unsigned Opcode = Inst.getOpcode();
1304 MCOperand Opnd;
1305 int Imm;
1306
1307 switch (Opcode) {
1308 default:
1309 break;
1310
1311 case Mips::BBIT0:
1312 case Mips::BBIT032:
1313 case Mips::BBIT1:
1314 case Mips::BBIT132:
1315 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1316 // The offset is handled above
1317 Opnd = Inst.getOperand(1);
1318 if (!Opnd.isImm())
1319 return Error(IDLoc, "expected immediate operand kind");
1320 Imm = Opnd.getImm();
1321 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1322 Opcode == Mips::BBIT1 ? 63 : 31))
1323 return Error(IDLoc, "immediate operand value out of range");
1324 if (Imm > 31) {
1325 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1326 : Mips::BBIT132);
1327 Inst.getOperand(1).setImm(Imm - 32);
1328 }
1329 break;
1330
1331 case Mips::CINS:
1332 case Mips::CINS32:
1333 case Mips::EXTS:
1334 case Mips::EXTS32:
1335 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1336 // Check length
1337 Opnd = Inst.getOperand(3);
1338 if (!Opnd.isImm())
1339 return Error(IDLoc, "expected immediate operand kind");
1340 Imm = Opnd.getImm();
1341 if (Imm < 0 || Imm > 31)
1342 return Error(IDLoc, "immediate operand value out of range");
1343 // Check position
1344 Opnd = Inst.getOperand(2);
1345 if (!Opnd.isImm())
1346 return Error(IDLoc, "expected immediate operand kind");
1347 Imm = Opnd.getImm();
1348 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1349 Opcode == Mips::EXTS ? 63 : 31))
1350 return Error(IDLoc, "immediate operand value out of range");
1351 if (Imm > 31) {
1352 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1353 Inst.getOperand(2).setImm(Imm - 32);
1354 }
1355 break;
1356
1357 case Mips::SEQi:
1358 case Mips::SNEi:
1359 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1360 Opnd = Inst.getOperand(2);
1361 if (!Opnd.isImm())
1362 return Error(IDLoc, "expected immediate operand kind");
1363 Imm = Opnd.getImm();
1364 if (!isInt<10>(Imm))
1365 return Error(IDLoc, "immediate operand value out of range");
1366 break;
1367 }
1368 }
1369
Toma Tabacu9db22db2014-09-09 10:15:38 +00001370 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001371 // If this instruction has a delay slot and .set reorder is active,
1372 // emit a NOP after it.
1373 Instructions.push_back(Inst);
1374 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001375 if (hasShortDelaySlot(Inst.getOpcode())) {
1376 NopInst.setOpcode(Mips::MOVE16_MM);
1377 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1378 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1379 } else {
1380 NopInst.setOpcode(Mips::SLL);
1381 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1382 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1383 NopInst.addOperand(MCOperand::CreateImm(0));
1384 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001385 Instructions.push_back(NopInst);
1386 return false;
1387 }
1388
Jack Carter9e65aa32013-03-22 00:05:30 +00001389 if (MCID.mayLoad() || MCID.mayStore()) {
1390 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001391 // reference or immediate we may have to expand instructions.
1392 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001393 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001394 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1395 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001396 MCOperand &Op = Inst.getOperand(i);
1397 if (Op.isImm()) {
1398 int MemOffset = Op.getImm();
1399 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 // Offset can't exceed 16bit value.
1401 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001402 return false;
1403 }
1404 } else if (Op.isExpr()) {
1405 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001406 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001407 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001408 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001410 // Expand symbol.
1411 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001412 return false;
1413 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001414 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001415 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001416 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001417 }
1418 }
1419 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001420 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001421 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001422
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001423 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001424 if (MCID.mayLoad()) {
1425 // Try to create 16-bit GP relative load instruction.
1426 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1427 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1428 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1429 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1430 MCOperand &Op = Inst.getOperand(i);
1431 if (Op.isImm()) {
1432 int MemOffset = Op.getImm();
1433 MCOperand &DstReg = Inst.getOperand(0);
1434 MCOperand &BaseReg = Inst.getOperand(1);
1435 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1436 getContext().getRegisterInfo()->getRegClass(
1437 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1438 BaseReg.getReg() == Mips::GP) {
1439 MCInst TmpInst;
1440 TmpInst.setLoc(IDLoc);
1441 TmpInst.setOpcode(Mips::LWGP_MM);
1442 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1443 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1444 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1445 Instructions.push_back(TmpInst);
1446 return false;
1447 }
1448 }
1449 }
1450 } // for
1451 } // if load
1452
1453 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1454
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001455 MCOperand Opnd;
1456 int Imm;
1457
1458 switch (Inst.getOpcode()) {
1459 default:
1460 break;
1461 case Mips::ADDIUS5_MM:
1462 Opnd = Inst.getOperand(2);
1463 if (!Opnd.isImm())
1464 return Error(IDLoc, "expected immediate operand kind");
1465 Imm = Opnd.getImm();
1466 if (Imm < -8 || Imm > 7)
1467 return Error(IDLoc, "immediate operand value out of range");
1468 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001469 case Mips::ADDIUSP_MM:
1470 Opnd = Inst.getOperand(0);
1471 if (!Opnd.isImm())
1472 return Error(IDLoc, "expected immediate operand kind");
1473 Imm = Opnd.getImm();
1474 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1475 Imm % 4 != 0)
1476 return Error(IDLoc, "immediate operand value out of range");
1477 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001478 case Mips::SLL16_MM:
1479 case Mips::SRL16_MM:
1480 Opnd = Inst.getOperand(2);
1481 if (!Opnd.isImm())
1482 return Error(IDLoc, "expected immediate operand kind");
1483 Imm = Opnd.getImm();
1484 if (Imm < 1 || Imm > 8)
1485 return Error(IDLoc, "immediate operand value out of range");
1486 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001487 case Mips::LI16_MM:
1488 Opnd = Inst.getOperand(1);
1489 if (!Opnd.isImm())
1490 return Error(IDLoc, "expected immediate operand kind");
1491 Imm = Opnd.getImm();
1492 if (Imm < -1 || Imm > 126)
1493 return Error(IDLoc, "immediate operand value out of range");
1494 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001495 case Mips::ADDIUR2_MM:
1496 Opnd = Inst.getOperand(2);
1497 if (!Opnd.isImm())
1498 return Error(IDLoc, "expected immediate operand kind");
1499 Imm = Opnd.getImm();
1500 if (!(Imm == 1 || Imm == -1 ||
1501 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1502 return Error(IDLoc, "immediate operand value out of range");
1503 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001504 case Mips::ADDIUR1SP_MM:
1505 Opnd = Inst.getOperand(1);
1506 if (!Opnd.isImm())
1507 return Error(IDLoc, "expected immediate operand kind");
1508 Imm = Opnd.getImm();
1509 if (OffsetToAlignment(Imm, 4LL))
1510 return Error(IDLoc, "misaligned immediate operand value");
1511 if (Imm < 0 || Imm > 255)
1512 return Error(IDLoc, "immediate operand value out of range");
1513 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001514 case Mips::ANDI16_MM:
1515 Opnd = Inst.getOperand(2);
1516 if (!Opnd.isImm())
1517 return Error(IDLoc, "expected immediate operand kind");
1518 Imm = Opnd.getImm();
1519 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1520 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1521 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1522 return Error(IDLoc, "immediate operand value out of range");
1523 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001524 case Mips::LBU16_MM:
1525 Opnd = Inst.getOperand(2);
1526 if (!Opnd.isImm())
1527 return Error(IDLoc, "expected immediate operand kind");
1528 Imm = Opnd.getImm();
1529 if (Imm < -1 || Imm > 14)
1530 return Error(IDLoc, "immediate operand value out of range");
1531 break;
1532 case Mips::SB16_MM:
1533 Opnd = Inst.getOperand(2);
1534 if (!Opnd.isImm())
1535 return Error(IDLoc, "expected immediate operand kind");
1536 Imm = Opnd.getImm();
1537 if (Imm < 0 || Imm > 15)
1538 return Error(IDLoc, "immediate operand value out of range");
1539 break;
1540 case Mips::LHU16_MM:
1541 case Mips::SH16_MM:
1542 Opnd = Inst.getOperand(2);
1543 if (!Opnd.isImm())
1544 return Error(IDLoc, "expected immediate operand kind");
1545 Imm = Opnd.getImm();
1546 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1547 return Error(IDLoc, "immediate operand value out of range");
1548 break;
1549 case Mips::LW16_MM:
1550 case Mips::SW16_MM:
1551 Opnd = Inst.getOperand(2);
1552 if (!Opnd.isImm())
1553 return Error(IDLoc, "expected immediate operand kind");
1554 Imm = Opnd.getImm();
1555 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1556 return Error(IDLoc, "immediate operand value out of range");
1557 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001558 case Mips::CACHE:
1559 case Mips::PREF:
1560 Opnd = Inst.getOperand(2);
1561 if (!Opnd.isImm())
1562 return Error(IDLoc, "expected immediate operand kind");
1563 Imm = Opnd.getImm();
1564 if (!isUInt<5>(Imm))
1565 return Error(IDLoc, "immediate operand value out of range");
1566 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001567 case Mips::ADDIUPC_MM:
1568 MCOperand Opnd = Inst.getOperand(1);
1569 if (!Opnd.isImm())
1570 return Error(IDLoc, "expected immediate operand kind");
1571 int Imm = Opnd.getImm();
1572 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1573 return Error(IDLoc, "immediate operand value out of range");
1574 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001575 }
1576 }
1577
Jack Carter9e65aa32013-03-22 00:05:30 +00001578 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001579 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001580 else
1581 Instructions.push_back(Inst);
1582
1583 return false;
1584}
1585
Jack Carter30a59822012-10-04 04:03:53 +00001586bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1587
Jack Carterd0bd6422013-04-18 00:41:53 +00001588 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001589 case Mips::LoadImm32:
1590 case Mips::LoadImm64:
1591 case Mips::LoadAddrImm32:
1592 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001593 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001594 case Mips::LWM_MM:
1595 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001596 case Mips::JalOneReg:
1597 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001598 return true;
1599 default:
1600 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001601 }
1602}
Jack Carter92995f12012-10-06 00:53:28 +00001603
Matheus Almeida3813d572014-06-19 14:39:14 +00001604bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001605 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001606 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001607 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001608 case Mips::LoadImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001610 case Mips::LoadImm64:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001611 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001612 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001613 return true;
1614 }
1615 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001616 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001617 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001618 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001620 case Mips::B_MM_Pseudo:
1621 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001622 case Mips::SWM_MM:
1623 case Mips::LWM_MM:
1624 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001625 case Mips::JalOneReg:
1626 case Mips::JalTwoReg:
1627 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 }
Jack Carter30a59822012-10-04 04:03:53 +00001629}
Jack Carter92995f12012-10-06 00:53:28 +00001630
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001631namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001632template <bool PerformShift>
1633void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001634 SmallVectorImpl<MCInst> &Instructions) {
1635 MCInst tmpInst;
1636 if (PerformShift) {
1637 tmpInst.setOpcode(Mips::DSLL);
1638 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1639 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1640 tmpInst.addOperand(MCOperand::CreateImm(16));
1641 tmpInst.setLoc(IDLoc);
1642 Instructions.push_back(tmpInst);
1643 tmpInst.clear();
1644 }
1645 tmpInst.setOpcode(Mips::ORi);
1646 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1647 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001648 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001649 tmpInst.setLoc(IDLoc);
1650 Instructions.push_back(tmpInst);
1651}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001652
1653template <int Shift, bool PerformShift>
1654void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1655 SmallVectorImpl<MCInst> &Instructions) {
1656 createShiftOr<PerformShift>(
1657 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1658 IDLoc, Instructions);
1659}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001660}
1661
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001662bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1663 SmallVectorImpl<MCInst> &Instructions) {
1664 // Create a JALR instruction which is going to replace the pseudo-JAL.
1665 MCInst JalrInst;
1666 JalrInst.setLoc(IDLoc);
1667 const MCOperand FirstRegOp = Inst.getOperand(0);
1668 const unsigned Opcode = Inst.getOpcode();
1669
1670 if (Opcode == Mips::JalOneReg) {
1671 // jal $rs => jalr $rs
1672 if (inMicroMipsMode()) {
1673 JalrInst.setOpcode(Mips::JALR16_MM);
1674 JalrInst.addOperand(FirstRegOp);
1675 } else {
1676 JalrInst.setOpcode(Mips::JALR);
1677 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1678 JalrInst.addOperand(FirstRegOp);
1679 }
1680 } else if (Opcode == Mips::JalTwoReg) {
1681 // jal $rd, $rs => jalr $rd, $rs
1682 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1683 JalrInst.addOperand(FirstRegOp);
1684 const MCOperand SecondRegOp = Inst.getOperand(1);
1685 JalrInst.addOperand(SecondRegOp);
1686 }
1687 Instructions.push_back(JalrInst);
1688
1689 // If .set reorder is active, emit a NOP after it.
1690 if (AssemblerOptions.back()->isReorder()) {
1691 // This is a 32-bit NOP because these 2 pseudo-instructions
1692 // do not have a short delay slot.
1693 MCInst NopInst;
1694 NopInst.setOpcode(Mips::SLL);
1695 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1696 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1697 NopInst.addOperand(MCOperand::CreateImm(0));
1698 Instructions.push_back(NopInst);
1699 }
1700
1701 return false;
1702}
1703
Matheus Almeida3813d572014-06-19 14:39:14 +00001704bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001706 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001707 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001708 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001709 const MCOperand &RegOp = Inst.getOperand(0);
1710 assert(RegOp.isReg() && "expected register operand kind");
1711
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001712 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001713 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001714 // FIXME: gas has a special case for values that are 000...1111, which
1715 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 if (0 <= ImmValue && ImmValue <= 65535) {
1717 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001718 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001719 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001720 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001721 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001722 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001723 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 } else if (ImmValue < 0 && ImmValue >= -32768) {
1725 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001726 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001727 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001728 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001730 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001731 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001732 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1733 // For any value of j that is representable as a 32-bit integer, create
1734 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001735 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001736 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001737 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001738 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1739 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001740 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001741 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1742 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001743 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001744 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001745 return true;
1746 }
1747
1748 // <------- lo32 ------>
1749 // <------- hi32 ------>
1750 // <- hi16 -> <- lo16 ->
1751 // _________________________________
1752 // | | | |
1753 // | 16-bytes | 16-bytes | 16-bytes |
1754 // |__________|__________|__________|
1755 //
1756 // For any value of j that is representable as a 48-bit integer, create
1757 // a sequence of:
1758 // li d,j => lui d,hi16(j)
1759 // ori d,d,hi16(lo32(j))
1760 // dsll d,d,16
1761 // ori d,d,lo16(lo32(j))
1762 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001763 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001764 tmpInst.addOperand(
1765 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001766 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001767 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1768 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1769 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001770 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001771 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001772 return true;
1773 }
1774
1775 // <------- hi32 ------> <------- lo32 ------>
1776 // <- hi16 -> <- lo16 ->
1777 // ___________________________________________
1778 // | | | | |
1779 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1780 // |__________|__________|__________|__________|
1781 //
1782 // For any value of j that isn't representable as a 48-bit integer.
1783 // li d,j => lui d,hi16(j)
1784 // ori d,d,lo16(hi32(j))
1785 // dsll d,d,16
1786 // ori d,d,hi16(lo32(j))
1787 // dsll d,d,16
1788 // ori d,d,lo16(lo32(j))
1789 tmpInst.setOpcode(Mips::LUi);
1790 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1791 tmpInst.addOperand(
1792 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1793 Instructions.push_back(tmpInst);
1794 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1795 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1796 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001797 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001798 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001799}
Jack Carter92995f12012-10-06 00:53:28 +00001800
Matheus Almeida3813d572014-06-19 14:39:14 +00001801bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001802MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1803 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001804 MCInst tmpInst;
1805 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001806 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1807 "expected immediate operand kind");
1808 if (!ImmOp.isImm()) {
1809 expandLoadAddressSym(Inst, IDLoc, Instructions);
1810 return false;
1811 }
Jack Carter543fdf82012-10-09 23:29:45 +00001812 const MCOperand &SrcRegOp = Inst.getOperand(1);
1813 assert(SrcRegOp.isReg() && "expected register operand kind");
1814 const MCOperand &DstRegOp = Inst.getOperand(0);
1815 assert(DstRegOp.isReg() && "expected register operand kind");
1816 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001817 if (-32768 <= ImmValue && ImmValue <= 65535) {
1818 // For -32768 <= j <= 65535.
1819 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001820 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001821 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1822 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1823 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1824 Instructions.push_back(tmpInst);
1825 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001826 // For any other value of j that is representable as a 32-bit integer.
1827 // la d,j(s) => lui d,hi16(j)
1828 // ori d,d,lo16(j)
1829 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001830 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001831 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1832 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1833 Instructions.push_back(tmpInst);
1834 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001835 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001836 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1837 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1838 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1839 Instructions.push_back(tmpInst);
1840 tmpInst.clear();
1841 tmpInst.setOpcode(Mips::ADDu);
1842 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1843 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1844 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1845 Instructions.push_back(tmpInst);
1846 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001847 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001848}
1849
Matheus Almeida3813d572014-06-19 14:39:14 +00001850bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001851MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1852 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001853 MCInst tmpInst;
1854 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001855 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1856 "expected immediate operand kind");
1857 if (!ImmOp.isImm()) {
1858 expandLoadAddressSym(Inst, IDLoc, Instructions);
1859 return false;
1860 }
Jack Carter543fdf82012-10-09 23:29:45 +00001861 const MCOperand &RegOp = Inst.getOperand(0);
1862 assert(RegOp.isReg() && "expected register operand kind");
1863 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001864 if (-32768 <= ImmValue && ImmValue <= 65535) {
1865 // For -32768 <= j <= 65535.
1866 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001867 tmpInst.setOpcode(Mips::ADDiu);
1868 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001869 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001870 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1871 Instructions.push_back(tmpInst);
1872 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001873 // For any other value of j that is representable as a 32-bit integer.
1874 // la d,j => lui d,hi16(j)
1875 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001876 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001877 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1878 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1879 Instructions.push_back(tmpInst);
1880 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001881 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001882 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1883 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1884 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1885 Instructions.push_back(tmpInst);
1886 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001887 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001888}
1889
Toma Tabacu0d64b202014-08-14 10:29:17 +00001890void
1891MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1892 SmallVectorImpl<MCInst> &Instructions) {
1893 // FIXME: If we do have a valid at register to use, we should generate a
1894 // slightly shorter sequence here.
1895 MCInst tmpInst;
1896 int ExprOperandNo = 1;
1897 // Sometimes the assembly parser will get the immediate expression as
1898 // a $zero + an immediate.
1899 if (Inst.getNumOperands() == 3) {
1900 assert(Inst.getOperand(1).getReg() ==
1901 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1902 ExprOperandNo = 2;
1903 }
1904 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1905 assert(SymOp.isExpr() && "expected symbol operand kind");
1906 const MCOperand &RegOp = Inst.getOperand(0);
1907 unsigned RegNo = RegOp.getReg();
1908 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1909 const MCSymbolRefExpr *HiExpr =
1910 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1911 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1912 const MCSymbolRefExpr *LoExpr =
1913 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1914 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1915 if (isGP64bit()) {
1916 // If it's a 64-bit architecture, expand to:
1917 // la d,sym => lui d,highest(sym)
1918 // ori d,d,higher(sym)
1919 // dsll d,d,16
1920 // ori d,d,hi16(sym)
1921 // dsll d,d,16
1922 // ori d,d,lo16(sym)
1923 const MCSymbolRefExpr *HighestExpr =
1924 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1925 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1926 const MCSymbolRefExpr *HigherExpr =
1927 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1928 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1929
1930 tmpInst.setOpcode(Mips::LUi);
1931 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1932 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1933 Instructions.push_back(tmpInst);
1934
1935 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1936 Instructions);
1937 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1938 Instructions);
1939 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1940 Instructions);
1941 } else {
1942 // Otherwise, expand to:
1943 // la d,sym => lui d,hi16(sym)
1944 // ori d,d,lo16(sym)
1945 tmpInst.setOpcode(Mips::LUi);
1946 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1947 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1948 Instructions.push_back(tmpInst);
1949
1950 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1951 Instructions);
1952 }
1953}
1954
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001955bool MipsAsmParser::expandUncondBranchMMPseudo(
1956 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001957 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1958 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001959
1960 MCOperand Offset = Inst.getOperand(0);
1961 if (Offset.isExpr()) {
1962 Inst.clear();
1963 Inst.setOpcode(Mips::BEQ_MM);
1964 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1965 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1966 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1967 } else {
1968 assert(Offset.isImm() && "expected immediate operand kind");
1969 if (isIntN(11, Offset.getImm())) {
1970 // If offset fits into 11 bits then this instruction becomes microMIPS
1971 // 16-bit unconditional branch instruction.
1972 Inst.setOpcode(Mips::B16_MM);
1973 } else {
1974 if (!isIntN(17, Offset.getImm()))
1975 Error(IDLoc, "branch target out of range");
1976 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1977 Error(IDLoc, "branch to misaligned address");
1978 Inst.clear();
1979 Inst.setOpcode(Mips::BEQ_MM);
1980 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1981 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1982 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1983 }
1984 }
1985 Instructions.push_back(Inst);
1986
1987 if (AssemblerOptions.back()->isReorder()) {
1988 // If .set reorder is active, emit a NOP after the branch instruction.
1989 MCInst NopInst;
1990 NopInst.setOpcode(Mips::MOVE16_MM);
1991 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1992 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1993 Instructions.push_back(NopInst);
1994 }
1995 return false;
1996}
1997
Jack Carter9e65aa32013-03-22 00:05:30 +00001998void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001999 SmallVectorImpl<MCInst> &Instructions,
2000 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002001 const MCSymbolRefExpr *SR;
2002 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002003 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002004 const MCExpr *ExprOffset;
2005 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002006 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002007 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2008 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002010 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2011 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002012 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002013 if (isImmOpnd) {
2014 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2015 ImmOffset = Inst.getOperand(2).getImm();
2016 LoOffset = ImmOffset & 0x0000ffff;
2017 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002018 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002019 if (LoOffset & 0x8000)
2020 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002021 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002022 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002023 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002024 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002025 // These are some of the types of expansions we perform here:
2026 // 1) lw $8, sym => lui $8, %hi(sym)
2027 // lw $8, %lo(sym)($8)
2028 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2029 // add $8, $8, $9
2030 // lw $8, %lo(offset)($9)
2031 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2032 // add $at, $at, $8
2033 // lw $8, %lo(offset)($at)
2034 // 4) sw $8, sym => lui $at, %hi(sym)
2035 // sw $8, %lo(sym)($at)
2036 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2037 // add $at, $at, $8
2038 // sw $8, %lo(offset)($at)
2039 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2040 // ldc1 $f0, %lo(sym)($at)
2041 //
2042 // For load instructions we can use the destination register as a temporary
2043 // if base and dst are different (examples 1 and 2) and if the base register
2044 // is general purpose otherwise we must use $at (example 6) and error if it's
2045 // not available. For stores we must use $at (examples 4 and 5) because we
2046 // must not clobber the source register setting up the offset.
2047 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2048 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2049 unsigned RegClassIDOp0 =
2050 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2051 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2052 (RegClassIDOp0 == Mips::GPR64RegClassID);
2053 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002054 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002055 else {
2056 int AT = getATReg(IDLoc);
2057 // At this point we need AT to perform the expansions and we exit if it is
2058 // not available.
2059 if (!AT)
2060 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002061 TmpRegNum = getReg(
2062 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002063 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002064
Jack Carter9e65aa32013-03-22 00:05:30 +00002065 TempInst.setOpcode(Mips::LUi);
2066 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2067 if (isImmOpnd)
2068 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2069 else {
2070 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002071 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2073 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2074 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002075 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002076 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002077 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002078 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 }
2080 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002082 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002083 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002084 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002086 TempInst.setOpcode(Mips::ADDu);
2087 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2088 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2089 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2090 Instructions.push_back(TempInst);
2091 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00002092 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002094 TempInst.setOpcode(Inst.getOpcode());
2095 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2096 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2097 if (isImmOpnd)
2098 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2099 else {
2100 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2102 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2103 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002104 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002105 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 }
2109 }
2110 Instructions.push_back(TempInst);
2111 TempInst.clear();
2112}
2113
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002114bool
2115MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2116 SmallVectorImpl<MCInst> &Instructions) {
2117 unsigned OpNum = Inst.getNumOperands();
2118 unsigned Opcode = Inst.getOpcode();
2119 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2120
2121 assert (Inst.getOperand(OpNum - 1).isImm() &&
2122 Inst.getOperand(OpNum - 2).isReg() &&
2123 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2124
2125 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2126 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2127 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2128 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2129 // It can be implemented as SWM16 or LWM16 instruction.
2130 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2131
2132 Inst.setOpcode(NewOpcode);
2133 Instructions.push_back(Inst);
2134 return false;
2135}
2136
Matheus Almeida595fcab2014-06-11 15:05:56 +00002137unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2138 // As described by the Mips32r2 spec, the registers Rd and Rs for
2139 // jalr.hb must be different.
2140 unsigned Opcode = Inst.getOpcode();
2141
2142 if (Opcode == Mips::JALR_HB &&
2143 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2144 return Match_RequiresDifferentSrcAndDst;
2145
2146 return Match_Success;
2147}
2148
David Blaikie960ea3f2014-06-08 16:18:35 +00002149bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2150 OperandVector &Operands,
2151 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002152 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002153 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002154
Jack Carterb4dbc172012-09-05 23:34:03 +00002155 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002156 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002157 unsigned MatchResult =
2158 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002159
2160 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002161 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002163 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002164 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002165 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002166 return false;
2167 }
2168 case Match_MissingFeature:
2169 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2170 return true;
2171 case Match_InvalidOperand: {
2172 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002173 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002174 if (ErrorInfo >= Operands.size())
2175 return Error(IDLoc, "too few operands for instruction");
2176
David Blaikie960ea3f2014-06-08 16:18:35 +00002177 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 if (ErrorLoc == SMLoc())
2179 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002180 }
2181
2182 return Error(ErrorLoc, "invalid operand for instruction");
2183 }
2184 case Match_MnemonicFail:
2185 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002186 case Match_RequiresDifferentSrcAndDst:
2187 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002188 }
Craig Topper589ceee2015-01-03 08:16:34 +00002189
2190 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002191}
2192
Toma Tabacu13964452014-09-04 13:23:44 +00002193void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002194 if ((RegIndex != 0) &&
2195 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002196 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002197 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002198 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002199 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002200 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002201 }
2202}
2203
Daniel Sandersef638fe2014-10-03 15:37:37 +00002204void
2205MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2206 SMRange Range, bool ShowColors) {
2207 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002208 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002209 ShowColors);
2210}
2211
Jack Carter1ac53222013-02-20 23:11:17 +00002212int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002213 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002214
Vladimir Medic4c299852013-11-06 11:27:05 +00002215 CC = StringSwitch<unsigned>(Name)
2216 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002217 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002218 .Case("a0", 4)
2219 .Case("a1", 5)
2220 .Case("a2", 6)
2221 .Case("a3", 7)
2222 .Case("v0", 2)
2223 .Case("v1", 3)
2224 .Case("s0", 16)
2225 .Case("s1", 17)
2226 .Case("s2", 18)
2227 .Case("s3", 19)
2228 .Case("s4", 20)
2229 .Case("s5", 21)
2230 .Case("s6", 22)
2231 .Case("s7", 23)
2232 .Case("k0", 26)
2233 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002234 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002235 .Case("sp", 29)
2236 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002237 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002238 .Case("ra", 31)
2239 .Case("t0", 8)
2240 .Case("t1", 9)
2241 .Case("t2", 10)
2242 .Case("t3", 11)
2243 .Case("t4", 12)
2244 .Case("t5", 13)
2245 .Case("t6", 14)
2246 .Case("t7", 15)
2247 .Case("t8", 24)
2248 .Case("t9", 25)
2249 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002250
Toma Tabacufda445c2014-09-15 15:33:01 +00002251 if (!(isABI_N32() || isABI_N64()))
2252 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002253
Daniel Sandersef638fe2014-10-03 15:37:37 +00002254 if (12 <= CC && CC <= 15) {
2255 // Name is one of t4-t7
2256 AsmToken RegTok = getLexer().peekTok();
2257 SMRange RegRange = RegTok.getLocRange();
2258
2259 StringRef FixedName = StringSwitch<StringRef>(Name)
2260 .Case("t4", "t0")
2261 .Case("t5", "t1")
2262 .Case("t6", "t2")
2263 .Case("t7", "t3")
2264 .Default("");
2265 assert(FixedName != "" && "Register name is not one of t4-t7.");
2266
2267 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2268 "Did you mean $" + FixedName + "?", RegRange);
2269 }
2270
Toma Tabacufda445c2014-09-15 15:33:01 +00002271 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2272 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2273 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2274 if (8 <= CC && CC <= 11)
2275 CC += 4;
2276
2277 if (CC == -1)
2278 CC = StringSwitch<unsigned>(Name)
2279 .Case("a4", 8)
2280 .Case("a5", 9)
2281 .Case("a6", 10)
2282 .Case("a7", 11)
2283 .Case("kt0", 26)
2284 .Case("kt1", 27)
2285 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002286
2287 return CC;
2288}
Jack Carterd0bd6422013-04-18 00:41:53 +00002289
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002290int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2291 int CC;
2292
2293 CC = StringSwitch<unsigned>(Name)
2294 .Case("hwr_cpunum", 0)
2295 .Case("hwr_synci_step", 1)
2296 .Case("hwr_cc", 2)
2297 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002298 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002299 .Default(-1);
2300
2301 return CC;
2302}
2303
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002304int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002305
Jack Cartera63b16a2012-09-07 00:23:42 +00002306 if (Name[0] == 'f') {
2307 StringRef NumString = Name.substr(1);
2308 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002309 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002310 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002311 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002312 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002313 return IntVal;
2314 }
2315 return -1;
2316}
Jack Cartera63b16a2012-09-07 00:23:42 +00002317
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002318int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2319
2320 if (Name.startswith("fcc")) {
2321 StringRef NumString = Name.substr(3);
2322 unsigned IntVal;
2323 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002324 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002325 if (IntVal > 7) // There are only 8 fcc registers.
2326 return -1;
2327 return IntVal;
2328 }
2329 return -1;
2330}
2331
2332int MipsAsmParser::matchACRegisterName(StringRef Name) {
2333
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002334 if (Name.startswith("ac")) {
2335 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002336 unsigned IntVal;
2337 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002338 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002339 if (IntVal > 3) // There are only 3 acc registers.
2340 return -1;
2341 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002342 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002343 return -1;
2344}
Jack Carterd0bd6422013-04-18 00:41:53 +00002345
Jack Carter5dc8ac92013-09-25 23:50:44 +00002346int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2347 unsigned IntVal;
2348
2349 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2350 return -1;
2351
2352 if (IntVal > 31)
2353 return -1;
2354
2355 return IntVal;
2356}
2357
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002358int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2359 int CC;
2360
2361 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002362 .Case("msair", 0)
2363 .Case("msacsr", 1)
2364 .Case("msaaccess", 2)
2365 .Case("msasave", 3)
2366 .Case("msamodify", 4)
2367 .Case("msarequest", 5)
2368 .Case("msamap", 6)
2369 .Case("msaunmap", 7)
2370 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002371
2372 return CC;
2373}
2374
Jack Carter0b744b32012-10-04 02:29:46 +00002375bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2376 if (Reg > 31)
2377 return false;
2378
Toma Tabacu3c24b042014-09-05 15:43:21 +00002379 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002380 return true;
2381}
2382
Matheus Almeida7de68e72014-06-18 14:46:05 +00002383int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002384 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002385 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002386 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002387 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002388 return AT;
2389}
Jack Carter0b744b32012-10-04 02:29:46 +00002390
Jack Carterd0bd6422013-04-18 00:41:53 +00002391unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002392 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002393}
2394
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002395unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002396 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002397 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002398}
2399
Jack Carter873c7242013-01-12 01:03:14 +00002400int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002401 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002402 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002403 return -1;
2404
Jack Carter873c7242013-01-12 01:03:14 +00002405 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002406}
2407
Toma Tabacu13964452014-09-04 13:23:44 +00002408bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002409 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002410 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002411
Jack Carter30a59822012-10-04 04:03:53 +00002412 // Check if the current operand has a custom associated parser, if so, try to
2413 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002414 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2415 if (ResTy == MatchOperand_Success)
2416 return false;
2417 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2418 // there was a match, but an error occurred, in which case, just return that
2419 // the operand parsing failed.
2420 if (ResTy == MatchOperand_ParseFail)
2421 return true;
2422
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002423 DEBUG(dbgs() << ".. Generic Parser\n");
2424
Jack Carterb4dbc172012-09-05 23:34:03 +00002425 switch (getLexer().getKind()) {
2426 default:
2427 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2428 return true;
2429 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002431 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002432
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002433 // Almost all registers have been parsed by custom parsers. There is only
2434 // one exception to this. $zero (and it's alias $0) will reach this point
2435 // for div, divu, and similar instructions because it is not an operand
2436 // to the instruction definition but an explicit register. Special case
2437 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002438 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002439 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002440
Jack Carterd0bd6422013-04-18 00:41:53 +00002441 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002442 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002443 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002444 return true;
2445
Jack Carter873c7242013-01-12 01:03:14 +00002446 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002447 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002448 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002449 const MCExpr *Res =
2450 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002451
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002452 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002453 return false;
2454 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002455 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002456 case AsmToken::LParen:
2457 case AsmToken::Minus:
2458 case AsmToken::Plus:
2459 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002460 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002461 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002463 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002464 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002466 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002467 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002468 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002469 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002470 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002471 return true;
2472
Jack Carter873c7242013-01-12 01:03:14 +00002473 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2474
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002475 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002476 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002477 } // case AsmToken::Percent
2478 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002479 return true;
2480}
2481
Vladimir Medic4c299852013-11-06 11:27:05 +00002482const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002483 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002484 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002485 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002486 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002487 // It's a constant, evaluate reloc value.
2488 int16_t Val;
2489 switch (getVariantKind(RelocStr)) {
2490 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2491 // Get the 1st 16-bits.
2492 Val = MCE->getValue() & 0xffff;
2493 break;
2494 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2495 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2496 // 16 bits being negative.
2497 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2498 break;
2499 case MCSymbolRefExpr::VK_Mips_HIGHER:
2500 // Get the 3rd 16-bits.
2501 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2502 break;
2503 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2504 // Get the 4th 16-bits.
2505 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2506 break;
2507 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002508 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002509 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002510 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002511 }
2512
Jack Carterb5cf5902013-04-17 00:18:04 +00002513 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002514 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002515 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002516 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002518 return Res;
2519 }
2520
2521 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002522 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2523
Sasa Stankovic06c47802014-04-03 10:37:45 +00002524 // Try to create target expression.
2525 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2526 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002527
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2529 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002530 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2531 return Res;
2532 }
2533
2534 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002535 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2536 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2537 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002538 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002540 return Expr;
2541}
2542
2543bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2544
2545 switch (Expr->getKind()) {
2546 case MCExpr::Constant:
2547 return true;
2548 case MCExpr::SymbolRef:
2549 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2550 case MCExpr::Binary:
2551 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2552 if (!isEvaluated(BE->getLHS()))
2553 return false;
2554 return isEvaluated(BE->getRHS());
2555 }
2556 case MCExpr::Unary:
2557 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002558 case MCExpr::Target:
2559 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002560 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002561 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002562}
Jack Carterd0bd6422013-04-18 00:41:53 +00002563
Jack Carterb5cf5902013-04-17 00:18:04 +00002564bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002565 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002566 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002568 if (Tok.isNot(AsmToken::Identifier))
2569 return true;
2570
2571 std::string Str = Tok.getIdentifier().str();
2572
Jack Carterd0bd6422013-04-18 00:41:53 +00002573 Parser.Lex(); // Eat the identifier.
2574 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002575 const MCExpr *IdVal;
2576 SMLoc EndLoc;
2577
2578 if (getLexer().getKind() == AsmToken::LParen) {
2579 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002581 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002582 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002583 const AsmToken &nextTok = Parser.getTok();
2584 if (nextTok.isNot(AsmToken::Identifier))
2585 return true;
2586 Str += "(%";
2587 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002589 if (getLexer().getKind() != AsmToken::LParen)
2590 return true;
2591 } else
2592 break;
2593 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002594 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002595 return true;
2596
2597 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002598 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002599
2600 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002601 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002602
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002604 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002605}
2606
Jack Carterb4dbc172012-09-05 23:34:03 +00002607bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2608 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002609 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002610 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002611 if (ResTy == MatchOperand_Success) {
2612 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002613 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002614 StartLoc = Operand.getStartLoc();
2615 EndLoc = Operand.getEndLoc();
2616
2617 // AFAIK, we only support numeric registers and named GPR's in CFI
2618 // directives.
2619 // Don't worry about eating tokens before failing. Using an unrecognised
2620 // register is a parse error.
2621 if (Operand.isGPRAsmReg()) {
2622 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002623 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002624 }
2625
2626 return (RegNo == (unsigned)-1);
2627 }
2628
2629 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002630 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002631}
2632
Jack Carterb5cf5902013-04-17 00:18:04 +00002633bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002634 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002635 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002636 bool Result = true;
2637
2638 while (getLexer().getKind() == AsmToken::LParen)
2639 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002640
Jack Carterd0bd6422013-04-18 00:41:53 +00002641 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002642 default:
2643 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002644 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002645 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002646 case AsmToken::Integer:
2647 case AsmToken::Minus:
2648 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002649 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002650 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002651 else
2652 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002653 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002654 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002655 break;
Jack Carter873c7242013-01-12 01:03:14 +00002656 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002657 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002658 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002659 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002660}
2661
David Blaikie960ea3f2014-06-08 16:18:35 +00002662MipsAsmParser::OperandMatchResultTy
2663MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002664 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002665 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002666 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002667 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002668 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002669 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002670 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002671 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002672
Jack Carterb5cf5902013-04-17 00:18:04 +00002673 if (getLexer().getKind() == AsmToken::LParen) {
2674 Parser.Lex();
2675 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002676 }
2677
Jack Carterb5cf5902013-04-17 00:18:04 +00002678 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002679 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002680 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002681
Jack Carterd0bd6422013-04-18 00:41:53 +00002682 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002683 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002684 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2685 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002686 SMLoc E =
2687 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002688 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002689 return MatchOperand_Success;
2690 }
2691 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002692 SMLoc E =
2693 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002694
Jack Carterd0bd6422013-04-18 00:41:53 +00002695 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002696 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002697 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002698 S, E, *this);
2699 Operands.push_back(
2700 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002701 return MatchOperand_Success;
2702 }
2703 Error(Parser.getTok().getLoc(), "'(' expected");
2704 return MatchOperand_ParseFail;
2705 }
2706
Jack Carterd0bd6422013-04-18 00:41:53 +00002707 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002708 }
2709
Toma Tabacu13964452014-09-04 13:23:44 +00002710 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002711 if (Res != MatchOperand_Success)
2712 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002713
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002714 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002715 Error(Parser.getTok().getLoc(), "')' expected");
2716 return MatchOperand_ParseFail;
2717 }
2718
Jack Carter873c7242013-01-12 01:03:14 +00002719 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2720
Jack Carterd0bd6422013-04-18 00:41:53 +00002721 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002722
Craig Topper062a2ba2014-04-25 05:30:21 +00002723 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002724 IdVal = MCConstantExpr::Create(0, getContext());
2725
Jack Carterd0bd6422013-04-18 00:41:53 +00002726 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002727 std::unique_ptr<MipsOperand> op(
2728 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002729 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002730 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002731 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002732 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002733 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2734 int64_t Imm;
2735 if (IdVal->EvaluateAsAbsolute(Imm))
2736 IdVal = MCConstantExpr::Create(Imm, getContext());
2737 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2738 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2739 getContext());
2740 }
2741
David Blaikie960ea3f2014-06-08 16:18:35 +00002742 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002743 return MatchOperand_Success;
2744}
2745
David Blaikie960ea3f2014-06-08 16:18:35 +00002746bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002747 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002748 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2749 if (Sym) {
2750 SMLoc S = Parser.getTok().getLoc();
2751 const MCExpr *Expr;
2752 if (Sym->isVariable())
2753 Expr = Sym->getVariableValue();
2754 else
2755 return false;
2756 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002757 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002758 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002759 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002760 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002761 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002762 if (ResTy == MatchOperand_Success) {
2763 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002764 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002765 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002766 llvm_unreachable("Should never ParseFail");
2767 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002768 }
2769 } else if (Expr->getKind() == MCExpr::Constant) {
2770 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002771 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002772 Operands.push_back(
2773 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002774 return true;
2775 }
2776 }
2777 return false;
2778}
Jack Carterd0bd6422013-04-18 00:41:53 +00002779
Jack Carter873c7242013-01-12 01:03:14 +00002780MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002781MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002782 StringRef Identifier,
2783 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002784 int Index = matchCPURegisterName(Identifier);
2785 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002786 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002787 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2788 return MatchOperand_Success;
2789 }
2790
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002791 Index = matchHWRegsRegisterName(Identifier);
2792 if (Index != -1) {
2793 Operands.push_back(MipsOperand::createHWRegsReg(
2794 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2795 return MatchOperand_Success;
2796 }
2797
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002798 Index = matchFPURegisterName(Identifier);
2799 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002800 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002801 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2802 return MatchOperand_Success;
2803 }
2804
2805 Index = matchFCCRegisterName(Identifier);
2806 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002807 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002808 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2809 return MatchOperand_Success;
2810 }
2811
2812 Index = matchACRegisterName(Identifier);
2813 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002814 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002815 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2816 return MatchOperand_Success;
2817 }
2818
2819 Index = matchMSA128RegisterName(Identifier);
2820 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002821 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002822 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2823 return MatchOperand_Success;
2824 }
2825
2826 Index = matchMSA128CtrlRegisterName(Identifier);
2827 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002828 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002829 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2830 return MatchOperand_Success;
2831 }
2832
2833 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002834}
2835
2836MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002837MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002838 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002839 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002840
2841 if (Token.is(AsmToken::Identifier)) {
2842 DEBUG(dbgs() << ".. identifier\n");
2843 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002844 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002845 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002846 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002847 } else if (Token.is(AsmToken::Integer)) {
2848 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002849 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2851 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002852 return MatchOperand_Success;
2853 }
2854
2855 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2856
2857 return MatchOperand_NoMatch;
2858}
2859
David Blaikie960ea3f2014-06-08 16:18:35 +00002860MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002861MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002862 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002863 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002864
2865 auto Token = Parser.getTok();
2866
2867 SMLoc S = Token.getLoc();
2868
2869 if (Token.isNot(AsmToken::Dollar)) {
2870 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2871 if (Token.is(AsmToken::Identifier)) {
2872 if (searchSymbolAlias(Operands))
2873 return MatchOperand_Success;
2874 }
2875 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2876 return MatchOperand_NoMatch;
2877 }
2878 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002879
Toma Tabacu13964452014-09-04 13:23:44 +00002880 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002881 if (ResTy == MatchOperand_Success) {
2882 Parser.Lex(); // $
2883 Parser.Lex(); // identifier
2884 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002885 return ResTy;
2886}
2887
2888MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002889MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002890 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002891 switch (getLexer().getKind()) {
2892 default:
2893 return MatchOperand_NoMatch;
2894 case AsmToken::LParen:
2895 case AsmToken::Minus:
2896 case AsmToken::Plus:
2897 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002898 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002899 case AsmToken::String:
2900 break;
2901 }
2902
2903 const MCExpr *IdVal;
2904 SMLoc S = Parser.getTok().getLoc();
2905 if (getParser().parseExpression(IdVal))
2906 return MatchOperand_ParseFail;
2907
2908 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2909 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2910 return MatchOperand_Success;
2911}
2912
David Blaikie960ea3f2014-06-08 16:18:35 +00002913MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002914MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002915 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002916 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002917
2918 SMLoc S = getLexer().getLoc();
2919
2920 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002921 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922 if (ResTy != MatchOperand_NoMatch)
2923 return ResTy;
2924
Daniel Sanders315386c2014-04-01 10:40:14 +00002925 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002926 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002927 if (ResTy != MatchOperand_NoMatch)
2928 return ResTy;
2929
Daniel Sandersffd84362014-04-01 10:41:48 +00002930 const MCExpr *Expr = nullptr;
2931 if (Parser.parseExpression(Expr)) {
2932 // We have no way of knowing if a symbol was consumed so we must ParseFail
2933 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002934 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002935 Operands.push_back(
2936 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002937 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002938}
2939
Vladimir Medic2b953d02013-10-01 09:48:56 +00002940MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002941MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002942 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002943 const MCExpr *IdVal;
2944 // If the first token is '$' we may have register operand.
2945 if (Parser.getTok().is(AsmToken::Dollar))
2946 return MatchOperand_NoMatch;
2947 SMLoc S = Parser.getTok().getLoc();
2948 if (getParser().parseExpression(IdVal))
2949 return MatchOperand_ParseFail;
2950 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002951 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002952 int64_t Val = MCE->getValue();
2953 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2954 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002955 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002956 return MatchOperand_Success;
2957}
2958
Matheus Almeida779c5932013-11-18 12:32:49 +00002959MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002960MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002961 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002962 switch (getLexer().getKind()) {
2963 default:
2964 return MatchOperand_NoMatch;
2965 case AsmToken::LParen:
2966 case AsmToken::Plus:
2967 case AsmToken::Minus:
2968 case AsmToken::Integer:
2969 break;
2970 }
2971
2972 const MCExpr *Expr;
2973 SMLoc S = Parser.getTok().getLoc();
2974
2975 if (getParser().parseExpression(Expr))
2976 return MatchOperand_ParseFail;
2977
2978 int64_t Val;
2979 if (!Expr->EvaluateAsAbsolute(Val)) {
2980 Error(S, "expected immediate value");
2981 return MatchOperand_ParseFail;
2982 }
2983
2984 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2985 // and because the CPU always adds one to the immediate field, the allowed
2986 // range becomes 1..4. We'll only check the range here and will deal
2987 // with the addition/subtraction when actually decoding/encoding
2988 // the instruction.
2989 if (Val < 1 || Val > 4) {
2990 Error(S, "immediate not in range (1..4)");
2991 return MatchOperand_ParseFail;
2992 }
2993
Jack Carter3b2c96e2014-01-22 23:31:38 +00002994 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002995 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002996 return MatchOperand_Success;
2997}
2998
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002999MipsAsmParser::OperandMatchResultTy
3000MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3001 MCAsmParser &Parser = getParser();
3002 SmallVector<unsigned, 10> Regs;
3003 unsigned RegNo;
3004 unsigned PrevReg = Mips::NoRegister;
3005 bool RegRange = false;
3006 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3007
3008 if (Parser.getTok().isNot(AsmToken::Dollar))
3009 return MatchOperand_ParseFail;
3010
3011 SMLoc S = Parser.getTok().getLoc();
3012 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3013 SMLoc E = getLexer().getLoc();
3014 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3015 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3016 if (RegRange) {
3017 // Remove last register operand because registers from register range
3018 // should be inserted first.
3019 if (RegNo == Mips::RA) {
3020 Regs.push_back(RegNo);
3021 } else {
3022 unsigned TmpReg = PrevReg + 1;
3023 while (TmpReg <= RegNo) {
3024 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3025 Error(E, "invalid register operand");
3026 return MatchOperand_ParseFail;
3027 }
3028
3029 PrevReg = TmpReg;
3030 Regs.push_back(TmpReg++);
3031 }
3032 }
3033
3034 RegRange = false;
3035 } else {
3036 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3037 (RegNo != Mips::RA)) {
3038 Error(E, "$16 or $31 expected");
3039 return MatchOperand_ParseFail;
3040 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3041 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3042 Error(E, "invalid register operand");
3043 return MatchOperand_ParseFail;
3044 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3045 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3046 Error(E, "consecutive register numbers expected");
3047 return MatchOperand_ParseFail;
3048 }
3049
3050 Regs.push_back(RegNo);
3051 }
3052
3053 if (Parser.getTok().is(AsmToken::Minus))
3054 RegRange = true;
3055
3056 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3057 !Parser.getTok().isNot(AsmToken::Comma)) {
3058 Error(E, "',' or '-' expected");
3059 return MatchOperand_ParseFail;
3060 }
3061
3062 Lex(); // Consume comma or minus
3063 if (Parser.getTok().isNot(AsmToken::Dollar))
3064 break;
3065
3066 PrevReg = RegNo;
3067 }
3068
3069 SMLoc E = Parser.getTok().getLoc();
3070 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3071 parseMemOperand(Operands);
3072 return MatchOperand_Success;
3073}
3074
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003075MipsAsmParser::OperandMatchResultTy
3076MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3077 MCAsmParser &Parser = getParser();
3078
3079 SMLoc S = Parser.getTok().getLoc();
3080 if (parseAnyRegister(Operands) != MatchOperand_Success)
3081 return MatchOperand_ParseFail;
3082
3083 SMLoc E = Parser.getTok().getLoc();
3084 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3085 unsigned Reg = Op.getGPR32Reg();
3086 Operands.pop_back();
3087 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3088 return MatchOperand_Success;
3089}
3090
Zoran Jovanovic41688672015-02-10 16:36:20 +00003091MipsAsmParser::OperandMatchResultTy
3092MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3093 MCAsmParser &Parser = getParser();
3094 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3095 SmallVector<unsigned, 10> Regs;
3096
3097 if (Parser.getTok().isNot(AsmToken::Dollar))
3098 return MatchOperand_ParseFail;
3099
3100 SMLoc S = Parser.getTok().getLoc();
3101
3102 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3103 return MatchOperand_ParseFail;
3104
3105 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3106 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3107 Regs.push_back(RegNo);
3108
3109 SMLoc E = Parser.getTok().getLoc();
3110 if (Parser.getTok().isNot(AsmToken::Comma)) {
3111 Error(E, "',' expected");
3112 return MatchOperand_ParseFail;
3113 }
3114
3115 // Remove comma.
3116 Parser.Lex();
3117
3118 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3119 return MatchOperand_ParseFail;
3120
3121 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3122 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3123 Regs.push_back(RegNo);
3124
3125 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3126
3127 return MatchOperand_Success;
3128}
3129
Jack Carterdc1e35d2012-09-06 20:00:02 +00003130MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3131
Vladimir Medic4c299852013-11-06 11:27:05 +00003132 MCSymbolRefExpr::VariantKind VK =
3133 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3134 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3135 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3136 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3137 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3138 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3139 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3140 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3141 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3142 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3143 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3144 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3145 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3146 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3147 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3148 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3149 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3150 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003151 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3152 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3153 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3154 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3155 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3156 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003157 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3158 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003159 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003160
Matheus Almeida2852af82014-04-22 10:15:54 +00003161 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003162
Jack Carterdc1e35d2012-09-06 20:00:02 +00003163 return VK;
3164}
Jack Cartera63b16a2012-09-07 00:23:42 +00003165
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003166/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3167/// either this.
3168/// ::= '(', register, ')'
3169/// handle it before we iterate so we don't get tripped up by the lack of
3170/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003171bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003172 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003173 if (getLexer().is(AsmToken::LParen)) {
3174 Operands.push_back(
3175 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3176 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003177 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003178 SMLoc Loc = getLexer().getLoc();
3179 Parser.eatToEndOfStatement();
3180 return Error(Loc, "unexpected token in argument list");
3181 }
3182 if (Parser.getTok().isNot(AsmToken::RParen)) {
3183 SMLoc Loc = getLexer().getLoc();
3184 Parser.eatToEndOfStatement();
3185 return Error(Loc, "unexpected token, expected ')'");
3186 }
3187 Operands.push_back(
3188 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3189 Parser.Lex();
3190 }
3191 return false;
3192}
3193
3194/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3195/// either one of these.
3196/// ::= '[', register, ']'
3197/// ::= '[', integer, ']'
3198/// handle it before we iterate so we don't get tripped up by the lack of
3199/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003200bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003201 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003202 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003203 if (getLexer().is(AsmToken::LBrac)) {
3204 Operands.push_back(
3205 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3206 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003207 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003208 SMLoc Loc = getLexer().getLoc();
3209 Parser.eatToEndOfStatement();
3210 return Error(Loc, "unexpected token in argument list");
3211 }
3212 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3213 SMLoc Loc = getLexer().getLoc();
3214 Parser.eatToEndOfStatement();
3215 return Error(Loc, "unexpected token, expected ']'");
3216 }
3217 Operands.push_back(
3218 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3219 Parser.Lex();
3220 }
3221 return false;
3222}
3223
David Blaikie960ea3f2014-06-08 16:18:35 +00003224bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3225 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003226 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003227 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003228
3229 // We have reached first instruction, module directive are now forbidden.
3230 getTargetStreamer().forbidModuleDirective();
3231
Vladimir Medic74593e62013-07-17 15:00:42 +00003232 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003233 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003234 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003235 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003236 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003237 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003238 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003239
3240 // Read the remaining operands.
3241 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3242 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003243 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003244 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003245 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003246 return Error(Loc, "unexpected token in argument list");
3247 }
Toma Tabacu13964452014-09-04 13:23:44 +00003248 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003249 return true;
3250 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003251
Jack Carterd0bd6422013-04-18 00:41:53 +00003252 while (getLexer().is(AsmToken::Comma)) {
3253 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003254 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003255 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003256 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003257 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003258 return Error(Loc, "unexpected token in argument list");
3259 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003260 // Parse bracket and parenthesis suffixes before we iterate
3261 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003262 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003263 return true;
3264 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003265 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003266 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003267 }
3268 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3270 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003271 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003272 return Error(Loc, "unexpected token in argument list");
3273 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003274 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003275 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003276}
3277
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003278bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003279 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003280 SMLoc Loc = getLexer().getLoc();
3281 Parser.eatToEndOfStatement();
3282 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003283}
3284
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003285bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003286 return Error(Loc, ErrorMsg);
3287}
3288
Jack Carter0b744b32012-10-04 02:29:46 +00003289bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003290 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003291 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003292
3293 // Set the $at register to $0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003294 AssemblerOptions.back()->setATReg(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003295
3296 Parser.Lex(); // Eat "noat".
3297
Jack Carterd0bd6422013-04-18 00:41:53 +00003298 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003299 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003300 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003301 return false;
3302 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003303
3304 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003305 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003306 return false;
3307}
Jack Carterd0bd6422013-04-18 00:41:53 +00003308
Jack Carter0b744b32012-10-04 02:29:46 +00003309bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003310 // Line can be: ".set at", which sets $at to $1
3311 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003312 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003313 Parser.Lex(); // Eat "at".
3314
Jack Carter0b744b32012-10-04 02:29:46 +00003315 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003316 // No register was specified, so we set $at to $1.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003317 AssemblerOptions.back()->setATReg(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003318
3319 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003320 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003321 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003322 }
3323
3324 if (getLexer().isNot(AsmToken::Equal)) {
3325 reportParseError("unexpected token, expected equals sign");
3326 return false;
3327 }
3328 Parser.Lex(); // Eat "=".
3329
3330 if (getLexer().isNot(AsmToken::Dollar)) {
3331 if (getLexer().is(AsmToken::EndOfStatement)) {
3332 reportParseError("no register specified");
3333 return false;
3334 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003335 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003336 return false;
3337 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003338 }
3339 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003340
Toma Tabacu16a74492015-02-13 10:30:57 +00003341 // Find out what "reg" is.
3342 unsigned AtRegNo;
3343 const AsmToken &Reg = Parser.getTok();
3344 if (Reg.is(AsmToken::Identifier)) {
3345 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3346 } else if (Reg.is(AsmToken::Integer)) {
3347 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003348 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003349 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003350 return false;
3351 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003352
3353 // Check if $reg is a valid register. If it is, set $at to $reg.
3354 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3355 reportParseError("invalid register");
3356 return false;
3357 }
3358 Parser.Lex(); // Eat "reg".
3359
3360 // If this is not the end of the statement, report an error.
3361 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3362 reportParseError("unexpected token, expected end of statement");
3363 return false;
3364 }
3365
3366 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3367
3368 Parser.Lex(); // Consume the EndOfStatement.
3369 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003370}
3371
3372bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003373 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003374 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003375 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003376 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003377 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003378 return false;
3379 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003380 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003381 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003382 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003383 return false;
3384}
3385
3386bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003387 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003388 Parser.Lex();
3389 // If this is not the end of the statement, report an error.
3390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003391 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003392 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003393 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003394 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003395 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003396 Parser.Lex(); // Consume the EndOfStatement.
3397 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003398}
3399
3400bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003401 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003402 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003403 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003405 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003406 return false;
3407 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003408 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003409 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003410 return false;
3411}
3412
3413bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003414 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003415 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003416 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003417 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003418 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003419 return false;
3420 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003421 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003422 reportParseError("`noreorder' must be set before `nomacro'");
3423 return false;
3424 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003425 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003426 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003427 return false;
3428}
Jack Carterd76b2372013-03-21 21:44:16 +00003429
Daniel Sanders44934432014-08-07 12:03:36 +00003430bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003431 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003432 Parser.Lex();
3433
3434 // If this is not the end of the statement, report an error.
3435 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003436 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003437
3438 setFeatureBits(Mips::FeatureMSA, "msa");
3439 getTargetStreamer().emitDirectiveSetMsa();
3440 return false;
3441}
3442
3443bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003444 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003445 Parser.Lex();
3446
3447 // If this is not the end of the statement, report an error.
3448 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003449 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003450
3451 clearFeatureBits(Mips::FeatureMSA, "msa");
3452 getTargetStreamer().emitDirectiveSetNoMsa();
3453 return false;
3454}
3455
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003456bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003457 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003458 Parser.Lex(); // Eat "nodsp".
3459
3460 // If this is not the end of the statement, report an error.
3461 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3462 reportParseError("unexpected token, expected end of statement");
3463 return false;
3464 }
3465
3466 clearFeatureBits(Mips::FeatureDSP, "dsp");
3467 getTargetStreamer().emitDirectiveSetNoDsp();
3468 return false;
3469}
3470
Toma Tabacucc2502d2014-11-04 17:18:07 +00003471bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003472 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003473 Parser.Lex(); // Eat "mips16".
3474
Jack Carter39536722014-01-22 23:08:42 +00003475 // If this is not the end of the statement, report an error.
3476 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003477 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003478 return false;
3479 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003480
3481 setFeatureBits(Mips::FeatureMips16, "mips16");
3482 getTargetStreamer().emitDirectiveSetMips16();
3483 Parser.Lex(); // Consume the EndOfStatement.
3484 return false;
3485}
3486
3487bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003488 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003489 Parser.Lex(); // Eat "nomips16".
3490
3491 // If this is not the end of the statement, report an error.
3492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3493 reportParseError("unexpected token, expected end of statement");
3494 return false;
3495 }
3496
3497 clearFeatureBits(Mips::FeatureMips16, "mips16");
3498 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003499 Parser.Lex(); // Consume the EndOfStatement.
3500 return false;
3501}
3502
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003503bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003504 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003505 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003506 // Line can be: .set fp=32
3507 // .set fp=xx
3508 // .set fp=64
3509 Parser.Lex(); // Eat fp token
3510 AsmToken Tok = Parser.getTok();
3511 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003512 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003513 return false;
3514 }
3515 Parser.Lex(); // Eat '=' token.
3516 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003517
3518 if (!parseFpABIValue(FpAbiVal, ".set"))
3519 return false;
3520
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003521 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003522 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003523 return false;
3524 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003525 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003526 Parser.Lex(); // Consume the EndOfStatement.
3527 return false;
3528}
3529
Toma Tabacu9db22db2014-09-09 10:15:38 +00003530bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003531 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003532 SMLoc Loc = getLexer().getLoc();
3533
3534 Parser.Lex();
3535 if (getLexer().isNot(AsmToken::EndOfStatement))
3536 return reportParseError("unexpected token, expected end of statement");
3537
3538 // Always keep an element on the options "stack" to prevent the user
3539 // from changing the initial options. This is how we remember them.
3540 if (AssemblerOptions.size() == 2)
3541 return reportParseError(Loc, ".set pop with no .set push");
3542
3543 AssemblerOptions.pop_back();
3544 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3545
3546 getTargetStreamer().emitDirectiveSetPop();
3547 return false;
3548}
3549
3550bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003551 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003552 Parser.Lex();
3553 if (getLexer().isNot(AsmToken::EndOfStatement))
3554 return reportParseError("unexpected token, expected end of statement");
3555
3556 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003557 AssemblerOptions.push_back(
3558 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003559
3560 getTargetStreamer().emitDirectiveSetPush();
3561 return false;
3562}
3563
Jack Carterd76b2372013-03-21 21:44:16 +00003564bool MipsAsmParser::parseSetAssignment() {
3565 StringRef Name;
3566 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003567 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003568
3569 if (Parser.parseIdentifier(Name))
3570 reportParseError("expected identifier after .set");
3571
3572 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003573 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003574 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003575
Jack Carter3b2c96e2014-01-22 23:31:38 +00003576 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003577 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003578
Jack Carterd0bd6422013-04-18 00:41:53 +00003579 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003580 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003581 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003582 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003583 Sym = getContext().GetOrCreateSymbol(Name);
3584 Sym->setVariableValue(Value);
3585
3586 return false;
3587}
Jack Carterd0bd6422013-04-18 00:41:53 +00003588
Toma Tabacu26647792014-09-09 12:52:14 +00003589bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003590 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003591 Parser.Lex();
3592 if (getLexer().isNot(AsmToken::EndOfStatement))
3593 return reportParseError("unexpected token, expected end of statement");
3594
3595 // Reset assembler options to their initial values.
3596 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3597 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3598
3599 getTargetStreamer().emitDirectiveSetMips0();
3600 return false;
3601}
3602
Toma Tabacu85618b32014-08-19 14:22:52 +00003603bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003604 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003605 Parser.Lex();
3606 if (getLexer().isNot(AsmToken::Equal))
3607 return reportParseError("unexpected token, expected equals sign");
3608
3609 Parser.Lex();
3610 StringRef Arch;
3611 if (Parser.parseIdentifier(Arch))
3612 return reportParseError("expected arch identifier");
3613
3614 StringRef ArchFeatureName =
3615 StringSwitch<StringRef>(Arch)
3616 .Case("mips1", "mips1")
3617 .Case("mips2", "mips2")
3618 .Case("mips3", "mips3")
3619 .Case("mips4", "mips4")
3620 .Case("mips5", "mips5")
3621 .Case("mips32", "mips32")
3622 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003623 .Case("mips32r3", "mips32r3")
3624 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003625 .Case("mips32r6", "mips32r6")
3626 .Case("mips64", "mips64")
3627 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003628 .Case("mips64r3", "mips64r3")
3629 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003630 .Case("mips64r6", "mips64r6")
3631 .Case("cnmips", "cnmips")
3632 .Case("r4000", "mips3") // This is an implementation of Mips3.
3633 .Default("");
3634
3635 if (ArchFeatureName.empty())
3636 return reportParseError("unsupported architecture");
3637
3638 selectArch(ArchFeatureName);
3639 getTargetStreamer().emitDirectiveSetArch(Arch);
3640 return false;
3641}
3642
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003643bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003644 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003645 Parser.Lex();
3646 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003647 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003648
Matheus Almeida2852af82014-04-22 10:15:54 +00003649 switch (Feature) {
3650 default:
3651 llvm_unreachable("Unimplemented feature");
3652 case Mips::FeatureDSP:
3653 setFeatureBits(Mips::FeatureDSP, "dsp");
3654 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003655 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003656 case Mips::FeatureMicroMips:
3657 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003658 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003659 case Mips::FeatureMips1:
3660 selectArch("mips1");
3661 getTargetStreamer().emitDirectiveSetMips1();
3662 break;
3663 case Mips::FeatureMips2:
3664 selectArch("mips2");
3665 getTargetStreamer().emitDirectiveSetMips2();
3666 break;
3667 case Mips::FeatureMips3:
3668 selectArch("mips3");
3669 getTargetStreamer().emitDirectiveSetMips3();
3670 break;
3671 case Mips::FeatureMips4:
3672 selectArch("mips4");
3673 getTargetStreamer().emitDirectiveSetMips4();
3674 break;
3675 case Mips::FeatureMips5:
3676 selectArch("mips5");
3677 getTargetStreamer().emitDirectiveSetMips5();
3678 break;
3679 case Mips::FeatureMips32:
3680 selectArch("mips32");
3681 getTargetStreamer().emitDirectiveSetMips32();
3682 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003683 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003684 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003685 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003686 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003687 case Mips::FeatureMips32r3:
3688 selectArch("mips32r3");
3689 getTargetStreamer().emitDirectiveSetMips32R3();
3690 break;
3691 case Mips::FeatureMips32r5:
3692 selectArch("mips32r5");
3693 getTargetStreamer().emitDirectiveSetMips32R5();
3694 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003695 case Mips::FeatureMips32r6:
3696 selectArch("mips32r6");
3697 getTargetStreamer().emitDirectiveSetMips32R6();
3698 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003699 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003700 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003701 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003702 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003703 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003704 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003705 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003706 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003707 case Mips::FeatureMips64r3:
3708 selectArch("mips64r3");
3709 getTargetStreamer().emitDirectiveSetMips64R3();
3710 break;
3711 case Mips::FeatureMips64r5:
3712 selectArch("mips64r5");
3713 getTargetStreamer().emitDirectiveSetMips64R5();
3714 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003715 case Mips::FeatureMips64r6:
3716 selectArch("mips64r6");
3717 getTargetStreamer().emitDirectiveSetMips64R6();
3718 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003719 }
3720 return false;
3721}
3722
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003723bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003724 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003725 if (getLexer().isNot(AsmToken::Comma)) {
3726 SMLoc Loc = getLexer().getLoc();
3727 Parser.eatToEndOfStatement();
3728 return Error(Loc, ErrorStr);
3729 }
3730
Matheus Almeida2852af82014-04-22 10:15:54 +00003731 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003732 return true;
3733}
3734
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003735bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003736 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003737 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003738
Toma Tabacudde4c462014-11-06 10:02:45 +00003739 if (inMips16Mode()) {
3740 reportParseError(".cpload is not supported in Mips16 mode");
3741 return false;
3742 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003743
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003745 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003746 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3747 reportParseError("expected register containing function address");
3748 return false;
3749 }
3750
David Blaikie960ea3f2014-06-08 16:18:35 +00003751 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3752 if (!RegOpnd.isGPRAsmReg()) {
3753 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003754 return false;
3755 }
3756
Toma Tabacudde4c462014-11-06 10:02:45 +00003757 // If this is not the end of the statement, report an error.
3758 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3759 reportParseError("unexpected token, expected end of statement");
3760 return false;
3761 }
3762
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003763 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003764 return false;
3765}
3766
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003767bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003768 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003769 unsigned FuncReg;
3770 unsigned Save;
3771 bool SaveIsReg = true;
3772
Matheus Almeida7e815762014-06-18 13:08:59 +00003773 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003774 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003775 if (ResTy == MatchOperand_NoMatch) {
3776 reportParseError("expected register containing function address");
3777 Parser.eatToEndOfStatement();
3778 return false;
3779 }
3780
3781 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3782 if (!FuncRegOpnd.isGPRAsmReg()) {
3783 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3784 Parser.eatToEndOfStatement();
3785 return false;
3786 }
3787
3788 FuncReg = FuncRegOpnd.getGPR32Reg();
3789 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003790
Toma Tabacu65f10572014-09-16 15:00:52 +00003791 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003792 return true;
3793
Toma Tabacu13964452014-09-04 13:23:44 +00003794 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003795 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003796 const AsmToken &Tok = Parser.getTok();
3797 if (Tok.is(AsmToken::Integer)) {
3798 Save = Tok.getIntVal();
3799 SaveIsReg = false;
3800 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003801 } else {
3802 reportParseError("expected save register or stack offset");
3803 Parser.eatToEndOfStatement();
3804 return false;
3805 }
3806 } else {
3807 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3808 if (!SaveOpnd.isGPRAsmReg()) {
3809 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3810 Parser.eatToEndOfStatement();
3811 return false;
3812 }
3813 Save = SaveOpnd.getGPR32Reg();
3814 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003815
Toma Tabacu65f10572014-09-16 15:00:52 +00003816 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003817 return true;
3818
Toma Tabacu8874eac2015-02-18 13:46:53 +00003819 const MCExpr *Expr;
3820 if (Parser.parseExpression(Expr)) {
3821 reportParseError("expected expression");
3822 return false;
3823 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003824
Toma Tabacu8874eac2015-02-18 13:46:53 +00003825 if (Expr->getKind() != MCExpr::SymbolRef) {
3826 reportParseError("expected symbol");
3827 return false;
3828 }
3829 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3830
3831 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3832 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003833 return false;
3834}
3835
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003836bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003837 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003838 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3839 const AsmToken &Tok = Parser.getTok();
3840
3841 if (Tok.getString() == "2008") {
3842 Parser.Lex();
3843 getTargetStreamer().emitDirectiveNaN2008();
3844 return false;
3845 } else if (Tok.getString() == "legacy") {
3846 Parser.Lex();
3847 getTargetStreamer().emitDirectiveNaNLegacy();
3848 return false;
3849 }
3850 }
3851 // If we don't recognize the option passed to the .nan
3852 // directive (e.g. no option or unknown option), emit an error.
3853 reportParseError("invalid option in .nan directive");
3854 return false;
3855}
3856
Jack Carter0b744b32012-10-04 02:29:46 +00003857bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003858 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003859 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003860 const AsmToken &Tok = Parser.getTok();
3861
3862 if (Tok.getString() == "noat") {
3863 return parseSetNoAtDirective();
3864 } else if (Tok.getString() == "at") {
3865 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003866 } else if (Tok.getString() == "arch") {
3867 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003868 } else if (Tok.getString() == "fp") {
3869 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003870 } else if (Tok.getString() == "pop") {
3871 return parseSetPopDirective();
3872 } else if (Tok.getString() == "push") {
3873 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003874 } else if (Tok.getString() == "reorder") {
3875 return parseSetReorderDirective();
3876 } else if (Tok.getString() == "noreorder") {
3877 return parseSetNoReorderDirective();
3878 } else if (Tok.getString() == "macro") {
3879 return parseSetMacroDirective();
3880 } else if (Tok.getString() == "nomacro") {
3881 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003882 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003883 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003884 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003885 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003886 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003887 getTargetStreamer().emitDirectiveSetNoMicroMips();
3888 Parser.eatToEndOfStatement();
3889 return false;
3890 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003891 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003892 } else if (Tok.getString() == "mips0") {
3893 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003894 } else if (Tok.getString() == "mips1") {
3895 return parseSetFeature(Mips::FeatureMips1);
3896 } else if (Tok.getString() == "mips2") {
3897 return parseSetFeature(Mips::FeatureMips2);
3898 } else if (Tok.getString() == "mips3") {
3899 return parseSetFeature(Mips::FeatureMips3);
3900 } else if (Tok.getString() == "mips4") {
3901 return parseSetFeature(Mips::FeatureMips4);
3902 } else if (Tok.getString() == "mips5") {
3903 return parseSetFeature(Mips::FeatureMips5);
3904 } else if (Tok.getString() == "mips32") {
3905 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003906 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003907 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003908 } else if (Tok.getString() == "mips32r3") {
3909 return parseSetFeature(Mips::FeatureMips32r3);
3910 } else if (Tok.getString() == "mips32r5") {
3911 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003912 } else if (Tok.getString() == "mips32r6") {
3913 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003914 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003915 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003916 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003917 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003918 } else if (Tok.getString() == "mips64r3") {
3919 return parseSetFeature(Mips::FeatureMips64r3);
3920 } else if (Tok.getString() == "mips64r5") {
3921 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003922 } else if (Tok.getString() == "mips64r6") {
3923 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003924 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003925 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003926 } else if (Tok.getString() == "nodsp") {
3927 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003928 } else if (Tok.getString() == "msa") {
3929 return parseSetMsaDirective();
3930 } else if (Tok.getString() == "nomsa") {
3931 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003932 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003933 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003934 parseSetAssignment();
3935 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003936 }
Jack Carter07c818d2013-01-25 01:31:34 +00003937
Jack Carter0b744b32012-10-04 02:29:46 +00003938 return true;
3939}
3940
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003941/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003942/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003943bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003944 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003945 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3946 for (;;) {
3947 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003948 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003949 return true;
3950
3951 getParser().getStreamer().EmitValue(Value, Size);
3952
3953 if (getLexer().is(AsmToken::EndOfStatement))
3954 break;
3955
Jack Carter07c818d2013-01-25 01:31:34 +00003956 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003957 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003958 Parser.Lex();
3959 }
3960 }
3961
3962 Parser.Lex();
3963 return false;
3964}
3965
Vladimir Medic4c299852013-11-06 11:27:05 +00003966/// parseDirectiveGpWord
3967/// ::= .gpword local_sym
3968bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003969 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003970 const MCExpr *Value;
3971 // EmitGPRel32Value requires an expression, so we are using base class
3972 // method to evaluate the expression.
3973 if (getParser().parseExpression(Value))
3974 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003975 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003976
Vladimir Medice10c1122013-11-13 13:18:04 +00003977 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003978 return Error(getLexer().getLoc(),
3979 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003980 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003981 return false;
3982}
3983
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003984/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003985/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003986bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003987 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003988 const MCExpr *Value;
3989 // EmitGPRel64Value requires an expression, so we are using base class
3990 // method to evaluate the expression.
3991 if (getParser().parseExpression(Value))
3992 return true;
3993 getParser().getStreamer().EmitGPRel64Value(Value);
3994
3995 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003996 return Error(getLexer().getLoc(),
3997 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003998 Parser.Lex(); // Eat EndOfStatement token.
3999 return false;
4000}
4001
Jack Carter0cd3c192014-01-06 23:27:31 +00004002bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004003 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004004 // Get the option token.
4005 AsmToken Tok = Parser.getTok();
4006 // At the moment only identifiers are supported.
4007 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004008 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004009 Parser.eatToEndOfStatement();
4010 return false;
4011 }
4012
4013 StringRef Option = Tok.getIdentifier();
4014
4015 if (Option == "pic0") {
4016 getTargetStreamer().emitDirectiveOptionPic0();
4017 Parser.Lex();
4018 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4019 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004020 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004021 Parser.eatToEndOfStatement();
4022 }
4023 return false;
4024 }
4025
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004026 if (Option == "pic2") {
4027 getTargetStreamer().emitDirectiveOptionPic2();
4028 Parser.Lex();
4029 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4030 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004031 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004032 Parser.eatToEndOfStatement();
4033 }
4034 return false;
4035 }
4036
Jack Carter0cd3c192014-01-06 23:27:31 +00004037 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004038 Warning(Parser.getTok().getLoc(),
4039 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004040 Parser.eatToEndOfStatement();
4041 return false;
4042}
4043
Daniel Sanders7e527422014-07-10 13:38:23 +00004044/// parseDirectiveModule
4045/// ::= .module oddspreg
4046/// ::= .module nooddspreg
4047/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004048bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004049 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004050 MCAsmLexer &Lexer = getLexer();
4051 SMLoc L = Lexer.getLoc();
4052
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004053 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004054 // TODO : get a better message.
4055 reportParseError(".module directive must appear before any code");
4056 return false;
4057 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004058
Toma Tabacuc405c822015-01-23 10:40:19 +00004059 StringRef Option;
4060 if (Parser.parseIdentifier(Option)) {
4061 reportParseError("expected .module option identifier");
4062 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004063 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004064
Toma Tabacuc405c822015-01-23 10:40:19 +00004065 if (Option == "oddspreg") {
4066 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4067 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4068
4069 // If this is not the end of the statement, report an error.
4070 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4071 reportParseError("unexpected token, expected end of statement");
4072 return false;
4073 }
4074
4075 return false; // parseDirectiveModule has finished successfully.
4076 } else if (Option == "nooddspreg") {
4077 if (!isABI_O32()) {
4078 Error(L, "'.module nooddspreg' requires the O32 ABI");
4079 return false;
4080 }
4081
4082 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4083 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4084
4085 // If this is not the end of the statement, report an error.
4086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4087 reportParseError("unexpected token, expected end of statement");
4088 return false;
4089 }
4090
4091 return false; // parseDirectiveModule has finished successfully.
4092 } else if (Option == "fp") {
4093 return parseDirectiveModuleFP();
4094 } else {
4095 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4096 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004097}
4098
4099/// parseDirectiveModuleFP
4100/// ::= =32
4101/// ::= =xx
4102/// ::= =64
4103bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004104 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004105 MCAsmLexer &Lexer = getLexer();
4106
4107 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004108 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004109 return false;
4110 }
4111 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004112
Daniel Sanders7e527422014-07-10 13:38:23 +00004113 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004114 if (!parseFpABIValue(FpABI, ".module"))
4115 return false;
4116
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004117 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004118 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004119 return false;
4120 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004121
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004122 // Emit appropriate flags.
4123 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004124 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004125 return false;
4126}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004127
Daniel Sanders7e527422014-07-10 13:38:23 +00004128bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004129 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004130 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004131 MCAsmLexer &Lexer = getLexer();
4132
4133 if (Lexer.is(AsmToken::Identifier)) {
4134 StringRef Value = Parser.getTok().getString();
4135 Parser.Lex();
4136
4137 if (Value != "xx") {
4138 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4139 return false;
4140 }
4141
4142 if (!isABI_O32()) {
4143 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4144 return false;
4145 }
4146
Daniel Sanders7e527422014-07-10 13:38:23 +00004147 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004148 return true;
4149 }
4150
4151 if (Lexer.is(AsmToken::Integer)) {
4152 unsigned Value = Parser.getTok().getIntVal();
4153 Parser.Lex();
4154
4155 if (Value != 32 && Value != 64) {
4156 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4157 return false;
4158 }
4159
4160 if (Value == 32) {
4161 if (!isABI_O32()) {
4162 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4163 return false;
4164 }
4165
Daniel Sanders7e527422014-07-10 13:38:23 +00004166 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4167 } else
4168 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004169
Daniel Sanders7e527422014-07-10 13:38:23 +00004170 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004171 }
4172
4173 return false;
4174}
4175
Jack Carter0b744b32012-10-04 02:29:46 +00004176bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004177 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004178 StringRef IDVal = DirectiveID.getString();
4179
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004180 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004181 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004182 if (IDVal == ".dword") {
4183 parseDataDirective(8, DirectiveID.getLoc());
4184 return false;
4185 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004186 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004187 StringRef SymbolName;
4188
4189 if (Parser.parseIdentifier(SymbolName)) {
4190 reportParseError("expected identifier after .ent");
4191 return false;
4192 }
4193
4194 // There's an undocumented extension that allows an integer to
4195 // follow the name of the procedure which AFAICS is ignored by GAS.
4196 // Example: .ent foo,2
4197 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4198 if (getLexer().isNot(AsmToken::Comma)) {
4199 // Even though we accept this undocumented extension for compatibility
4200 // reasons, the additional integer argument does not actually change
4201 // the behaviour of the '.ent' directive, so we would like to discourage
4202 // its use. We do this by not referring to the extended version in
4203 // error messages which are not directly related to its use.
4204 reportParseError("unexpected token, expected end of statement");
4205 return false;
4206 }
4207 Parser.Lex(); // Eat the comma.
4208 const MCExpr *DummyNumber;
4209 int64_t DummyNumberVal;
4210 // If the user was explicitly trying to use the extended version,
4211 // we still give helpful extension-related error messages.
4212 if (Parser.parseExpression(DummyNumber)) {
4213 reportParseError("expected number after comma");
4214 return false;
4215 }
4216 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4217 reportParseError("expected an absolute expression after comma");
4218 return false;
4219 }
4220 }
4221
4222 // If this is not the end of the statement, report an error.
4223 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4224 reportParseError("unexpected token, expected end of statement");
4225 return false;
4226 }
4227
4228 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4229
4230 getTargetStreamer().emitDirectiveEnt(*Sym);
4231 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004232 return false;
4233 }
4234
Jack Carter07c818d2013-01-25 01:31:34 +00004235 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004236 StringRef SymbolName;
4237
4238 if (Parser.parseIdentifier(SymbolName)) {
4239 reportParseError("expected identifier after .end");
4240 return false;
4241 }
4242
4243 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4244 reportParseError("unexpected token, expected end of statement");
4245 return false;
4246 }
4247
4248 if (CurrentFn == nullptr) {
4249 reportParseError(".end used without .ent");
4250 return false;
4251 }
4252
4253 if ((SymbolName != CurrentFn->getName())) {
4254 reportParseError(".end symbol does not match .ent symbol");
4255 return false;
4256 }
4257
4258 getTargetStreamer().emitDirectiveEnd(SymbolName);
4259 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004260 return false;
4261 }
4262
Jack Carter07c818d2013-01-25 01:31:34 +00004263 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004264 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4265 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004266 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004267 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4268 reportParseError("expected stack register");
4269 return false;
4270 }
4271
4272 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4273 if (!StackRegOpnd.isGPRAsmReg()) {
4274 reportParseError(StackRegOpnd.getStartLoc(),
4275 "expected general purpose register");
4276 return false;
4277 }
4278 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4279
4280 if (Parser.getTok().is(AsmToken::Comma))
4281 Parser.Lex();
4282 else {
4283 reportParseError("unexpected token, expected comma");
4284 return false;
4285 }
4286
4287 // Parse the frame size.
4288 const MCExpr *FrameSize;
4289 int64_t FrameSizeVal;
4290
4291 if (Parser.parseExpression(FrameSize)) {
4292 reportParseError("expected frame size value");
4293 return false;
4294 }
4295
4296 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4297 reportParseError("frame size not an absolute expression");
4298 return false;
4299 }
4300
4301 if (Parser.getTok().is(AsmToken::Comma))
4302 Parser.Lex();
4303 else {
4304 reportParseError("unexpected token, expected comma");
4305 return false;
4306 }
4307
4308 // Parse the return register.
4309 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004310 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004311 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4312 reportParseError("expected return register");
4313 return false;
4314 }
4315
4316 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4317 if (!ReturnRegOpnd.isGPRAsmReg()) {
4318 reportParseError(ReturnRegOpnd.getStartLoc(),
4319 "expected general purpose register");
4320 return false;
4321 }
4322
4323 // If this is not the end of the statement, report an error.
4324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4325 reportParseError("unexpected token, expected end of statement");
4326 return false;
4327 }
4328
4329 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4330 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004331 return false;
4332 }
4333
Jack Carter07c818d2013-01-25 01:31:34 +00004334 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004335 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004336 }
4337
Daniel Sandersd97a6342014-08-13 10:07:34 +00004338 if (IDVal == ".mask" || IDVal == ".fmask") {
4339 // .mask bitmask, frame_offset
4340 // bitmask: One bit for each register used.
4341 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4342 // first register is expected to be saved.
4343 // Examples:
4344 // .mask 0x80000000, -4
4345 // .fmask 0x80000000, -4
4346 //
Jack Carterbe332172012-09-07 00:48:02 +00004347
Daniel Sandersd97a6342014-08-13 10:07:34 +00004348 // Parse the bitmask
4349 const MCExpr *BitMask;
4350 int64_t BitMaskVal;
4351
4352 if (Parser.parseExpression(BitMask)) {
4353 reportParseError("expected bitmask value");
4354 return false;
4355 }
4356
4357 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4358 reportParseError("bitmask not an absolute expression");
4359 return false;
4360 }
4361
4362 if (Parser.getTok().is(AsmToken::Comma))
4363 Parser.Lex();
4364 else {
4365 reportParseError("unexpected token, expected comma");
4366 return false;
4367 }
4368
4369 // Parse the frame_offset
4370 const MCExpr *FrameOffset;
4371 int64_t FrameOffsetVal;
4372
4373 if (Parser.parseExpression(FrameOffset)) {
4374 reportParseError("expected frame offset value");
4375 return false;
4376 }
4377
4378 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4379 reportParseError("frame offset not an absolute expression");
4380 return false;
4381 }
4382
4383 // If this is not the end of the statement, report an error.
4384 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4385 reportParseError("unexpected token, expected end of statement");
4386 return false;
4387 }
4388
4389 if (IDVal == ".mask")
4390 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4391 else
4392 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004393 return false;
4394 }
4395
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004396 if (IDVal == ".nan")
4397 return parseDirectiveNaN();
4398
Jack Carter07c818d2013-01-25 01:31:34 +00004399 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004400 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004401 return false;
4402 }
4403
Rafael Espindolab59fb732014-03-28 18:50:26 +00004404 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004405 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004406 return false;
4407 }
4408
Jack Carter07c818d2013-01-25 01:31:34 +00004409 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004410 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004411 return false;
4412 }
4413
Jack Carter0cd3c192014-01-06 23:27:31 +00004414 if (IDVal == ".option")
4415 return parseDirectiveOption();
4416
4417 if (IDVal == ".abicalls") {
4418 getTargetStreamer().emitDirectiveAbiCalls();
4419 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004420 Error(Parser.getTok().getLoc(),
4421 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004422 // Clear line
4423 Parser.eatToEndOfStatement();
4424 }
4425 return false;
4426 }
4427
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004428 if (IDVal == ".cpsetup")
4429 return parseDirectiveCPSetup();
4430
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004431 if (IDVal == ".module")
4432 return parseDirectiveModule();
4433
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004434 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4435 return parseInternalDirectiveReallowModule();
4436
Rafael Espindola870c4e92012-01-11 03:56:41 +00004437 return true;
4438}
4439
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004440bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4441 // If this is not the end of the statement, report an error.
4442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4443 reportParseError("unexpected token, expected end of statement");
4444 return false;
4445 }
4446
4447 getTargetStreamer().reallowModuleDirective();
4448
4449 getParser().Lex(); // Eat EndOfStatement token.
4450 return false;
4451}
4452
Rafael Espindola870c4e92012-01-11 03:56:41 +00004453extern "C" void LLVMInitializeMipsAsmParser() {
4454 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4455 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4456 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4457 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4458}
Jack Carterb4dbc172012-09-05 23:34:03 +00004459
4460#define GET_REGISTER_MATCHER
4461#define GET_MATCHER_IMPLEMENTATION
4462#include "MipsGenAsmMatcher.inc"