blob: ade5e7b26a95f3658a8326c0c878a6ea14669f94 [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
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000015#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000016#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000017#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000020#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCParser/MCAsmLexer.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000026#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000027#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000028#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000029#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000030#include "llvm/Support/TargetRegistry.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000031#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000032
33using namespace llvm;
34
Chandler Carruthe96dd892014-04-21 22:55:11 +000035#define DEBUG_TYPE "mips-asm-parser"
36
Joey Gouly0e76fa72013-09-12 10:28:05 +000037namespace llvm {
38class MCInstrInfo;
39}
40
Rafael Espindola870c4e92012-01-11 03:56:41 +000041namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000042class MipsAssemblerOptions {
43public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000044 MipsAssemblerOptions(uint64_t Features_) :
45 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000046
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48 ATReg = Opts->getATRegNum();
49 Reorder = Opts->isReorder();
50 Macro = Opts->isMacro();
51 Features = Opts->getFeatures();
52 }
53
54 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000055 bool setATReg(unsigned Reg);
56
Toma Tabacu9db22db2014-09-09 10:15:38 +000057 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000058 void setReorder() { Reorder = true; }
59 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000060
Toma Tabacu9db22db2014-09-09 10:15:38 +000061 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000062 void setMacro() { Macro = true; }
63 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 uint64_t getFeatures() const { return Features; }
66 void setFeatures(uint64_t Features_) { Features = Features_; }
67
Daniel Sandersf0df2212014-08-04 12:20:00 +000068 // Set of features that are either architecture features or referenced
69 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71 // The reason we need this mask is explained in the selectArch function.
72 // FIXME: Ideally we would like TableGen to generate this information.
73 static const uint64_t AllArchRelatedMask =
74 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81
Jack Carter0b744b32012-10-04 02:29:46 +000082private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000083 unsigned ATReg;
84 bool Reorder;
85 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000086 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000087};
88}
89
90namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000091class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000092 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000093 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 return static_cast<MipsTargetStreamer &>(TS);
95 }
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 MCSubtargetInfo &STI;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Daniel Sandersef638fe2014-10-03 15:37:37 +0000104 // Print a warning along with its fix-it message at the given range.
105 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
106 SMRange Range, bool ShowColors = true);
107
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000108#define GET_ASSEMBLER_HEADER
109#include "MipsGenAsmMatcher.inc"
110
Matheus Almeida595fcab2014-06-11 15:05:56 +0000111 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
112
Chad Rosier49963552012-10-13 00:26:04 +0000113 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000114 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000115 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000116 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000117
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Toma Tabacu13964452014-09-04 13:23:44 +0000121 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
David Blaikie960ea3f2014-06-08 16:18:35 +0000125 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
126 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Craig Topper56c590a2014-04-29 07:58:02 +0000128 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000135
Jack Carter873c7242013-01-12 01:03:14 +0000136 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000137 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000149 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000150 parseRegisterPair (OperandVector &Operands);
151
152 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000153 parseRegisterList (OperandVector &Operands);
154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 bool searchSymbolAlias(OperandVector &Operands);
156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000158
Jack Carter30a59822012-10-04 04:03:53 +0000159 bool needsExpansion(MCInst &Inst);
160
Matheus Almeida3813d572014-06-19 14:39:14 +0000161 // Expands assembly pseudo instructions.
162 // Returns false on success, true otherwise.
163 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000164 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000165
166 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000167 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000168
169 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
172 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000173 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000174 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
175 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000176
Toma Tabacu0d64b202014-08-14 10:29:17 +0000177 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
179
Jack Carter9e65aa32013-03-22 00:05:30 +0000180 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000181 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
182 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000183 bool reportParseError(Twine ErrorMsg);
184 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000185
Jack Carterb5cf5902013-04-17 00:18:04 +0000186 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000187 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000188
Vladimir Medic4c299852013-11-06 11:27:05 +0000189 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000190
191 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000192 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000193 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000194 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000195 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000196 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000197 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000198 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000199 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000200
201 bool parseSetAtDirective();
202 bool parseSetNoAtDirective();
203 bool parseSetMacroDirective();
204 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000205 bool parseSetMsaDirective();
206 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000207 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000208 bool parseSetReorderDirective();
209 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000210 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000211 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000212 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000213 bool parseSetPopDirective();
214 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000215
Jack Carterd76b2372013-03-21 21:44:16 +0000216 bool parseSetAssignment();
217
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000218 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000219 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000220 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000221 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000222 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000223 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
224 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000225
Jack Carterdc1e35d2012-09-06 20:00:02 +0000226 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000227
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000228 bool eatComma(StringRef ErrorStr);
229
Jack Carter1ac53222013-02-20 23:11:17 +0000230 int matchCPURegisterName(StringRef Symbol);
231
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000232 int matchHWRegsRegisterName(StringRef Symbol);
233
Jack Carter873c7242013-01-12 01:03:14 +0000234 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000235
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000236 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000237
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000238 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000239
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000240 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000241
Jack Carter5dc8ac92013-09-25 23:50:44 +0000242 int matchMSA128RegisterName(StringRef Name);
243
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000244 int matchMSA128CtrlRegisterName(StringRef Name);
245
Jack Carterd0bd6422013-04-18 00:41:53 +0000246 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000247
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000248 unsigned getGPR(int RegNo);
249
Matheus Almeida7de68e72014-06-18 14:46:05 +0000250 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000251
252 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000253 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000254
255 // Helper function that checks if the value of a vector index is within the
256 // boundaries of accepted values for each RegisterKind
257 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
258 bool validateMSAIndex(int Val, int RegKind);
259
Daniel Sandersf0df2212014-08-04 12:20:00 +0000260 // Selects a new architecture by updating the FeatureBits with the necessary
261 // info including implied dependencies.
262 // Internally, it clears all the feature bits related to *any* architecture
263 // and selects the new one using the ToggleFeature functionality of the
264 // MCSubtargetInfo object that handles implied dependencies. The reason we
265 // clear all the arch related bits manually is because ToggleFeature only
266 // clears the features that imply the feature being cleared and not the
267 // features implied by the feature being cleared. This is easier to see
268 // with an example:
269 // --------------------------------------------------
270 // | Feature | Implies |
271 // | -------------------------------------------------|
272 // | FeatureMips1 | None |
273 // | FeatureMips2 | FeatureMips1 |
274 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
275 // | FeatureMips4 | FeatureMips3 |
276 // | ... | |
277 // --------------------------------------------------
278 //
279 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
280 // FeatureMipsGP64 | FeatureMips1)
281 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
282 void selectArch(StringRef ArchFeature) {
283 uint64_t FeatureBits = STI.getFeatureBits();
284 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
285 STI.setFeatureBits(FeatureBits);
286 setAvailableFeatures(
287 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000288 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000289 }
290
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000291 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000292 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000293 setAvailableFeatures(
294 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000296 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000297 }
298
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000299 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000300 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000301 setAvailableFeatures(
302 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000303 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000304 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000305 }
306
Rafael Espindola870c4e92012-01-11 03:56:41 +0000307public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000308 enum MipsMatchResultTy {
309 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
310#define GET_OPERAND_DIAGNOSTIC_TYPES
311#include "MipsGenAsmMatcher.inc"
312#undef GET_OPERAND_DIAGNOSTIC_TYPES
313
314 };
315
Joey Gouly0e76fa72013-09-12 10:28:05 +0000316 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000317 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000318 : MCTargetAsmParser(), STI(sti) {
319 MCAsmParserExtension::Initialize(parser);
320
Jack Carterb4dbc172012-09-05 23:34:03 +0000321 // Initialize the set of available features.
322 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000323
324 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000325 AssemblerOptions.push_back(
326 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000327
328 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000329 AssemblerOptions.push_back(
330 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000331
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000332 getTargetStreamer().updateABIInfo(*this);
333
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000334 // Assert exactly one ABI was chosen.
335 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
336 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
337 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
338 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000339
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000340 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000341 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000342
343 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000344 }
345
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000346 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
347 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
348
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000349 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
350 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
351 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
352 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
353 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000354 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000355
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000356 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000357 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
358 }
359
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000360 bool inMicroMipsMode() const {
361 return STI.getFeatureBits() & Mips::FeatureMicroMips;
362 }
363 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
364 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
365 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
366 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
367 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
368 bool hasMips32() const {
369 return (STI.getFeatureBits() & Mips::FeatureMips32);
370 }
371 bool hasMips64() const {
372 return (STI.getFeatureBits() & Mips::FeatureMips64);
373 }
374 bool hasMips32r2() const {
375 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
376 }
377 bool hasMips64r2() const {
378 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
379 }
380 bool hasMips32r6() const {
381 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
382 }
383 bool hasMips64r6() const {
384 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
385 }
386 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
387 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
388 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
389
390 bool inMips16Mode() const {
391 return STI.getFeatureBits() & Mips::FeatureMips16;
392 }
393 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000394 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000396 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000397 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000398};
399}
400
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000401namespace {
402
403/// MipsOperand - Instances of this class represent a parsed Mips machine
404/// instruction.
405class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000406public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000407 /// Broad categories of register classes
408 /// The exact class is finalized by the render method.
409 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000411 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000413 RegKind_FCC = 4, /// FCC
414 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
415 RegKind_MSACtrl = 16, /// MSA control registers
416 RegKind_COP2 = 32, /// COP2
417 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
418 /// context).
419 RegKind_CCR = 128, /// CCR
420 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000421 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000422
423 /// Potentially any (e.g. $1)
424 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
425 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000426 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000427 };
428
429private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000430 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000431 k_Immediate, /// An immediate (possibly involving symbol references)
432 k_Memory, /// Base + Offset Memory Address
433 k_PhysRegister, /// A physical register from the Mips namespace
434 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000435 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000436 k_RegList, /// A physical register list
437 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000438 } Kind;
439
David Blaikie960ea3f2014-06-08 16:18:35 +0000440public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000441 MipsOperand(KindTy K, MipsAsmParser &Parser)
442 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
443
David Blaikie960ea3f2014-06-08 16:18:35 +0000444private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000445 /// For diagnostics, and checking the assembler temporary
446 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000447
Eric Christopher8996c5d2013-03-15 00:42:55 +0000448 struct Token {
449 const char *Data;
450 unsigned Length;
451 };
452
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000453 struct PhysRegOp {
454 unsigned Num; /// Register Number
455 };
456
457 struct RegIdxOp {
458 unsigned Index; /// Index into the register class
459 RegKind Kind; /// Bitfield of the kinds it could possibly be
460 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000461 };
462
463 struct ImmOp {
464 const MCExpr *Val;
465 };
466
467 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000468 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000469 const MCExpr *Off;
470 };
471
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000472 struct RegListOp {
473 SmallVector<unsigned, 10> *List;
474 };
475
Jack Carterb4dbc172012-09-05 23:34:03 +0000476 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000477 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000478 struct PhysRegOp PhysReg;
479 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000480 struct ImmOp Imm;
481 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000482 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000483 };
484
485 SMLoc StartLoc, EndLoc;
486
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000487 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000488 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
489 const MCRegisterInfo *RegInfo,
490 SMLoc S, SMLoc E,
491 MipsAsmParser &Parser) {
492 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000493 Op->RegIdx.Index = Index;
494 Op->RegIdx.RegInfo = RegInfo;
495 Op->RegIdx.Kind = RegKind;
496 Op->StartLoc = S;
497 Op->EndLoc = E;
498 return Op;
499 }
500
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000501public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000502 /// Coerce the register to GPR32 and return the real register for the current
503 /// target.
504 unsigned getGPR32Reg() const {
505 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000506 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000507 unsigned ClassID = Mips::GPR32RegClassID;
508 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000509 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000510
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000511 /// Coerce the register to GPR32 and return the real register for the current
512 /// target.
513 unsigned getGPRMM16Reg() const {
514 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
515 unsigned ClassID = Mips::GPR32RegClassID;
516 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
517 }
518
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000519 /// Coerce the register to GPR64 and return the real register for the current
520 /// target.
521 unsigned getGPR64Reg() const {
522 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
523 unsigned ClassID = Mips::GPR64RegClassID;
524 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000525 }
526
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527private:
528 /// Coerce the register to AFGR64 and return the real register for the current
529 /// target.
530 unsigned getAFGR64Reg() const {
531 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
532 if (RegIdx.Index % 2 != 0)
533 AsmParser.Warning(StartLoc, "Float register should be even.");
534 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
535 .getRegister(RegIdx.Index / 2);
536 }
537
538 /// Coerce the register to FGR64 and return the real register for the current
539 /// target.
540 unsigned getFGR64Reg() const {
541 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
542 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
543 .getRegister(RegIdx.Index);
544 }
545
546 /// Coerce the register to FGR32 and return the real register for the current
547 /// target.
548 unsigned getFGR32Reg() const {
549 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
550 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
551 .getRegister(RegIdx.Index);
552 }
553
554 /// Coerce the register to FGRH32 and return the real register for the current
555 /// target.
556 unsigned getFGRH32Reg() const {
557 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
558 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
559 .getRegister(RegIdx.Index);
560 }
561
562 /// Coerce the register to FCC and return the real register for the current
563 /// target.
564 unsigned getFCCReg() const {
565 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
566 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
567 .getRegister(RegIdx.Index);
568 }
569
570 /// Coerce the register to MSA128 and return the real register for the current
571 /// target.
572 unsigned getMSA128Reg() const {
573 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
574 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
575 // identical
576 unsigned ClassID = Mips::MSA128BRegClassID;
577 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
578 }
579
580 /// Coerce the register to MSACtrl and return the real register for the
581 /// current target.
582 unsigned getMSACtrlReg() const {
583 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
584 unsigned ClassID = Mips::MSACtrlRegClassID;
585 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
586 }
587
588 /// Coerce the register to COP2 and return the real register for the
589 /// current target.
590 unsigned getCOP2Reg() const {
591 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
592 unsigned ClassID = Mips::COP2RegClassID;
593 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
594 }
595
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000596 /// Coerce the register to COP3 and return the real register for the
597 /// current target.
598 unsigned getCOP3Reg() const {
599 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
600 unsigned ClassID = Mips::COP3RegClassID;
601 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
602 }
603
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 /// Coerce the register to ACC64DSP and return the real register for the
605 /// current target.
606 unsigned getACC64DSPReg() const {
607 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
608 unsigned ClassID = Mips::ACC64DSPRegClassID;
609 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
610 }
611
612 /// Coerce the register to HI32DSP and return the real register for the
613 /// current target.
614 unsigned getHI32DSPReg() const {
615 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
616 unsigned ClassID = Mips::HI32DSPRegClassID;
617 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
618 }
619
620 /// Coerce the register to LO32DSP and return the real register for the
621 /// current target.
622 unsigned getLO32DSPReg() const {
623 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
624 unsigned ClassID = Mips::LO32DSPRegClassID;
625 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
626 }
627
628 /// Coerce the register to CCR and return the real register for the
629 /// current target.
630 unsigned getCCRReg() const {
631 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
632 unsigned ClassID = Mips::CCRRegClassID;
633 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
634 }
635
636 /// Coerce the register to HWRegs and return the real register for the
637 /// current target.
638 unsigned getHWRegsReg() const {
639 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
640 unsigned ClassID = Mips::HWRegsRegClassID;
641 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
642 }
643
644public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000645 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000647 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000648 Inst.addOperand(MCOperand::CreateImm(0));
649 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
650 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
651 else
652 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000653 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000654
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000655 void addRegOperands(MCInst &Inst, unsigned N) const {
656 llvm_unreachable("Use a custom parser instead");
657 }
658
Daniel Sanders21bce302014-04-01 12:35:23 +0000659 /// Render the operand to an MCInst as a GPR32
660 /// Asserts if the wrong number of operands are requested, or the operand
661 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000662 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
663 assert(N == 1 && "Invalid number of operands!");
664 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
665 }
666
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000667 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
668 assert(N == 1 && "Invalid number of operands!");
669 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
670 }
671
Jozef Kolek1904fa22014-11-24 14:25:53 +0000672 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
673 assert(N == 1 && "Invalid number of operands!");
674 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
675 }
676
Daniel Sanders21bce302014-04-01 12:35:23 +0000677 /// Render the operand to an MCInst as a GPR64
678 /// Asserts if the wrong number of operands are requested, or the operand
679 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000680 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
681 assert(N == 1 && "Invalid number of operands!");
682 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
683 }
684
685 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
686 assert(N == 1 && "Invalid number of operands!");
687 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
688 }
689
690 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
691 assert(N == 1 && "Invalid number of operands!");
692 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
693 }
694
695 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
696 assert(N == 1 && "Invalid number of operands!");
697 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000698 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000699 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000700 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
701 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000702 }
703
704 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
705 assert(N == 1 && "Invalid number of operands!");
706 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
707 }
708
709 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
710 assert(N == 1 && "Invalid number of operands!");
711 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
712 }
713
714 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
715 assert(N == 1 && "Invalid number of operands!");
716 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
717 }
718
719 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
720 assert(N == 1 && "Invalid number of operands!");
721 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
722 }
723
724 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
725 assert(N == 1 && "Invalid number of operands!");
726 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
727 }
728
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000729 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
730 assert(N == 1 && "Invalid number of operands!");
731 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
732 }
733
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
735 assert(N == 1 && "Invalid number of operands!");
736 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
737 }
738
739 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
740 assert(N == 1 && "Invalid number of operands!");
741 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
742 }
743
744 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
746 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
747 }
748
749 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
750 assert(N == 1 && "Invalid number of operands!");
751 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
752 }
753
754 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
755 assert(N == 1 && "Invalid number of operands!");
756 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
757 }
758
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000760 assert(N == 1 && "Invalid number of operands!");
761 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000762 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000763 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000764
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000765 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000766 assert(N == 2 && "Invalid number of operands!");
767
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000769
770 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000771 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000772 }
773
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000774 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
775 assert(N == 2 && "Invalid number of operands!");
776
777 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
778
779 const MCExpr *Expr = getMemOff();
780 addExpr(Inst, Expr);
781 }
782
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000783 void addRegListOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
785
786 for (auto RegNo : getRegList())
787 Inst.addOperand(MCOperand::CreateReg(RegNo));
788 }
789
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000790 void addRegPairOperands(MCInst &Inst, unsigned N) const {
791 assert(N == 2 && "Invalid number of operands!");
792 unsigned RegNo = getRegPair();
793 Inst.addOperand(MCOperand::CreateReg(RegNo++));
794 Inst.addOperand(MCOperand::CreateReg(RegNo));
795 }
796
Craig Topper56c590a2014-04-29 07:58:02 +0000797 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 // As a special case until we sort out the definition of div/divu, pretend
799 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
800 if (isGPRAsmReg() && RegIdx.Index == 0)
801 return true;
802
803 return Kind == k_PhysRegister;
804 }
805 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000806 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 bool isConstantImm() const {
808 return isImm() && dyn_cast<MCConstantExpr>(getImm());
809 }
Craig Topper56c590a2014-04-29 07:58:02 +0000810 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 // Note: It's not possible to pretend that other operand kinds are tokens.
812 // The matcher emitter checks tokens first.
813 return Kind == k_Token;
814 }
Craig Topper56c590a2014-04-29 07:58:02 +0000815 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000816 bool isConstantMemOff() const {
817 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
818 }
819 template <unsigned Bits> bool isMemWithSimmOffset() const {
820 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
821 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000822 bool isMemWithGRPMM16Base() const {
823 return isMem() && getMemBase()->isMM16AsmReg();
824 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000825 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
826 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
827 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
828 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000829 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
830 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
831 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
832 && (getMemBase()->getGPR32Reg() == Mips::SP);
833 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000834 bool isRegList16() const {
835 if (!isRegList())
836 return false;
837
838 int Size = RegList.List->size();
839 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
840 RegList.List->back() != Mips::RA)
841 return false;
842
843 int PrevReg = *RegList.List->begin();
844 for (int i = 1; i < Size - 1; i++) {
845 int Reg = (*(RegList.List))[i];
846 if ( Reg != PrevReg + 1)
847 return false;
848 PrevReg = Reg;
849 }
850
851 return true;
852 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000853 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 bool isLSAImm() const {
855 if (!isConstantImm())
856 return false;
857 int64_t Val = getConstantImm();
858 return 1 <= Val && Val <= 4;
859 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000860 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000861
862 StringRef getToken() const {
863 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000864 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000865 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000866 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000867
Craig Topper56c590a2014-04-29 07:58:02 +0000868 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 // As a special case until we sort out the definition of div/divu, pretend
870 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
871 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
872 RegIdx.Kind & RegKind_GPR)
873 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000874
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 assert(Kind == k_PhysRegister && "Invalid access!");
876 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000877 }
878
Jack Carterb4dbc172012-09-05 23:34:03 +0000879 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000881 return Imm.Val;
882 }
883
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000884 int64_t getConstantImm() const {
885 const MCExpr *Val = getImm();
886 return static_cast<const MCConstantExpr *>(Val)->getValue();
887 }
888
889 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000890 assert((Kind == k_Memory) && "Invalid access!");
891 return Mem.Base;
892 }
893
894 const MCExpr *getMemOff() const {
895 assert((Kind == k_Memory) && "Invalid access!");
896 return Mem.Off;
897 }
898
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000899 int64_t getConstantMemOff() const {
900 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
901 }
902
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000903 const SmallVectorImpl<unsigned> &getRegList() const {
904 assert((Kind == k_RegList) && "Invalid access!");
905 return *(RegList.List);
906 }
907
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000908 unsigned getRegPair() const {
909 assert((Kind == k_RegPair) && "Invalid access!");
910 return RegIdx.Index;
911 }
912
David Blaikie960ea3f2014-06-08 16:18:35 +0000913 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
914 MipsAsmParser &Parser) {
915 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000916 Op->Tok.Data = Str.data();
917 Op->Tok.Length = Str.size();
918 Op->StartLoc = S;
919 Op->EndLoc = S;
920 return Op;
921 }
922
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 /// Create a numeric register (e.g. $1). The exact register remains
924 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000925 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000926 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000927 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000928 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000930 }
931
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 /// Create a register that is definitely a GPR.
933 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000934 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000935 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000936 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000937 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000938 }
939
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000940 /// Create a register that is definitely a FGR.
941 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000942 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000943 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000944 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000945 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
946 }
947
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000948 /// Create a register that is definitely a HWReg.
949 /// This is typically only used for named registers such as $hwr_cpunum.
950 static std::unique_ptr<MipsOperand>
951 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
952 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
953 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
954 }
955
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 /// Create a register that is definitely an FCC.
957 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000958 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000959 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000960 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000961 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
962 }
963
964 /// Create a register that is definitely an ACC.
965 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000966 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000967 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000968 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
970 }
971
972 /// Create a register that is definitely an MSA128.
973 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000974 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000975 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000976 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000977 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
978 }
979
980 /// Create a register that is definitely an MSACtrl.
981 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000982 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000983 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000984 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000985 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
986 }
987
David Blaikie960ea3f2014-06-08 16:18:35 +0000988 static std::unique_ptr<MipsOperand>
989 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
990 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000991 Op->Imm.Val = Val;
992 Op->StartLoc = S;
993 Op->EndLoc = E;
994 return Op;
995 }
996
David Blaikie960ea3f2014-06-08 16:18:35 +0000997 static std::unique_ptr<MipsOperand>
998 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
999 SMLoc E, MipsAsmParser &Parser) {
1000 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1001 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001002 Op->Mem.Off = Off;
1003 Op->StartLoc = S;
1004 Op->EndLoc = E;
1005 return Op;
1006 }
1007
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001008 static std::unique_ptr<MipsOperand>
1009 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1010 MipsAsmParser &Parser) {
1011 assert (Regs.size() > 0 && "Empty list not allowed");
1012
1013 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1014 Op->RegList.List = new SmallVector<unsigned, 10>();
1015 for (auto Reg : Regs)
1016 Op->RegList.List->push_back(Reg);
1017 Op->StartLoc = StartLoc;
1018 Op->EndLoc = EndLoc;
1019 return Op;
1020 }
1021
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001022 static std::unique_ptr<MipsOperand>
1023 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1024 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1025 Op->RegIdx.Index = RegNo;
1026 Op->StartLoc = S;
1027 Op->EndLoc = E;
1028 return Op;
1029 }
1030
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 bool isGPRAsmReg() const {
1032 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001033 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001034 bool isMM16AsmReg() const {
1035 if (!(isRegIdx() && RegIdx.Kind))
1036 return false;
1037 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1038 || RegIdx.Index == 16 || RegIdx.Index == 17);
1039 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001040 bool isMM16AsmRegZero() const {
1041 if (!(isRegIdx() && RegIdx.Kind))
1042 return false;
1043 return (RegIdx.Index == 0 ||
1044 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1045 RegIdx.Index == 17);
1046 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 bool isFGRAsmReg() const {
1048 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1049 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001050 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001051 bool isHWRegsAsmReg() const {
1052 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001053 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001054 bool isCCRAsmReg() const {
1055 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001056 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001058 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1059 return false;
1060 if (!AsmParser.hasEightFccRegisters())
1061 return RegIdx.Index == 0;
1062 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001063 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 bool isACCAsmReg() const {
1065 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001066 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001067 bool isCOP2AsmReg() const {
1068 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001069 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001070 bool isCOP3AsmReg() const {
1071 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1072 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 bool isMSA128AsmReg() const {
1074 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001075 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001076 bool isMSACtrlAsmReg() const {
1077 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001078 }
1079
Jack Carterb4dbc172012-09-05 23:34:03 +00001080 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001081 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001082 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001083 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001084
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001085 virtual ~MipsOperand() {
1086 switch (Kind) {
1087 case k_Immediate:
1088 break;
1089 case k_Memory:
1090 delete Mem.Base;
1091 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001092 case k_RegList:
1093 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001094 case k_PhysRegister:
1095 case k_RegisterIndex:
1096 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001097 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001098 break;
1099 }
1100 }
1101
Craig Topper56c590a2014-04-29 07:58:02 +00001102 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 switch (Kind) {
1104 case k_Immediate:
1105 OS << "Imm<";
1106 Imm.Val->print(OS);
1107 OS << ">";
1108 break;
1109 case k_Memory:
1110 OS << "Mem<";
1111 Mem.Base->print(OS);
1112 OS << ", ";
1113 Mem.Off->print(OS);
1114 OS << ">";
1115 break;
1116 case k_PhysRegister:
1117 OS << "PhysReg<" << PhysReg.Num << ">";
1118 break;
1119 case k_RegisterIndex:
1120 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1121 break;
1122 case k_Token:
1123 OS << Tok.Data;
1124 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001125 case k_RegList:
1126 OS << "RegList< ";
1127 for (auto Reg : (*RegList.List))
1128 OS << Reg << " ";
1129 OS << ">";
1130 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001131 case k_RegPair:
1132 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1133 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001135 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001136}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001137} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001138
Jack Carter9e65aa32013-03-22 00:05:30 +00001139namespace llvm {
1140extern const MCInstrDesc MipsInsts[];
1141}
1142static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1143 return MipsInsts[Opcode];
1144}
1145
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001146static bool hasShortDelaySlot(unsigned Opcode) {
1147 switch (Opcode) {
1148 case Mips::JALS_MM:
1149 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001150 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001151 case Mips::BGEZALS_MM:
1152 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001153 return true;
1154 default:
1155 return false;
1156 }
1157}
1158
Jack Carter9e65aa32013-03-22 00:05:30 +00001159bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001160 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001161 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001162
Jack Carter9e65aa32013-03-22 00:05:30 +00001163 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001164
1165 if (MCID.isBranch() || MCID.isCall()) {
1166 const unsigned Opcode = Inst.getOpcode();
1167 MCOperand Offset;
1168
1169 switch (Opcode) {
1170 default:
1171 break;
1172 case Mips::BEQ:
1173 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001174 case Mips::BEQ_MM:
1175 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001176 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001177 Offset = Inst.getOperand(2);
1178 if (!Offset.isImm())
1179 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001180 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001181 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001182 if (OffsetToAlignment(Offset.getImm(),
1183 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001184 return Error(IDLoc, "branch to misaligned address");
1185 break;
1186 case Mips::BGEZ:
1187 case Mips::BGTZ:
1188 case Mips::BLEZ:
1189 case Mips::BLTZ:
1190 case Mips::BGEZAL:
1191 case Mips::BLTZAL:
1192 case Mips::BC1F:
1193 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001194 case Mips::BGEZ_MM:
1195 case Mips::BGTZ_MM:
1196 case Mips::BLEZ_MM:
1197 case Mips::BLTZ_MM:
1198 case Mips::BGEZAL_MM:
1199 case Mips::BLTZAL_MM:
1200 case Mips::BC1F_MM:
1201 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001202 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001203 Offset = Inst.getOperand(1);
1204 if (!Offset.isImm())
1205 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001206 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001207 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001208 if (OffsetToAlignment(Offset.getImm(),
1209 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001210 return Error(IDLoc, "branch to misaligned address");
1211 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001212 case Mips::BEQZ16_MM:
1213 case Mips::BNEZ16_MM:
1214 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1215 Offset = Inst.getOperand(1);
1216 if (!Offset.isImm())
1217 break; // We'll deal with this situation later on when applying fixups.
1218 if (!isIntN(8, Offset.getImm()))
1219 return Error(IDLoc, "branch target out of range");
1220 if (OffsetToAlignment(Offset.getImm(), 2LL))
1221 return Error(IDLoc, "branch to misaligned address");
1222 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001223 }
1224 }
1225
Daniel Sandersa84989a2014-06-16 13:25:35 +00001226 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1227 // We still accept it but it is a normal nop.
1228 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1229 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1230 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1231 "nop instruction");
1232 }
1233
Toma Tabacu9db22db2014-09-09 10:15:38 +00001234 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001235 // If this instruction has a delay slot and .set reorder is active,
1236 // emit a NOP after it.
1237 Instructions.push_back(Inst);
1238 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001239 if (hasShortDelaySlot(Inst.getOpcode())) {
1240 NopInst.setOpcode(Mips::MOVE16_MM);
1241 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1242 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1243 } else {
1244 NopInst.setOpcode(Mips::SLL);
1245 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1246 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1247 NopInst.addOperand(MCOperand::CreateImm(0));
1248 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001249 Instructions.push_back(NopInst);
1250 return false;
1251 }
1252
Jack Carter9e65aa32013-03-22 00:05:30 +00001253 if (MCID.mayLoad() || MCID.mayStore()) {
1254 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001255 // reference or immediate we may have to expand instructions.
1256 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001257 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001258 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1259 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001260 MCOperand &Op = Inst.getOperand(i);
1261 if (Op.isImm()) {
1262 int MemOffset = Op.getImm();
1263 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001264 // Offset can't exceed 16bit value.
1265 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001266 return false;
1267 }
1268 } else if (Op.isExpr()) {
1269 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001270 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001271 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001272 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001273 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001274 // Expand symbol.
1275 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001276 return false;
1277 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001278 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001279 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001280 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001281 }
1282 }
1283 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001284 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001285 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001286
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001287 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1288 if (inMicroMipsMode()) {
1289 MCOperand Opnd;
1290 int Imm;
1291
1292 switch (Inst.getOpcode()) {
1293 default:
1294 break;
1295 case Mips::ADDIUS5_MM:
1296 Opnd = Inst.getOperand(2);
1297 if (!Opnd.isImm())
1298 return Error(IDLoc, "expected immediate operand kind");
1299 Imm = Opnd.getImm();
1300 if (Imm < -8 || Imm > 7)
1301 return Error(IDLoc, "immediate operand value out of range");
1302 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001303 case Mips::ADDIUSP_MM:
1304 Opnd = Inst.getOperand(0);
1305 if (!Opnd.isImm())
1306 return Error(IDLoc, "expected immediate operand kind");
1307 Imm = Opnd.getImm();
1308 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1309 Imm % 4 != 0)
1310 return Error(IDLoc, "immediate operand value out of range");
1311 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001312 case Mips::SLL16_MM:
1313 case Mips::SRL16_MM:
1314 Opnd = Inst.getOperand(2);
1315 if (!Opnd.isImm())
1316 return Error(IDLoc, "expected immediate operand kind");
1317 Imm = Opnd.getImm();
1318 if (Imm < 1 || Imm > 8)
1319 return Error(IDLoc, "immediate operand value out of range");
1320 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001321 case Mips::LI16_MM:
1322 Opnd = Inst.getOperand(1);
1323 if (!Opnd.isImm())
1324 return Error(IDLoc, "expected immediate operand kind");
1325 Imm = Opnd.getImm();
1326 if (Imm < -1 || Imm > 126)
1327 return Error(IDLoc, "immediate operand value out of range");
1328 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001329 case Mips::ADDIUR2_MM:
1330 Opnd = Inst.getOperand(2);
1331 if (!Opnd.isImm())
1332 return Error(IDLoc, "expected immediate operand kind");
1333 Imm = Opnd.getImm();
1334 if (!(Imm == 1 || Imm == -1 ||
1335 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1336 return Error(IDLoc, "immediate operand value out of range");
1337 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001338 case Mips::ADDIUR1SP_MM:
1339 Opnd = Inst.getOperand(1);
1340 if (!Opnd.isImm())
1341 return Error(IDLoc, "expected immediate operand kind");
1342 Imm = Opnd.getImm();
1343 if (OffsetToAlignment(Imm, 4LL))
1344 return Error(IDLoc, "misaligned immediate operand value");
1345 if (Imm < 0 || Imm > 255)
1346 return Error(IDLoc, "immediate operand value out of range");
1347 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001348 case Mips::ANDI16_MM:
1349 Opnd = Inst.getOperand(2);
1350 if (!Opnd.isImm())
1351 return Error(IDLoc, "expected immediate operand kind");
1352 Imm = Opnd.getImm();
1353 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1354 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1355 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1356 return Error(IDLoc, "immediate operand value out of range");
1357 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001358 case Mips::LBU16_MM:
1359 Opnd = Inst.getOperand(2);
1360 if (!Opnd.isImm())
1361 return Error(IDLoc, "expected immediate operand kind");
1362 Imm = Opnd.getImm();
1363 if (Imm < -1 || Imm > 14)
1364 return Error(IDLoc, "immediate operand value out of range");
1365 break;
1366 case Mips::SB16_MM:
1367 Opnd = Inst.getOperand(2);
1368 if (!Opnd.isImm())
1369 return Error(IDLoc, "expected immediate operand kind");
1370 Imm = Opnd.getImm();
1371 if (Imm < 0 || Imm > 15)
1372 return Error(IDLoc, "immediate operand value out of range");
1373 break;
1374 case Mips::LHU16_MM:
1375 case Mips::SH16_MM:
1376 Opnd = Inst.getOperand(2);
1377 if (!Opnd.isImm())
1378 return Error(IDLoc, "expected immediate operand kind");
1379 Imm = Opnd.getImm();
1380 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1381 return Error(IDLoc, "immediate operand value out of range");
1382 break;
1383 case Mips::LW16_MM:
1384 case Mips::SW16_MM:
1385 Opnd = Inst.getOperand(2);
1386 if (!Opnd.isImm())
1387 return Error(IDLoc, "expected immediate operand kind");
1388 Imm = Opnd.getImm();
1389 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1390 return Error(IDLoc, "immediate operand value out of range");
1391 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001392 case Mips::CACHE:
1393 case Mips::PREF:
1394 Opnd = Inst.getOperand(2);
1395 if (!Opnd.isImm())
1396 return Error(IDLoc, "expected immediate operand kind");
1397 Imm = Opnd.getImm();
1398 if (!isUInt<5>(Imm))
1399 return Error(IDLoc, "immediate operand value out of range");
1400 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001401 case Mips::ADDIUPC_MM:
1402 MCOperand Opnd = Inst.getOperand(1);
1403 if (!Opnd.isImm())
1404 return Error(IDLoc, "expected immediate operand kind");
1405 int Imm = Opnd.getImm();
1406 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1407 return Error(IDLoc, "immediate operand value out of range");
1408 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001409 }
1410 }
1411
Jack Carter9e65aa32013-03-22 00:05:30 +00001412 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001413 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 else
1415 Instructions.push_back(Inst);
1416
1417 return false;
1418}
1419
Jack Carter30a59822012-10-04 04:03:53 +00001420bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1421
Jack Carterd0bd6422013-04-18 00:41:53 +00001422 switch (Inst.getOpcode()) {
1423 case Mips::LoadImm32Reg:
1424 case Mips::LoadAddr32Imm:
1425 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001426 case Mips::LoadImm64Reg:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001427 case Mips::B_MM_Pseudo:
Jack Carterd0bd6422013-04-18 00:41:53 +00001428 return true;
1429 default:
1430 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001431 }
1432}
Jack Carter92995f12012-10-06 00:53:28 +00001433
Matheus Almeida3813d572014-06-19 14:39:14 +00001434bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001435 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001436 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001437 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001438 case Mips::LoadImm32Reg:
1439 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001440 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001441 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001442 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001443 return true;
1444 }
1445 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001446 case Mips::LoadAddr32Imm:
1447 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1448 case Mips::LoadAddr32Reg:
1449 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001450 case Mips::B_MM_Pseudo:
1451 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001452 }
Jack Carter30a59822012-10-04 04:03:53 +00001453}
Jack Carter92995f12012-10-06 00:53:28 +00001454
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001455namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001456template <bool PerformShift>
1457void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001458 SmallVectorImpl<MCInst> &Instructions) {
1459 MCInst tmpInst;
1460 if (PerformShift) {
1461 tmpInst.setOpcode(Mips::DSLL);
1462 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1463 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1464 tmpInst.addOperand(MCOperand::CreateImm(16));
1465 tmpInst.setLoc(IDLoc);
1466 Instructions.push_back(tmpInst);
1467 tmpInst.clear();
1468 }
1469 tmpInst.setOpcode(Mips::ORi);
1470 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1471 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001472 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001473 tmpInst.setLoc(IDLoc);
1474 Instructions.push_back(tmpInst);
1475}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001476
1477template <int Shift, bool PerformShift>
1478void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1479 SmallVectorImpl<MCInst> &Instructions) {
1480 createShiftOr<PerformShift>(
1481 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1482 IDLoc, Instructions);
1483}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001484}
1485
Matheus Almeida3813d572014-06-19 14:39:14 +00001486bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001487 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001488 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001489 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001490 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001491 const MCOperand &RegOp = Inst.getOperand(0);
1492 assert(RegOp.isReg() && "expected register operand kind");
1493
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001494 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001495 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001496 // FIXME: gas has a special case for values that are 000...1111, which
1497 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 if (0 <= ImmValue && ImmValue <= 65535) {
1499 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001500 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001501 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001502 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001503 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001504 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001505 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001506 } else if (ImmValue < 0 && ImmValue >= -32768) {
1507 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001508 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001509 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001510 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001511 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001512 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001513 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001514 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1515 // For any value of j that is representable as a 32-bit integer, create
1516 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001517 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001518 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001519 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001520 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1521 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001522 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001523 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1524 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001525 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001526 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001527 return true;
1528 }
1529
1530 // <------- lo32 ------>
1531 // <------- hi32 ------>
1532 // <- hi16 -> <- lo16 ->
1533 // _________________________________
1534 // | | | |
1535 // | 16-bytes | 16-bytes | 16-bytes |
1536 // |__________|__________|__________|
1537 //
1538 // For any value of j that is representable as a 48-bit integer, create
1539 // a sequence of:
1540 // li d,j => lui d,hi16(j)
1541 // ori d,d,hi16(lo32(j))
1542 // dsll d,d,16
1543 // ori d,d,lo16(lo32(j))
1544 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001545 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001546 tmpInst.addOperand(
1547 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001548 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001549 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1550 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1551 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001552 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001553 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001554 return true;
1555 }
1556
1557 // <------- hi32 ------> <------- lo32 ------>
1558 // <- hi16 -> <- lo16 ->
1559 // ___________________________________________
1560 // | | | | |
1561 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1562 // |__________|__________|__________|__________|
1563 //
1564 // For any value of j that isn't representable as a 48-bit integer.
1565 // li d,j => lui d,hi16(j)
1566 // ori d,d,lo16(hi32(j))
1567 // dsll d,d,16
1568 // ori d,d,hi16(lo32(j))
1569 // dsll d,d,16
1570 // ori d,d,lo16(lo32(j))
1571 tmpInst.setOpcode(Mips::LUi);
1572 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1573 tmpInst.addOperand(
1574 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1575 Instructions.push_back(tmpInst);
1576 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1577 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1578 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001579 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001580 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001581}
Jack Carter92995f12012-10-06 00:53:28 +00001582
Matheus Almeida3813d572014-06-19 14:39:14 +00001583bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001584MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1585 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001586 MCInst tmpInst;
1587 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001588 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1589 "expected immediate operand kind");
1590 if (!ImmOp.isImm()) {
1591 expandLoadAddressSym(Inst, IDLoc, Instructions);
1592 return false;
1593 }
Jack Carter543fdf82012-10-09 23:29:45 +00001594 const MCOperand &SrcRegOp = Inst.getOperand(1);
1595 assert(SrcRegOp.isReg() && "expected register operand kind");
1596 const MCOperand &DstRegOp = Inst.getOperand(0);
1597 assert(DstRegOp.isReg() && "expected register operand kind");
1598 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001599 if (-32768 <= ImmValue && ImmValue <= 65535) {
1600 // For -32768 <= j <= 65535.
1601 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001602 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001603 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1604 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1605 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1606 Instructions.push_back(tmpInst);
1607 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 // For any other value of j that is representable as a 32-bit integer.
1609 // la d,j(s) => lui d,hi16(j)
1610 // ori d,d,lo16(j)
1611 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001612 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001613 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1614 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1615 Instructions.push_back(tmpInst);
1616 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001617 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001618 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1619 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1620 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1621 Instructions.push_back(tmpInst);
1622 tmpInst.clear();
1623 tmpInst.setOpcode(Mips::ADDu);
1624 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1625 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1626 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1627 Instructions.push_back(tmpInst);
1628 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001629 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001630}
1631
Matheus Almeida3813d572014-06-19 14:39:14 +00001632bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001633MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1634 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001635 MCInst tmpInst;
1636 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001637 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1638 "expected immediate operand kind");
1639 if (!ImmOp.isImm()) {
1640 expandLoadAddressSym(Inst, IDLoc, Instructions);
1641 return false;
1642 }
Jack Carter543fdf82012-10-09 23:29:45 +00001643 const MCOperand &RegOp = Inst.getOperand(0);
1644 assert(RegOp.isReg() && "expected register operand kind");
1645 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 if (-32768 <= ImmValue && ImmValue <= 65535) {
1647 // For -32768 <= j <= 65535.
1648 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001649 tmpInst.setOpcode(Mips::ADDiu);
1650 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001651 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001652 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1653 Instructions.push_back(tmpInst);
1654 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001655 // For any other value of j that is representable as a 32-bit integer.
1656 // la d,j => lui d,hi16(j)
1657 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001658 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001659 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1660 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1661 Instructions.push_back(tmpInst);
1662 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001663 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001664 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1665 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1666 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1667 Instructions.push_back(tmpInst);
1668 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001669 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001670}
1671
Toma Tabacu0d64b202014-08-14 10:29:17 +00001672void
1673MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1674 SmallVectorImpl<MCInst> &Instructions) {
1675 // FIXME: If we do have a valid at register to use, we should generate a
1676 // slightly shorter sequence here.
1677 MCInst tmpInst;
1678 int ExprOperandNo = 1;
1679 // Sometimes the assembly parser will get the immediate expression as
1680 // a $zero + an immediate.
1681 if (Inst.getNumOperands() == 3) {
1682 assert(Inst.getOperand(1).getReg() ==
1683 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1684 ExprOperandNo = 2;
1685 }
1686 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1687 assert(SymOp.isExpr() && "expected symbol operand kind");
1688 const MCOperand &RegOp = Inst.getOperand(0);
1689 unsigned RegNo = RegOp.getReg();
1690 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1691 const MCSymbolRefExpr *HiExpr =
1692 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1693 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1694 const MCSymbolRefExpr *LoExpr =
1695 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1696 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1697 if (isGP64bit()) {
1698 // If it's a 64-bit architecture, expand to:
1699 // la d,sym => lui d,highest(sym)
1700 // ori d,d,higher(sym)
1701 // dsll d,d,16
1702 // ori d,d,hi16(sym)
1703 // dsll d,d,16
1704 // ori d,d,lo16(sym)
1705 const MCSymbolRefExpr *HighestExpr =
1706 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1707 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1708 const MCSymbolRefExpr *HigherExpr =
1709 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1710 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1711
1712 tmpInst.setOpcode(Mips::LUi);
1713 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1714 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1715 Instructions.push_back(tmpInst);
1716
1717 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1718 Instructions);
1719 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1720 Instructions);
1721 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1722 Instructions);
1723 } else {
1724 // Otherwise, expand to:
1725 // la d,sym => lui d,hi16(sym)
1726 // ori d,d,lo16(sym)
1727 tmpInst.setOpcode(Mips::LUi);
1728 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1729 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1730 Instructions.push_back(tmpInst);
1731
1732 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1733 Instructions);
1734 }
1735}
1736
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001737bool MipsAsmParser::
1738expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
1739 SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001740 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1741 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001742
1743 MCOperand Offset = Inst.getOperand(0);
1744 if (Offset.isExpr()) {
1745 Inst.clear();
1746 Inst.setOpcode(Mips::BEQ_MM);
1747 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1748 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1749 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1750 } else {
1751 assert(Offset.isImm() && "expected immediate operand kind");
1752 if (isIntN(11, Offset.getImm())) {
1753 // If offset fits into 11 bits then this instruction becomes microMIPS
1754 // 16-bit unconditional branch instruction.
1755 Inst.setOpcode(Mips::B16_MM);
1756 } else {
1757 if (!isIntN(17, Offset.getImm()))
1758 Error(IDLoc, "branch target out of range");
1759 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1760 Error(IDLoc, "branch to misaligned address");
1761 Inst.clear();
1762 Inst.setOpcode(Mips::BEQ_MM);
1763 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1764 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1765 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1766 }
1767 }
1768 Instructions.push_back(Inst);
1769
1770 if (AssemblerOptions.back()->isReorder()) {
1771 // If .set reorder is active, emit a NOP after the branch instruction.
1772 MCInst NopInst;
1773 NopInst.setOpcode(Mips::MOVE16_MM);
1774 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1775 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1776 Instructions.push_back(NopInst);
1777 }
1778 return false;
1779}
1780
Jack Carter9e65aa32013-03-22 00:05:30 +00001781void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001782 SmallVectorImpl<MCInst> &Instructions,
1783 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001784 const MCSymbolRefExpr *SR;
1785 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001786 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001787 const MCExpr *ExprOffset;
1788 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001789 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001790 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1791 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001792 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001793 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1794 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001795 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001796 if (isImmOpnd) {
1797 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1798 ImmOffset = Inst.getOperand(2).getImm();
1799 LoOffset = ImmOffset & 0x0000ffff;
1800 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001801 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001802 if (LoOffset & 0x8000)
1803 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001805 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001806 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001807 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001808 // These are some of the types of expansions we perform here:
1809 // 1) lw $8, sym => lui $8, %hi(sym)
1810 // lw $8, %lo(sym)($8)
1811 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1812 // add $8, $8, $9
1813 // lw $8, %lo(offset)($9)
1814 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1815 // add $at, $at, $8
1816 // lw $8, %lo(offset)($at)
1817 // 4) sw $8, sym => lui $at, %hi(sym)
1818 // sw $8, %lo(sym)($at)
1819 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1820 // add $at, $at, $8
1821 // sw $8, %lo(offset)($at)
1822 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1823 // ldc1 $f0, %lo(sym)($at)
1824 //
1825 // For load instructions we can use the destination register as a temporary
1826 // if base and dst are different (examples 1 and 2) and if the base register
1827 // is general purpose otherwise we must use $at (example 6) and error if it's
1828 // not available. For stores we must use $at (examples 4 and 5) because we
1829 // must not clobber the source register setting up the offset.
1830 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1831 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1832 unsigned RegClassIDOp0 =
1833 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1834 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1835 (RegClassIDOp0 == Mips::GPR64RegClassID);
1836 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001837 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001838 else {
1839 int AT = getATReg(IDLoc);
1840 // At this point we need AT to perform the expansions and we exit if it is
1841 // not available.
1842 if (!AT)
1843 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001844 TmpRegNum = getReg(
1845 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001846 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001847
Jack Carter9e65aa32013-03-22 00:05:30 +00001848 TempInst.setOpcode(Mips::LUi);
1849 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1850 if (isImmOpnd)
1851 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1852 else {
1853 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001854 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001855 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1856 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1857 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001858 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001859 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001860 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001861 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001862 }
1863 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001864 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001865 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001866 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001867 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001868 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001869 TempInst.setOpcode(Mips::ADDu);
1870 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1871 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1872 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1873 Instructions.push_back(TempInst);
1874 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001875 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001877 TempInst.setOpcode(Inst.getOpcode());
1878 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1879 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1880 if (isImmOpnd)
1881 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1882 else {
1883 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001884 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1885 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1886 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001887 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001888 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001889 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001890 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001891 }
1892 }
1893 Instructions.push_back(TempInst);
1894 TempInst.clear();
1895}
1896
Matheus Almeida595fcab2014-06-11 15:05:56 +00001897unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1898 // As described by the Mips32r2 spec, the registers Rd and Rs for
1899 // jalr.hb must be different.
1900 unsigned Opcode = Inst.getOpcode();
1901
1902 if (Opcode == Mips::JALR_HB &&
1903 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1904 return Match_RequiresDifferentSrcAndDst;
1905
1906 return Match_Success;
1907}
1908
David Blaikie960ea3f2014-06-08 16:18:35 +00001909bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1910 OperandVector &Operands,
1911 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001912 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001913 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001914
Jack Carterb4dbc172012-09-05 23:34:03 +00001915 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001916 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001917 unsigned MatchResult =
1918 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001919
1920 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001921 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001923 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001924 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001925 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001926 return false;
1927 }
1928 case Match_MissingFeature:
1929 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1930 return true;
1931 case Match_InvalidOperand: {
1932 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001933 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001934 if (ErrorInfo >= Operands.size())
1935 return Error(IDLoc, "too few operands for instruction");
1936
David Blaikie960ea3f2014-06-08 16:18:35 +00001937 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001938 if (ErrorLoc == SMLoc())
1939 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001940 }
1941
1942 return Error(ErrorLoc, "invalid operand for instruction");
1943 }
1944 case Match_MnemonicFail:
1945 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001946 case Match_RequiresDifferentSrcAndDst:
1947 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001948 }
Craig Topper589ceee2015-01-03 08:16:34 +00001949
1950 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00001951}
1952
Toma Tabacu13964452014-09-04 13:23:44 +00001953void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001954 if ((RegIndex != 0) &&
1955 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001956 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001957 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001958 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001959 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001960 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001961 }
1962}
1963
Daniel Sandersef638fe2014-10-03 15:37:37 +00001964void
1965MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1966 SMRange Range, bool ShowColors) {
1967 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001968 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001969 ShowColors);
1970}
1971
Jack Carter1ac53222013-02-20 23:11:17 +00001972int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001973 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001974
Vladimir Medic4c299852013-11-06 11:27:05 +00001975 CC = StringSwitch<unsigned>(Name)
1976 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001977 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001978 .Case("a0", 4)
1979 .Case("a1", 5)
1980 .Case("a2", 6)
1981 .Case("a3", 7)
1982 .Case("v0", 2)
1983 .Case("v1", 3)
1984 .Case("s0", 16)
1985 .Case("s1", 17)
1986 .Case("s2", 18)
1987 .Case("s3", 19)
1988 .Case("s4", 20)
1989 .Case("s5", 21)
1990 .Case("s6", 22)
1991 .Case("s7", 23)
1992 .Case("k0", 26)
1993 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001994 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001995 .Case("sp", 29)
1996 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001997 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001998 .Case("ra", 31)
1999 .Case("t0", 8)
2000 .Case("t1", 9)
2001 .Case("t2", 10)
2002 .Case("t3", 11)
2003 .Case("t4", 12)
2004 .Case("t5", 13)
2005 .Case("t6", 14)
2006 .Case("t7", 15)
2007 .Case("t8", 24)
2008 .Case("t9", 25)
2009 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002010
Toma Tabacufda445c2014-09-15 15:33:01 +00002011 if (!(isABI_N32() || isABI_N64()))
2012 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002013
Daniel Sandersef638fe2014-10-03 15:37:37 +00002014 if (12 <= CC && CC <= 15) {
2015 // Name is one of t4-t7
2016 AsmToken RegTok = getLexer().peekTok();
2017 SMRange RegRange = RegTok.getLocRange();
2018
2019 StringRef FixedName = StringSwitch<StringRef>(Name)
2020 .Case("t4", "t0")
2021 .Case("t5", "t1")
2022 .Case("t6", "t2")
2023 .Case("t7", "t3")
2024 .Default("");
2025 assert(FixedName != "" && "Register name is not one of t4-t7.");
2026
2027 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2028 "Did you mean $" + FixedName + "?", RegRange);
2029 }
2030
Toma Tabacufda445c2014-09-15 15:33:01 +00002031 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2032 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2033 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2034 if (8 <= CC && CC <= 11)
2035 CC += 4;
2036
2037 if (CC == -1)
2038 CC = StringSwitch<unsigned>(Name)
2039 .Case("a4", 8)
2040 .Case("a5", 9)
2041 .Case("a6", 10)
2042 .Case("a7", 11)
2043 .Case("kt0", 26)
2044 .Case("kt1", 27)
2045 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002046
2047 return CC;
2048}
Jack Carterd0bd6422013-04-18 00:41:53 +00002049
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002050int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2051 int CC;
2052
2053 CC = StringSwitch<unsigned>(Name)
2054 .Case("hwr_cpunum", 0)
2055 .Case("hwr_synci_step", 1)
2056 .Case("hwr_cc", 2)
2057 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002058 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002059 .Default(-1);
2060
2061 return CC;
2062}
2063
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002064int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002065
Jack Cartera63b16a2012-09-07 00:23:42 +00002066 if (Name[0] == 'f') {
2067 StringRef NumString = Name.substr(1);
2068 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002069 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002070 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002071 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002072 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002073 return IntVal;
2074 }
2075 return -1;
2076}
Jack Cartera63b16a2012-09-07 00:23:42 +00002077
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002078int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2079
2080 if (Name.startswith("fcc")) {
2081 StringRef NumString = Name.substr(3);
2082 unsigned IntVal;
2083 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002084 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002085 if (IntVal > 7) // There are only 8 fcc registers.
2086 return -1;
2087 return IntVal;
2088 }
2089 return -1;
2090}
2091
2092int MipsAsmParser::matchACRegisterName(StringRef Name) {
2093
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002094 if (Name.startswith("ac")) {
2095 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002096 unsigned IntVal;
2097 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002098 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002099 if (IntVal > 3) // There are only 3 acc registers.
2100 return -1;
2101 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002102 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002103 return -1;
2104}
Jack Carterd0bd6422013-04-18 00:41:53 +00002105
Jack Carter5dc8ac92013-09-25 23:50:44 +00002106int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2107 unsigned IntVal;
2108
2109 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2110 return -1;
2111
2112 if (IntVal > 31)
2113 return -1;
2114
2115 return IntVal;
2116}
2117
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002118int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2119 int CC;
2120
2121 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002122 .Case("msair", 0)
2123 .Case("msacsr", 1)
2124 .Case("msaaccess", 2)
2125 .Case("msasave", 3)
2126 .Case("msamodify", 4)
2127 .Case("msarequest", 5)
2128 .Case("msamap", 6)
2129 .Case("msaunmap", 7)
2130 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002131
2132 return CC;
2133}
2134
Jack Carter0b744b32012-10-04 02:29:46 +00002135bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2136 if (Reg > 31)
2137 return false;
2138
Toma Tabacu3c24b042014-09-05 15:43:21 +00002139 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002140 return true;
2141}
2142
Matheus Almeida7de68e72014-06-18 14:46:05 +00002143int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002144 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002145 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002146 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002147 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002148 return AT;
2149}
Jack Carter0b744b32012-10-04 02:29:46 +00002150
Jack Carterd0bd6422013-04-18 00:41:53 +00002151unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002152 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002153}
2154
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002155unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002156 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002157 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002158}
2159
Jack Carter873c7242013-01-12 01:03:14 +00002160int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002161 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002162 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002163 return -1;
2164
Jack Carter873c7242013-01-12 01:03:14 +00002165 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002166}
2167
Toma Tabacu13964452014-09-04 13:23:44 +00002168bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002169 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002170 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002171
Jack Carter30a59822012-10-04 04:03:53 +00002172 // Check if the current operand has a custom associated parser, if so, try to
2173 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002174 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2175 if (ResTy == MatchOperand_Success)
2176 return false;
2177 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2178 // there was a match, but an error occurred, in which case, just return that
2179 // the operand parsing failed.
2180 if (ResTy == MatchOperand_ParseFail)
2181 return true;
2182
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002183 DEBUG(dbgs() << ".. Generic Parser\n");
2184
Jack Carterb4dbc172012-09-05 23:34:03 +00002185 switch (getLexer().getKind()) {
2186 default:
2187 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2188 return true;
2189 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002191 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002192
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002193 // Almost all registers have been parsed by custom parsers. There is only
2194 // one exception to this. $zero (and it's alias $0) will reach this point
2195 // for div, divu, and similar instructions because it is not an operand
2196 // to the instruction definition but an explicit register. Special case
2197 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002198 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002199 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002200
Jack Carterd0bd6422013-04-18 00:41:53 +00002201 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002202 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002203 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002204 return true;
2205
Jack Carter873c7242013-01-12 01:03:14 +00002206 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002207 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002208 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002209 const MCExpr *Res =
2210 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002211
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002212 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002213 return false;
2214 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002215 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002216 case AsmToken::LParen:
2217 case AsmToken::Minus:
2218 case AsmToken::Plus:
2219 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002220 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002221 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002222 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002223 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002224 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002225 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002226 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002227 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002228 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002229 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002230 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002231 return true;
2232
Jack Carter873c7242013-01-12 01:03:14 +00002233 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2234
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002235 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002236 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002237 } // case AsmToken::Percent
2238 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002239 return true;
2240}
2241
Vladimir Medic4c299852013-11-06 11:27:05 +00002242const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002243 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002244 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002245 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002246 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002247 // It's a constant, evaluate reloc value.
2248 int16_t Val;
2249 switch (getVariantKind(RelocStr)) {
2250 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2251 // Get the 1st 16-bits.
2252 Val = MCE->getValue() & 0xffff;
2253 break;
2254 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2255 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2256 // 16 bits being negative.
2257 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2258 break;
2259 case MCSymbolRefExpr::VK_Mips_HIGHER:
2260 // Get the 3rd 16-bits.
2261 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2262 break;
2263 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2264 // Get the 4th 16-bits.
2265 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2266 break;
2267 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002268 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002269 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002270 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002271 }
2272
Jack Carterb5cf5902013-04-17 00:18:04 +00002273 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002274 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002275 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002276 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002278 return Res;
2279 }
2280
2281 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002282 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2283
Sasa Stankovic06c47802014-04-03 10:37:45 +00002284 // Try to create target expression.
2285 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2286 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002287
Jack Carterd0bd6422013-04-18 00:41:53 +00002288 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2289 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002290 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2291 return Res;
2292 }
2293
2294 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002295 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2296 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2297 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002298 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002299 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002300 return Expr;
2301}
2302
2303bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2304
2305 switch (Expr->getKind()) {
2306 case MCExpr::Constant:
2307 return true;
2308 case MCExpr::SymbolRef:
2309 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2310 case MCExpr::Binary:
2311 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2312 if (!isEvaluated(BE->getLHS()))
2313 return false;
2314 return isEvaluated(BE->getRHS());
2315 }
2316 case MCExpr::Unary:
2317 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002318 case MCExpr::Target:
2319 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002320 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002321 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002322}
Jack Carterd0bd6422013-04-18 00:41:53 +00002323
Jack Carterb5cf5902013-04-17 00:18:04 +00002324bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002325 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002326 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002327 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002328 if (Tok.isNot(AsmToken::Identifier))
2329 return true;
2330
2331 std::string Str = Tok.getIdentifier().str();
2332
Jack Carterd0bd6422013-04-18 00:41:53 +00002333 Parser.Lex(); // Eat the identifier.
2334 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002335 const MCExpr *IdVal;
2336 SMLoc EndLoc;
2337
2338 if (getLexer().getKind() == AsmToken::LParen) {
2339 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002340 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002341 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002342 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002343 const AsmToken &nextTok = Parser.getTok();
2344 if (nextTok.isNot(AsmToken::Identifier))
2345 return true;
2346 Str += "(%";
2347 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002348 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002349 if (getLexer().getKind() != AsmToken::LParen)
2350 return true;
2351 } else
2352 break;
2353 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002354 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002355 return true;
2356
2357 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002358 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002359
2360 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002361 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002362
Jack Carterd0bd6422013-04-18 00:41:53 +00002363 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002364 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002365}
2366
Jack Carterb4dbc172012-09-05 23:34:03 +00002367bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2368 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002369 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002370 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002371 if (ResTy == MatchOperand_Success) {
2372 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002373 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002374 StartLoc = Operand.getStartLoc();
2375 EndLoc = Operand.getEndLoc();
2376
2377 // AFAIK, we only support numeric registers and named GPR's in CFI
2378 // directives.
2379 // Don't worry about eating tokens before failing. Using an unrecognised
2380 // register is a parse error.
2381 if (Operand.isGPRAsmReg()) {
2382 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002383 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002384 }
2385
2386 return (RegNo == (unsigned)-1);
2387 }
2388
2389 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002390 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002391}
2392
Jack Carterb5cf5902013-04-17 00:18:04 +00002393bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002394 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002395 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002396 bool Result = true;
2397
2398 while (getLexer().getKind() == AsmToken::LParen)
2399 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002400
Jack Carterd0bd6422013-04-18 00:41:53 +00002401 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002402 default:
2403 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002404 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002405 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002406 case AsmToken::Integer:
2407 case AsmToken::Minus:
2408 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002409 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002410 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002411 else
2412 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002413 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002414 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002415 break;
Jack Carter873c7242013-01-12 01:03:14 +00002416 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002417 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002418 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002419 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002420}
2421
David Blaikie960ea3f2014-06-08 16:18:35 +00002422MipsAsmParser::OperandMatchResultTy
2423MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002424 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002425 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002426 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002427 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002428 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002429 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002431 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002432
Jack Carterb5cf5902013-04-17 00:18:04 +00002433 if (getLexer().getKind() == AsmToken::LParen) {
2434 Parser.Lex();
2435 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002436 }
2437
Jack Carterb5cf5902013-04-17 00:18:04 +00002438 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002439 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002440 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002441
Jack Carterd0bd6422013-04-18 00:41:53 +00002442 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002443 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002444 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2445 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002446 SMLoc E =
2447 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002448 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002449 return MatchOperand_Success;
2450 }
2451 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002452 SMLoc E =
2453 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002454
Jack Carterd0bd6422013-04-18 00:41:53 +00002455 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002456 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002457 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002458 S, E, *this);
2459 Operands.push_back(
2460 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002461 return MatchOperand_Success;
2462 }
2463 Error(Parser.getTok().getLoc(), "'(' expected");
2464 return MatchOperand_ParseFail;
2465 }
2466
Jack Carterd0bd6422013-04-18 00:41:53 +00002467 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002468 }
2469
Toma Tabacu13964452014-09-04 13:23:44 +00002470 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002471 if (Res != MatchOperand_Success)
2472 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002473
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002474 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002475 Error(Parser.getTok().getLoc(), "')' expected");
2476 return MatchOperand_ParseFail;
2477 }
2478
Jack Carter873c7242013-01-12 01:03:14 +00002479 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2480
Jack Carterd0bd6422013-04-18 00:41:53 +00002481 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002482
Craig Topper062a2ba2014-04-25 05:30:21 +00002483 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002484 IdVal = MCConstantExpr::Create(0, getContext());
2485
Jack Carterd0bd6422013-04-18 00:41:53 +00002486 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002487 std::unique_ptr<MipsOperand> op(
2488 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002490 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002491 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002492 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002493 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2494 int64_t Imm;
2495 if (IdVal->EvaluateAsAbsolute(Imm))
2496 IdVal = MCConstantExpr::Create(Imm, getContext());
2497 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2498 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2499 getContext());
2500 }
2501
David Blaikie960ea3f2014-06-08 16:18:35 +00002502 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002503 return MatchOperand_Success;
2504}
2505
David Blaikie960ea3f2014-06-08 16:18:35 +00002506bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002507 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002508 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2509 if (Sym) {
2510 SMLoc S = Parser.getTok().getLoc();
2511 const MCExpr *Expr;
2512 if (Sym->isVariable())
2513 Expr = Sym->getVariableValue();
2514 else
2515 return false;
2516 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002517 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002518 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002519 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002520 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002521 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002522 if (ResTy == MatchOperand_Success) {
2523 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002524 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002525 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002526 llvm_unreachable("Should never ParseFail");
2527 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002528 }
2529 } else if (Expr->getKind() == MCExpr::Constant) {
2530 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002531 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002532 Operands.push_back(
2533 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002534 return true;
2535 }
2536 }
2537 return false;
2538}
Jack Carterd0bd6422013-04-18 00:41:53 +00002539
Jack Carter873c7242013-01-12 01:03:14 +00002540MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002541MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002542 StringRef Identifier,
2543 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002544 int Index = matchCPURegisterName(Identifier);
2545 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002546 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002547 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2548 return MatchOperand_Success;
2549 }
2550
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002551 Index = matchHWRegsRegisterName(Identifier);
2552 if (Index != -1) {
2553 Operands.push_back(MipsOperand::createHWRegsReg(
2554 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2555 return MatchOperand_Success;
2556 }
2557
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002558 Index = matchFPURegisterName(Identifier);
2559 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002560 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002561 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2562 return MatchOperand_Success;
2563 }
2564
2565 Index = matchFCCRegisterName(Identifier);
2566 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002567 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002568 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2569 return MatchOperand_Success;
2570 }
2571
2572 Index = matchACRegisterName(Identifier);
2573 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002574 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002575 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2576 return MatchOperand_Success;
2577 }
2578
2579 Index = matchMSA128RegisterName(Identifier);
2580 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002581 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002582 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2583 return MatchOperand_Success;
2584 }
2585
2586 Index = matchMSA128CtrlRegisterName(Identifier);
2587 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002588 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002589 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2590 return MatchOperand_Success;
2591 }
2592
2593 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002594}
2595
2596MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002597MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002598 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002599 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002600
2601 if (Token.is(AsmToken::Identifier)) {
2602 DEBUG(dbgs() << ".. identifier\n");
2603 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002604 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002605 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002606 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002607 } else if (Token.is(AsmToken::Integer)) {
2608 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002609 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002610 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2611 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002612 return MatchOperand_Success;
2613 }
2614
2615 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2616
2617 return MatchOperand_NoMatch;
2618}
2619
David Blaikie960ea3f2014-06-08 16:18:35 +00002620MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002621MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002622 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002623 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002624
2625 auto Token = Parser.getTok();
2626
2627 SMLoc S = Token.getLoc();
2628
2629 if (Token.isNot(AsmToken::Dollar)) {
2630 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2631 if (Token.is(AsmToken::Identifier)) {
2632 if (searchSymbolAlias(Operands))
2633 return MatchOperand_Success;
2634 }
2635 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2636 return MatchOperand_NoMatch;
2637 }
2638 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002639
Toma Tabacu13964452014-09-04 13:23:44 +00002640 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002641 if (ResTy == MatchOperand_Success) {
2642 Parser.Lex(); // $
2643 Parser.Lex(); // identifier
2644 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002645 return ResTy;
2646}
2647
2648MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002649MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002650 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002651 switch (getLexer().getKind()) {
2652 default:
2653 return MatchOperand_NoMatch;
2654 case AsmToken::LParen:
2655 case AsmToken::Minus:
2656 case AsmToken::Plus:
2657 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002658 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002659 case AsmToken::String:
2660 break;
2661 }
2662
2663 const MCExpr *IdVal;
2664 SMLoc S = Parser.getTok().getLoc();
2665 if (getParser().parseExpression(IdVal))
2666 return MatchOperand_ParseFail;
2667
2668 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2669 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2670 return MatchOperand_Success;
2671}
2672
David Blaikie960ea3f2014-06-08 16:18:35 +00002673MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002674MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002675 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002676 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002677
2678 SMLoc S = getLexer().getLoc();
2679
2680 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002681 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002682 if (ResTy != MatchOperand_NoMatch)
2683 return ResTy;
2684
Daniel Sanders315386c2014-04-01 10:40:14 +00002685 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002686 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002687 if (ResTy != MatchOperand_NoMatch)
2688 return ResTy;
2689
Daniel Sandersffd84362014-04-01 10:41:48 +00002690 const MCExpr *Expr = nullptr;
2691 if (Parser.parseExpression(Expr)) {
2692 // We have no way of knowing if a symbol was consumed so we must ParseFail
2693 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002694 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002695 Operands.push_back(
2696 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002697 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002698}
2699
Vladimir Medic2b953d02013-10-01 09:48:56 +00002700MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002701MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002702 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002703 const MCExpr *IdVal;
2704 // If the first token is '$' we may have register operand.
2705 if (Parser.getTok().is(AsmToken::Dollar))
2706 return MatchOperand_NoMatch;
2707 SMLoc S = Parser.getTok().getLoc();
2708 if (getParser().parseExpression(IdVal))
2709 return MatchOperand_ParseFail;
2710 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002711 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002712 int64_t Val = MCE->getValue();
2713 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2714 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002715 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002716 return MatchOperand_Success;
2717}
2718
Matheus Almeida779c5932013-11-18 12:32:49 +00002719MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002720MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002721 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002722 switch (getLexer().getKind()) {
2723 default:
2724 return MatchOperand_NoMatch;
2725 case AsmToken::LParen:
2726 case AsmToken::Plus:
2727 case AsmToken::Minus:
2728 case AsmToken::Integer:
2729 break;
2730 }
2731
2732 const MCExpr *Expr;
2733 SMLoc S = Parser.getTok().getLoc();
2734
2735 if (getParser().parseExpression(Expr))
2736 return MatchOperand_ParseFail;
2737
2738 int64_t Val;
2739 if (!Expr->EvaluateAsAbsolute(Val)) {
2740 Error(S, "expected immediate value");
2741 return MatchOperand_ParseFail;
2742 }
2743
2744 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2745 // and because the CPU always adds one to the immediate field, the allowed
2746 // range becomes 1..4. We'll only check the range here and will deal
2747 // with the addition/subtraction when actually decoding/encoding
2748 // the instruction.
2749 if (Val < 1 || Val > 4) {
2750 Error(S, "immediate not in range (1..4)");
2751 return MatchOperand_ParseFail;
2752 }
2753
Jack Carter3b2c96e2014-01-22 23:31:38 +00002754 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002755 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002756 return MatchOperand_Success;
2757}
2758
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002759MipsAsmParser::OperandMatchResultTy
2760MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2761 MCAsmParser &Parser = getParser();
2762 SmallVector<unsigned, 10> Regs;
2763 unsigned RegNo;
2764 unsigned PrevReg = Mips::NoRegister;
2765 bool RegRange = false;
2766 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2767
2768 if (Parser.getTok().isNot(AsmToken::Dollar))
2769 return MatchOperand_ParseFail;
2770
2771 SMLoc S = Parser.getTok().getLoc();
2772 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2773 SMLoc E = getLexer().getLoc();
2774 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2775 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2776 if (RegRange) {
2777 // Remove last register operand because registers from register range
2778 // should be inserted first.
2779 if (RegNo == Mips::RA) {
2780 Regs.push_back(RegNo);
2781 } else {
2782 unsigned TmpReg = PrevReg + 1;
2783 while (TmpReg <= RegNo) {
2784 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2785 Error(E, "invalid register operand");
2786 return MatchOperand_ParseFail;
2787 }
2788
2789 PrevReg = TmpReg;
2790 Regs.push_back(TmpReg++);
2791 }
2792 }
2793
2794 RegRange = false;
2795 } else {
2796 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2797 (RegNo != Mips::RA)) {
2798 Error(E, "$16 or $31 expected");
2799 return MatchOperand_ParseFail;
2800 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2801 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2802 Error(E, "invalid register operand");
2803 return MatchOperand_ParseFail;
2804 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2805 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2806 Error(E, "consecutive register numbers expected");
2807 return MatchOperand_ParseFail;
2808 }
2809
2810 Regs.push_back(RegNo);
2811 }
2812
2813 if (Parser.getTok().is(AsmToken::Minus))
2814 RegRange = true;
2815
2816 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2817 !Parser.getTok().isNot(AsmToken::Comma)) {
2818 Error(E, "',' or '-' expected");
2819 return MatchOperand_ParseFail;
2820 }
2821
2822 Lex(); // Consume comma or minus
2823 if (Parser.getTok().isNot(AsmToken::Dollar))
2824 break;
2825
2826 PrevReg = RegNo;
2827 }
2828
2829 SMLoc E = Parser.getTok().getLoc();
2830 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2831 parseMemOperand(Operands);
2832 return MatchOperand_Success;
2833}
2834
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002835MipsAsmParser::OperandMatchResultTy
2836MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2837 MCAsmParser &Parser = getParser();
2838
2839 SMLoc S = Parser.getTok().getLoc();
2840 if (parseAnyRegister(Operands) != MatchOperand_Success)
2841 return MatchOperand_ParseFail;
2842
2843 SMLoc E = Parser.getTok().getLoc();
2844 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2845 unsigned Reg = Op.getGPR32Reg();
2846 Operands.pop_back();
2847 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2848 return MatchOperand_Success;
2849}
2850
Jack Carterdc1e35d2012-09-06 20:00:02 +00002851MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2852
Vladimir Medic4c299852013-11-06 11:27:05 +00002853 MCSymbolRefExpr::VariantKind VK =
2854 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2855 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2856 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2857 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2858 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2859 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2860 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2861 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2862 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2863 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2864 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2865 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2866 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2867 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2868 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2869 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2870 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2871 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002872 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2873 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2874 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2875 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2876 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2877 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002878 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2879 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002880 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002881
Matheus Almeida2852af82014-04-22 10:15:54 +00002882 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002883
Jack Carterdc1e35d2012-09-06 20:00:02 +00002884 return VK;
2885}
Jack Cartera63b16a2012-09-07 00:23:42 +00002886
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002887/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2888/// either this.
2889/// ::= '(', register, ')'
2890/// handle it before we iterate so we don't get tripped up by the lack of
2891/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002892bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002893 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002894 if (getLexer().is(AsmToken::LParen)) {
2895 Operands.push_back(
2896 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2897 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002898 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002899 SMLoc Loc = getLexer().getLoc();
2900 Parser.eatToEndOfStatement();
2901 return Error(Loc, "unexpected token in argument list");
2902 }
2903 if (Parser.getTok().isNot(AsmToken::RParen)) {
2904 SMLoc Loc = getLexer().getLoc();
2905 Parser.eatToEndOfStatement();
2906 return Error(Loc, "unexpected token, expected ')'");
2907 }
2908 Operands.push_back(
2909 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2910 Parser.Lex();
2911 }
2912 return false;
2913}
2914
2915/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2916/// either one of these.
2917/// ::= '[', register, ']'
2918/// ::= '[', integer, ']'
2919/// handle it before we iterate so we don't get tripped up by the lack of
2920/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002921bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002922 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002923 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002924 if (getLexer().is(AsmToken::LBrac)) {
2925 Operands.push_back(
2926 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2927 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002928 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002929 SMLoc Loc = getLexer().getLoc();
2930 Parser.eatToEndOfStatement();
2931 return Error(Loc, "unexpected token in argument list");
2932 }
2933 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2934 SMLoc Loc = getLexer().getLoc();
2935 Parser.eatToEndOfStatement();
2936 return Error(Loc, "unexpected token, expected ']'");
2937 }
2938 Operands.push_back(
2939 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2940 Parser.Lex();
2941 }
2942 return false;
2943}
2944
David Blaikie960ea3f2014-06-08 16:18:35 +00002945bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2946 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002947 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002948 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002949
2950 // We have reached first instruction, module directive are now forbidden.
2951 getTargetStreamer().forbidModuleDirective();
2952
Vladimir Medic74593e62013-07-17 15:00:42 +00002953 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002954 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002955 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002956 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002957 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002958 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002959 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002960
2961 // Read the remaining operands.
2962 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2963 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002964 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002965 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002966 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002967 return Error(Loc, "unexpected token in argument list");
2968 }
Toma Tabacu13964452014-09-04 13:23:44 +00002969 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002970 return true;
2971 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002972
Jack Carterd0bd6422013-04-18 00:41:53 +00002973 while (getLexer().is(AsmToken::Comma)) {
2974 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002975 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002976 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002977 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002978 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002979 return Error(Loc, "unexpected token in argument list");
2980 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002981 // Parse bracket and parenthesis suffixes before we iterate
2982 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002983 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002984 return true;
2985 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002986 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002987 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002988 }
2989 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002990 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2991 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002992 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002993 return Error(Loc, "unexpected token in argument list");
2994 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002995 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002996 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002997}
2998
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002999bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003000 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003001 SMLoc Loc = getLexer().getLoc();
3002 Parser.eatToEndOfStatement();
3003 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003004}
3005
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003006bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003007 return Error(Loc, ErrorMsg);
3008}
3009
Jack Carter0b744b32012-10-04 02:29:46 +00003010bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003011 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003012 // Line should look like: ".set noat".
3013 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003014 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00003015 // eat noat
3016 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003017 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003019 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003020 return false;
3021 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003022 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003023 return false;
3024}
Jack Carterd0bd6422013-04-18 00:41:53 +00003025
Jack Carter0b744b32012-10-04 02:29:46 +00003026bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003027 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003028 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00003029 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00003030 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00003031 getParser().Lex();
3032 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003033 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00003034 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003035 return false;
3036 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003037 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00003038 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003039 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003040 return false;
3041 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003042 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00003043 const AsmToken &Reg = Parser.getTok();
3044 if (Reg.is(AsmToken::Identifier)) {
3045 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3046 } else if (Reg.is(AsmToken::Integer)) {
3047 AtRegNo = Reg.getIntVal();
3048 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003049 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003050 return false;
3051 }
Jack Carter1ac53222013-02-20 23:11:17 +00003052
Daniel Sanders71a89d922014-03-25 13:01:06 +00003053 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00003054 reportParseError("unexpected token in statement");
3055 return false;
3056 }
3057
Toma Tabacu9db22db2014-09-09 10:15:38 +00003058 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003059 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00003060 return false;
3061 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003062 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00003063
3064 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003065 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003066 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003067 }
3068 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003069 return false;
3070 } else {
3071 reportParseError("unexpected token in statement");
3072 return false;
3073 }
3074}
3075
3076bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003077 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003078 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003079 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003080 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003081 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003082 return false;
3083 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003084 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003085 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003086 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003087 return false;
3088}
3089
3090bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003091 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003092 Parser.Lex();
3093 // If this is not the end of the statement, report an error.
3094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003095 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003096 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003097 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003098 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003099 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003100 Parser.Lex(); // Consume the EndOfStatement.
3101 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003102}
3103
3104bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003105 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003106 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003107 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003109 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003110 return false;
3111 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003112 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003113 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003114 return false;
3115}
3116
3117bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003118 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003119 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003120 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003122 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003123 return false;
3124 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003125 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003126 reportParseError("`noreorder' must be set before `nomacro'");
3127 return false;
3128 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003129 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003130 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003131 return false;
3132}
Jack Carterd76b2372013-03-21 21:44:16 +00003133
Daniel Sanders44934432014-08-07 12:03:36 +00003134bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003135 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003136 Parser.Lex();
3137
3138 // If this is not the end of the statement, report an error.
3139 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003140 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003141
3142 setFeatureBits(Mips::FeatureMSA, "msa");
3143 getTargetStreamer().emitDirectiveSetMsa();
3144 return false;
3145}
3146
3147bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003148 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003149 Parser.Lex();
3150
3151 // If this is not the end of the statement, report an error.
3152 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003153 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003154
3155 clearFeatureBits(Mips::FeatureMSA, "msa");
3156 getTargetStreamer().emitDirectiveSetNoMsa();
3157 return false;
3158}
3159
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003160bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003161 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003162 Parser.Lex(); // Eat "nodsp".
3163
3164 // If this is not the end of the statement, report an error.
3165 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3166 reportParseError("unexpected token, expected end of statement");
3167 return false;
3168 }
3169
3170 clearFeatureBits(Mips::FeatureDSP, "dsp");
3171 getTargetStreamer().emitDirectiveSetNoDsp();
3172 return false;
3173}
3174
Toma Tabacucc2502d2014-11-04 17:18:07 +00003175bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003176 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003177 Parser.Lex(); // Eat "mips16".
3178
Jack Carter39536722014-01-22 23:08:42 +00003179 // If this is not the end of the statement, report an error.
3180 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003181 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003182 return false;
3183 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003184
3185 setFeatureBits(Mips::FeatureMips16, "mips16");
3186 getTargetStreamer().emitDirectiveSetMips16();
3187 Parser.Lex(); // Consume the EndOfStatement.
3188 return false;
3189}
3190
3191bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003192 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003193 Parser.Lex(); // Eat "nomips16".
3194
3195 // If this is not the end of the statement, report an error.
3196 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3197 reportParseError("unexpected token, expected end of statement");
3198 return false;
3199 }
3200
3201 clearFeatureBits(Mips::FeatureMips16, "mips16");
3202 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003203 Parser.Lex(); // Consume the EndOfStatement.
3204 return false;
3205}
3206
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003207bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003208 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003209 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003210 // Line can be: .set fp=32
3211 // .set fp=xx
3212 // .set fp=64
3213 Parser.Lex(); // Eat fp token
3214 AsmToken Tok = Parser.getTok();
3215 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003216 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003217 return false;
3218 }
3219 Parser.Lex(); // Eat '=' token.
3220 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003221
3222 if (!parseFpABIValue(FpAbiVal, ".set"))
3223 return false;
3224
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003225 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003226 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003227 return false;
3228 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003229 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003230 Parser.Lex(); // Consume the EndOfStatement.
3231 return false;
3232}
3233
Toma Tabacu9db22db2014-09-09 10:15:38 +00003234bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003235 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003236 SMLoc Loc = getLexer().getLoc();
3237
3238 Parser.Lex();
3239 if (getLexer().isNot(AsmToken::EndOfStatement))
3240 return reportParseError("unexpected token, expected end of statement");
3241
3242 // Always keep an element on the options "stack" to prevent the user
3243 // from changing the initial options. This is how we remember them.
3244 if (AssemblerOptions.size() == 2)
3245 return reportParseError(Loc, ".set pop with no .set push");
3246
3247 AssemblerOptions.pop_back();
3248 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3249
3250 getTargetStreamer().emitDirectiveSetPop();
3251 return false;
3252}
3253
3254bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003255 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003256 Parser.Lex();
3257 if (getLexer().isNot(AsmToken::EndOfStatement))
3258 return reportParseError("unexpected token, expected end of statement");
3259
3260 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003261 AssemblerOptions.push_back(
3262 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003263
3264 getTargetStreamer().emitDirectiveSetPush();
3265 return false;
3266}
3267
Jack Carterd76b2372013-03-21 21:44:16 +00003268bool MipsAsmParser::parseSetAssignment() {
3269 StringRef Name;
3270 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003271 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003272
3273 if (Parser.parseIdentifier(Name))
3274 reportParseError("expected identifier after .set");
3275
3276 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003277 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003278 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003279
Jack Carter3b2c96e2014-01-22 23:31:38 +00003280 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003281 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003282
Jack Carterd0bd6422013-04-18 00:41:53 +00003283 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003284 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003285 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003286 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003287 Sym = getContext().GetOrCreateSymbol(Name);
3288 Sym->setVariableValue(Value);
3289
3290 return false;
3291}
Jack Carterd0bd6422013-04-18 00:41:53 +00003292
Toma Tabacu26647792014-09-09 12:52:14 +00003293bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003294 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003295 Parser.Lex();
3296 if (getLexer().isNot(AsmToken::EndOfStatement))
3297 return reportParseError("unexpected token, expected end of statement");
3298
3299 // Reset assembler options to their initial values.
3300 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3301 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3302
3303 getTargetStreamer().emitDirectiveSetMips0();
3304 return false;
3305}
3306
Toma Tabacu85618b32014-08-19 14:22:52 +00003307bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003308 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003309 Parser.Lex();
3310 if (getLexer().isNot(AsmToken::Equal))
3311 return reportParseError("unexpected token, expected equals sign");
3312
3313 Parser.Lex();
3314 StringRef Arch;
3315 if (Parser.parseIdentifier(Arch))
3316 return reportParseError("expected arch identifier");
3317
3318 StringRef ArchFeatureName =
3319 StringSwitch<StringRef>(Arch)
3320 .Case("mips1", "mips1")
3321 .Case("mips2", "mips2")
3322 .Case("mips3", "mips3")
3323 .Case("mips4", "mips4")
3324 .Case("mips5", "mips5")
3325 .Case("mips32", "mips32")
3326 .Case("mips32r2", "mips32r2")
3327 .Case("mips32r6", "mips32r6")
3328 .Case("mips64", "mips64")
3329 .Case("mips64r2", "mips64r2")
3330 .Case("mips64r6", "mips64r6")
3331 .Case("cnmips", "cnmips")
3332 .Case("r4000", "mips3") // This is an implementation of Mips3.
3333 .Default("");
3334
3335 if (ArchFeatureName.empty())
3336 return reportParseError("unsupported architecture");
3337
3338 selectArch(ArchFeatureName);
3339 getTargetStreamer().emitDirectiveSetArch(Arch);
3340 return false;
3341}
3342
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003343bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003344 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003345 Parser.Lex();
3346 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003347 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003348
Matheus Almeida2852af82014-04-22 10:15:54 +00003349 switch (Feature) {
3350 default:
3351 llvm_unreachable("Unimplemented feature");
3352 case Mips::FeatureDSP:
3353 setFeatureBits(Mips::FeatureDSP, "dsp");
3354 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003355 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003356 case Mips::FeatureMicroMips:
3357 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003358 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003359 case Mips::FeatureMips1:
3360 selectArch("mips1");
3361 getTargetStreamer().emitDirectiveSetMips1();
3362 break;
3363 case Mips::FeatureMips2:
3364 selectArch("mips2");
3365 getTargetStreamer().emitDirectiveSetMips2();
3366 break;
3367 case Mips::FeatureMips3:
3368 selectArch("mips3");
3369 getTargetStreamer().emitDirectiveSetMips3();
3370 break;
3371 case Mips::FeatureMips4:
3372 selectArch("mips4");
3373 getTargetStreamer().emitDirectiveSetMips4();
3374 break;
3375 case Mips::FeatureMips5:
3376 selectArch("mips5");
3377 getTargetStreamer().emitDirectiveSetMips5();
3378 break;
3379 case Mips::FeatureMips32:
3380 selectArch("mips32");
3381 getTargetStreamer().emitDirectiveSetMips32();
3382 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003383 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003384 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003385 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003386 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003387 case Mips::FeatureMips32r6:
3388 selectArch("mips32r6");
3389 getTargetStreamer().emitDirectiveSetMips32R6();
3390 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003391 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003392 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003393 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003394 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003395 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003396 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003397 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003398 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003399 case Mips::FeatureMips64r6:
3400 selectArch("mips64r6");
3401 getTargetStreamer().emitDirectiveSetMips64R6();
3402 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003403 }
3404 return false;
3405}
3406
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003407bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003408 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003409 if (getLexer().isNot(AsmToken::Comma)) {
3410 SMLoc Loc = getLexer().getLoc();
3411 Parser.eatToEndOfStatement();
3412 return Error(Loc, ErrorStr);
3413 }
3414
Matheus Almeida2852af82014-04-22 10:15:54 +00003415 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003416 return true;
3417}
3418
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003419bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003420 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003421 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003422
Toma Tabacudde4c462014-11-06 10:02:45 +00003423 if (inMips16Mode()) {
3424 reportParseError(".cpload is not supported in Mips16 mode");
3425 return false;
3426 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003427
David Blaikie960ea3f2014-06-08 16:18:35 +00003428 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003429 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003430 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3431 reportParseError("expected register containing function address");
3432 return false;
3433 }
3434
David Blaikie960ea3f2014-06-08 16:18:35 +00003435 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3436 if (!RegOpnd.isGPRAsmReg()) {
3437 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003438 return false;
3439 }
3440
Toma Tabacudde4c462014-11-06 10:02:45 +00003441 // If this is not the end of the statement, report an error.
3442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3443 reportParseError("unexpected token, expected end of statement");
3444 return false;
3445 }
3446
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003447 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003448 return false;
3449}
3450
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003451bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003452 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003453 unsigned FuncReg;
3454 unsigned Save;
3455 bool SaveIsReg = true;
3456
Matheus Almeida7e815762014-06-18 13:08:59 +00003457 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003458 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003459 if (ResTy == MatchOperand_NoMatch) {
3460 reportParseError("expected register containing function address");
3461 Parser.eatToEndOfStatement();
3462 return false;
3463 }
3464
3465 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3466 if (!FuncRegOpnd.isGPRAsmReg()) {
3467 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3468 Parser.eatToEndOfStatement();
3469 return false;
3470 }
3471
3472 FuncReg = FuncRegOpnd.getGPR32Reg();
3473 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003474
Toma Tabacu65f10572014-09-16 15:00:52 +00003475 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003476 return true;
3477
Toma Tabacu13964452014-09-04 13:23:44 +00003478 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003479 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003480 const AsmToken &Tok = Parser.getTok();
3481 if (Tok.is(AsmToken::Integer)) {
3482 Save = Tok.getIntVal();
3483 SaveIsReg = false;
3484 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003485 } else {
3486 reportParseError("expected save register or stack offset");
3487 Parser.eatToEndOfStatement();
3488 return false;
3489 }
3490 } else {
3491 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3492 if (!SaveOpnd.isGPRAsmReg()) {
3493 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3494 Parser.eatToEndOfStatement();
3495 return false;
3496 }
3497 Save = SaveOpnd.getGPR32Reg();
3498 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003499
Toma Tabacu65f10572014-09-16 15:00:52 +00003500 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003501 return true;
3502
3503 StringRef Name;
3504 if (Parser.parseIdentifier(Name))
3505 reportParseError("expected identifier");
3506 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003507
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003508 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003509 return false;
3510}
3511
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003512bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003513 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3515 const AsmToken &Tok = Parser.getTok();
3516
3517 if (Tok.getString() == "2008") {
3518 Parser.Lex();
3519 getTargetStreamer().emitDirectiveNaN2008();
3520 return false;
3521 } else if (Tok.getString() == "legacy") {
3522 Parser.Lex();
3523 getTargetStreamer().emitDirectiveNaNLegacy();
3524 return false;
3525 }
3526 }
3527 // If we don't recognize the option passed to the .nan
3528 // directive (e.g. no option or unknown option), emit an error.
3529 reportParseError("invalid option in .nan directive");
3530 return false;
3531}
3532
Jack Carter0b744b32012-10-04 02:29:46 +00003533bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003534 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003535 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003536 const AsmToken &Tok = Parser.getTok();
3537
3538 if (Tok.getString() == "noat") {
3539 return parseSetNoAtDirective();
3540 } else if (Tok.getString() == "at") {
3541 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003542 } else if (Tok.getString() == "arch") {
3543 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003544 } else if (Tok.getString() == "fp") {
3545 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003546 } else if (Tok.getString() == "pop") {
3547 return parseSetPopDirective();
3548 } else if (Tok.getString() == "push") {
3549 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003550 } else if (Tok.getString() == "reorder") {
3551 return parseSetReorderDirective();
3552 } else if (Tok.getString() == "noreorder") {
3553 return parseSetNoReorderDirective();
3554 } else if (Tok.getString() == "macro") {
3555 return parseSetMacroDirective();
3556 } else if (Tok.getString() == "nomacro") {
3557 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003558 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003559 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003560 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003561 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003562 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003563 getTargetStreamer().emitDirectiveSetNoMicroMips();
3564 Parser.eatToEndOfStatement();
3565 return false;
3566 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003567 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003568 } else if (Tok.getString() == "mips0") {
3569 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003570 } else if (Tok.getString() == "mips1") {
3571 return parseSetFeature(Mips::FeatureMips1);
3572 } else if (Tok.getString() == "mips2") {
3573 return parseSetFeature(Mips::FeatureMips2);
3574 } else if (Tok.getString() == "mips3") {
3575 return parseSetFeature(Mips::FeatureMips3);
3576 } else if (Tok.getString() == "mips4") {
3577 return parseSetFeature(Mips::FeatureMips4);
3578 } else if (Tok.getString() == "mips5") {
3579 return parseSetFeature(Mips::FeatureMips5);
3580 } else if (Tok.getString() == "mips32") {
3581 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003582 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003583 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003584 } else if (Tok.getString() == "mips32r6") {
3585 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003586 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003587 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003588 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003589 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003590 } else if (Tok.getString() == "mips64r6") {
3591 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003592 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003593 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003594 } else if (Tok.getString() == "nodsp") {
3595 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003596 } else if (Tok.getString() == "msa") {
3597 return parseSetMsaDirective();
3598 } else if (Tok.getString() == "nomsa") {
3599 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003600 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003601 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003602 parseSetAssignment();
3603 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003604 }
Jack Carter07c818d2013-01-25 01:31:34 +00003605
Jack Carter0b744b32012-10-04 02:29:46 +00003606 return true;
3607}
3608
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003609/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003610/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003611bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003612 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003613 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3614 for (;;) {
3615 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003616 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003617 return true;
3618
3619 getParser().getStreamer().EmitValue(Value, Size);
3620
3621 if (getLexer().is(AsmToken::EndOfStatement))
3622 break;
3623
Jack Carter07c818d2013-01-25 01:31:34 +00003624 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003625 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003626 Parser.Lex();
3627 }
3628 }
3629
3630 Parser.Lex();
3631 return false;
3632}
3633
Vladimir Medic4c299852013-11-06 11:27:05 +00003634/// parseDirectiveGpWord
3635/// ::= .gpword local_sym
3636bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003637 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003638 const MCExpr *Value;
3639 // EmitGPRel32Value requires an expression, so we are using base class
3640 // method to evaluate the expression.
3641 if (getParser().parseExpression(Value))
3642 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003643 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003644
Vladimir Medice10c1122013-11-13 13:18:04 +00003645 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003646 return Error(getLexer().getLoc(),
3647 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003648 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003649 return false;
3650}
3651
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003652/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003653/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003654bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003655 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003656 const MCExpr *Value;
3657 // EmitGPRel64Value requires an expression, so we are using base class
3658 // method to evaluate the expression.
3659 if (getParser().parseExpression(Value))
3660 return true;
3661 getParser().getStreamer().EmitGPRel64Value(Value);
3662
3663 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003664 return Error(getLexer().getLoc(),
3665 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003666 Parser.Lex(); // Eat EndOfStatement token.
3667 return false;
3668}
3669
Jack Carter0cd3c192014-01-06 23:27:31 +00003670bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003671 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003672 // Get the option token.
3673 AsmToken Tok = Parser.getTok();
3674 // At the moment only identifiers are supported.
3675 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003676 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003677 Parser.eatToEndOfStatement();
3678 return false;
3679 }
3680
3681 StringRef Option = Tok.getIdentifier();
3682
3683 if (Option == "pic0") {
3684 getTargetStreamer().emitDirectiveOptionPic0();
3685 Parser.Lex();
3686 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3687 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003688 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003689 Parser.eatToEndOfStatement();
3690 }
3691 return false;
3692 }
3693
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003694 if (Option == "pic2") {
3695 getTargetStreamer().emitDirectiveOptionPic2();
3696 Parser.Lex();
3697 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3698 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003699 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003700 Parser.eatToEndOfStatement();
3701 }
3702 return false;
3703 }
3704
Jack Carter0cd3c192014-01-06 23:27:31 +00003705 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003706 Warning(Parser.getTok().getLoc(),
3707 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003708 Parser.eatToEndOfStatement();
3709 return false;
3710}
3711
Daniel Sanders7e527422014-07-10 13:38:23 +00003712/// parseDirectiveModule
3713/// ::= .module oddspreg
3714/// ::= .module nooddspreg
3715/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003716bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003717 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003718 MCAsmLexer &Lexer = getLexer();
3719 SMLoc L = Lexer.getLoc();
3720
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003721 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003722 // TODO : get a better message.
3723 reportParseError(".module directive must appear before any code");
3724 return false;
3725 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003726
3727 if (Lexer.is(AsmToken::Identifier)) {
3728 StringRef Option = Parser.getTok().getString();
3729 Parser.Lex();
3730
3731 if (Option == "oddspreg") {
3732 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3733 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3734
3735 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003736 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003737 return false;
3738 }
3739
3740 return false;
3741 } else if (Option == "nooddspreg") {
3742 if (!isABI_O32()) {
3743 Error(L, "'.module nooddspreg' requires the O32 ABI");
3744 return false;
3745 }
3746
3747 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3748 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3749
3750 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003751 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003752 return false;
3753 }
3754
3755 return false;
3756 } else if (Option == "fp") {
3757 return parseDirectiveModuleFP();
3758 }
3759
3760 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003761 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003762
3763 return false;
3764}
3765
3766/// parseDirectiveModuleFP
3767/// ::= =32
3768/// ::= =xx
3769/// ::= =64
3770bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003771 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003772 MCAsmLexer &Lexer = getLexer();
3773
3774 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003775 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003776 return false;
3777 }
3778 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003779
Daniel Sanders7e527422014-07-10 13:38:23 +00003780 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003781 if (!parseFpABIValue(FpABI, ".module"))
3782 return false;
3783
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003785 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003786 return false;
3787 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003788
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003789 // Emit appropriate flags.
3790 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003791 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003792 return false;
3793}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003794
Daniel Sanders7e527422014-07-10 13:38:23 +00003795bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003796 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003797 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003798 MCAsmLexer &Lexer = getLexer();
3799
3800 if (Lexer.is(AsmToken::Identifier)) {
3801 StringRef Value = Parser.getTok().getString();
3802 Parser.Lex();
3803
3804 if (Value != "xx") {
3805 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3806 return false;
3807 }
3808
3809 if (!isABI_O32()) {
3810 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3811 return false;
3812 }
3813
Daniel Sanders7e527422014-07-10 13:38:23 +00003814 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003815 return true;
3816 }
3817
3818 if (Lexer.is(AsmToken::Integer)) {
3819 unsigned Value = Parser.getTok().getIntVal();
3820 Parser.Lex();
3821
3822 if (Value != 32 && Value != 64) {
3823 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3824 return false;
3825 }
3826
3827 if (Value == 32) {
3828 if (!isABI_O32()) {
3829 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3830 return false;
3831 }
3832
Daniel Sanders7e527422014-07-10 13:38:23 +00003833 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3834 } else
3835 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003836
Daniel Sanders7e527422014-07-10 13:38:23 +00003837 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003838 }
3839
3840 return false;
3841}
3842
Jack Carter0b744b32012-10-04 02:29:46 +00003843bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003844 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003845 StringRef IDVal = DirectiveID.getString();
3846
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003847 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003848 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003849 if (IDVal == ".dword") {
3850 parseDataDirective(8, DirectiveID.getLoc());
3851 return false;
3852 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003853 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003854 StringRef SymbolName;
3855
3856 if (Parser.parseIdentifier(SymbolName)) {
3857 reportParseError("expected identifier after .ent");
3858 return false;
3859 }
3860
3861 // There's an undocumented extension that allows an integer to
3862 // follow the name of the procedure which AFAICS is ignored by GAS.
3863 // Example: .ent foo,2
3864 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3865 if (getLexer().isNot(AsmToken::Comma)) {
3866 // Even though we accept this undocumented extension for compatibility
3867 // reasons, the additional integer argument does not actually change
3868 // the behaviour of the '.ent' directive, so we would like to discourage
3869 // its use. We do this by not referring to the extended version in
3870 // error messages which are not directly related to its use.
3871 reportParseError("unexpected token, expected end of statement");
3872 return false;
3873 }
3874 Parser.Lex(); // Eat the comma.
3875 const MCExpr *DummyNumber;
3876 int64_t DummyNumberVal;
3877 // If the user was explicitly trying to use the extended version,
3878 // we still give helpful extension-related error messages.
3879 if (Parser.parseExpression(DummyNumber)) {
3880 reportParseError("expected number after comma");
3881 return false;
3882 }
3883 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3884 reportParseError("expected an absolute expression after comma");
3885 return false;
3886 }
3887 }
3888
3889 // If this is not the end of the statement, report an error.
3890 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3891 reportParseError("unexpected token, expected end of statement");
3892 return false;
3893 }
3894
3895 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3896
3897 getTargetStreamer().emitDirectiveEnt(*Sym);
3898 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003899 return false;
3900 }
3901
Jack Carter07c818d2013-01-25 01:31:34 +00003902 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003903 StringRef SymbolName;
3904
3905 if (Parser.parseIdentifier(SymbolName)) {
3906 reportParseError("expected identifier after .end");
3907 return false;
3908 }
3909
3910 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3911 reportParseError("unexpected token, expected end of statement");
3912 return false;
3913 }
3914
3915 if (CurrentFn == nullptr) {
3916 reportParseError(".end used without .ent");
3917 return false;
3918 }
3919
3920 if ((SymbolName != CurrentFn->getName())) {
3921 reportParseError(".end symbol does not match .ent symbol");
3922 return false;
3923 }
3924
3925 getTargetStreamer().emitDirectiveEnd(SymbolName);
3926 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003927 return false;
3928 }
3929
Jack Carter07c818d2013-01-25 01:31:34 +00003930 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003931 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3932 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003933 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003934 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3935 reportParseError("expected stack register");
3936 return false;
3937 }
3938
3939 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3940 if (!StackRegOpnd.isGPRAsmReg()) {
3941 reportParseError(StackRegOpnd.getStartLoc(),
3942 "expected general purpose register");
3943 return false;
3944 }
3945 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3946
3947 if (Parser.getTok().is(AsmToken::Comma))
3948 Parser.Lex();
3949 else {
3950 reportParseError("unexpected token, expected comma");
3951 return false;
3952 }
3953
3954 // Parse the frame size.
3955 const MCExpr *FrameSize;
3956 int64_t FrameSizeVal;
3957
3958 if (Parser.parseExpression(FrameSize)) {
3959 reportParseError("expected frame size value");
3960 return false;
3961 }
3962
3963 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3964 reportParseError("frame size not an absolute expression");
3965 return false;
3966 }
3967
3968 if (Parser.getTok().is(AsmToken::Comma))
3969 Parser.Lex();
3970 else {
3971 reportParseError("unexpected token, expected comma");
3972 return false;
3973 }
3974
3975 // Parse the return register.
3976 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003977 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003978 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3979 reportParseError("expected return register");
3980 return false;
3981 }
3982
3983 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3984 if (!ReturnRegOpnd.isGPRAsmReg()) {
3985 reportParseError(ReturnRegOpnd.getStartLoc(),
3986 "expected general purpose register");
3987 return false;
3988 }
3989
3990 // If this is not the end of the statement, report an error.
3991 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3992 reportParseError("unexpected token, expected end of statement");
3993 return false;
3994 }
3995
3996 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3997 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003998 return false;
3999 }
4000
Jack Carter07c818d2013-01-25 01:31:34 +00004001 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004002 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004003 }
4004
Daniel Sandersd97a6342014-08-13 10:07:34 +00004005 if (IDVal == ".mask" || IDVal == ".fmask") {
4006 // .mask bitmask, frame_offset
4007 // bitmask: One bit for each register used.
4008 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4009 // first register is expected to be saved.
4010 // Examples:
4011 // .mask 0x80000000, -4
4012 // .fmask 0x80000000, -4
4013 //
Jack Carterbe332172012-09-07 00:48:02 +00004014
Daniel Sandersd97a6342014-08-13 10:07:34 +00004015 // Parse the bitmask
4016 const MCExpr *BitMask;
4017 int64_t BitMaskVal;
4018
4019 if (Parser.parseExpression(BitMask)) {
4020 reportParseError("expected bitmask value");
4021 return false;
4022 }
4023
4024 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4025 reportParseError("bitmask not an absolute expression");
4026 return false;
4027 }
4028
4029 if (Parser.getTok().is(AsmToken::Comma))
4030 Parser.Lex();
4031 else {
4032 reportParseError("unexpected token, expected comma");
4033 return false;
4034 }
4035
4036 // Parse the frame_offset
4037 const MCExpr *FrameOffset;
4038 int64_t FrameOffsetVal;
4039
4040 if (Parser.parseExpression(FrameOffset)) {
4041 reportParseError("expected frame offset value");
4042 return false;
4043 }
4044
4045 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4046 reportParseError("frame offset not an absolute expression");
4047 return false;
4048 }
4049
4050 // If this is not the end of the statement, report an error.
4051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4052 reportParseError("unexpected token, expected end of statement");
4053 return false;
4054 }
4055
4056 if (IDVal == ".mask")
4057 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4058 else
4059 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004060 return false;
4061 }
4062
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004063 if (IDVal == ".nan")
4064 return parseDirectiveNaN();
4065
Jack Carter07c818d2013-01-25 01:31:34 +00004066 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004067 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004068 return false;
4069 }
4070
Rafael Espindolab59fb732014-03-28 18:50:26 +00004071 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004072 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004073 return false;
4074 }
4075
Jack Carter07c818d2013-01-25 01:31:34 +00004076 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004077 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004078 return false;
4079 }
4080
Jack Carter0cd3c192014-01-06 23:27:31 +00004081 if (IDVal == ".option")
4082 return parseDirectiveOption();
4083
4084 if (IDVal == ".abicalls") {
4085 getTargetStreamer().emitDirectiveAbiCalls();
4086 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004087 Error(Parser.getTok().getLoc(),
4088 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004089 // Clear line
4090 Parser.eatToEndOfStatement();
4091 }
4092 return false;
4093 }
4094
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004095 if (IDVal == ".cpsetup")
4096 return parseDirectiveCPSetup();
4097
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004098 if (IDVal == ".module")
4099 return parseDirectiveModule();
4100
Rafael Espindola870c4e92012-01-11 03:56:41 +00004101 return true;
4102}
4103
Rafael Espindola870c4e92012-01-11 03:56:41 +00004104extern "C" void LLVMInitializeMipsAsmParser() {
4105 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4106 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4107 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4108 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4109}
Jack Carterb4dbc172012-09-05 23:34:03 +00004110
4111#define GET_REGISTER_MATCHER
4112#define GET_MATCHER_IMPLEMENTATION
4113#include "MipsGenAsmMatcher.inc"