blob: 2e572c124dceadb1659222ab8473e2ab89da5c50 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000032#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000033
34using namespace llvm;
35
Chandler Carruthe96dd892014-04-21 22:55:11 +000036#define DEBUG_TYPE "mips-asm-parser"
37
Joey Gouly0e76fa72013-09-12 10:28:05 +000038namespace llvm {
39class MCInstrInfo;
40}
41
Rafael Espindola870c4e92012-01-11 03:56:41 +000042namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000043class MipsAssemblerOptions {
44public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000045 MipsAssemblerOptions(uint64_t Features_) :
46 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000047
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
49 ATReg = Opts->getATRegNum();
50 Reorder = Opts->isReorder();
51 Macro = Opts->isMacro();
52 Features = Opts->getFeatures();
53 }
54
55 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000056 bool setATReg(unsigned Reg);
57
Toma Tabacu9db22db2014-09-09 10:15:38 +000058 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000059 void setReorder() { Reorder = true; }
60 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000061
Toma Tabacu9db22db2014-09-09 10:15:38 +000062 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000063 void setMacro() { Macro = true; }
64 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 uint64_t getFeatures() const { return Features; }
67 void setFeatures(uint64_t Features_) { Features = Features_; }
68
Daniel Sandersf0df2212014-08-04 12:20:00 +000069 // Set of features that are either architecture features or referenced
70 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
71 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
72 // The reason we need this mask is explained in the selectArch function.
73 // FIXME: Ideally we would like TableGen to generate this information.
74 static const uint64_t AllArchRelatedMask =
75 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
76 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
77 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
78 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
79 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
80 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
81 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
82
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000087 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
91namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000092class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000093 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000094 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000095 return static_cast<MipsTargetStreamer &>(TS);
96 }
97
Jack Carterb4dbc172012-09-05 23:34:03 +000098 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +000099 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000100 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000101 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
102 // nullptr, which indicates that no function is currently
103 // selected. This usually happens after an '.end func'
104 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000105
Daniel Sandersef638fe2014-10-03 15:37:37 +0000106 // Print a warning along with its fix-it message at the given range.
107 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
108 SMRange Range, bool ShowColors = true);
109
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000110#define GET_ASSEMBLER_HEADER
111#include "MipsGenAsmMatcher.inc"
112
Matheus Almeida595fcab2014-06-11 15:05:56 +0000113 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
114
Chad Rosier49963552012-10-13 00:26:04 +0000115 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000116 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000117 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000118 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000119
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000120 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000121 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
Toma Tabacu13964452014-09-04 13:23:44 +0000125 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000126
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
128 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
David Blaikie960ea3f2014-06-08 16:18:35 +0000132 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000133
134 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000135 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000137
Jack Carter873c7242013-01-12 01:03:14 +0000138 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000139 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000150
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000151 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000152 parseRegisterPair (OperandVector &Operands);
153
154 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000155 parseRegisterList (OperandVector &Operands);
156
David Blaikie960ea3f2014-06-08 16:18:35 +0000157 bool searchSymbolAlias(OperandVector &Operands);
158
Toma Tabacu13964452014-09-04 13:23:44 +0000159 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000160
Jack Carter30a59822012-10-04 04:03:53 +0000161 bool needsExpansion(MCInst &Inst);
162
Matheus Almeida3813d572014-06-19 14:39:14 +0000163 // Expands assembly pseudo instructions.
164 // Returns false on success, true otherwise.
165 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000166 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000167
168 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000169 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000170
171 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000172 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000173
174 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000175 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000176 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu0d64b202014-08-14 10:29:17 +0000179 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Jack Carter9e65aa32013-03-22 00:05:30 +0000182 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000183 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
184 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000185 bool reportParseError(Twine ErrorMsg);
186 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000187
Jack Carterb5cf5902013-04-17 00:18:04 +0000188 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000189 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000190
Vladimir Medic4c299852013-11-06 11:27:05 +0000191 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000192
193 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000194 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000195 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000196 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000197 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000198 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000199 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000200 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000201 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000202
203 bool parseSetAtDirective();
204 bool parseSetNoAtDirective();
205 bool parseSetMacroDirective();
206 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000207 bool parseSetMsaDirective();
208 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000209 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000210 bool parseSetReorderDirective();
211 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000212 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000213 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000214 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000215 bool parseSetPopDirective();
216 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000217
Jack Carterd76b2372013-03-21 21:44:16 +0000218 bool parseSetAssignment();
219
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000220 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000221 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000222 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000223 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000224 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000225 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
226 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000227
Jack Carterdc1e35d2012-09-06 20:00:02 +0000228 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000229
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000230 bool eatComma(StringRef ErrorStr);
231
Jack Carter1ac53222013-02-20 23:11:17 +0000232 int matchCPURegisterName(StringRef Symbol);
233
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000234 int matchHWRegsRegisterName(StringRef Symbol);
235
Jack Carter873c7242013-01-12 01:03:14 +0000236 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000237
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000238 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000239
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000240 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000241
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000242 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000243
Jack Carter5dc8ac92013-09-25 23:50:44 +0000244 int matchMSA128RegisterName(StringRef Name);
245
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000246 int matchMSA128CtrlRegisterName(StringRef Name);
247
Jack Carterd0bd6422013-04-18 00:41:53 +0000248 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000249
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000250 unsigned getGPR(int RegNo);
251
Matheus Almeida7de68e72014-06-18 14:46:05 +0000252 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000253
254 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000255 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000256
257 // Helper function that checks if the value of a vector index is within the
258 // boundaries of accepted values for each RegisterKind
259 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
260 bool validateMSAIndex(int Val, int RegKind);
261
Daniel Sandersf0df2212014-08-04 12:20:00 +0000262 // Selects a new architecture by updating the FeatureBits with the necessary
263 // info including implied dependencies.
264 // Internally, it clears all the feature bits related to *any* architecture
265 // and selects the new one using the ToggleFeature functionality of the
266 // MCSubtargetInfo object that handles implied dependencies. The reason we
267 // clear all the arch related bits manually is because ToggleFeature only
268 // clears the features that imply the feature being cleared and not the
269 // features implied by the feature being cleared. This is easier to see
270 // with an example:
271 // --------------------------------------------------
272 // | Feature | Implies |
273 // | -------------------------------------------------|
274 // | FeatureMips1 | None |
275 // | FeatureMips2 | FeatureMips1 |
276 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
277 // | FeatureMips4 | FeatureMips3 |
278 // | ... | |
279 // --------------------------------------------------
280 //
281 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
282 // FeatureMipsGP64 | FeatureMips1)
283 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
284 void selectArch(StringRef ArchFeature) {
285 uint64_t FeatureBits = STI.getFeatureBits();
286 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
287 STI.setFeatureBits(FeatureBits);
288 setAvailableFeatures(
289 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000290 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000291 }
292
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000293 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000294 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000295 setAvailableFeatures(
296 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000297 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000298 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000299 }
300
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000301 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000302 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000303 setAvailableFeatures(
304 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000305 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000306 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000307 }
308
Rafael Espindola870c4e92012-01-11 03:56:41 +0000309public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000310 enum MipsMatchResultTy {
311 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
312#define GET_OPERAND_DIAGNOSTIC_TYPES
313#include "MipsGenAsmMatcher.inc"
314#undef GET_OPERAND_DIAGNOSTIC_TYPES
315
316 };
317
Joey Gouly0e76fa72013-09-12 10:28:05 +0000318 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000319 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000320 : MCTargetAsmParser(), STI(sti),
321 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
322 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000323 MCAsmParserExtension::Initialize(parser);
324
Jack Carterb4dbc172012-09-05 23:34:03 +0000325 // Initialize the set of available features.
326 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000327
328 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000329 AssemblerOptions.push_back(
330 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000331
332 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000333 AssemblerOptions.push_back(
334 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000335
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000336 getTargetStreamer().updateABIInfo(*this);
337
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000338 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000339 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000340
341 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000342 }
343
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000344 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
345 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
348 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000349 const MipsABIInfo &getABI() const { return ABI; }
350 bool isABI_N32() const { return ABI.IsN32(); }
351 bool isABI_N64() const { return ABI.IsN64(); }
352 bool isABI_O32() const { return ABI.IsO32(); }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000353 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000354
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000355 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000356 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
357 }
358
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000359 bool inMicroMipsMode() const {
360 return STI.getFeatureBits() & Mips::FeatureMicroMips;
361 }
362 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
363 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
364 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
365 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
366 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
367 bool hasMips32() const {
368 return (STI.getFeatureBits() & Mips::FeatureMips32);
369 }
370 bool hasMips64() const {
371 return (STI.getFeatureBits() & Mips::FeatureMips64);
372 }
373 bool hasMips32r2() const {
374 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
375 }
376 bool hasMips64r2() const {
377 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
378 }
379 bool hasMips32r6() const {
380 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
381 }
382 bool hasMips64r6() const {
383 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
384 }
385 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
386 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
387 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
388
389 bool inMips16Mode() const {
390 return STI.getFeatureBits() & Mips::FeatureMips16;
391 }
392 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000393 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000394
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000395 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000396 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000397};
398}
399
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000400namespace {
401
402/// MipsOperand - Instances of this class represent a parsed Mips machine
403/// instruction.
404class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000405public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000406 /// Broad categories of register classes
407 /// The exact class is finalized by the render method.
408 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000410 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000411 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000412 RegKind_FCC = 4, /// FCC
413 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
414 RegKind_MSACtrl = 16, /// MSA control registers
415 RegKind_COP2 = 32, /// COP2
416 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
417 /// context).
418 RegKind_CCR = 128, /// CCR
419 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000420 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000421
422 /// Potentially any (e.g. $1)
423 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
424 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000425 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000426 };
427
428private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000429 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000430 k_Immediate, /// An immediate (possibly involving symbol references)
431 k_Memory, /// Base + Offset Memory Address
432 k_PhysRegister, /// A physical register from the Mips namespace
433 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000434 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000435 k_RegList, /// A physical register list
436 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000437 } Kind;
438
David Blaikie960ea3f2014-06-08 16:18:35 +0000439public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000440 MipsOperand(KindTy K, MipsAsmParser &Parser)
441 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
442
David Blaikie960ea3f2014-06-08 16:18:35 +0000443private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000444 /// For diagnostics, and checking the assembler temporary
445 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000446
Eric Christopher8996c5d2013-03-15 00:42:55 +0000447 struct Token {
448 const char *Data;
449 unsigned Length;
450 };
451
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000452 struct PhysRegOp {
453 unsigned Num; /// Register Number
454 };
455
456 struct RegIdxOp {
457 unsigned Index; /// Index into the register class
458 RegKind Kind; /// Bitfield of the kinds it could possibly be
459 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000460 };
461
462 struct ImmOp {
463 const MCExpr *Val;
464 };
465
466 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000467 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000468 const MCExpr *Off;
469 };
470
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000471 struct RegListOp {
472 SmallVector<unsigned, 10> *List;
473 };
474
Jack Carterb4dbc172012-09-05 23:34:03 +0000475 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000476 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000477 struct PhysRegOp PhysReg;
478 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000479 struct ImmOp Imm;
480 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000481 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000482 };
483
484 SMLoc StartLoc, EndLoc;
485
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000487 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
488 const MCRegisterInfo *RegInfo,
489 SMLoc S, SMLoc E,
490 MipsAsmParser &Parser) {
491 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000492 Op->RegIdx.Index = Index;
493 Op->RegIdx.RegInfo = RegInfo;
494 Op->RegIdx.Kind = RegKind;
495 Op->StartLoc = S;
496 Op->EndLoc = E;
497 return Op;
498 }
499
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000500public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000501 /// Coerce the register to GPR32 and return the real register for the current
502 /// target.
503 unsigned getGPR32Reg() const {
504 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000505 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000506 unsigned ClassID = Mips::GPR32RegClassID;
507 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000508 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000509
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000510 /// Coerce the register to GPR32 and return the real register for the current
511 /// target.
512 unsigned getGPRMM16Reg() const {
513 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
514 unsigned ClassID = Mips::GPR32RegClassID;
515 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
516 }
517
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000518 /// Coerce the register to GPR64 and return the real register for the current
519 /// target.
520 unsigned getGPR64Reg() const {
521 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
522 unsigned ClassID = Mips::GPR64RegClassID;
523 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000524 }
525
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000526private:
527 /// Coerce the register to AFGR64 and return the real register for the current
528 /// target.
529 unsigned getAFGR64Reg() const {
530 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
531 if (RegIdx.Index % 2 != 0)
532 AsmParser.Warning(StartLoc, "Float register should be even.");
533 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
534 .getRegister(RegIdx.Index / 2);
535 }
536
537 /// Coerce the register to FGR64 and return the real register for the current
538 /// target.
539 unsigned getFGR64Reg() const {
540 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
541 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
542 .getRegister(RegIdx.Index);
543 }
544
545 /// Coerce the register to FGR32 and return the real register for the current
546 /// target.
547 unsigned getFGR32Reg() const {
548 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
549 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
550 .getRegister(RegIdx.Index);
551 }
552
553 /// Coerce the register to FGRH32 and return the real register for the current
554 /// target.
555 unsigned getFGRH32Reg() const {
556 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
557 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
558 .getRegister(RegIdx.Index);
559 }
560
561 /// Coerce the register to FCC and return the real register for the current
562 /// target.
563 unsigned getFCCReg() const {
564 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
565 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
566 .getRegister(RegIdx.Index);
567 }
568
569 /// Coerce the register to MSA128 and return the real register for the current
570 /// target.
571 unsigned getMSA128Reg() const {
572 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
573 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
574 // identical
575 unsigned ClassID = Mips::MSA128BRegClassID;
576 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
577 }
578
579 /// Coerce the register to MSACtrl and return the real register for the
580 /// current target.
581 unsigned getMSACtrlReg() const {
582 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
583 unsigned ClassID = Mips::MSACtrlRegClassID;
584 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
585 }
586
587 /// Coerce the register to COP2 and return the real register for the
588 /// current target.
589 unsigned getCOP2Reg() const {
590 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
591 unsigned ClassID = Mips::COP2RegClassID;
592 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
593 }
594
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000595 /// Coerce the register to COP3 and return the real register for the
596 /// current target.
597 unsigned getCOP3Reg() const {
598 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
599 unsigned ClassID = Mips::COP3RegClassID;
600 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
601 }
602
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000603 /// Coerce the register to ACC64DSP and return the real register for the
604 /// current target.
605 unsigned getACC64DSPReg() const {
606 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
607 unsigned ClassID = Mips::ACC64DSPRegClassID;
608 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
609 }
610
611 /// Coerce the register to HI32DSP and return the real register for the
612 /// current target.
613 unsigned getHI32DSPReg() const {
614 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
615 unsigned ClassID = Mips::HI32DSPRegClassID;
616 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
617 }
618
619 /// Coerce the register to LO32DSP and return the real register for the
620 /// current target.
621 unsigned getLO32DSPReg() const {
622 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
623 unsigned ClassID = Mips::LO32DSPRegClassID;
624 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
625 }
626
627 /// Coerce the register to CCR and return the real register for the
628 /// current target.
629 unsigned getCCRReg() const {
630 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
631 unsigned ClassID = Mips::CCRRegClassID;
632 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
633 }
634
635 /// Coerce the register to HWRegs and return the real register for the
636 /// current target.
637 unsigned getHWRegsReg() const {
638 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
639 unsigned ClassID = Mips::HWRegsRegClassID;
640 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
641 }
642
643public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000644 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000645 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000646 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000647 Inst.addOperand(MCOperand::CreateImm(0));
648 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
649 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
650 else
651 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000652 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000653
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000654 void addRegOperands(MCInst &Inst, unsigned N) const {
655 llvm_unreachable("Use a custom parser instead");
656 }
657
Daniel Sanders21bce302014-04-01 12:35:23 +0000658 /// Render the operand to an MCInst as a GPR32
659 /// Asserts if the wrong number of operands are requested, or the operand
660 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
662 assert(N == 1 && "Invalid number of operands!");
663 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
664 }
665
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000666 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
667 assert(N == 1 && "Invalid number of operands!");
668 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
669 }
670
Jozef Kolek1904fa22014-11-24 14:25:53 +0000671 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
672 assert(N == 1 && "Invalid number of operands!");
673 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
674 }
675
Daniel Sanders21bce302014-04-01 12:35:23 +0000676 /// Render the operand to an MCInst as a GPR64
677 /// Asserts if the wrong number of operands are requested, or the operand
678 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000679 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
680 assert(N == 1 && "Invalid number of operands!");
681 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
682 }
683
684 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
685 assert(N == 1 && "Invalid number of operands!");
686 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
687 }
688
689 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
692 }
693
694 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
695 assert(N == 1 && "Invalid number of operands!");
696 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000697 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000698 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000699 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
700 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000701 }
702
703 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
704 assert(N == 1 && "Invalid number of operands!");
705 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
706 }
707
708 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
709 assert(N == 1 && "Invalid number of operands!");
710 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
711 }
712
713 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
714 assert(N == 1 && "Invalid number of operands!");
715 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
716 }
717
718 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
719 assert(N == 1 && "Invalid number of operands!");
720 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
721 }
722
723 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
724 assert(N == 1 && "Invalid number of operands!");
725 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
726 }
727
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000728 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
729 assert(N == 1 && "Invalid number of operands!");
730 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
731 }
732
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000733 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
734 assert(N == 1 && "Invalid number of operands!");
735 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
736 }
737
738 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
740 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
741 }
742
743 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
745 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
746 }
747
748 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
749 assert(N == 1 && "Invalid number of operands!");
750 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
751 }
752
753 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
754 assert(N == 1 && "Invalid number of operands!");
755 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
756 }
757
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000758 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000759 assert(N == 1 && "Invalid number of operands!");
760 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000761 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000762 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000763
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000764 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000765 assert(N == 2 && "Invalid number of operands!");
766
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000768
769 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000770 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000771 }
772
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000773 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
774 assert(N == 2 && "Invalid number of operands!");
775
776 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
777
778 const MCExpr *Expr = getMemOff();
779 addExpr(Inst, Expr);
780 }
781
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000782 void addRegListOperands(MCInst &Inst, unsigned N) const {
783 assert(N == 1 && "Invalid number of operands!");
784
785 for (auto RegNo : getRegList())
786 Inst.addOperand(MCOperand::CreateReg(RegNo));
787 }
788
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000789 void addRegPairOperands(MCInst &Inst, unsigned N) const {
790 assert(N == 2 && "Invalid number of operands!");
791 unsigned RegNo = getRegPair();
792 Inst.addOperand(MCOperand::CreateReg(RegNo++));
793 Inst.addOperand(MCOperand::CreateReg(RegNo));
794 }
795
Craig Topper56c590a2014-04-29 07:58:02 +0000796 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 // As a special case until we sort out the definition of div/divu, pretend
798 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
799 if (isGPRAsmReg() && RegIdx.Index == 0)
800 return true;
801
802 return Kind == k_PhysRegister;
803 }
804 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000805 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 bool isConstantImm() const {
807 return isImm() && dyn_cast<MCConstantExpr>(getImm());
808 }
Craig Topper56c590a2014-04-29 07:58:02 +0000809 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 // Note: It's not possible to pretend that other operand kinds are tokens.
811 // The matcher emitter checks tokens first.
812 return Kind == k_Token;
813 }
Craig Topper56c590a2014-04-29 07:58:02 +0000814 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000815 bool isConstantMemOff() const {
816 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
817 }
818 template <unsigned Bits> bool isMemWithSimmOffset() const {
819 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
820 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000821 bool isMemWithGRPMM16Base() const {
822 return isMem() && getMemBase()->isMM16AsmReg();
823 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000824 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
825 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
826 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
827 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000828 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
829 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
830 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
831 && (getMemBase()->getGPR32Reg() == Mips::SP);
832 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000833 bool isRegList16() const {
834 if (!isRegList())
835 return false;
836
837 int Size = RegList.List->size();
838 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
839 RegList.List->back() != Mips::RA)
840 return false;
841
842 int PrevReg = *RegList.List->begin();
843 for (int i = 1; i < Size - 1; i++) {
844 int Reg = (*(RegList.List))[i];
845 if ( Reg != PrevReg + 1)
846 return false;
847 PrevReg = Reg;
848 }
849
850 return true;
851 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000852 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 bool isLSAImm() const {
854 if (!isConstantImm())
855 return false;
856 int64_t Val = getConstantImm();
857 return 1 <= Val && Val <= 4;
858 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000859 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000860
861 StringRef getToken() const {
862 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000863 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000864 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000865 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000866
Craig Topper56c590a2014-04-29 07:58:02 +0000867 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 // As a special case until we sort out the definition of div/divu, pretend
869 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
870 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
871 RegIdx.Kind & RegKind_GPR)
872 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000873
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 assert(Kind == k_PhysRegister && "Invalid access!");
875 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000876 }
877
Jack Carterb4dbc172012-09-05 23:34:03 +0000878 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000880 return Imm.Val;
881 }
882
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 int64_t getConstantImm() const {
884 const MCExpr *Val = getImm();
885 return static_cast<const MCConstantExpr *>(Val)->getValue();
886 }
887
888 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000889 assert((Kind == k_Memory) && "Invalid access!");
890 return Mem.Base;
891 }
892
893 const MCExpr *getMemOff() const {
894 assert((Kind == k_Memory) && "Invalid access!");
895 return Mem.Off;
896 }
897
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000898 int64_t getConstantMemOff() const {
899 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
900 }
901
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000902 const SmallVectorImpl<unsigned> &getRegList() const {
903 assert((Kind == k_RegList) && "Invalid access!");
904 return *(RegList.List);
905 }
906
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000907 unsigned getRegPair() const {
908 assert((Kind == k_RegPair) && "Invalid access!");
909 return RegIdx.Index;
910 }
911
David Blaikie960ea3f2014-06-08 16:18:35 +0000912 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
913 MipsAsmParser &Parser) {
914 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000915 Op->Tok.Data = Str.data();
916 Op->Tok.Length = Str.size();
917 Op->StartLoc = S;
918 Op->EndLoc = S;
919 return Op;
920 }
921
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 /// Create a numeric register (e.g. $1). The exact register remains
923 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000924 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000925 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000926 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000927 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000928 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000929 }
930
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000931 /// Create a register that is definitely a GPR.
932 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000933 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000934 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000935 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000936 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000937 }
938
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 /// Create a register that is definitely a FGR.
940 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000941 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000942 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000943 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000944 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
945 }
946
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000947 /// Create a register that is definitely a HWReg.
948 /// This is typically only used for named registers such as $hwr_cpunum.
949 static std::unique_ptr<MipsOperand>
950 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
951 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
952 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
953 }
954
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 /// Create a register that is definitely an FCC.
956 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000957 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000958 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000959 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000960 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
961 }
962
963 /// Create a register that is definitely an ACC.
964 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000965 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000966 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000967 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000968 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
969 }
970
971 /// Create a register that is definitely an MSA128.
972 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000973 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000974 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000975 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000976 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
977 }
978
979 /// Create a register that is definitely an MSACtrl.
980 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000981 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000982 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000983 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
985 }
986
David Blaikie960ea3f2014-06-08 16:18:35 +0000987 static std::unique_ptr<MipsOperand>
988 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
989 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000990 Op->Imm.Val = Val;
991 Op->StartLoc = S;
992 Op->EndLoc = E;
993 return Op;
994 }
995
David Blaikie960ea3f2014-06-08 16:18:35 +0000996 static std::unique_ptr<MipsOperand>
997 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
998 SMLoc E, MipsAsmParser &Parser) {
999 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1000 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001001 Op->Mem.Off = Off;
1002 Op->StartLoc = S;
1003 Op->EndLoc = E;
1004 return Op;
1005 }
1006
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001007 static std::unique_ptr<MipsOperand>
1008 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1009 MipsAsmParser &Parser) {
1010 assert (Regs.size() > 0 && "Empty list not allowed");
1011
1012 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1013 Op->RegList.List = new SmallVector<unsigned, 10>();
1014 for (auto Reg : Regs)
1015 Op->RegList.List->push_back(Reg);
1016 Op->StartLoc = StartLoc;
1017 Op->EndLoc = EndLoc;
1018 return Op;
1019 }
1020
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001021 static std::unique_ptr<MipsOperand>
1022 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1023 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1024 Op->RegIdx.Index = RegNo;
1025 Op->StartLoc = S;
1026 Op->EndLoc = E;
1027 return Op;
1028 }
1029
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 bool isGPRAsmReg() const {
1031 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001032 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001033 bool isMM16AsmReg() const {
1034 if (!(isRegIdx() && RegIdx.Kind))
1035 return false;
1036 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1037 || RegIdx.Index == 16 || RegIdx.Index == 17);
1038 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001039 bool isMM16AsmRegZero() const {
1040 if (!(isRegIdx() && RegIdx.Kind))
1041 return false;
1042 return (RegIdx.Index == 0 ||
1043 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1044 RegIdx.Index == 17);
1045 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 bool isFGRAsmReg() const {
1047 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1048 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001049 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 bool isHWRegsAsmReg() const {
1051 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001052 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001053 bool isCCRAsmReg() const {
1054 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001055 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001057 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1058 return false;
1059 if (!AsmParser.hasEightFccRegisters())
1060 return RegIdx.Index == 0;
1061 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001062 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001063 bool isACCAsmReg() const {
1064 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001065 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 bool isCOP2AsmReg() const {
1067 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001068 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001069 bool isCOP3AsmReg() const {
1070 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1071 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001072 bool isMSA128AsmReg() const {
1073 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001074 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 bool isMSACtrlAsmReg() const {
1076 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001077 }
1078
Jack Carterb4dbc172012-09-05 23:34:03 +00001079 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001080 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001081 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001082 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001083
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001084 virtual ~MipsOperand() {
1085 switch (Kind) {
1086 case k_Immediate:
1087 break;
1088 case k_Memory:
1089 delete Mem.Base;
1090 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001091 case k_RegList:
1092 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001093 case k_PhysRegister:
1094 case k_RegisterIndex:
1095 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001096 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001097 break;
1098 }
1099 }
1100
Craig Topper56c590a2014-04-29 07:58:02 +00001101 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 switch (Kind) {
1103 case k_Immediate:
1104 OS << "Imm<";
1105 Imm.Val->print(OS);
1106 OS << ">";
1107 break;
1108 case k_Memory:
1109 OS << "Mem<";
1110 Mem.Base->print(OS);
1111 OS << ", ";
1112 Mem.Off->print(OS);
1113 OS << ">";
1114 break;
1115 case k_PhysRegister:
1116 OS << "PhysReg<" << PhysReg.Num << ">";
1117 break;
1118 case k_RegisterIndex:
1119 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1120 break;
1121 case k_Token:
1122 OS << Tok.Data;
1123 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001124 case k_RegList:
1125 OS << "RegList< ";
1126 for (auto Reg : (*RegList.List))
1127 OS << Reg << " ";
1128 OS << ">";
1129 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001130 case k_RegPair:
1131 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1132 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001134 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001135}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001136} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001137
Jack Carter9e65aa32013-03-22 00:05:30 +00001138namespace llvm {
1139extern const MCInstrDesc MipsInsts[];
1140}
1141static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1142 return MipsInsts[Opcode];
1143}
1144
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001145static bool hasShortDelaySlot(unsigned Opcode) {
1146 switch (Opcode) {
1147 case Mips::JALS_MM:
1148 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001149 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001150 case Mips::BGEZALS_MM:
1151 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001152 return true;
1153 default:
1154 return false;
1155 }
1156}
1157
Jack Carter9e65aa32013-03-22 00:05:30 +00001158bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001159 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001160 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001161
Jack Carter9e65aa32013-03-22 00:05:30 +00001162 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001163
1164 if (MCID.isBranch() || MCID.isCall()) {
1165 const unsigned Opcode = Inst.getOpcode();
1166 MCOperand Offset;
1167
1168 switch (Opcode) {
1169 default:
1170 break;
1171 case Mips::BEQ:
1172 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001173 case Mips::BEQ_MM:
1174 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001175 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001176 Offset = Inst.getOperand(2);
1177 if (!Offset.isImm())
1178 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001179 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001180 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001181 if (OffsetToAlignment(Offset.getImm(),
1182 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001183 return Error(IDLoc, "branch to misaligned address");
1184 break;
1185 case Mips::BGEZ:
1186 case Mips::BGTZ:
1187 case Mips::BLEZ:
1188 case Mips::BLTZ:
1189 case Mips::BGEZAL:
1190 case Mips::BLTZAL:
1191 case Mips::BC1F:
1192 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 case Mips::BGEZ_MM:
1194 case Mips::BGTZ_MM:
1195 case Mips::BLEZ_MM:
1196 case Mips::BLTZ_MM:
1197 case Mips::BGEZAL_MM:
1198 case Mips::BLTZAL_MM:
1199 case Mips::BC1F_MM:
1200 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001201 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001202 Offset = Inst.getOperand(1);
1203 if (!Offset.isImm())
1204 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001205 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001206 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001207 if (OffsetToAlignment(Offset.getImm(),
1208 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001209 return Error(IDLoc, "branch to misaligned address");
1210 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001211 case Mips::BEQZ16_MM:
1212 case Mips::BNEZ16_MM:
1213 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1214 Offset = Inst.getOperand(1);
1215 if (!Offset.isImm())
1216 break; // We'll deal with this situation later on when applying fixups.
1217 if (!isIntN(8, Offset.getImm()))
1218 return Error(IDLoc, "branch target out of range");
1219 if (OffsetToAlignment(Offset.getImm(), 2LL))
1220 return Error(IDLoc, "branch to misaligned address");
1221 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001222 }
1223 }
1224
Daniel Sandersa84989a2014-06-16 13:25:35 +00001225 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1226 // We still accept it but it is a normal nop.
1227 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1228 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1229 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1230 "nop instruction");
1231 }
1232
Toma Tabacu9db22db2014-09-09 10:15:38 +00001233 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001234 // If this instruction has a delay slot and .set reorder is active,
1235 // emit a NOP after it.
1236 Instructions.push_back(Inst);
1237 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001238 if (hasShortDelaySlot(Inst.getOpcode())) {
1239 NopInst.setOpcode(Mips::MOVE16_MM);
1240 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1241 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1242 } else {
1243 NopInst.setOpcode(Mips::SLL);
1244 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1245 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1246 NopInst.addOperand(MCOperand::CreateImm(0));
1247 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001248 Instructions.push_back(NopInst);
1249 return false;
1250 }
1251
Jack Carter9e65aa32013-03-22 00:05:30 +00001252 if (MCID.mayLoad() || MCID.mayStore()) {
1253 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001254 // reference or immediate we may have to expand instructions.
1255 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001256 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001257 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1258 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001259 MCOperand &Op = Inst.getOperand(i);
1260 if (Op.isImm()) {
1261 int MemOffset = Op.getImm();
1262 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001263 // Offset can't exceed 16bit value.
1264 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001265 return false;
1266 }
1267 } else if (Op.isExpr()) {
1268 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001269 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001270 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001271 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001272 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001273 // Expand symbol.
1274 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001275 return false;
1276 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001277 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001278 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001279 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001280 }
1281 }
1282 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001283 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001284 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001285
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001286 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1287 if (inMicroMipsMode()) {
1288 MCOperand Opnd;
1289 int Imm;
1290
1291 switch (Inst.getOpcode()) {
1292 default:
1293 break;
1294 case Mips::ADDIUS5_MM:
1295 Opnd = Inst.getOperand(2);
1296 if (!Opnd.isImm())
1297 return Error(IDLoc, "expected immediate operand kind");
1298 Imm = Opnd.getImm();
1299 if (Imm < -8 || Imm > 7)
1300 return Error(IDLoc, "immediate operand value out of range");
1301 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001302 case Mips::ADDIUSP_MM:
1303 Opnd = Inst.getOperand(0);
1304 if (!Opnd.isImm())
1305 return Error(IDLoc, "expected immediate operand kind");
1306 Imm = Opnd.getImm();
1307 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1308 Imm % 4 != 0)
1309 return Error(IDLoc, "immediate operand value out of range");
1310 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001311 case Mips::SLL16_MM:
1312 case Mips::SRL16_MM:
1313 Opnd = Inst.getOperand(2);
1314 if (!Opnd.isImm())
1315 return Error(IDLoc, "expected immediate operand kind");
1316 Imm = Opnd.getImm();
1317 if (Imm < 1 || Imm > 8)
1318 return Error(IDLoc, "immediate operand value out of range");
1319 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001320 case Mips::LI16_MM:
1321 Opnd = Inst.getOperand(1);
1322 if (!Opnd.isImm())
1323 return Error(IDLoc, "expected immediate operand kind");
1324 Imm = Opnd.getImm();
1325 if (Imm < -1 || Imm > 126)
1326 return Error(IDLoc, "immediate operand value out of range");
1327 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001328 case Mips::ADDIUR2_MM:
1329 Opnd = Inst.getOperand(2);
1330 if (!Opnd.isImm())
1331 return Error(IDLoc, "expected immediate operand kind");
1332 Imm = Opnd.getImm();
1333 if (!(Imm == 1 || Imm == -1 ||
1334 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1335 return Error(IDLoc, "immediate operand value out of range");
1336 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001337 case Mips::ADDIUR1SP_MM:
1338 Opnd = Inst.getOperand(1);
1339 if (!Opnd.isImm())
1340 return Error(IDLoc, "expected immediate operand kind");
1341 Imm = Opnd.getImm();
1342 if (OffsetToAlignment(Imm, 4LL))
1343 return Error(IDLoc, "misaligned immediate operand value");
1344 if (Imm < 0 || Imm > 255)
1345 return Error(IDLoc, "immediate operand value out of range");
1346 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001347 case Mips::ANDI16_MM:
1348 Opnd = Inst.getOperand(2);
1349 if (!Opnd.isImm())
1350 return Error(IDLoc, "expected immediate operand kind");
1351 Imm = Opnd.getImm();
1352 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1353 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1354 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1355 return Error(IDLoc, "immediate operand value out of range");
1356 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001357 case Mips::LBU16_MM:
1358 Opnd = Inst.getOperand(2);
1359 if (!Opnd.isImm())
1360 return Error(IDLoc, "expected immediate operand kind");
1361 Imm = Opnd.getImm();
1362 if (Imm < -1 || Imm > 14)
1363 return Error(IDLoc, "immediate operand value out of range");
1364 break;
1365 case Mips::SB16_MM:
1366 Opnd = Inst.getOperand(2);
1367 if (!Opnd.isImm())
1368 return Error(IDLoc, "expected immediate operand kind");
1369 Imm = Opnd.getImm();
1370 if (Imm < 0 || Imm > 15)
1371 return Error(IDLoc, "immediate operand value out of range");
1372 break;
1373 case Mips::LHU16_MM:
1374 case Mips::SH16_MM:
1375 Opnd = Inst.getOperand(2);
1376 if (!Opnd.isImm())
1377 return Error(IDLoc, "expected immediate operand kind");
1378 Imm = Opnd.getImm();
1379 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1380 return Error(IDLoc, "immediate operand value out of range");
1381 break;
1382 case Mips::LW16_MM:
1383 case Mips::SW16_MM:
1384 Opnd = Inst.getOperand(2);
1385 if (!Opnd.isImm())
1386 return Error(IDLoc, "expected immediate operand kind");
1387 Imm = Opnd.getImm();
1388 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1389 return Error(IDLoc, "immediate operand value out of range");
1390 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001391 case Mips::CACHE:
1392 case Mips::PREF:
1393 Opnd = Inst.getOperand(2);
1394 if (!Opnd.isImm())
1395 return Error(IDLoc, "expected immediate operand kind");
1396 Imm = Opnd.getImm();
1397 if (!isUInt<5>(Imm))
1398 return Error(IDLoc, "immediate operand value out of range");
1399 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001400 case Mips::ADDIUPC_MM:
1401 MCOperand Opnd = Inst.getOperand(1);
1402 if (!Opnd.isImm())
1403 return Error(IDLoc, "expected immediate operand kind");
1404 int Imm = Opnd.getImm();
1405 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1406 return Error(IDLoc, "immediate operand value out of range");
1407 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001408 }
1409 }
1410
Jack Carter9e65aa32013-03-22 00:05:30 +00001411 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001412 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001413 else
1414 Instructions.push_back(Inst);
1415
1416 return false;
1417}
1418
Jack Carter30a59822012-10-04 04:03:53 +00001419bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1420
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 switch (Inst.getOpcode()) {
1422 case Mips::LoadImm32Reg:
1423 case Mips::LoadAddr32Imm:
1424 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001425 case Mips::LoadImm64Reg:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001426 case Mips::B_MM_Pseudo:
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 return true;
1428 default:
1429 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001430 }
1431}
Jack Carter92995f12012-10-06 00:53:28 +00001432
Matheus Almeida3813d572014-06-19 14:39:14 +00001433bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001434 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001435 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001436 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001437 case Mips::LoadImm32Reg:
1438 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001439 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001440 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001441 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001442 return true;
1443 }
1444 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001445 case Mips::LoadAddr32Imm:
1446 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1447 case Mips::LoadAddr32Reg:
1448 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001449 case Mips::B_MM_Pseudo:
1450 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001451 }
Jack Carter30a59822012-10-04 04:03:53 +00001452}
Jack Carter92995f12012-10-06 00:53:28 +00001453
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001454namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001455template <bool PerformShift>
1456void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001457 SmallVectorImpl<MCInst> &Instructions) {
1458 MCInst tmpInst;
1459 if (PerformShift) {
1460 tmpInst.setOpcode(Mips::DSLL);
1461 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1462 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1463 tmpInst.addOperand(MCOperand::CreateImm(16));
1464 tmpInst.setLoc(IDLoc);
1465 Instructions.push_back(tmpInst);
1466 tmpInst.clear();
1467 }
1468 tmpInst.setOpcode(Mips::ORi);
1469 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1470 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001471 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001472 tmpInst.setLoc(IDLoc);
1473 Instructions.push_back(tmpInst);
1474}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001475
1476template <int Shift, bool PerformShift>
1477void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1478 SmallVectorImpl<MCInst> &Instructions) {
1479 createShiftOr<PerformShift>(
1480 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1481 IDLoc, Instructions);
1482}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001483}
1484
Matheus Almeida3813d572014-06-19 14:39:14 +00001485bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001487 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001488 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001489 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001490 const MCOperand &RegOp = Inst.getOperand(0);
1491 assert(RegOp.isReg() && "expected register operand kind");
1492
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001493 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001494 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001495 // FIXME: gas has a special case for values that are 000...1111, which
1496 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001497 if (0 <= ImmValue && ImmValue <= 65535) {
1498 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001499 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001500 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001501 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001502 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001503 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001504 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001505 } else if (ImmValue < 0 && ImmValue >= -32768) {
1506 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001507 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001508 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001509 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001510 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001511 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001512 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001513 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1514 // For any value of j that is representable as a 32-bit integer, create
1515 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001516 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001517 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001518 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001519 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1520 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001521 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001522 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1523 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001524 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001525 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001526 return true;
1527 }
1528
1529 // <------- lo32 ------>
1530 // <------- hi32 ------>
1531 // <- hi16 -> <- lo16 ->
1532 // _________________________________
1533 // | | | |
1534 // | 16-bytes | 16-bytes | 16-bytes |
1535 // |__________|__________|__________|
1536 //
1537 // For any value of j that is representable as a 48-bit integer, create
1538 // a sequence of:
1539 // li d,j => lui d,hi16(j)
1540 // ori d,d,hi16(lo32(j))
1541 // dsll d,d,16
1542 // ori d,d,lo16(lo32(j))
1543 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001544 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001545 tmpInst.addOperand(
1546 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001547 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001548 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1549 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1550 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001551 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001552 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001553 return true;
1554 }
1555
1556 // <------- hi32 ------> <------- lo32 ------>
1557 // <- hi16 -> <- lo16 ->
1558 // ___________________________________________
1559 // | | | | |
1560 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1561 // |__________|__________|__________|__________|
1562 //
1563 // For any value of j that isn't representable as a 48-bit integer.
1564 // li d,j => lui d,hi16(j)
1565 // ori d,d,lo16(hi32(j))
1566 // dsll d,d,16
1567 // ori d,d,hi16(lo32(j))
1568 // dsll d,d,16
1569 // ori d,d,lo16(lo32(j))
1570 tmpInst.setOpcode(Mips::LUi);
1571 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1572 tmpInst.addOperand(
1573 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1574 Instructions.push_back(tmpInst);
1575 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1576 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1577 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001578 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001579 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001580}
Jack Carter92995f12012-10-06 00:53:28 +00001581
Matheus Almeida3813d572014-06-19 14:39:14 +00001582bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001583MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1584 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001585 MCInst tmpInst;
1586 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001587 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1588 "expected immediate operand kind");
1589 if (!ImmOp.isImm()) {
1590 expandLoadAddressSym(Inst, IDLoc, Instructions);
1591 return false;
1592 }
Jack Carter543fdf82012-10-09 23:29:45 +00001593 const MCOperand &SrcRegOp = Inst.getOperand(1);
1594 assert(SrcRegOp.isReg() && "expected register operand kind");
1595 const MCOperand &DstRegOp = Inst.getOperand(0);
1596 assert(DstRegOp.isReg() && "expected register operand kind");
1597 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001598 if (-32768 <= ImmValue && ImmValue <= 65535) {
1599 // For -32768 <= j <= 65535.
1600 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001601 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001602 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1603 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1604 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1605 Instructions.push_back(tmpInst);
1606 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 // For any other value of j that is representable as a 32-bit integer.
1608 // la d,j(s) => lui d,hi16(j)
1609 // ori d,d,lo16(j)
1610 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001611 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001612 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1613 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1614 Instructions.push_back(tmpInst);
1615 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001616 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001617 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1618 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1619 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1620 Instructions.push_back(tmpInst);
1621 tmpInst.clear();
1622 tmpInst.setOpcode(Mips::ADDu);
1623 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1624 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1625 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1626 Instructions.push_back(tmpInst);
1627 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001628 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001629}
1630
Matheus Almeida3813d572014-06-19 14:39:14 +00001631bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001632MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1633 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001634 MCInst tmpInst;
1635 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001636 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1637 "expected immediate operand kind");
1638 if (!ImmOp.isImm()) {
1639 expandLoadAddressSym(Inst, IDLoc, Instructions);
1640 return false;
1641 }
Jack Carter543fdf82012-10-09 23:29:45 +00001642 const MCOperand &RegOp = Inst.getOperand(0);
1643 assert(RegOp.isReg() && "expected register operand kind");
1644 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001645 if (-32768 <= ImmValue && ImmValue <= 65535) {
1646 // For -32768 <= j <= 65535.
1647 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001648 tmpInst.setOpcode(Mips::ADDiu);
1649 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001650 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001651 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1652 Instructions.push_back(tmpInst);
1653 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001654 // For any other value of j that is representable as a 32-bit integer.
1655 // la d,j => lui d,hi16(j)
1656 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001657 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001658 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1659 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1660 Instructions.push_back(tmpInst);
1661 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001662 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001663 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1664 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1665 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1666 Instructions.push_back(tmpInst);
1667 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001668 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001669}
1670
Toma Tabacu0d64b202014-08-14 10:29:17 +00001671void
1672MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1673 SmallVectorImpl<MCInst> &Instructions) {
1674 // FIXME: If we do have a valid at register to use, we should generate a
1675 // slightly shorter sequence here.
1676 MCInst tmpInst;
1677 int ExprOperandNo = 1;
1678 // Sometimes the assembly parser will get the immediate expression as
1679 // a $zero + an immediate.
1680 if (Inst.getNumOperands() == 3) {
1681 assert(Inst.getOperand(1).getReg() ==
1682 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1683 ExprOperandNo = 2;
1684 }
1685 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1686 assert(SymOp.isExpr() && "expected symbol operand kind");
1687 const MCOperand &RegOp = Inst.getOperand(0);
1688 unsigned RegNo = RegOp.getReg();
1689 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1690 const MCSymbolRefExpr *HiExpr =
1691 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1692 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1693 const MCSymbolRefExpr *LoExpr =
1694 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1695 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1696 if (isGP64bit()) {
1697 // If it's a 64-bit architecture, expand to:
1698 // la d,sym => lui d,highest(sym)
1699 // ori d,d,higher(sym)
1700 // dsll d,d,16
1701 // ori d,d,hi16(sym)
1702 // dsll d,d,16
1703 // ori d,d,lo16(sym)
1704 const MCSymbolRefExpr *HighestExpr =
1705 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1706 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1707 const MCSymbolRefExpr *HigherExpr =
1708 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1709 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1710
1711 tmpInst.setOpcode(Mips::LUi);
1712 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1713 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1714 Instructions.push_back(tmpInst);
1715
1716 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1717 Instructions);
1718 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1719 Instructions);
1720 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1721 Instructions);
1722 } else {
1723 // Otherwise, expand to:
1724 // la d,sym => lui d,hi16(sym)
1725 // ori d,d,lo16(sym)
1726 tmpInst.setOpcode(Mips::LUi);
1727 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1728 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1729 Instructions.push_back(tmpInst);
1730
1731 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1732 Instructions);
1733 }
1734}
1735
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001736bool MipsAsmParser::expandUncondBranchMMPseudo(
1737 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001738 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1739 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001740
1741 MCOperand Offset = Inst.getOperand(0);
1742 if (Offset.isExpr()) {
1743 Inst.clear();
1744 Inst.setOpcode(Mips::BEQ_MM);
1745 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1746 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1747 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1748 } else {
1749 assert(Offset.isImm() && "expected immediate operand kind");
1750 if (isIntN(11, Offset.getImm())) {
1751 // If offset fits into 11 bits then this instruction becomes microMIPS
1752 // 16-bit unconditional branch instruction.
1753 Inst.setOpcode(Mips::B16_MM);
1754 } else {
1755 if (!isIntN(17, Offset.getImm()))
1756 Error(IDLoc, "branch target out of range");
1757 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1758 Error(IDLoc, "branch to misaligned address");
1759 Inst.clear();
1760 Inst.setOpcode(Mips::BEQ_MM);
1761 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1762 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1763 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1764 }
1765 }
1766 Instructions.push_back(Inst);
1767
1768 if (AssemblerOptions.back()->isReorder()) {
1769 // If .set reorder is active, emit a NOP after the branch instruction.
1770 MCInst NopInst;
1771 NopInst.setOpcode(Mips::MOVE16_MM);
1772 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1773 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1774 Instructions.push_back(NopInst);
1775 }
1776 return false;
1777}
1778
Jack Carter9e65aa32013-03-22 00:05:30 +00001779void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001780 SmallVectorImpl<MCInst> &Instructions,
1781 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 const MCSymbolRefExpr *SR;
1783 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001784 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001785 const MCExpr *ExprOffset;
1786 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001787 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001788 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1789 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001791 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1792 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001793 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001794 if (isImmOpnd) {
1795 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1796 ImmOffset = Inst.getOperand(2).getImm();
1797 LoOffset = ImmOffset & 0x0000ffff;
1798 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001799 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001800 if (LoOffset & 0x8000)
1801 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001802 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001803 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001805 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001806 // These are some of the types of expansions we perform here:
1807 // 1) lw $8, sym => lui $8, %hi(sym)
1808 // lw $8, %lo(sym)($8)
1809 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1810 // add $8, $8, $9
1811 // lw $8, %lo(offset)($9)
1812 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1813 // add $at, $at, $8
1814 // lw $8, %lo(offset)($at)
1815 // 4) sw $8, sym => lui $at, %hi(sym)
1816 // sw $8, %lo(sym)($at)
1817 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1818 // add $at, $at, $8
1819 // sw $8, %lo(offset)($at)
1820 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1821 // ldc1 $f0, %lo(sym)($at)
1822 //
1823 // For load instructions we can use the destination register as a temporary
1824 // if base and dst are different (examples 1 and 2) and if the base register
1825 // is general purpose otherwise we must use $at (example 6) and error if it's
1826 // not available. For stores we must use $at (examples 4 and 5) because we
1827 // must not clobber the source register setting up the offset.
1828 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1829 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1830 unsigned RegClassIDOp0 =
1831 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1832 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1833 (RegClassIDOp0 == Mips::GPR64RegClassID);
1834 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001835 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001836 else {
1837 int AT = getATReg(IDLoc);
1838 // At this point we need AT to perform the expansions and we exit if it is
1839 // not available.
1840 if (!AT)
1841 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001842 TmpRegNum = getReg(
1843 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001844 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001845
Jack Carter9e65aa32013-03-22 00:05:30 +00001846 TempInst.setOpcode(Mips::LUi);
1847 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1848 if (isImmOpnd)
1849 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1850 else {
1851 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001852 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001853 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1854 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1855 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001856 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001857 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001859 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001860 }
1861 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001862 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001863 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001864 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001865 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001866 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001867 TempInst.setOpcode(Mips::ADDu);
1868 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1869 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1870 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1871 Instructions.push_back(TempInst);
1872 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001873 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001874 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001875 TempInst.setOpcode(Inst.getOpcode());
1876 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1877 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1878 if (isImmOpnd)
1879 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1880 else {
1881 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001882 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1883 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1884 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001885 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001886 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001887 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001888 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001889 }
1890 }
1891 Instructions.push_back(TempInst);
1892 TempInst.clear();
1893}
1894
Matheus Almeida595fcab2014-06-11 15:05:56 +00001895unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1896 // As described by the Mips32r2 spec, the registers Rd and Rs for
1897 // jalr.hb must be different.
1898 unsigned Opcode = Inst.getOpcode();
1899
1900 if (Opcode == Mips::JALR_HB &&
1901 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1902 return Match_RequiresDifferentSrcAndDst;
1903
1904 return Match_Success;
1905}
1906
David Blaikie960ea3f2014-06-08 16:18:35 +00001907bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1908 OperandVector &Operands,
1909 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001910 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001911 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001912
Jack Carterb4dbc172012-09-05 23:34:03 +00001913 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001914 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001915 unsigned MatchResult =
1916 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001917
1918 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001919 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001920 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001921 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001923 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001924 return false;
1925 }
1926 case Match_MissingFeature:
1927 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1928 return true;
1929 case Match_InvalidOperand: {
1930 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001931 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001932 if (ErrorInfo >= Operands.size())
1933 return Error(IDLoc, "too few operands for instruction");
1934
David Blaikie960ea3f2014-06-08 16:18:35 +00001935 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001936 if (ErrorLoc == SMLoc())
1937 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001938 }
1939
1940 return Error(ErrorLoc, "invalid operand for instruction");
1941 }
1942 case Match_MnemonicFail:
1943 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001944 case Match_RequiresDifferentSrcAndDst:
1945 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001946 }
Craig Topper589ceee2015-01-03 08:16:34 +00001947
1948 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00001949}
1950
Toma Tabacu13964452014-09-04 13:23:44 +00001951void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001952 if ((RegIndex != 0) &&
1953 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001954 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001955 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001956 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001957 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001958 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001959 }
1960}
1961
Daniel Sandersef638fe2014-10-03 15:37:37 +00001962void
1963MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1964 SMRange Range, bool ShowColors) {
1965 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001966 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001967 ShowColors);
1968}
1969
Jack Carter1ac53222013-02-20 23:11:17 +00001970int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001971 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001972
Vladimir Medic4c299852013-11-06 11:27:05 +00001973 CC = StringSwitch<unsigned>(Name)
1974 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001975 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001976 .Case("a0", 4)
1977 .Case("a1", 5)
1978 .Case("a2", 6)
1979 .Case("a3", 7)
1980 .Case("v0", 2)
1981 .Case("v1", 3)
1982 .Case("s0", 16)
1983 .Case("s1", 17)
1984 .Case("s2", 18)
1985 .Case("s3", 19)
1986 .Case("s4", 20)
1987 .Case("s5", 21)
1988 .Case("s6", 22)
1989 .Case("s7", 23)
1990 .Case("k0", 26)
1991 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001992 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001993 .Case("sp", 29)
1994 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001995 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001996 .Case("ra", 31)
1997 .Case("t0", 8)
1998 .Case("t1", 9)
1999 .Case("t2", 10)
2000 .Case("t3", 11)
2001 .Case("t4", 12)
2002 .Case("t5", 13)
2003 .Case("t6", 14)
2004 .Case("t7", 15)
2005 .Case("t8", 24)
2006 .Case("t9", 25)
2007 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002008
Toma Tabacufda445c2014-09-15 15:33:01 +00002009 if (!(isABI_N32() || isABI_N64()))
2010 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002011
Daniel Sandersef638fe2014-10-03 15:37:37 +00002012 if (12 <= CC && CC <= 15) {
2013 // Name is one of t4-t7
2014 AsmToken RegTok = getLexer().peekTok();
2015 SMRange RegRange = RegTok.getLocRange();
2016
2017 StringRef FixedName = StringSwitch<StringRef>(Name)
2018 .Case("t4", "t0")
2019 .Case("t5", "t1")
2020 .Case("t6", "t2")
2021 .Case("t7", "t3")
2022 .Default("");
2023 assert(FixedName != "" && "Register name is not one of t4-t7.");
2024
2025 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2026 "Did you mean $" + FixedName + "?", RegRange);
2027 }
2028
Toma Tabacufda445c2014-09-15 15:33:01 +00002029 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2030 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2031 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2032 if (8 <= CC && CC <= 11)
2033 CC += 4;
2034
2035 if (CC == -1)
2036 CC = StringSwitch<unsigned>(Name)
2037 .Case("a4", 8)
2038 .Case("a5", 9)
2039 .Case("a6", 10)
2040 .Case("a7", 11)
2041 .Case("kt0", 26)
2042 .Case("kt1", 27)
2043 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002044
2045 return CC;
2046}
Jack Carterd0bd6422013-04-18 00:41:53 +00002047
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002048int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2049 int CC;
2050
2051 CC = StringSwitch<unsigned>(Name)
2052 .Case("hwr_cpunum", 0)
2053 .Case("hwr_synci_step", 1)
2054 .Case("hwr_cc", 2)
2055 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002056 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002057 .Default(-1);
2058
2059 return CC;
2060}
2061
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002062int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002063
Jack Cartera63b16a2012-09-07 00:23:42 +00002064 if (Name[0] == 'f') {
2065 StringRef NumString = Name.substr(1);
2066 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002068 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002069 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002070 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002071 return IntVal;
2072 }
2073 return -1;
2074}
Jack Cartera63b16a2012-09-07 00:23:42 +00002075
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002076int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2077
2078 if (Name.startswith("fcc")) {
2079 StringRef NumString = Name.substr(3);
2080 unsigned IntVal;
2081 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002082 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002083 if (IntVal > 7) // There are only 8 fcc registers.
2084 return -1;
2085 return IntVal;
2086 }
2087 return -1;
2088}
2089
2090int MipsAsmParser::matchACRegisterName(StringRef Name) {
2091
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002092 if (Name.startswith("ac")) {
2093 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002094 unsigned IntVal;
2095 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002096 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002097 if (IntVal > 3) // There are only 3 acc registers.
2098 return -1;
2099 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002100 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002101 return -1;
2102}
Jack Carterd0bd6422013-04-18 00:41:53 +00002103
Jack Carter5dc8ac92013-09-25 23:50:44 +00002104int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2105 unsigned IntVal;
2106
2107 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2108 return -1;
2109
2110 if (IntVal > 31)
2111 return -1;
2112
2113 return IntVal;
2114}
2115
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002116int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2117 int CC;
2118
2119 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002120 .Case("msair", 0)
2121 .Case("msacsr", 1)
2122 .Case("msaaccess", 2)
2123 .Case("msasave", 3)
2124 .Case("msamodify", 4)
2125 .Case("msarequest", 5)
2126 .Case("msamap", 6)
2127 .Case("msaunmap", 7)
2128 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002129
2130 return CC;
2131}
2132
Jack Carter0b744b32012-10-04 02:29:46 +00002133bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2134 if (Reg > 31)
2135 return false;
2136
Toma Tabacu3c24b042014-09-05 15:43:21 +00002137 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002138 return true;
2139}
2140
Matheus Almeida7de68e72014-06-18 14:46:05 +00002141int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002142 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002143 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002144 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002145 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002146 return AT;
2147}
Jack Carter0b744b32012-10-04 02:29:46 +00002148
Jack Carterd0bd6422013-04-18 00:41:53 +00002149unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002150 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002151}
2152
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002153unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002154 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002155 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002156}
2157
Jack Carter873c7242013-01-12 01:03:14 +00002158int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002159 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002160 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002161 return -1;
2162
Jack Carter873c7242013-01-12 01:03:14 +00002163 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002164}
2165
Toma Tabacu13964452014-09-04 13:23:44 +00002166bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002167 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002168 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002169
Jack Carter30a59822012-10-04 04:03:53 +00002170 // Check if the current operand has a custom associated parser, if so, try to
2171 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002172 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2173 if (ResTy == MatchOperand_Success)
2174 return false;
2175 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2176 // there was a match, but an error occurred, in which case, just return that
2177 // the operand parsing failed.
2178 if (ResTy == MatchOperand_ParseFail)
2179 return true;
2180
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002181 DEBUG(dbgs() << ".. Generic Parser\n");
2182
Jack Carterb4dbc172012-09-05 23:34:03 +00002183 switch (getLexer().getKind()) {
2184 default:
2185 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2186 return true;
2187 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002188 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002189 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002190
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002191 // Almost all registers have been parsed by custom parsers. There is only
2192 // one exception to this. $zero (and it's alias $0) will reach this point
2193 // for div, divu, and similar instructions because it is not an operand
2194 // to the instruction definition but an explicit register. Special case
2195 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002196 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002197 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002198
Jack Carterd0bd6422013-04-18 00:41:53 +00002199 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002200 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002201 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002202 return true;
2203
Jack Carter873c7242013-01-12 01:03:14 +00002204 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002205 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002206 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002207 const MCExpr *Res =
2208 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002209
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002210 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002211 return false;
2212 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002213 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002214 case AsmToken::LParen:
2215 case AsmToken::Minus:
2216 case AsmToken::Plus:
2217 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002218 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002219 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002220 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002221 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002222 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002223 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002224 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002226 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002227 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002228 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002229 return true;
2230
Jack Carter873c7242013-01-12 01:03:14 +00002231 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2232
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002233 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002234 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002235 } // case AsmToken::Percent
2236 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002237 return true;
2238}
2239
Vladimir Medic4c299852013-11-06 11:27:05 +00002240const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002241 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002242 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002243 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002244 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002245 // It's a constant, evaluate reloc value.
2246 int16_t Val;
2247 switch (getVariantKind(RelocStr)) {
2248 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2249 // Get the 1st 16-bits.
2250 Val = MCE->getValue() & 0xffff;
2251 break;
2252 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2253 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2254 // 16 bits being negative.
2255 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2256 break;
2257 case MCSymbolRefExpr::VK_Mips_HIGHER:
2258 // Get the 3rd 16-bits.
2259 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2260 break;
2261 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2262 // Get the 4th 16-bits.
2263 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2264 break;
2265 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002266 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002267 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002268 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002269 }
2270
Jack Carterb5cf5902013-04-17 00:18:04 +00002271 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002272 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002273 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002274 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002275 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002276 return Res;
2277 }
2278
2279 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002280 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2281
Sasa Stankovic06c47802014-04-03 10:37:45 +00002282 // Try to create target expression.
2283 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2284 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002285
Jack Carterd0bd6422013-04-18 00:41:53 +00002286 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2287 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002288 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2289 return Res;
2290 }
2291
2292 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002293 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2294 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2295 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002296 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002297 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002298 return Expr;
2299}
2300
2301bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2302
2303 switch (Expr->getKind()) {
2304 case MCExpr::Constant:
2305 return true;
2306 case MCExpr::SymbolRef:
2307 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2308 case MCExpr::Binary:
2309 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2310 if (!isEvaluated(BE->getLHS()))
2311 return false;
2312 return isEvaluated(BE->getRHS());
2313 }
2314 case MCExpr::Unary:
2315 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002316 case MCExpr::Target:
2317 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002318 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002319 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002320}
Jack Carterd0bd6422013-04-18 00:41:53 +00002321
Jack Carterb5cf5902013-04-17 00:18:04 +00002322bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002323 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002324 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002325 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002326 if (Tok.isNot(AsmToken::Identifier))
2327 return true;
2328
2329 std::string Str = Tok.getIdentifier().str();
2330
Jack Carterd0bd6422013-04-18 00:41:53 +00002331 Parser.Lex(); // Eat the identifier.
2332 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002333 const MCExpr *IdVal;
2334 SMLoc EndLoc;
2335
2336 if (getLexer().getKind() == AsmToken::LParen) {
2337 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002338 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002339 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002340 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002341 const AsmToken &nextTok = Parser.getTok();
2342 if (nextTok.isNot(AsmToken::Identifier))
2343 return true;
2344 Str += "(%";
2345 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002346 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002347 if (getLexer().getKind() != AsmToken::LParen)
2348 return true;
2349 } else
2350 break;
2351 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002352 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002353 return true;
2354
2355 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002356 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002357
2358 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002359 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002360
Jack Carterd0bd6422013-04-18 00:41:53 +00002361 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002362 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002363}
2364
Jack Carterb4dbc172012-09-05 23:34:03 +00002365bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2366 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002367 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002368 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002369 if (ResTy == MatchOperand_Success) {
2370 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002371 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002372 StartLoc = Operand.getStartLoc();
2373 EndLoc = Operand.getEndLoc();
2374
2375 // AFAIK, we only support numeric registers and named GPR's in CFI
2376 // directives.
2377 // Don't worry about eating tokens before failing. Using an unrecognised
2378 // register is a parse error.
2379 if (Operand.isGPRAsmReg()) {
2380 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002381 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002382 }
2383
2384 return (RegNo == (unsigned)-1);
2385 }
2386
2387 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002388 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002389}
2390
Jack Carterb5cf5902013-04-17 00:18:04 +00002391bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002392 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002393 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002394 bool Result = true;
2395
2396 while (getLexer().getKind() == AsmToken::LParen)
2397 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002398
Jack Carterd0bd6422013-04-18 00:41:53 +00002399 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002400 default:
2401 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002402 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002403 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002404 case AsmToken::Integer:
2405 case AsmToken::Minus:
2406 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002407 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002408 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002409 else
2410 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002411 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002412 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002413 break;
Jack Carter873c7242013-01-12 01:03:14 +00002414 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002415 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002416 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002417 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002418}
2419
David Blaikie960ea3f2014-06-08 16:18:35 +00002420MipsAsmParser::OperandMatchResultTy
2421MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002422 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002423 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002424 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002425 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002426 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002427 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002428 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002429 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002430
Jack Carterb5cf5902013-04-17 00:18:04 +00002431 if (getLexer().getKind() == AsmToken::LParen) {
2432 Parser.Lex();
2433 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002434 }
2435
Jack Carterb5cf5902013-04-17 00:18:04 +00002436 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002437 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002438 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002439
Jack Carterd0bd6422013-04-18 00:41:53 +00002440 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002441 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002442 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2443 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002444 SMLoc E =
2445 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002446 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002447 return MatchOperand_Success;
2448 }
2449 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002450 SMLoc E =
2451 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002452
Jack Carterd0bd6422013-04-18 00:41:53 +00002453 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002454 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002455 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002456 S, E, *this);
2457 Operands.push_back(
2458 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002459 return MatchOperand_Success;
2460 }
2461 Error(Parser.getTok().getLoc(), "'(' expected");
2462 return MatchOperand_ParseFail;
2463 }
2464
Jack Carterd0bd6422013-04-18 00:41:53 +00002465 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002466 }
2467
Toma Tabacu13964452014-09-04 13:23:44 +00002468 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002469 if (Res != MatchOperand_Success)
2470 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002471
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002472 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002473 Error(Parser.getTok().getLoc(), "')' expected");
2474 return MatchOperand_ParseFail;
2475 }
2476
Jack Carter873c7242013-01-12 01:03:14 +00002477 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2478
Jack Carterd0bd6422013-04-18 00:41:53 +00002479 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002480
Craig Topper062a2ba2014-04-25 05:30:21 +00002481 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002482 IdVal = MCConstantExpr::Create(0, getContext());
2483
Jack Carterd0bd6422013-04-18 00:41:53 +00002484 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002485 std::unique_ptr<MipsOperand> op(
2486 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002487 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002488 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002489 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002490 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002491 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2492 int64_t Imm;
2493 if (IdVal->EvaluateAsAbsolute(Imm))
2494 IdVal = MCConstantExpr::Create(Imm, getContext());
2495 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2496 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2497 getContext());
2498 }
2499
David Blaikie960ea3f2014-06-08 16:18:35 +00002500 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002501 return MatchOperand_Success;
2502}
2503
David Blaikie960ea3f2014-06-08 16:18:35 +00002504bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002505 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002506 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2507 if (Sym) {
2508 SMLoc S = Parser.getTok().getLoc();
2509 const MCExpr *Expr;
2510 if (Sym->isVariable())
2511 Expr = Sym->getVariableValue();
2512 else
2513 return false;
2514 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002515 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002516 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002517 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002518 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002519 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002520 if (ResTy == MatchOperand_Success) {
2521 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002522 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002523 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002524 llvm_unreachable("Should never ParseFail");
2525 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002526 }
2527 } else if (Expr->getKind() == MCExpr::Constant) {
2528 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002529 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002530 Operands.push_back(
2531 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002532 return true;
2533 }
2534 }
2535 return false;
2536}
Jack Carterd0bd6422013-04-18 00:41:53 +00002537
Jack Carter873c7242013-01-12 01:03:14 +00002538MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002539MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002540 StringRef Identifier,
2541 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002542 int Index = matchCPURegisterName(Identifier);
2543 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002544 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002545 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2546 return MatchOperand_Success;
2547 }
2548
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002549 Index = matchHWRegsRegisterName(Identifier);
2550 if (Index != -1) {
2551 Operands.push_back(MipsOperand::createHWRegsReg(
2552 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2553 return MatchOperand_Success;
2554 }
2555
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002556 Index = matchFPURegisterName(Identifier);
2557 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002558 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002559 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2560 return MatchOperand_Success;
2561 }
2562
2563 Index = matchFCCRegisterName(Identifier);
2564 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002565 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002566 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2567 return MatchOperand_Success;
2568 }
2569
2570 Index = matchACRegisterName(Identifier);
2571 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002572 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002573 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2574 return MatchOperand_Success;
2575 }
2576
2577 Index = matchMSA128RegisterName(Identifier);
2578 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002579 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002580 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2581 return MatchOperand_Success;
2582 }
2583
2584 Index = matchMSA128CtrlRegisterName(Identifier);
2585 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002586 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002587 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2588 return MatchOperand_Success;
2589 }
2590
2591 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002592}
2593
2594MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002595MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002596 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002597 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002598
2599 if (Token.is(AsmToken::Identifier)) {
2600 DEBUG(dbgs() << ".. identifier\n");
2601 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002602 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002603 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002604 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002605 } else if (Token.is(AsmToken::Integer)) {
2606 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002607 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002608 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2609 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002610 return MatchOperand_Success;
2611 }
2612
2613 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2614
2615 return MatchOperand_NoMatch;
2616}
2617
David Blaikie960ea3f2014-06-08 16:18:35 +00002618MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002619MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002620 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002621 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002622
2623 auto Token = Parser.getTok();
2624
2625 SMLoc S = Token.getLoc();
2626
2627 if (Token.isNot(AsmToken::Dollar)) {
2628 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2629 if (Token.is(AsmToken::Identifier)) {
2630 if (searchSymbolAlias(Operands))
2631 return MatchOperand_Success;
2632 }
2633 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2634 return MatchOperand_NoMatch;
2635 }
2636 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002637
Toma Tabacu13964452014-09-04 13:23:44 +00002638 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002639 if (ResTy == MatchOperand_Success) {
2640 Parser.Lex(); // $
2641 Parser.Lex(); // identifier
2642 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002643 return ResTy;
2644}
2645
2646MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002647MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002648 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002649 switch (getLexer().getKind()) {
2650 default:
2651 return MatchOperand_NoMatch;
2652 case AsmToken::LParen:
2653 case AsmToken::Minus:
2654 case AsmToken::Plus:
2655 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002656 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002657 case AsmToken::String:
2658 break;
2659 }
2660
2661 const MCExpr *IdVal;
2662 SMLoc S = Parser.getTok().getLoc();
2663 if (getParser().parseExpression(IdVal))
2664 return MatchOperand_ParseFail;
2665
2666 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2667 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2668 return MatchOperand_Success;
2669}
2670
David Blaikie960ea3f2014-06-08 16:18:35 +00002671MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002672MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002673 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002674 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002675
2676 SMLoc S = getLexer().getLoc();
2677
2678 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002679 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002680 if (ResTy != MatchOperand_NoMatch)
2681 return ResTy;
2682
Daniel Sanders315386c2014-04-01 10:40:14 +00002683 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002684 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002685 if (ResTy != MatchOperand_NoMatch)
2686 return ResTy;
2687
Daniel Sandersffd84362014-04-01 10:41:48 +00002688 const MCExpr *Expr = nullptr;
2689 if (Parser.parseExpression(Expr)) {
2690 // We have no way of knowing if a symbol was consumed so we must ParseFail
2691 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002692 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002693 Operands.push_back(
2694 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002695 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002696}
2697
Vladimir Medic2b953d02013-10-01 09:48:56 +00002698MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002699MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002700 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002701 const MCExpr *IdVal;
2702 // If the first token is '$' we may have register operand.
2703 if (Parser.getTok().is(AsmToken::Dollar))
2704 return MatchOperand_NoMatch;
2705 SMLoc S = Parser.getTok().getLoc();
2706 if (getParser().parseExpression(IdVal))
2707 return MatchOperand_ParseFail;
2708 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002709 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002710 int64_t Val = MCE->getValue();
2711 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2712 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002713 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002714 return MatchOperand_Success;
2715}
2716
Matheus Almeida779c5932013-11-18 12:32:49 +00002717MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002718MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002719 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002720 switch (getLexer().getKind()) {
2721 default:
2722 return MatchOperand_NoMatch;
2723 case AsmToken::LParen:
2724 case AsmToken::Plus:
2725 case AsmToken::Minus:
2726 case AsmToken::Integer:
2727 break;
2728 }
2729
2730 const MCExpr *Expr;
2731 SMLoc S = Parser.getTok().getLoc();
2732
2733 if (getParser().parseExpression(Expr))
2734 return MatchOperand_ParseFail;
2735
2736 int64_t Val;
2737 if (!Expr->EvaluateAsAbsolute(Val)) {
2738 Error(S, "expected immediate value");
2739 return MatchOperand_ParseFail;
2740 }
2741
2742 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2743 // and because the CPU always adds one to the immediate field, the allowed
2744 // range becomes 1..4. We'll only check the range here and will deal
2745 // with the addition/subtraction when actually decoding/encoding
2746 // the instruction.
2747 if (Val < 1 || Val > 4) {
2748 Error(S, "immediate not in range (1..4)");
2749 return MatchOperand_ParseFail;
2750 }
2751
Jack Carter3b2c96e2014-01-22 23:31:38 +00002752 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002753 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002754 return MatchOperand_Success;
2755}
2756
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002757MipsAsmParser::OperandMatchResultTy
2758MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2759 MCAsmParser &Parser = getParser();
2760 SmallVector<unsigned, 10> Regs;
2761 unsigned RegNo;
2762 unsigned PrevReg = Mips::NoRegister;
2763 bool RegRange = false;
2764 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2765
2766 if (Parser.getTok().isNot(AsmToken::Dollar))
2767 return MatchOperand_ParseFail;
2768
2769 SMLoc S = Parser.getTok().getLoc();
2770 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2771 SMLoc E = getLexer().getLoc();
2772 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2773 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2774 if (RegRange) {
2775 // Remove last register operand because registers from register range
2776 // should be inserted first.
2777 if (RegNo == Mips::RA) {
2778 Regs.push_back(RegNo);
2779 } else {
2780 unsigned TmpReg = PrevReg + 1;
2781 while (TmpReg <= RegNo) {
2782 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2783 Error(E, "invalid register operand");
2784 return MatchOperand_ParseFail;
2785 }
2786
2787 PrevReg = TmpReg;
2788 Regs.push_back(TmpReg++);
2789 }
2790 }
2791
2792 RegRange = false;
2793 } else {
2794 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2795 (RegNo != Mips::RA)) {
2796 Error(E, "$16 or $31 expected");
2797 return MatchOperand_ParseFail;
2798 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2799 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2800 Error(E, "invalid register operand");
2801 return MatchOperand_ParseFail;
2802 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2803 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2804 Error(E, "consecutive register numbers expected");
2805 return MatchOperand_ParseFail;
2806 }
2807
2808 Regs.push_back(RegNo);
2809 }
2810
2811 if (Parser.getTok().is(AsmToken::Minus))
2812 RegRange = true;
2813
2814 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2815 !Parser.getTok().isNot(AsmToken::Comma)) {
2816 Error(E, "',' or '-' expected");
2817 return MatchOperand_ParseFail;
2818 }
2819
2820 Lex(); // Consume comma or minus
2821 if (Parser.getTok().isNot(AsmToken::Dollar))
2822 break;
2823
2824 PrevReg = RegNo;
2825 }
2826
2827 SMLoc E = Parser.getTok().getLoc();
2828 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2829 parseMemOperand(Operands);
2830 return MatchOperand_Success;
2831}
2832
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002833MipsAsmParser::OperandMatchResultTy
2834MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2835 MCAsmParser &Parser = getParser();
2836
2837 SMLoc S = Parser.getTok().getLoc();
2838 if (parseAnyRegister(Operands) != MatchOperand_Success)
2839 return MatchOperand_ParseFail;
2840
2841 SMLoc E = Parser.getTok().getLoc();
2842 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2843 unsigned Reg = Op.getGPR32Reg();
2844 Operands.pop_back();
2845 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2846 return MatchOperand_Success;
2847}
2848
Jack Carterdc1e35d2012-09-06 20:00:02 +00002849MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2850
Vladimir Medic4c299852013-11-06 11:27:05 +00002851 MCSymbolRefExpr::VariantKind VK =
2852 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2853 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2854 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2855 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2856 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2857 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2858 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2859 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2860 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2861 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2862 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2863 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2864 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2865 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2866 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2867 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2868 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2869 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002870 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2871 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2872 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2873 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2874 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2875 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002876 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2877 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002878 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002879
Matheus Almeida2852af82014-04-22 10:15:54 +00002880 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002881
Jack Carterdc1e35d2012-09-06 20:00:02 +00002882 return VK;
2883}
Jack Cartera63b16a2012-09-07 00:23:42 +00002884
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002885/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2886/// either this.
2887/// ::= '(', register, ')'
2888/// handle it before we iterate so we don't get tripped up by the lack of
2889/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002890bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002891 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002892 if (getLexer().is(AsmToken::LParen)) {
2893 Operands.push_back(
2894 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2895 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002896 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002897 SMLoc Loc = getLexer().getLoc();
2898 Parser.eatToEndOfStatement();
2899 return Error(Loc, "unexpected token in argument list");
2900 }
2901 if (Parser.getTok().isNot(AsmToken::RParen)) {
2902 SMLoc Loc = getLexer().getLoc();
2903 Parser.eatToEndOfStatement();
2904 return Error(Loc, "unexpected token, expected ')'");
2905 }
2906 Operands.push_back(
2907 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2908 Parser.Lex();
2909 }
2910 return false;
2911}
2912
2913/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2914/// either one of these.
2915/// ::= '[', register, ']'
2916/// ::= '[', integer, ']'
2917/// handle it before we iterate so we don't get tripped up by the lack of
2918/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002919bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002920 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002921 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922 if (getLexer().is(AsmToken::LBrac)) {
2923 Operands.push_back(
2924 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2925 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002926 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002927 SMLoc Loc = getLexer().getLoc();
2928 Parser.eatToEndOfStatement();
2929 return Error(Loc, "unexpected token in argument list");
2930 }
2931 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2932 SMLoc Loc = getLexer().getLoc();
2933 Parser.eatToEndOfStatement();
2934 return Error(Loc, "unexpected token, expected ']'");
2935 }
2936 Operands.push_back(
2937 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2938 Parser.Lex();
2939 }
2940 return false;
2941}
2942
David Blaikie960ea3f2014-06-08 16:18:35 +00002943bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2944 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002945 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002946 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002947
2948 // We have reached first instruction, module directive are now forbidden.
2949 getTargetStreamer().forbidModuleDirective();
2950
Vladimir Medic74593e62013-07-17 15:00:42 +00002951 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002952 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002953 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002954 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002955 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002956 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002957 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002958
2959 // Read the remaining operands.
2960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2961 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002962 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002963 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002964 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002965 return Error(Loc, "unexpected token in argument list");
2966 }
Toma Tabacu13964452014-09-04 13:23:44 +00002967 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002968 return true;
2969 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002970
Jack Carterd0bd6422013-04-18 00:41:53 +00002971 while (getLexer().is(AsmToken::Comma)) {
2972 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002973 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002974 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002975 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002976 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002977 return Error(Loc, "unexpected token in argument list");
2978 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002979 // Parse bracket and parenthesis suffixes before we iterate
2980 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002981 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002982 return true;
2983 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002984 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002985 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002986 }
2987 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2989 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002990 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002991 return Error(Loc, "unexpected token in argument list");
2992 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002993 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002994 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002995}
2996
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002997bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002998 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002999 SMLoc Loc = getLexer().getLoc();
3000 Parser.eatToEndOfStatement();
3001 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003002}
3003
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003004bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003005 return Error(Loc, ErrorMsg);
3006}
3007
Jack Carter0b744b32012-10-04 02:29:46 +00003008bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003009 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003010 // Line should look like: ".set noat".
3011 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003012 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00003013 // eat noat
3014 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003015 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003016 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003017 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003018 return false;
3019 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003020 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003021 return false;
3022}
Jack Carterd0bd6422013-04-18 00:41:53 +00003023
Jack Carter0b744b32012-10-04 02:29:46 +00003024bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003025 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003026 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00003027 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00003028 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00003029 getParser().Lex();
3030 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003031 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00003032 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003033 return false;
3034 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003035 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00003036 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003037 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003038 return false;
3039 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003040 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00003041 const AsmToken &Reg = Parser.getTok();
3042 if (Reg.is(AsmToken::Identifier)) {
3043 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3044 } else if (Reg.is(AsmToken::Integer)) {
3045 AtRegNo = Reg.getIntVal();
3046 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003047 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003048 return false;
3049 }
Jack Carter1ac53222013-02-20 23:11:17 +00003050
Daniel Sanders71a89d922014-03-25 13:01:06 +00003051 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00003052 reportParseError("unexpected token in statement");
3053 return false;
3054 }
3055
Toma Tabacu9db22db2014-09-09 10:15:38 +00003056 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003057 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00003058 return false;
3059 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003060 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00003061
3062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003063 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003064 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003065 }
3066 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003067 return false;
3068 } else {
3069 reportParseError("unexpected token in statement");
3070 return false;
3071 }
3072}
3073
3074bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003075 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003076 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003077 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003079 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003080 return false;
3081 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003082 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003083 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003084 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003085 return false;
3086}
3087
3088bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003089 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003090 Parser.Lex();
3091 // If this is not the end of the statement, report an error.
3092 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003093 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003094 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003095 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003096 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003097 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003098 Parser.Lex(); // Consume the EndOfStatement.
3099 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003100}
3101
3102bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003103 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003104 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003105 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003106 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003107 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003108 return false;
3109 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003110 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003111 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003112 return false;
3113}
3114
3115bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003116 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003117 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003118 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003120 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003121 return false;
3122 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003123 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003124 reportParseError("`noreorder' must be set before `nomacro'");
3125 return false;
3126 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003127 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003128 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003129 return false;
3130}
Jack Carterd76b2372013-03-21 21:44:16 +00003131
Daniel Sanders44934432014-08-07 12:03:36 +00003132bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003133 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003134 Parser.Lex();
3135
3136 // If this is not the end of the statement, report an error.
3137 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003138 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003139
3140 setFeatureBits(Mips::FeatureMSA, "msa");
3141 getTargetStreamer().emitDirectiveSetMsa();
3142 return false;
3143}
3144
3145bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003146 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003147 Parser.Lex();
3148
3149 // If this is not the end of the statement, report an error.
3150 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003151 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003152
3153 clearFeatureBits(Mips::FeatureMSA, "msa");
3154 getTargetStreamer().emitDirectiveSetNoMsa();
3155 return false;
3156}
3157
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003158bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003159 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003160 Parser.Lex(); // Eat "nodsp".
3161
3162 // If this is not the end of the statement, report an error.
3163 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3164 reportParseError("unexpected token, expected end of statement");
3165 return false;
3166 }
3167
3168 clearFeatureBits(Mips::FeatureDSP, "dsp");
3169 getTargetStreamer().emitDirectiveSetNoDsp();
3170 return false;
3171}
3172
Toma Tabacucc2502d2014-11-04 17:18:07 +00003173bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003174 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003175 Parser.Lex(); // Eat "mips16".
3176
Jack Carter39536722014-01-22 23:08:42 +00003177 // If this is not the end of the statement, report an error.
3178 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003179 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003180 return false;
3181 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003182
3183 setFeatureBits(Mips::FeatureMips16, "mips16");
3184 getTargetStreamer().emitDirectiveSetMips16();
3185 Parser.Lex(); // Consume the EndOfStatement.
3186 return false;
3187}
3188
3189bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003190 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003191 Parser.Lex(); // Eat "nomips16".
3192
3193 // If this is not the end of the statement, report an error.
3194 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3195 reportParseError("unexpected token, expected end of statement");
3196 return false;
3197 }
3198
3199 clearFeatureBits(Mips::FeatureMips16, "mips16");
3200 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003201 Parser.Lex(); // Consume the EndOfStatement.
3202 return false;
3203}
3204
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003205bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003206 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003207 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003208 // Line can be: .set fp=32
3209 // .set fp=xx
3210 // .set fp=64
3211 Parser.Lex(); // Eat fp token
3212 AsmToken Tok = Parser.getTok();
3213 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003214 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003215 return false;
3216 }
3217 Parser.Lex(); // Eat '=' token.
3218 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003219
3220 if (!parseFpABIValue(FpAbiVal, ".set"))
3221 return false;
3222
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003223 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003224 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003225 return false;
3226 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003227 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003228 Parser.Lex(); // Consume the EndOfStatement.
3229 return false;
3230}
3231
Toma Tabacu9db22db2014-09-09 10:15:38 +00003232bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003233 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003234 SMLoc Loc = getLexer().getLoc();
3235
3236 Parser.Lex();
3237 if (getLexer().isNot(AsmToken::EndOfStatement))
3238 return reportParseError("unexpected token, expected end of statement");
3239
3240 // Always keep an element on the options "stack" to prevent the user
3241 // from changing the initial options. This is how we remember them.
3242 if (AssemblerOptions.size() == 2)
3243 return reportParseError(Loc, ".set pop with no .set push");
3244
3245 AssemblerOptions.pop_back();
3246 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3247
3248 getTargetStreamer().emitDirectiveSetPop();
3249 return false;
3250}
3251
3252bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003253 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003254 Parser.Lex();
3255 if (getLexer().isNot(AsmToken::EndOfStatement))
3256 return reportParseError("unexpected token, expected end of statement");
3257
3258 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003259 AssemblerOptions.push_back(
3260 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003261
3262 getTargetStreamer().emitDirectiveSetPush();
3263 return false;
3264}
3265
Jack Carterd76b2372013-03-21 21:44:16 +00003266bool MipsAsmParser::parseSetAssignment() {
3267 StringRef Name;
3268 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003269 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003270
3271 if (Parser.parseIdentifier(Name))
3272 reportParseError("expected identifier after .set");
3273
3274 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003275 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003276 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003277
Jack Carter3b2c96e2014-01-22 23:31:38 +00003278 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003279 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003280
Jack Carterd0bd6422013-04-18 00:41:53 +00003281 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003282 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003283 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003284 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003285 Sym = getContext().GetOrCreateSymbol(Name);
3286 Sym->setVariableValue(Value);
3287
3288 return false;
3289}
Jack Carterd0bd6422013-04-18 00:41:53 +00003290
Toma Tabacu26647792014-09-09 12:52:14 +00003291bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003292 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003293 Parser.Lex();
3294 if (getLexer().isNot(AsmToken::EndOfStatement))
3295 return reportParseError("unexpected token, expected end of statement");
3296
3297 // Reset assembler options to their initial values.
3298 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3299 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3300
3301 getTargetStreamer().emitDirectiveSetMips0();
3302 return false;
3303}
3304
Toma Tabacu85618b32014-08-19 14:22:52 +00003305bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003306 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003307 Parser.Lex();
3308 if (getLexer().isNot(AsmToken::Equal))
3309 return reportParseError("unexpected token, expected equals sign");
3310
3311 Parser.Lex();
3312 StringRef Arch;
3313 if (Parser.parseIdentifier(Arch))
3314 return reportParseError("expected arch identifier");
3315
3316 StringRef ArchFeatureName =
3317 StringSwitch<StringRef>(Arch)
3318 .Case("mips1", "mips1")
3319 .Case("mips2", "mips2")
3320 .Case("mips3", "mips3")
3321 .Case("mips4", "mips4")
3322 .Case("mips5", "mips5")
3323 .Case("mips32", "mips32")
3324 .Case("mips32r2", "mips32r2")
3325 .Case("mips32r6", "mips32r6")
3326 .Case("mips64", "mips64")
3327 .Case("mips64r2", "mips64r2")
3328 .Case("mips64r6", "mips64r6")
3329 .Case("cnmips", "cnmips")
3330 .Case("r4000", "mips3") // This is an implementation of Mips3.
3331 .Default("");
3332
3333 if (ArchFeatureName.empty())
3334 return reportParseError("unsupported architecture");
3335
3336 selectArch(ArchFeatureName);
3337 getTargetStreamer().emitDirectiveSetArch(Arch);
3338 return false;
3339}
3340
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003341bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003342 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003343 Parser.Lex();
3344 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003345 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003346
Matheus Almeida2852af82014-04-22 10:15:54 +00003347 switch (Feature) {
3348 default:
3349 llvm_unreachable("Unimplemented feature");
3350 case Mips::FeatureDSP:
3351 setFeatureBits(Mips::FeatureDSP, "dsp");
3352 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003353 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003354 case Mips::FeatureMicroMips:
3355 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003356 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003357 case Mips::FeatureMips1:
3358 selectArch("mips1");
3359 getTargetStreamer().emitDirectiveSetMips1();
3360 break;
3361 case Mips::FeatureMips2:
3362 selectArch("mips2");
3363 getTargetStreamer().emitDirectiveSetMips2();
3364 break;
3365 case Mips::FeatureMips3:
3366 selectArch("mips3");
3367 getTargetStreamer().emitDirectiveSetMips3();
3368 break;
3369 case Mips::FeatureMips4:
3370 selectArch("mips4");
3371 getTargetStreamer().emitDirectiveSetMips4();
3372 break;
3373 case Mips::FeatureMips5:
3374 selectArch("mips5");
3375 getTargetStreamer().emitDirectiveSetMips5();
3376 break;
3377 case Mips::FeatureMips32:
3378 selectArch("mips32");
3379 getTargetStreamer().emitDirectiveSetMips32();
3380 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003381 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003382 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003383 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003384 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003385 case Mips::FeatureMips32r6:
3386 selectArch("mips32r6");
3387 getTargetStreamer().emitDirectiveSetMips32R6();
3388 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003389 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003390 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003391 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003392 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003393 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003394 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003395 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003396 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003397 case Mips::FeatureMips64r6:
3398 selectArch("mips64r6");
3399 getTargetStreamer().emitDirectiveSetMips64R6();
3400 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003401 }
3402 return false;
3403}
3404
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003405bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003406 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003407 if (getLexer().isNot(AsmToken::Comma)) {
3408 SMLoc Loc = getLexer().getLoc();
3409 Parser.eatToEndOfStatement();
3410 return Error(Loc, ErrorStr);
3411 }
3412
Matheus Almeida2852af82014-04-22 10:15:54 +00003413 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003414 return true;
3415}
3416
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003417bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003418 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003419 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003420
Toma Tabacudde4c462014-11-06 10:02:45 +00003421 if (inMips16Mode()) {
3422 reportParseError(".cpload is not supported in Mips16 mode");
3423 return false;
3424 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003425
David Blaikie960ea3f2014-06-08 16:18:35 +00003426 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003427 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003428 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3429 reportParseError("expected register containing function address");
3430 return false;
3431 }
3432
David Blaikie960ea3f2014-06-08 16:18:35 +00003433 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3434 if (!RegOpnd.isGPRAsmReg()) {
3435 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003436 return false;
3437 }
3438
Toma Tabacudde4c462014-11-06 10:02:45 +00003439 // If this is not the end of the statement, report an error.
3440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3441 reportParseError("unexpected token, expected end of statement");
3442 return false;
3443 }
3444
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003445 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003446 return false;
3447}
3448
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003449bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003450 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003451 unsigned FuncReg;
3452 unsigned Save;
3453 bool SaveIsReg = true;
3454
Matheus Almeida7e815762014-06-18 13:08:59 +00003455 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003456 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003457 if (ResTy == MatchOperand_NoMatch) {
3458 reportParseError("expected register containing function address");
3459 Parser.eatToEndOfStatement();
3460 return false;
3461 }
3462
3463 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3464 if (!FuncRegOpnd.isGPRAsmReg()) {
3465 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3466 Parser.eatToEndOfStatement();
3467 return false;
3468 }
3469
3470 FuncReg = FuncRegOpnd.getGPR32Reg();
3471 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003472
Toma Tabacu65f10572014-09-16 15:00:52 +00003473 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003474 return true;
3475
Toma Tabacu13964452014-09-04 13:23:44 +00003476 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003477 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003478 const AsmToken &Tok = Parser.getTok();
3479 if (Tok.is(AsmToken::Integer)) {
3480 Save = Tok.getIntVal();
3481 SaveIsReg = false;
3482 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003483 } else {
3484 reportParseError("expected save register or stack offset");
3485 Parser.eatToEndOfStatement();
3486 return false;
3487 }
3488 } else {
3489 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3490 if (!SaveOpnd.isGPRAsmReg()) {
3491 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3492 Parser.eatToEndOfStatement();
3493 return false;
3494 }
3495 Save = SaveOpnd.getGPR32Reg();
3496 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003497
Toma Tabacu65f10572014-09-16 15:00:52 +00003498 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003499 return true;
3500
3501 StringRef Name;
3502 if (Parser.parseIdentifier(Name))
3503 reportParseError("expected identifier");
3504 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003505
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003506 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003507 return false;
3508}
3509
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003510bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003511 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003512 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3513 const AsmToken &Tok = Parser.getTok();
3514
3515 if (Tok.getString() == "2008") {
3516 Parser.Lex();
3517 getTargetStreamer().emitDirectiveNaN2008();
3518 return false;
3519 } else if (Tok.getString() == "legacy") {
3520 Parser.Lex();
3521 getTargetStreamer().emitDirectiveNaNLegacy();
3522 return false;
3523 }
3524 }
3525 // If we don't recognize the option passed to the .nan
3526 // directive (e.g. no option or unknown option), emit an error.
3527 reportParseError("invalid option in .nan directive");
3528 return false;
3529}
3530
Jack Carter0b744b32012-10-04 02:29:46 +00003531bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003532 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003533 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003534 const AsmToken &Tok = Parser.getTok();
3535
3536 if (Tok.getString() == "noat") {
3537 return parseSetNoAtDirective();
3538 } else if (Tok.getString() == "at") {
3539 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003540 } else if (Tok.getString() == "arch") {
3541 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003542 } else if (Tok.getString() == "fp") {
3543 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003544 } else if (Tok.getString() == "pop") {
3545 return parseSetPopDirective();
3546 } else if (Tok.getString() == "push") {
3547 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003548 } else if (Tok.getString() == "reorder") {
3549 return parseSetReorderDirective();
3550 } else if (Tok.getString() == "noreorder") {
3551 return parseSetNoReorderDirective();
3552 } else if (Tok.getString() == "macro") {
3553 return parseSetMacroDirective();
3554 } else if (Tok.getString() == "nomacro") {
3555 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003556 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003557 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003558 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003559 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003560 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003561 getTargetStreamer().emitDirectiveSetNoMicroMips();
3562 Parser.eatToEndOfStatement();
3563 return false;
3564 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003565 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003566 } else if (Tok.getString() == "mips0") {
3567 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003568 } else if (Tok.getString() == "mips1") {
3569 return parseSetFeature(Mips::FeatureMips1);
3570 } else if (Tok.getString() == "mips2") {
3571 return parseSetFeature(Mips::FeatureMips2);
3572 } else if (Tok.getString() == "mips3") {
3573 return parseSetFeature(Mips::FeatureMips3);
3574 } else if (Tok.getString() == "mips4") {
3575 return parseSetFeature(Mips::FeatureMips4);
3576 } else if (Tok.getString() == "mips5") {
3577 return parseSetFeature(Mips::FeatureMips5);
3578 } else if (Tok.getString() == "mips32") {
3579 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003580 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003581 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003582 } else if (Tok.getString() == "mips32r6") {
3583 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003584 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003585 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003586 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003587 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003588 } else if (Tok.getString() == "mips64r6") {
3589 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003590 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003591 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003592 } else if (Tok.getString() == "nodsp") {
3593 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003594 } else if (Tok.getString() == "msa") {
3595 return parseSetMsaDirective();
3596 } else if (Tok.getString() == "nomsa") {
3597 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003598 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003599 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003600 parseSetAssignment();
3601 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003602 }
Jack Carter07c818d2013-01-25 01:31:34 +00003603
Jack Carter0b744b32012-10-04 02:29:46 +00003604 return true;
3605}
3606
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003607/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003608/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003609bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003610 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003611 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3612 for (;;) {
3613 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003614 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003615 return true;
3616
3617 getParser().getStreamer().EmitValue(Value, Size);
3618
3619 if (getLexer().is(AsmToken::EndOfStatement))
3620 break;
3621
Jack Carter07c818d2013-01-25 01:31:34 +00003622 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003623 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003624 Parser.Lex();
3625 }
3626 }
3627
3628 Parser.Lex();
3629 return false;
3630}
3631
Vladimir Medic4c299852013-11-06 11:27:05 +00003632/// parseDirectiveGpWord
3633/// ::= .gpword local_sym
3634bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003635 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003636 const MCExpr *Value;
3637 // EmitGPRel32Value requires an expression, so we are using base class
3638 // method to evaluate the expression.
3639 if (getParser().parseExpression(Value))
3640 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003641 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003642
Vladimir Medice10c1122013-11-13 13:18:04 +00003643 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003644 return Error(getLexer().getLoc(),
3645 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003646 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003647 return false;
3648}
3649
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003650/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003651/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003652bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003653 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003654 const MCExpr *Value;
3655 // EmitGPRel64Value requires an expression, so we are using base class
3656 // method to evaluate the expression.
3657 if (getParser().parseExpression(Value))
3658 return true;
3659 getParser().getStreamer().EmitGPRel64Value(Value);
3660
3661 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003662 return Error(getLexer().getLoc(),
3663 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003664 Parser.Lex(); // Eat EndOfStatement token.
3665 return false;
3666}
3667
Jack Carter0cd3c192014-01-06 23:27:31 +00003668bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003669 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003670 // Get the option token.
3671 AsmToken Tok = Parser.getTok();
3672 // At the moment only identifiers are supported.
3673 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003674 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003675 Parser.eatToEndOfStatement();
3676 return false;
3677 }
3678
3679 StringRef Option = Tok.getIdentifier();
3680
3681 if (Option == "pic0") {
3682 getTargetStreamer().emitDirectiveOptionPic0();
3683 Parser.Lex();
3684 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3685 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003686 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003687 Parser.eatToEndOfStatement();
3688 }
3689 return false;
3690 }
3691
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003692 if (Option == "pic2") {
3693 getTargetStreamer().emitDirectiveOptionPic2();
3694 Parser.Lex();
3695 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3696 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003697 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003698 Parser.eatToEndOfStatement();
3699 }
3700 return false;
3701 }
3702
Jack Carter0cd3c192014-01-06 23:27:31 +00003703 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003704 Warning(Parser.getTok().getLoc(),
3705 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003706 Parser.eatToEndOfStatement();
3707 return false;
3708}
3709
Daniel Sanders7e527422014-07-10 13:38:23 +00003710/// parseDirectiveModule
3711/// ::= .module oddspreg
3712/// ::= .module nooddspreg
3713/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003714bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003715 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003716 MCAsmLexer &Lexer = getLexer();
3717 SMLoc L = Lexer.getLoc();
3718
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003719 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003720 // TODO : get a better message.
3721 reportParseError(".module directive must appear before any code");
3722 return false;
3723 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003724
Toma Tabacuc405c822015-01-23 10:40:19 +00003725 StringRef Option;
3726 if (Parser.parseIdentifier(Option)) {
3727 reportParseError("expected .module option identifier");
3728 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003729 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003730
Toma Tabacuc405c822015-01-23 10:40:19 +00003731 if (Option == "oddspreg") {
3732 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3733 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3734
3735 // If this is not the end of the statement, report an error.
3736 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3737 reportParseError("unexpected token, expected end of statement");
3738 return false;
3739 }
3740
3741 return false; // parseDirectiveModule has finished successfully.
3742 } else if (Option == "nooddspreg") {
3743 if (!isABI_O32()) {
3744 Error(L, "'.module nooddspreg' requires the O32 ABI");
3745 return false;
3746 }
3747
3748 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3749 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3750
3751 // If this is not the end of the statement, report an error.
3752 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3753 reportParseError("unexpected token, expected end of statement");
3754 return false;
3755 }
3756
3757 return false; // parseDirectiveModule has finished successfully.
3758 } else if (Option == "fp") {
3759 return parseDirectiveModuleFP();
3760 } else {
3761 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
3762 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003763}
3764
3765/// parseDirectiveModuleFP
3766/// ::= =32
3767/// ::= =xx
3768/// ::= =64
3769bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003770 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003771 MCAsmLexer &Lexer = getLexer();
3772
3773 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003774 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003775 return false;
3776 }
3777 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003778
Daniel Sanders7e527422014-07-10 13:38:23 +00003779 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003780 if (!parseFpABIValue(FpABI, ".module"))
3781 return false;
3782
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003783 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003784 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003785 return false;
3786 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003787
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003788 // Emit appropriate flags.
3789 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003790 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003791 return false;
3792}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003793
Daniel Sanders7e527422014-07-10 13:38:23 +00003794bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003795 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003796 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003797 MCAsmLexer &Lexer = getLexer();
3798
3799 if (Lexer.is(AsmToken::Identifier)) {
3800 StringRef Value = Parser.getTok().getString();
3801 Parser.Lex();
3802
3803 if (Value != "xx") {
3804 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3805 return false;
3806 }
3807
3808 if (!isABI_O32()) {
3809 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3810 return false;
3811 }
3812
Daniel Sanders7e527422014-07-10 13:38:23 +00003813 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003814 return true;
3815 }
3816
3817 if (Lexer.is(AsmToken::Integer)) {
3818 unsigned Value = Parser.getTok().getIntVal();
3819 Parser.Lex();
3820
3821 if (Value != 32 && Value != 64) {
3822 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3823 return false;
3824 }
3825
3826 if (Value == 32) {
3827 if (!isABI_O32()) {
3828 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3829 return false;
3830 }
3831
Daniel Sanders7e527422014-07-10 13:38:23 +00003832 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3833 } else
3834 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003835
Daniel Sanders7e527422014-07-10 13:38:23 +00003836 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003837 }
3838
3839 return false;
3840}
3841
Jack Carter0b744b32012-10-04 02:29:46 +00003842bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003843 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003844 StringRef IDVal = DirectiveID.getString();
3845
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003846 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003847 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003848 if (IDVal == ".dword") {
3849 parseDataDirective(8, DirectiveID.getLoc());
3850 return false;
3851 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003852 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003853 StringRef SymbolName;
3854
3855 if (Parser.parseIdentifier(SymbolName)) {
3856 reportParseError("expected identifier after .ent");
3857 return false;
3858 }
3859
3860 // There's an undocumented extension that allows an integer to
3861 // follow the name of the procedure which AFAICS is ignored by GAS.
3862 // Example: .ent foo,2
3863 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3864 if (getLexer().isNot(AsmToken::Comma)) {
3865 // Even though we accept this undocumented extension for compatibility
3866 // reasons, the additional integer argument does not actually change
3867 // the behaviour of the '.ent' directive, so we would like to discourage
3868 // its use. We do this by not referring to the extended version in
3869 // error messages which are not directly related to its use.
3870 reportParseError("unexpected token, expected end of statement");
3871 return false;
3872 }
3873 Parser.Lex(); // Eat the comma.
3874 const MCExpr *DummyNumber;
3875 int64_t DummyNumberVal;
3876 // If the user was explicitly trying to use the extended version,
3877 // we still give helpful extension-related error messages.
3878 if (Parser.parseExpression(DummyNumber)) {
3879 reportParseError("expected number after comma");
3880 return false;
3881 }
3882 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3883 reportParseError("expected an absolute expression after comma");
3884 return false;
3885 }
3886 }
3887
3888 // If this is not the end of the statement, report an error.
3889 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3890 reportParseError("unexpected token, expected end of statement");
3891 return false;
3892 }
3893
3894 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3895
3896 getTargetStreamer().emitDirectiveEnt(*Sym);
3897 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003898 return false;
3899 }
3900
Jack Carter07c818d2013-01-25 01:31:34 +00003901 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003902 StringRef SymbolName;
3903
3904 if (Parser.parseIdentifier(SymbolName)) {
3905 reportParseError("expected identifier after .end");
3906 return false;
3907 }
3908
3909 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3910 reportParseError("unexpected token, expected end of statement");
3911 return false;
3912 }
3913
3914 if (CurrentFn == nullptr) {
3915 reportParseError(".end used without .ent");
3916 return false;
3917 }
3918
3919 if ((SymbolName != CurrentFn->getName())) {
3920 reportParseError(".end symbol does not match .ent symbol");
3921 return false;
3922 }
3923
3924 getTargetStreamer().emitDirectiveEnd(SymbolName);
3925 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003926 return false;
3927 }
3928
Jack Carter07c818d2013-01-25 01:31:34 +00003929 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003930 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3931 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003932 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003933 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3934 reportParseError("expected stack register");
3935 return false;
3936 }
3937
3938 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3939 if (!StackRegOpnd.isGPRAsmReg()) {
3940 reportParseError(StackRegOpnd.getStartLoc(),
3941 "expected general purpose register");
3942 return false;
3943 }
3944 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3945
3946 if (Parser.getTok().is(AsmToken::Comma))
3947 Parser.Lex();
3948 else {
3949 reportParseError("unexpected token, expected comma");
3950 return false;
3951 }
3952
3953 // Parse the frame size.
3954 const MCExpr *FrameSize;
3955 int64_t FrameSizeVal;
3956
3957 if (Parser.parseExpression(FrameSize)) {
3958 reportParseError("expected frame size value");
3959 return false;
3960 }
3961
3962 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3963 reportParseError("frame size not an absolute expression");
3964 return false;
3965 }
3966
3967 if (Parser.getTok().is(AsmToken::Comma))
3968 Parser.Lex();
3969 else {
3970 reportParseError("unexpected token, expected comma");
3971 return false;
3972 }
3973
3974 // Parse the return register.
3975 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003976 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003977 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3978 reportParseError("expected return register");
3979 return false;
3980 }
3981
3982 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3983 if (!ReturnRegOpnd.isGPRAsmReg()) {
3984 reportParseError(ReturnRegOpnd.getStartLoc(),
3985 "expected general purpose register");
3986 return false;
3987 }
3988
3989 // If this is not the end of the statement, report an error.
3990 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3991 reportParseError("unexpected token, expected end of statement");
3992 return false;
3993 }
3994
3995 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3996 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003997 return false;
3998 }
3999
Jack Carter07c818d2013-01-25 01:31:34 +00004000 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004001 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004002 }
4003
Daniel Sandersd97a6342014-08-13 10:07:34 +00004004 if (IDVal == ".mask" || IDVal == ".fmask") {
4005 // .mask bitmask, frame_offset
4006 // bitmask: One bit for each register used.
4007 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4008 // first register is expected to be saved.
4009 // Examples:
4010 // .mask 0x80000000, -4
4011 // .fmask 0x80000000, -4
4012 //
Jack Carterbe332172012-09-07 00:48:02 +00004013
Daniel Sandersd97a6342014-08-13 10:07:34 +00004014 // Parse the bitmask
4015 const MCExpr *BitMask;
4016 int64_t BitMaskVal;
4017
4018 if (Parser.parseExpression(BitMask)) {
4019 reportParseError("expected bitmask value");
4020 return false;
4021 }
4022
4023 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4024 reportParseError("bitmask not an absolute expression");
4025 return false;
4026 }
4027
4028 if (Parser.getTok().is(AsmToken::Comma))
4029 Parser.Lex();
4030 else {
4031 reportParseError("unexpected token, expected comma");
4032 return false;
4033 }
4034
4035 // Parse the frame_offset
4036 const MCExpr *FrameOffset;
4037 int64_t FrameOffsetVal;
4038
4039 if (Parser.parseExpression(FrameOffset)) {
4040 reportParseError("expected frame offset value");
4041 return false;
4042 }
4043
4044 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4045 reportParseError("frame offset not an absolute expression");
4046 return false;
4047 }
4048
4049 // If this is not the end of the statement, report an error.
4050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4051 reportParseError("unexpected token, expected end of statement");
4052 return false;
4053 }
4054
4055 if (IDVal == ".mask")
4056 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4057 else
4058 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004059 return false;
4060 }
4061
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004062 if (IDVal == ".nan")
4063 return parseDirectiveNaN();
4064
Jack Carter07c818d2013-01-25 01:31:34 +00004065 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004066 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004067 return false;
4068 }
4069
Rafael Espindolab59fb732014-03-28 18:50:26 +00004070 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004071 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004072 return false;
4073 }
4074
Jack Carter07c818d2013-01-25 01:31:34 +00004075 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004076 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004077 return false;
4078 }
4079
Jack Carter0cd3c192014-01-06 23:27:31 +00004080 if (IDVal == ".option")
4081 return parseDirectiveOption();
4082
4083 if (IDVal == ".abicalls") {
4084 getTargetStreamer().emitDirectiveAbiCalls();
4085 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004086 Error(Parser.getTok().getLoc(),
4087 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004088 // Clear line
4089 Parser.eatToEndOfStatement();
4090 }
4091 return false;
4092 }
4093
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004094 if (IDVal == ".cpsetup")
4095 return parseDirectiveCPSetup();
4096
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004097 if (IDVal == ".module")
4098 return parseDirectiveModule();
4099
Rafael Espindola870c4e92012-01-11 03:56:41 +00004100 return true;
4101}
4102
Rafael Espindola870c4e92012-01-11 03:56:41 +00004103extern "C" void LLVMInitializeMipsAsmParser() {
4104 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4105 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4106 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4107 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4108}
Jack Carterb4dbc172012-09-05 23:34:03 +00004109
4110#define GET_REGISTER_MATCHER
4111#define GET_MATCHER_IMPLEMENTATION
4112#include "MipsGenAsmMatcher.inc"