blob: 44e0532f413c2365917db16b3433ba202153dcef [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"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.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"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000029#include "llvm/Support/TargetRegistry.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.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);
Matheus Almeida3813d572014-06-19 14:39:14 +0000174
Toma Tabacu0d64b202014-08-14 10:29:17 +0000175 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
176 SmallVectorImpl<MCInst> &Instructions);
177
Jack Carter9e65aa32013-03-22 00:05:30 +0000178 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000179 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
180 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000181 bool reportParseError(Twine ErrorMsg);
182 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000183
Jack Carterb5cf5902013-04-17 00:18:04 +0000184 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000185 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000186
Vladimir Medic4c299852013-11-06 11:27:05 +0000187 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000188
189 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000190 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000191 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000192 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000193 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000194 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000195 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000196 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000197 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000198
199 bool parseSetAtDirective();
200 bool parseSetNoAtDirective();
201 bool parseSetMacroDirective();
202 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000203 bool parseSetMsaDirective();
204 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000205 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000206 bool parseSetReorderDirective();
207 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000208 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000209 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000210 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000211 bool parseSetPopDirective();
212 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000213
Jack Carterd76b2372013-03-21 21:44:16 +0000214 bool parseSetAssignment();
215
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000216 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000217 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000218 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000219 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000220 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000221 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
222 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000223
Jack Carterdc1e35d2012-09-06 20:00:02 +0000224 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000225
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000226 bool eatComma(StringRef ErrorStr);
227
Jack Carter1ac53222013-02-20 23:11:17 +0000228 int matchCPURegisterName(StringRef Symbol);
229
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000230 int matchHWRegsRegisterName(StringRef Symbol);
231
Jack Carter873c7242013-01-12 01:03:14 +0000232 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000233
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000234 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000235
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000236 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000237
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000238 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000239
Jack Carter5dc8ac92013-09-25 23:50:44 +0000240 int matchMSA128RegisterName(StringRef Name);
241
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000242 int matchMSA128CtrlRegisterName(StringRef Name);
243
Jack Carterd0bd6422013-04-18 00:41:53 +0000244 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000245
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000246 unsigned getGPR(int RegNo);
247
Matheus Almeida7de68e72014-06-18 14:46:05 +0000248 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000249
250 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000252
253 // Helper function that checks if the value of a vector index is within the
254 // boundaries of accepted values for each RegisterKind
255 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
256 bool validateMSAIndex(int Val, int RegKind);
257
Daniel Sandersf0df2212014-08-04 12:20:00 +0000258 // Selects a new architecture by updating the FeatureBits with the necessary
259 // info including implied dependencies.
260 // Internally, it clears all the feature bits related to *any* architecture
261 // and selects the new one using the ToggleFeature functionality of the
262 // MCSubtargetInfo object that handles implied dependencies. The reason we
263 // clear all the arch related bits manually is because ToggleFeature only
264 // clears the features that imply the feature being cleared and not the
265 // features implied by the feature being cleared. This is easier to see
266 // with an example:
267 // --------------------------------------------------
268 // | Feature | Implies |
269 // | -------------------------------------------------|
270 // | FeatureMips1 | None |
271 // | FeatureMips2 | FeatureMips1 |
272 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
273 // | FeatureMips4 | FeatureMips3 |
274 // | ... | |
275 // --------------------------------------------------
276 //
277 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
278 // FeatureMipsGP64 | FeatureMips1)
279 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
280 void selectArch(StringRef ArchFeature) {
281 uint64_t FeatureBits = STI.getFeatureBits();
282 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
283 STI.setFeatureBits(FeatureBits);
284 setAvailableFeatures(
285 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000286 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000287 }
288
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000289 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000291 setAvailableFeatures(
292 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000293 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000294 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
296
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000297 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000298 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000299 setAvailableFeatures(
300 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000301 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000302 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000303 }
304
Rafael Espindola870c4e92012-01-11 03:56:41 +0000305public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000306 enum MipsMatchResultTy {
307 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
308#define GET_OPERAND_DIAGNOSTIC_TYPES
309#include "MipsGenAsmMatcher.inc"
310#undef GET_OPERAND_DIAGNOSTIC_TYPES
311
312 };
313
Joey Gouly0e76fa72013-09-12 10:28:05 +0000314 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000315 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000316 : MCTargetAsmParser(), STI(sti) {
317 MCAsmParserExtension::Initialize(parser);
318
Jack Carterb4dbc172012-09-05 23:34:03 +0000319 // Initialize the set of available features.
320 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000321
322 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000323 AssemblerOptions.push_back(
324 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325
326 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000327 AssemblerOptions.push_back(
328 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000329
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000330 getTargetStreamer().updateABIInfo(*this);
331
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000332 // Assert exactly one ABI was chosen.
333 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
334 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
335 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
336 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000337
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000338 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000339 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000340
341 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000342 }
343
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000344 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
345 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
348 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
349 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
350 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
351 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000352 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000353
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000354 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000355 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
356 }
357
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000358 bool inMicroMipsMode() const {
359 return STI.getFeatureBits() & Mips::FeatureMicroMips;
360 }
361 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
362 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
363 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
364 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
365 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
366 bool hasMips32() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips32);
368 }
369 bool hasMips64() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips64);
371 }
372 bool hasMips32r2() const {
373 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
374 }
375 bool hasMips64r2() const {
376 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
377 }
378 bool hasMips32r6() const {
379 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
380 }
381 bool hasMips64r6() const {
382 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
383 }
384 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
385 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
386 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
387
388 bool inMips16Mode() const {
389 return STI.getFeatureBits() & Mips::FeatureMips16;
390 }
391 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000392 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000393
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000394 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000395 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000396};
397}
398
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000399namespace {
400
401/// MipsOperand - Instances of this class represent a parsed Mips machine
402/// instruction.
403class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000404public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000405 /// Broad categories of register classes
406 /// The exact class is finalized by the render method.
407 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000408 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000409 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000411 RegKind_FCC = 4, /// FCC
412 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
413 RegKind_MSACtrl = 16, /// MSA control registers
414 RegKind_COP2 = 32, /// COP2
415 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
416 /// context).
417 RegKind_CCR = 128, /// CCR
418 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000419 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000420
421 /// Potentially any (e.g. $1)
422 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
423 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000424 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000425 };
426
427private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000428 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000429 k_Immediate, /// An immediate (possibly involving symbol references)
430 k_Memory, /// Base + Offset Memory Address
431 k_PhysRegister, /// A physical register from the Mips namespace
432 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000433 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000434 k_RegList, /// A physical register list
435 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000436 } Kind;
437
David Blaikie960ea3f2014-06-08 16:18:35 +0000438public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000439 MipsOperand(KindTy K, MipsAsmParser &Parser)
440 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
441
David Blaikie960ea3f2014-06-08 16:18:35 +0000442private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 /// For diagnostics, and checking the assembler temporary
444 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000445
Eric Christopher8996c5d2013-03-15 00:42:55 +0000446 struct Token {
447 const char *Data;
448 unsigned Length;
449 };
450
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000451 struct PhysRegOp {
452 unsigned Num; /// Register Number
453 };
454
455 struct RegIdxOp {
456 unsigned Index; /// Index into the register class
457 RegKind Kind; /// Bitfield of the kinds it could possibly be
458 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000459 };
460
461 struct ImmOp {
462 const MCExpr *Val;
463 };
464
465 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000467 const MCExpr *Off;
468 };
469
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000470 struct RegListOp {
471 SmallVector<unsigned, 10> *List;
472 };
473
Jack Carterb4dbc172012-09-05 23:34:03 +0000474 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000475 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000476 struct PhysRegOp PhysReg;
477 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000478 struct ImmOp Imm;
479 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000480 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000481 };
482
483 SMLoc StartLoc, EndLoc;
484
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000485 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000486 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
487 const MCRegisterInfo *RegInfo,
488 SMLoc S, SMLoc E,
489 MipsAsmParser &Parser) {
490 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 Op->RegIdx.Index = Index;
492 Op->RegIdx.RegInfo = RegInfo;
493 Op->RegIdx.Kind = RegKind;
494 Op->StartLoc = S;
495 Op->EndLoc = E;
496 return Op;
497 }
498
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000499public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000500 /// Coerce the register to GPR32 and return the real register for the current
501 /// target.
502 unsigned getGPR32Reg() const {
503 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000504 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 unsigned ClassID = Mips::GPR32RegClassID;
506 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000507 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000508
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000509 /// Coerce the register to GPR32 and return the real register for the current
510 /// target.
511 unsigned getGPRMM16Reg() const {
512 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
513 unsigned ClassID = Mips::GPR32RegClassID;
514 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
515 }
516
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 /// Coerce the register to GPR64 and return the real register for the current
518 /// target.
519 unsigned getGPR64Reg() const {
520 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
521 unsigned ClassID = Mips::GPR64RegClassID;
522 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000523 }
524
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000525private:
526 /// Coerce the register to AFGR64 and return the real register for the current
527 /// target.
528 unsigned getAFGR64Reg() const {
529 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
530 if (RegIdx.Index % 2 != 0)
531 AsmParser.Warning(StartLoc, "Float register should be even.");
532 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
533 .getRegister(RegIdx.Index / 2);
534 }
535
536 /// Coerce the register to FGR64 and return the real register for the current
537 /// target.
538 unsigned getFGR64Reg() const {
539 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
540 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
541 .getRegister(RegIdx.Index);
542 }
543
544 /// Coerce the register to FGR32 and return the real register for the current
545 /// target.
546 unsigned getFGR32Reg() const {
547 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
548 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
549 .getRegister(RegIdx.Index);
550 }
551
552 /// Coerce the register to FGRH32 and return the real register for the current
553 /// target.
554 unsigned getFGRH32Reg() const {
555 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
556 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
557 .getRegister(RegIdx.Index);
558 }
559
560 /// Coerce the register to FCC and return the real register for the current
561 /// target.
562 unsigned getFCCReg() const {
563 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
564 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
565 .getRegister(RegIdx.Index);
566 }
567
568 /// Coerce the register to MSA128 and return the real register for the current
569 /// target.
570 unsigned getMSA128Reg() const {
571 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
572 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
573 // identical
574 unsigned ClassID = Mips::MSA128BRegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
576 }
577
578 /// Coerce the register to MSACtrl and return the real register for the
579 /// current target.
580 unsigned getMSACtrlReg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
582 unsigned ClassID = Mips::MSACtrlRegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584 }
585
586 /// Coerce the register to COP2 and return the real register for the
587 /// current target.
588 unsigned getCOP2Reg() const {
589 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
590 unsigned ClassID = Mips::COP2RegClassID;
591 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
592 }
593
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000594 /// Coerce the register to COP3 and return the real register for the
595 /// current target.
596 unsigned getCOP3Reg() const {
597 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
598 unsigned ClassID = Mips::COP3RegClassID;
599 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
600 }
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// Coerce the register to ACC64DSP and return the real register for the
603 /// current target.
604 unsigned getACC64DSPReg() const {
605 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
606 unsigned ClassID = Mips::ACC64DSPRegClassID;
607 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
608 }
609
610 /// Coerce the register to HI32DSP and return the real register for the
611 /// current target.
612 unsigned getHI32DSPReg() const {
613 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
614 unsigned ClassID = Mips::HI32DSPRegClassID;
615 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
616 }
617
618 /// Coerce the register to LO32DSP and return the real register for the
619 /// current target.
620 unsigned getLO32DSPReg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
622 unsigned ClassID = Mips::LO32DSPRegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
624 }
625
626 /// Coerce the register to CCR and return the real register for the
627 /// current target.
628 unsigned getCCRReg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
630 unsigned ClassID = Mips::CCRRegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
634 /// Coerce the register to HWRegs and return the real register for the
635 /// current target.
636 unsigned getHWRegsReg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
638 unsigned ClassID = Mips::HWRegsRegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
640 }
641
642public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000643 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000644 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000645 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 Inst.addOperand(MCOperand::CreateImm(0));
647 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
648 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
649 else
650 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000651 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000652
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 void addRegOperands(MCInst &Inst, unsigned N) const {
654 llvm_unreachable("Use a custom parser instead");
655 }
656
Daniel Sanders21bce302014-04-01 12:35:23 +0000657 /// Render the operand to an MCInst as a GPR32
658 /// Asserts if the wrong number of operands are requested, or the operand
659 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000660 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
661 assert(N == 1 && "Invalid number of operands!");
662 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
663 }
664
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000665 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
666 assert(N == 1 && "Invalid number of operands!");
667 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
668 }
669
Jozef Kolek1904fa22014-11-24 14:25:53 +0000670 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
673 }
674
Daniel Sanders21bce302014-04-01 12:35:23 +0000675 /// Render the operand to an MCInst as a GPR64
676 /// Asserts if the wrong number of operands are requested, or the operand
677 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
679 assert(N == 1 && "Invalid number of operands!");
680 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
681 }
682
683 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
684 assert(N == 1 && "Invalid number of operands!");
685 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
686 }
687
688 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
689 assert(N == 1 && "Invalid number of operands!");
690 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
691 }
692
693 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
694 assert(N == 1 && "Invalid number of operands!");
695 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000696 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000697 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000698 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
699 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 }
701
702 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
703 assert(N == 1 && "Invalid number of operands!");
704 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
705 }
706
707 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
708 assert(N == 1 && "Invalid number of operands!");
709 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
710 }
711
712 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
713 assert(N == 1 && "Invalid number of operands!");
714 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
715 }
716
717 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
718 assert(N == 1 && "Invalid number of operands!");
719 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
720 }
721
722 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
724 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
725 }
726
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000727 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
728 assert(N == 1 && "Invalid number of operands!");
729 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
730 }
731
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
733 assert(N == 1 && "Invalid number of operands!");
734 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
735 }
736
737 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
738 assert(N == 1 && "Invalid number of operands!");
739 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
740 }
741
742 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
743 assert(N == 1 && "Invalid number of operands!");
744 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
745 }
746
747 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
748 assert(N == 1 && "Invalid number of operands!");
749 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
750 }
751
752 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
754 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
755 }
756
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000758 assert(N == 1 && "Invalid number of operands!");
759 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000760 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000761 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000762
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000763 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000764 assert(N == 2 && "Invalid number of operands!");
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000767
768 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000769 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000770 }
771
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000772 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 2 && "Invalid number of operands!");
774
775 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
776
777 const MCExpr *Expr = getMemOff();
778 addExpr(Inst, Expr);
779 }
780
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000781 void addRegListOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
783
784 for (auto RegNo : getRegList())
785 Inst.addOperand(MCOperand::CreateReg(RegNo));
786 }
787
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000788 void addRegPairOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 2 && "Invalid number of operands!");
790 unsigned RegNo = getRegPair();
791 Inst.addOperand(MCOperand::CreateReg(RegNo++));
792 Inst.addOperand(MCOperand::CreateReg(RegNo));
793 }
794
Craig Topper56c590a2014-04-29 07:58:02 +0000795 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 // As a special case until we sort out the definition of div/divu, pretend
797 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
798 if (isGPRAsmReg() && RegIdx.Index == 0)
799 return true;
800
801 return Kind == k_PhysRegister;
802 }
803 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000804 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 bool isConstantImm() const {
806 return isImm() && dyn_cast<MCConstantExpr>(getImm());
807 }
Craig Topper56c590a2014-04-29 07:58:02 +0000808 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 // Note: It's not possible to pretend that other operand kinds are tokens.
810 // The matcher emitter checks tokens first.
811 return Kind == k_Token;
812 }
Craig Topper56c590a2014-04-29 07:58:02 +0000813 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000814 bool isConstantMemOff() const {
815 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
816 }
817 template <unsigned Bits> bool isMemWithSimmOffset() const {
818 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
819 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000820 bool isMemWithGRPMM16Base() const {
821 return isMem() && getMemBase()->isMM16AsmReg();
822 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000823 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
824 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
825 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
826 }
827 bool isRegList16() const {
828 if (!isRegList())
829 return false;
830
831 int Size = RegList.List->size();
832 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
833 RegList.List->back() != Mips::RA)
834 return false;
835
836 int PrevReg = *RegList.List->begin();
837 for (int i = 1; i < Size - 1; i++) {
838 int Reg = (*(RegList.List))[i];
839 if ( Reg != PrevReg + 1)
840 return false;
841 PrevReg = Reg;
842 }
843
844 return true;
845 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000846 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 bool isLSAImm() const {
848 if (!isConstantImm())
849 return false;
850 int64_t Val = getConstantImm();
851 return 1 <= Val && Val <= 4;
852 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000853 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000854
855 StringRef getToken() const {
856 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000857 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000858 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000859 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000860
Craig Topper56c590a2014-04-29 07:58:02 +0000861 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 // As a special case until we sort out the definition of div/divu, pretend
863 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
864 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
865 RegIdx.Kind & RegKind_GPR)
866 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000867
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 assert(Kind == k_PhysRegister && "Invalid access!");
869 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000870 }
871
Jack Carterb4dbc172012-09-05 23:34:03 +0000872 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000874 return Imm.Val;
875 }
876
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 int64_t getConstantImm() const {
878 const MCExpr *Val = getImm();
879 return static_cast<const MCConstantExpr *>(Val)->getValue();
880 }
881
882 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000883 assert((Kind == k_Memory) && "Invalid access!");
884 return Mem.Base;
885 }
886
887 const MCExpr *getMemOff() const {
888 assert((Kind == k_Memory) && "Invalid access!");
889 return Mem.Off;
890 }
891
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000892 int64_t getConstantMemOff() const {
893 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
894 }
895
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000896 const SmallVectorImpl<unsigned> &getRegList() const {
897 assert((Kind == k_RegList) && "Invalid access!");
898 return *(RegList.List);
899 }
900
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000901 unsigned getRegPair() const {
902 assert((Kind == k_RegPair) && "Invalid access!");
903 return RegIdx.Index;
904 }
905
David Blaikie960ea3f2014-06-08 16:18:35 +0000906 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
907 MipsAsmParser &Parser) {
908 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000909 Op->Tok.Data = Str.data();
910 Op->Tok.Length = Str.size();
911 Op->StartLoc = S;
912 Op->EndLoc = S;
913 return Op;
914 }
915
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000916 /// Create a numeric register (e.g. $1). The exact register remains
917 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000918 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000919 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000920 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000921 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000923 }
924
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 /// Create a register that is definitely a GPR.
926 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000927 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000928 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000929 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000931 }
932
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 /// Create a register that is definitely a FGR.
934 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000935 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000936 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000937 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
939 }
940
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000941 /// Create a register that is definitely a HWReg.
942 /// This is typically only used for named registers such as $hwr_cpunum.
943 static std::unique_ptr<MipsOperand>
944 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
945 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
946 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
947 }
948
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000949 /// Create a register that is definitely an FCC.
950 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000951 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000952 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000953 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000954 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
955 }
956
957 /// Create a register that is definitely an ACC.
958 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000959 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000960 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000961 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000962 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
963 }
964
965 /// Create a register that is definitely an MSA128.
966 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000967 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000968 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000969 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000970 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
971 }
972
973 /// Create a register that is definitely an MSACtrl.
974 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000975 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000976 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000977 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000978 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
979 }
980
David Blaikie960ea3f2014-06-08 16:18:35 +0000981 static std::unique_ptr<MipsOperand>
982 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
983 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000984 Op->Imm.Val = Val;
985 Op->StartLoc = S;
986 Op->EndLoc = E;
987 return Op;
988 }
989
David Blaikie960ea3f2014-06-08 16:18:35 +0000990 static std::unique_ptr<MipsOperand>
991 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
992 SMLoc E, MipsAsmParser &Parser) {
993 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
994 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000995 Op->Mem.Off = Off;
996 Op->StartLoc = S;
997 Op->EndLoc = E;
998 return Op;
999 }
1000
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001001 static std::unique_ptr<MipsOperand>
1002 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1003 MipsAsmParser &Parser) {
1004 assert (Regs.size() > 0 && "Empty list not allowed");
1005
1006 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1007 Op->RegList.List = new SmallVector<unsigned, 10>();
1008 for (auto Reg : Regs)
1009 Op->RegList.List->push_back(Reg);
1010 Op->StartLoc = StartLoc;
1011 Op->EndLoc = EndLoc;
1012 return Op;
1013 }
1014
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001015 static std::unique_ptr<MipsOperand>
1016 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1017 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1018 Op->RegIdx.Index = RegNo;
1019 Op->StartLoc = S;
1020 Op->EndLoc = E;
1021 return Op;
1022 }
1023
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 bool isGPRAsmReg() const {
1025 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001026 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001027 bool isMM16AsmReg() const {
1028 if (!(isRegIdx() && RegIdx.Kind))
1029 return false;
1030 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1031 || RegIdx.Index == 16 || RegIdx.Index == 17);
1032 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001033 bool isMM16AsmRegZero() const {
1034 if (!(isRegIdx() && RegIdx.Kind))
1035 return false;
1036 return (RegIdx.Index == 0 ||
1037 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1038 RegIdx.Index == 17);
1039 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 bool isFGRAsmReg() const {
1041 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1042 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001043 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001044 bool isHWRegsAsmReg() const {
1045 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001046 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 bool isCCRAsmReg() const {
1048 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001049 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001051 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1052 return false;
1053 if (!AsmParser.hasEightFccRegisters())
1054 return RegIdx.Index == 0;
1055 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001056 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 bool isACCAsmReg() const {
1058 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001059 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 bool isCOP2AsmReg() const {
1061 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001062 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001063 bool isCOP3AsmReg() const {
1064 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1065 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 bool isMSA128AsmReg() const {
1067 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001068 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 bool isMSACtrlAsmReg() const {
1070 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001071 }
1072
Jack Carterb4dbc172012-09-05 23:34:03 +00001073 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001074 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001075 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001076 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001077
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001078 virtual ~MipsOperand() {
1079 switch (Kind) {
1080 case k_Immediate:
1081 break;
1082 case k_Memory:
1083 delete Mem.Base;
1084 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001085 case k_RegList:
1086 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001087 case k_PhysRegister:
1088 case k_RegisterIndex:
1089 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001090 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001091 break;
1092 }
1093 }
1094
Craig Topper56c590a2014-04-29 07:58:02 +00001095 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 switch (Kind) {
1097 case k_Immediate:
1098 OS << "Imm<";
1099 Imm.Val->print(OS);
1100 OS << ">";
1101 break;
1102 case k_Memory:
1103 OS << "Mem<";
1104 Mem.Base->print(OS);
1105 OS << ", ";
1106 Mem.Off->print(OS);
1107 OS << ">";
1108 break;
1109 case k_PhysRegister:
1110 OS << "PhysReg<" << PhysReg.Num << ">";
1111 break;
1112 case k_RegisterIndex:
1113 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1114 break;
1115 case k_Token:
1116 OS << Tok.Data;
1117 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001118 case k_RegList:
1119 OS << "RegList< ";
1120 for (auto Reg : (*RegList.List))
1121 OS << Reg << " ";
1122 OS << ">";
1123 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001124 case k_RegPair:
1125 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1126 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001128 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001129}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001130} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001131
Jack Carter9e65aa32013-03-22 00:05:30 +00001132namespace llvm {
1133extern const MCInstrDesc MipsInsts[];
1134}
1135static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1136 return MipsInsts[Opcode];
1137}
1138
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001139static bool hasShortDelaySlot(unsigned Opcode) {
1140 switch (Opcode) {
1141 case Mips::JALS_MM:
1142 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001143 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001144 case Mips::BGEZALS_MM:
1145 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001146 return true;
1147 default:
1148 return false;
1149 }
1150}
1151
Jack Carter9e65aa32013-03-22 00:05:30 +00001152bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001153 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001154 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001155
Jack Carter9e65aa32013-03-22 00:05:30 +00001156 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001157
1158 if (MCID.isBranch() || MCID.isCall()) {
1159 const unsigned Opcode = Inst.getOpcode();
1160 MCOperand Offset;
1161
1162 switch (Opcode) {
1163 default:
1164 break;
1165 case Mips::BEQ:
1166 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 case Mips::BEQ_MM:
1168 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001169 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001170 Offset = Inst.getOperand(2);
1171 if (!Offset.isImm())
1172 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001173 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001174 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001175 if (OffsetToAlignment(Offset.getImm(),
1176 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001177 return Error(IDLoc, "branch to misaligned address");
1178 break;
1179 case Mips::BGEZ:
1180 case Mips::BGTZ:
1181 case Mips::BLEZ:
1182 case Mips::BLTZ:
1183 case Mips::BGEZAL:
1184 case Mips::BLTZAL:
1185 case Mips::BC1F:
1186 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001187 case Mips::BGEZ_MM:
1188 case Mips::BGTZ_MM:
1189 case Mips::BLEZ_MM:
1190 case Mips::BLTZ_MM:
1191 case Mips::BGEZAL_MM:
1192 case Mips::BLTZAL_MM:
1193 case Mips::BC1F_MM:
1194 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001195 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001196 Offset = Inst.getOperand(1);
1197 if (!Offset.isImm())
1198 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001199 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001200 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001201 if (OffsetToAlignment(Offset.getImm(),
1202 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001203 return Error(IDLoc, "branch to misaligned address");
1204 break;
1205 }
1206 }
1207
Daniel Sandersa84989a2014-06-16 13:25:35 +00001208 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1209 // We still accept it but it is a normal nop.
1210 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1211 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1212 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1213 "nop instruction");
1214 }
1215
Toma Tabacu9db22db2014-09-09 10:15:38 +00001216 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001217 // If this instruction has a delay slot and .set reorder is active,
1218 // emit a NOP after it.
1219 Instructions.push_back(Inst);
1220 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001221 if (hasShortDelaySlot(Inst.getOpcode())) {
1222 NopInst.setOpcode(Mips::MOVE16_MM);
1223 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1224 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1225 } else {
1226 NopInst.setOpcode(Mips::SLL);
1227 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1228 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1229 NopInst.addOperand(MCOperand::CreateImm(0));
1230 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001231 Instructions.push_back(NopInst);
1232 return false;
1233 }
1234
Jack Carter9e65aa32013-03-22 00:05:30 +00001235 if (MCID.mayLoad() || MCID.mayStore()) {
1236 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001237 // reference or immediate we may have to expand instructions.
1238 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001239 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001240 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1241 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001242 MCOperand &Op = Inst.getOperand(i);
1243 if (Op.isImm()) {
1244 int MemOffset = Op.getImm();
1245 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001246 // Offset can't exceed 16bit value.
1247 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001248 return false;
1249 }
1250 } else if (Op.isExpr()) {
1251 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001252 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001253 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001254 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001255 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001256 // Expand symbol.
1257 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001258 return false;
1259 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001260 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001262 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001263 }
1264 }
1265 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001266 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001267 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001268
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001269 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1270 if (inMicroMipsMode()) {
1271 MCOperand Opnd;
1272 int Imm;
1273
1274 switch (Inst.getOpcode()) {
1275 default:
1276 break;
1277 case Mips::ADDIUS5_MM:
1278 Opnd = Inst.getOperand(2);
1279 if (!Opnd.isImm())
1280 return Error(IDLoc, "expected immediate operand kind");
1281 Imm = Opnd.getImm();
1282 if (Imm < -8 || Imm > 7)
1283 return Error(IDLoc, "immediate operand value out of range");
1284 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001285 case Mips::ADDIUSP_MM:
1286 Opnd = Inst.getOperand(0);
1287 if (!Opnd.isImm())
1288 return Error(IDLoc, "expected immediate operand kind");
1289 Imm = Opnd.getImm();
1290 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1291 Imm % 4 != 0)
1292 return Error(IDLoc, "immediate operand value out of range");
1293 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001294 case Mips::SLL16_MM:
1295 case Mips::SRL16_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 < 1 || Imm > 8)
1301 return Error(IDLoc, "immediate operand value out of range");
1302 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001303 case Mips::LI16_MM:
1304 Opnd = Inst.getOperand(1);
1305 if (!Opnd.isImm())
1306 return Error(IDLoc, "expected immediate operand kind");
1307 Imm = Opnd.getImm();
1308 if (Imm < -1 || Imm > 126)
1309 return Error(IDLoc, "immediate operand value out of range");
1310 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001311 case Mips::ADDIUR2_MM:
1312 Opnd = Inst.getOperand(2);
1313 if (!Opnd.isImm())
1314 return Error(IDLoc, "expected immediate operand kind");
1315 Imm = Opnd.getImm();
1316 if (!(Imm == 1 || Imm == -1 ||
1317 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1318 return Error(IDLoc, "immediate operand value out of range");
1319 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001320 case Mips::ADDIUR1SP_MM:
1321 Opnd = Inst.getOperand(1);
1322 if (!Opnd.isImm())
1323 return Error(IDLoc, "expected immediate operand kind");
1324 Imm = Opnd.getImm();
1325 if (OffsetToAlignment(Imm, 4LL))
1326 return Error(IDLoc, "misaligned immediate operand value");
1327 if (Imm < 0 || Imm > 255)
1328 return Error(IDLoc, "immediate operand value out of range");
1329 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001330 case Mips::ANDI16_MM:
1331 Opnd = Inst.getOperand(2);
1332 if (!Opnd.isImm())
1333 return Error(IDLoc, "expected immediate operand kind");
1334 Imm = Opnd.getImm();
1335 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1336 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1337 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1338 return Error(IDLoc, "immediate operand value out of range");
1339 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001340 case Mips::LBU16_MM:
1341 Opnd = Inst.getOperand(2);
1342 if (!Opnd.isImm())
1343 return Error(IDLoc, "expected immediate operand kind");
1344 Imm = Opnd.getImm();
1345 if (Imm < -1 || Imm > 14)
1346 return Error(IDLoc, "immediate operand value out of range");
1347 break;
1348 case Mips::SB16_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 < 0 || Imm > 15)
1354 return Error(IDLoc, "immediate operand value out of range");
1355 break;
1356 case Mips::LHU16_MM:
1357 case Mips::SH16_MM:
1358 Opnd = Inst.getOperand(2);
1359 if (!Opnd.isImm())
1360 return Error(IDLoc, "expected immediate operand kind");
1361 Imm = Opnd.getImm();
1362 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1363 return Error(IDLoc, "immediate operand value out of range");
1364 break;
1365 case Mips::LW16_MM:
1366 case Mips::SW16_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 > 60 || (Imm % 4 != 0))
1372 return Error(IDLoc, "immediate operand value out of range");
1373 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001374 }
1375 }
1376
Jack Carter9e65aa32013-03-22 00:05:30 +00001377 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001378 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001379 else
1380 Instructions.push_back(Inst);
1381
1382 return false;
1383}
1384
Jack Carter30a59822012-10-04 04:03:53 +00001385bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1386
Jack Carterd0bd6422013-04-18 00:41:53 +00001387 switch (Inst.getOpcode()) {
1388 case Mips::LoadImm32Reg:
1389 case Mips::LoadAddr32Imm:
1390 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001391 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001392 return true;
1393 default:
1394 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001395 }
1396}
Jack Carter92995f12012-10-06 00:53:28 +00001397
Matheus Almeida3813d572014-06-19 14:39:14 +00001398bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001399 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001401 default:
1402 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001403 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001404 case Mips::LoadImm32Reg:
1405 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001406 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001407 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001408 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001409 return true;
1410 }
1411 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 case Mips::LoadAddr32Imm:
1413 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1414 case Mips::LoadAddr32Reg:
1415 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1416 }
Jack Carter30a59822012-10-04 04:03:53 +00001417}
Jack Carter92995f12012-10-06 00:53:28 +00001418
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001419namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001420template <bool PerformShift>
1421void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001422 SmallVectorImpl<MCInst> &Instructions) {
1423 MCInst tmpInst;
1424 if (PerformShift) {
1425 tmpInst.setOpcode(Mips::DSLL);
1426 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1427 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1428 tmpInst.addOperand(MCOperand::CreateImm(16));
1429 tmpInst.setLoc(IDLoc);
1430 Instructions.push_back(tmpInst);
1431 tmpInst.clear();
1432 }
1433 tmpInst.setOpcode(Mips::ORi);
1434 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1435 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001436 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001437 tmpInst.setLoc(IDLoc);
1438 Instructions.push_back(tmpInst);
1439}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001440
1441template <int Shift, bool PerformShift>
1442void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1443 SmallVectorImpl<MCInst> &Instructions) {
1444 createShiftOr<PerformShift>(
1445 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1446 IDLoc, Instructions);
1447}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001448}
1449
Matheus Almeida3813d572014-06-19 14:39:14 +00001450bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001451 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001452 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001453 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001454 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001455 const MCOperand &RegOp = Inst.getOperand(0);
1456 assert(RegOp.isReg() && "expected register operand kind");
1457
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001458 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001459 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001460 // FIXME: gas has a special case for values that are 000...1111, which
1461 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001462 if (0 <= ImmValue && ImmValue <= 65535) {
1463 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001464 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001465 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001466 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001468 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001469 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001470 } else if (ImmValue < 0 && ImmValue >= -32768) {
1471 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001472 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001473 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001474 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001475 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001476 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001477 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001478 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1479 // For any value of j that is representable as a 32-bit integer, create
1480 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001481 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001482 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001483 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001484 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1485 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001486 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001487 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1488 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001489 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001490 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001491 return true;
1492 }
1493
1494 // <------- lo32 ------>
1495 // <------- hi32 ------>
1496 // <- hi16 -> <- lo16 ->
1497 // _________________________________
1498 // | | | |
1499 // | 16-bytes | 16-bytes | 16-bytes |
1500 // |__________|__________|__________|
1501 //
1502 // For any value of j that is representable as a 48-bit integer, create
1503 // a sequence of:
1504 // li d,j => lui d,hi16(j)
1505 // ori d,d,hi16(lo32(j))
1506 // dsll d,d,16
1507 // ori d,d,lo16(lo32(j))
1508 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001509 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001510 tmpInst.addOperand(
1511 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001512 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001513 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1514 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1515 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001516 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001517 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001518 return true;
1519 }
1520
1521 // <------- hi32 ------> <------- lo32 ------>
1522 // <- hi16 -> <- lo16 ->
1523 // ___________________________________________
1524 // | | | | |
1525 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1526 // |__________|__________|__________|__________|
1527 //
1528 // For any value of j that isn't representable as a 48-bit integer.
1529 // li d,j => lui d,hi16(j)
1530 // ori d,d,lo16(hi32(j))
1531 // dsll d,d,16
1532 // ori d,d,hi16(lo32(j))
1533 // dsll d,d,16
1534 // ori d,d,lo16(lo32(j))
1535 tmpInst.setOpcode(Mips::LUi);
1536 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1537 tmpInst.addOperand(
1538 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1539 Instructions.push_back(tmpInst);
1540 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1541 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1542 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001543 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001544 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001545}
Jack Carter92995f12012-10-06 00:53:28 +00001546
Matheus Almeida3813d572014-06-19 14:39:14 +00001547bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001548MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1549 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001550 MCInst tmpInst;
1551 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001552 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1553 "expected immediate operand kind");
1554 if (!ImmOp.isImm()) {
1555 expandLoadAddressSym(Inst, IDLoc, Instructions);
1556 return false;
1557 }
Jack Carter543fdf82012-10-09 23:29:45 +00001558 const MCOperand &SrcRegOp = Inst.getOperand(1);
1559 assert(SrcRegOp.isReg() && "expected register operand kind");
1560 const MCOperand &DstRegOp = Inst.getOperand(0);
1561 assert(DstRegOp.isReg() && "expected register operand kind");
1562 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 if (-32768 <= ImmValue && ImmValue <= 65535) {
1564 // For -32768 <= j <= 65535.
1565 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001566 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001567 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1568 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1569 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1570 Instructions.push_back(tmpInst);
1571 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001572 // For any other value of j that is representable as a 32-bit integer.
1573 // la d,j(s) => lui d,hi16(j)
1574 // ori d,d,lo16(j)
1575 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001576 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001577 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1578 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1579 Instructions.push_back(tmpInst);
1580 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001581 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001582 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1583 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1584 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1585 Instructions.push_back(tmpInst);
1586 tmpInst.clear();
1587 tmpInst.setOpcode(Mips::ADDu);
1588 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1589 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1590 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1591 Instructions.push_back(tmpInst);
1592 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001593 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001594}
1595
Matheus Almeida3813d572014-06-19 14:39:14 +00001596bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001597MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1598 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001599 MCInst tmpInst;
1600 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001601 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1602 "expected immediate operand kind");
1603 if (!ImmOp.isImm()) {
1604 expandLoadAddressSym(Inst, IDLoc, Instructions);
1605 return false;
1606 }
Jack Carter543fdf82012-10-09 23:29:45 +00001607 const MCOperand &RegOp = Inst.getOperand(0);
1608 assert(RegOp.isReg() && "expected register operand kind");
1609 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 if (-32768 <= ImmValue && ImmValue <= 65535) {
1611 // For -32768 <= j <= 65535.
1612 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001613 tmpInst.setOpcode(Mips::ADDiu);
1614 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001616 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1617 Instructions.push_back(tmpInst);
1618 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 // For any other value of j that is representable as a 32-bit integer.
1620 // la d,j => lui d,hi16(j)
1621 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001622 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001623 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1624 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1625 Instructions.push_back(tmpInst);
1626 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001627 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001628 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1629 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1630 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1631 Instructions.push_back(tmpInst);
1632 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001633 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001634}
1635
Toma Tabacu0d64b202014-08-14 10:29:17 +00001636void
1637MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1638 SmallVectorImpl<MCInst> &Instructions) {
1639 // FIXME: If we do have a valid at register to use, we should generate a
1640 // slightly shorter sequence here.
1641 MCInst tmpInst;
1642 int ExprOperandNo = 1;
1643 // Sometimes the assembly parser will get the immediate expression as
1644 // a $zero + an immediate.
1645 if (Inst.getNumOperands() == 3) {
1646 assert(Inst.getOperand(1).getReg() ==
1647 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1648 ExprOperandNo = 2;
1649 }
1650 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1651 assert(SymOp.isExpr() && "expected symbol operand kind");
1652 const MCOperand &RegOp = Inst.getOperand(0);
1653 unsigned RegNo = RegOp.getReg();
1654 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1655 const MCSymbolRefExpr *HiExpr =
1656 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1657 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1658 const MCSymbolRefExpr *LoExpr =
1659 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1660 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1661 if (isGP64bit()) {
1662 // If it's a 64-bit architecture, expand to:
1663 // la d,sym => lui d,highest(sym)
1664 // ori d,d,higher(sym)
1665 // dsll d,d,16
1666 // ori d,d,hi16(sym)
1667 // dsll d,d,16
1668 // ori d,d,lo16(sym)
1669 const MCSymbolRefExpr *HighestExpr =
1670 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1671 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1672 const MCSymbolRefExpr *HigherExpr =
1673 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1674 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1675
1676 tmpInst.setOpcode(Mips::LUi);
1677 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1678 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1679 Instructions.push_back(tmpInst);
1680
1681 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1682 Instructions);
1683 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1684 Instructions);
1685 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1686 Instructions);
1687 } else {
1688 // Otherwise, expand to:
1689 // la d,sym => lui d,hi16(sym)
1690 // ori d,d,lo16(sym)
1691 tmpInst.setOpcode(Mips::LUi);
1692 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1693 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1694 Instructions.push_back(tmpInst);
1695
1696 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1697 Instructions);
1698 }
1699}
1700
Jack Carter9e65aa32013-03-22 00:05:30 +00001701void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001702 SmallVectorImpl<MCInst> &Instructions,
1703 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001704 const MCSymbolRefExpr *SR;
1705 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001706 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001707 const MCExpr *ExprOffset;
1708 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001709 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001710 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1711 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001712 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001713 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1714 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001716 if (isImmOpnd) {
1717 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1718 ImmOffset = Inst.getOperand(2).getImm();
1719 LoOffset = ImmOffset & 0x0000ffff;
1720 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001721 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001722 if (LoOffset & 0x8000)
1723 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001725 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001728 // These are some of the types of expansions we perform here:
1729 // 1) lw $8, sym => lui $8, %hi(sym)
1730 // lw $8, %lo(sym)($8)
1731 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1732 // add $8, $8, $9
1733 // lw $8, %lo(offset)($9)
1734 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1735 // add $at, $at, $8
1736 // lw $8, %lo(offset)($at)
1737 // 4) sw $8, sym => lui $at, %hi(sym)
1738 // sw $8, %lo(sym)($at)
1739 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1740 // add $at, $at, $8
1741 // sw $8, %lo(offset)($at)
1742 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1743 // ldc1 $f0, %lo(sym)($at)
1744 //
1745 // For load instructions we can use the destination register as a temporary
1746 // if base and dst are different (examples 1 and 2) and if the base register
1747 // is general purpose otherwise we must use $at (example 6) and error if it's
1748 // not available. For stores we must use $at (examples 4 and 5) because we
1749 // must not clobber the source register setting up the offset.
1750 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1751 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1752 unsigned RegClassIDOp0 =
1753 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1754 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1755 (RegClassIDOp0 == Mips::GPR64RegClassID);
1756 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001757 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001758 else {
1759 int AT = getATReg(IDLoc);
1760 // At this point we need AT to perform the expansions and we exit if it is
1761 // not available.
1762 if (!AT)
1763 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001764 TmpRegNum = getReg(
1765 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001766 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001767
Jack Carter9e65aa32013-03-22 00:05:30 +00001768 TempInst.setOpcode(Mips::LUi);
1769 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1770 if (isImmOpnd)
1771 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1772 else {
1773 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001774 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1776 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1777 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001778 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001779 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001781 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 }
1783 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001784 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001785 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001786 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001787 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001788 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001789 TempInst.setOpcode(Mips::ADDu);
1790 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1791 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1792 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1793 Instructions.push_back(TempInst);
1794 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001795 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001796 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001797 TempInst.setOpcode(Inst.getOpcode());
1798 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1799 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1800 if (isImmOpnd)
1801 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1802 else {
1803 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1805 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1806 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001807 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001808 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001809 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001810 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001811 }
1812 }
1813 Instructions.push_back(TempInst);
1814 TempInst.clear();
1815}
1816
Matheus Almeida595fcab2014-06-11 15:05:56 +00001817unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1818 // As described by the Mips32r2 spec, the registers Rd and Rs for
1819 // jalr.hb must be different.
1820 unsigned Opcode = Inst.getOpcode();
1821
1822 if (Opcode == Mips::JALR_HB &&
1823 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1824 return Match_RequiresDifferentSrcAndDst;
1825
1826 return Match_Success;
1827}
1828
David Blaikie960ea3f2014-06-08 16:18:35 +00001829bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1830 OperandVector &Operands,
1831 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001832 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001833 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001834
Jack Carterb4dbc172012-09-05 23:34:03 +00001835 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001836 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001837 unsigned MatchResult =
1838 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001839
1840 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001841 default:
1842 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001843 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001844 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001845 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001846 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001847 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001848 return false;
1849 }
1850 case Match_MissingFeature:
1851 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1852 return true;
1853 case Match_InvalidOperand: {
1854 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001855 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001856 if (ErrorInfo >= Operands.size())
1857 return Error(IDLoc, "too few operands for instruction");
1858
David Blaikie960ea3f2014-06-08 16:18:35 +00001859 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001860 if (ErrorLoc == SMLoc())
1861 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001862 }
1863
1864 return Error(ErrorLoc, "invalid operand for instruction");
1865 }
1866 case Match_MnemonicFail:
1867 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001868 case Match_RequiresDifferentSrcAndDst:
1869 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001870 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001871 return true;
1872}
1873
Toma Tabacu13964452014-09-04 13:23:44 +00001874void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001875 if ((RegIndex != 0) &&
1876 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001877 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001878 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001879 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001880 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001881 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001882 }
1883}
1884
Daniel Sandersef638fe2014-10-03 15:37:37 +00001885void
1886MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1887 SMRange Range, bool ShowColors) {
1888 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001889 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001890 ShowColors);
1891}
1892
Jack Carter1ac53222013-02-20 23:11:17 +00001893int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001894 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001895
Vladimir Medic4c299852013-11-06 11:27:05 +00001896 CC = StringSwitch<unsigned>(Name)
1897 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001898 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001899 .Case("a0", 4)
1900 .Case("a1", 5)
1901 .Case("a2", 6)
1902 .Case("a3", 7)
1903 .Case("v0", 2)
1904 .Case("v1", 3)
1905 .Case("s0", 16)
1906 .Case("s1", 17)
1907 .Case("s2", 18)
1908 .Case("s3", 19)
1909 .Case("s4", 20)
1910 .Case("s5", 21)
1911 .Case("s6", 22)
1912 .Case("s7", 23)
1913 .Case("k0", 26)
1914 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001915 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001916 .Case("sp", 29)
1917 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001918 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001919 .Case("ra", 31)
1920 .Case("t0", 8)
1921 .Case("t1", 9)
1922 .Case("t2", 10)
1923 .Case("t3", 11)
1924 .Case("t4", 12)
1925 .Case("t5", 13)
1926 .Case("t6", 14)
1927 .Case("t7", 15)
1928 .Case("t8", 24)
1929 .Case("t9", 25)
1930 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001931
Toma Tabacufda445c2014-09-15 15:33:01 +00001932 if (!(isABI_N32() || isABI_N64()))
1933 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001934
Daniel Sandersef638fe2014-10-03 15:37:37 +00001935 if (12 <= CC && CC <= 15) {
1936 // Name is one of t4-t7
1937 AsmToken RegTok = getLexer().peekTok();
1938 SMRange RegRange = RegTok.getLocRange();
1939
1940 StringRef FixedName = StringSwitch<StringRef>(Name)
1941 .Case("t4", "t0")
1942 .Case("t5", "t1")
1943 .Case("t6", "t2")
1944 .Case("t7", "t3")
1945 .Default("");
1946 assert(FixedName != "" && "Register name is not one of t4-t7.");
1947
1948 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1949 "Did you mean $" + FixedName + "?", RegRange);
1950 }
1951
Toma Tabacufda445c2014-09-15 15:33:01 +00001952 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1953 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1954 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1955 if (8 <= CC && CC <= 11)
1956 CC += 4;
1957
1958 if (CC == -1)
1959 CC = StringSwitch<unsigned>(Name)
1960 .Case("a4", 8)
1961 .Case("a5", 9)
1962 .Case("a6", 10)
1963 .Case("a7", 11)
1964 .Case("kt0", 26)
1965 .Case("kt1", 27)
1966 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001967
1968 return CC;
1969}
Jack Carterd0bd6422013-04-18 00:41:53 +00001970
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001971int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1972 int CC;
1973
1974 CC = StringSwitch<unsigned>(Name)
1975 .Case("hwr_cpunum", 0)
1976 .Case("hwr_synci_step", 1)
1977 .Case("hwr_cc", 2)
1978 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001979 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001980 .Default(-1);
1981
1982 return CC;
1983}
1984
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001985int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001986
Jack Cartera63b16a2012-09-07 00:23:42 +00001987 if (Name[0] == 'f') {
1988 StringRef NumString = Name.substr(1);
1989 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001990 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001991 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001992 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001993 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001994 return IntVal;
1995 }
1996 return -1;
1997}
Jack Cartera63b16a2012-09-07 00:23:42 +00001998
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001999int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2000
2001 if (Name.startswith("fcc")) {
2002 StringRef NumString = Name.substr(3);
2003 unsigned IntVal;
2004 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002005 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002006 if (IntVal > 7) // There are only 8 fcc registers.
2007 return -1;
2008 return IntVal;
2009 }
2010 return -1;
2011}
2012
2013int MipsAsmParser::matchACRegisterName(StringRef Name) {
2014
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002015 if (Name.startswith("ac")) {
2016 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002017 unsigned IntVal;
2018 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002019 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002020 if (IntVal > 3) // There are only 3 acc registers.
2021 return -1;
2022 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002023 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002024 return -1;
2025}
Jack Carterd0bd6422013-04-18 00:41:53 +00002026
Jack Carter5dc8ac92013-09-25 23:50:44 +00002027int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2028 unsigned IntVal;
2029
2030 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2031 return -1;
2032
2033 if (IntVal > 31)
2034 return -1;
2035
2036 return IntVal;
2037}
2038
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002039int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2040 int CC;
2041
2042 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002043 .Case("msair", 0)
2044 .Case("msacsr", 1)
2045 .Case("msaaccess", 2)
2046 .Case("msasave", 3)
2047 .Case("msamodify", 4)
2048 .Case("msarequest", 5)
2049 .Case("msamap", 6)
2050 .Case("msaunmap", 7)
2051 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002052
2053 return CC;
2054}
2055
Jack Carter0b744b32012-10-04 02:29:46 +00002056bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2057 if (Reg > 31)
2058 return false;
2059
Toma Tabacu3c24b042014-09-05 15:43:21 +00002060 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002061 return true;
2062}
2063
Matheus Almeida7de68e72014-06-18 14:46:05 +00002064int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002065 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002066 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002067 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002068 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002069 return AT;
2070}
Jack Carter0b744b32012-10-04 02:29:46 +00002071
Jack Carterd0bd6422013-04-18 00:41:53 +00002072unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002073 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002074}
2075
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002076unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002077 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002078 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002079}
2080
Jack Carter873c7242013-01-12 01:03:14 +00002081int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002082 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002083 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002084 return -1;
2085
Jack Carter873c7242013-01-12 01:03:14 +00002086 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002087}
2088
Toma Tabacu13964452014-09-04 13:23:44 +00002089bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002090 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002091 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002092
Jack Carter30a59822012-10-04 04:03:53 +00002093 // Check if the current operand has a custom associated parser, if so, try to
2094 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002095 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2096 if (ResTy == MatchOperand_Success)
2097 return false;
2098 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2099 // there was a match, but an error occurred, in which case, just return that
2100 // the operand parsing failed.
2101 if (ResTy == MatchOperand_ParseFail)
2102 return true;
2103
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002104 DEBUG(dbgs() << ".. Generic Parser\n");
2105
Jack Carterb4dbc172012-09-05 23:34:03 +00002106 switch (getLexer().getKind()) {
2107 default:
2108 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2109 return true;
2110 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002111 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002112 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002113
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002114 // Almost all registers have been parsed by custom parsers. There is only
2115 // one exception to this. $zero (and it's alias $0) will reach this point
2116 // for div, divu, and similar instructions because it is not an operand
2117 // to the instruction definition but an explicit register. Special case
2118 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002119 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002120 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002121
Jack Carterd0bd6422013-04-18 00:41:53 +00002122 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002123 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002124 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002125 return true;
2126
Jack Carter873c7242013-01-12 01:03:14 +00002127 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002128 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002129 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002130 const MCExpr *Res =
2131 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002132
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002133 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002134 return false;
2135 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002136 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002137 case AsmToken::LParen:
2138 case AsmToken::Minus:
2139 case AsmToken::Plus:
2140 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002141 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002142 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002143 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002144 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002145 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002146 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002147 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002149 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002150 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002151 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002152 return true;
2153
Jack Carter873c7242013-01-12 01:03:14 +00002154 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2155
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002156 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002157 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002158 } // case AsmToken::Percent
2159 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002160 return true;
2161}
2162
Vladimir Medic4c299852013-11-06 11:27:05 +00002163const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002164 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002165 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002167 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002168 // It's a constant, evaluate reloc value.
2169 int16_t Val;
2170 switch (getVariantKind(RelocStr)) {
2171 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2172 // Get the 1st 16-bits.
2173 Val = MCE->getValue() & 0xffff;
2174 break;
2175 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2176 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2177 // 16 bits being negative.
2178 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2179 break;
2180 case MCSymbolRefExpr::VK_Mips_HIGHER:
2181 // Get the 3rd 16-bits.
2182 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2183 break;
2184 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2185 // Get the 4th 16-bits.
2186 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2187 break;
2188 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002189 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002190 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002191 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002192 }
2193
Jack Carterb5cf5902013-04-17 00:18:04 +00002194 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002196 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002197 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002198 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002199 return Res;
2200 }
2201
2202 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002203 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2204
Sasa Stankovic06c47802014-04-03 10:37:45 +00002205 // Try to create target expression.
2206 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2207 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002208
Jack Carterd0bd6422013-04-18 00:41:53 +00002209 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2210 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002211 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2212 return Res;
2213 }
2214
2215 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2217 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2218 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002219 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002220 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002221 return Expr;
2222}
2223
2224bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2225
2226 switch (Expr->getKind()) {
2227 case MCExpr::Constant:
2228 return true;
2229 case MCExpr::SymbolRef:
2230 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2231 case MCExpr::Binary:
2232 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2233 if (!isEvaluated(BE->getLHS()))
2234 return false;
2235 return isEvaluated(BE->getRHS());
2236 }
2237 case MCExpr::Unary:
2238 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002239 case MCExpr::Target:
2240 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002241 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002242 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002243}
Jack Carterd0bd6422013-04-18 00:41:53 +00002244
Jack Carterb5cf5902013-04-17 00:18:04 +00002245bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002246 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002247 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002248 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002249 if (Tok.isNot(AsmToken::Identifier))
2250 return true;
2251
2252 std::string Str = Tok.getIdentifier().str();
2253
Jack Carterd0bd6422013-04-18 00:41:53 +00002254 Parser.Lex(); // Eat the identifier.
2255 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002256 const MCExpr *IdVal;
2257 SMLoc EndLoc;
2258
2259 if (getLexer().getKind() == AsmToken::LParen) {
2260 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002261 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002262 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002263 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002264 const AsmToken &nextTok = Parser.getTok();
2265 if (nextTok.isNot(AsmToken::Identifier))
2266 return true;
2267 Str += "(%";
2268 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002269 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002270 if (getLexer().getKind() != AsmToken::LParen)
2271 return true;
2272 } else
2273 break;
2274 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002275 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002276 return true;
2277
2278 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002279 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002280
2281 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002282 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002283
Jack Carterd0bd6422013-04-18 00:41:53 +00002284 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002285 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002286}
2287
Jack Carterb4dbc172012-09-05 23:34:03 +00002288bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2289 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002290 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002291 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002292 if (ResTy == MatchOperand_Success) {
2293 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002294 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002295 StartLoc = Operand.getStartLoc();
2296 EndLoc = Operand.getEndLoc();
2297
2298 // AFAIK, we only support numeric registers and named GPR's in CFI
2299 // directives.
2300 // Don't worry about eating tokens before failing. Using an unrecognised
2301 // register is a parse error.
2302 if (Operand.isGPRAsmReg()) {
2303 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002304 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002305 }
2306
2307 return (RegNo == (unsigned)-1);
2308 }
2309
2310 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002311 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002312}
2313
Jack Carterb5cf5902013-04-17 00:18:04 +00002314bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002315 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002316 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002317 bool Result = true;
2318
2319 while (getLexer().getKind() == AsmToken::LParen)
2320 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002321
Jack Carterd0bd6422013-04-18 00:41:53 +00002322 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002323 default:
2324 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002325 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002326 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002327 case AsmToken::Integer:
2328 case AsmToken::Minus:
2329 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002330 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002331 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002332 else
2333 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002334 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002335 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002336 break;
Jack Carter873c7242013-01-12 01:03:14 +00002337 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002338 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002339 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002340 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002341}
2342
David Blaikie960ea3f2014-06-08 16:18:35 +00002343MipsAsmParser::OperandMatchResultTy
2344MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002345 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002346 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002347 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002348 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002349 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002350 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002351 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002352 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002353
Jack Carterb5cf5902013-04-17 00:18:04 +00002354 if (getLexer().getKind() == AsmToken::LParen) {
2355 Parser.Lex();
2356 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002357 }
2358
Jack Carterb5cf5902013-04-17 00:18:04 +00002359 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002360 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002361 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002362
Jack Carterd0bd6422013-04-18 00:41:53 +00002363 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002364 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002365 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2366 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002367 SMLoc E =
2368 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002369 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002370 return MatchOperand_Success;
2371 }
2372 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002373 SMLoc E =
2374 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002375
Jack Carterd0bd6422013-04-18 00:41:53 +00002376 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002377 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002378 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002379 S, E, *this);
2380 Operands.push_back(
2381 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002382 return MatchOperand_Success;
2383 }
2384 Error(Parser.getTok().getLoc(), "'(' expected");
2385 return MatchOperand_ParseFail;
2386 }
2387
Jack Carterd0bd6422013-04-18 00:41:53 +00002388 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002389 }
2390
Toma Tabacu13964452014-09-04 13:23:44 +00002391 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002392 if (Res != MatchOperand_Success)
2393 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002394
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002395 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002396 Error(Parser.getTok().getLoc(), "')' expected");
2397 return MatchOperand_ParseFail;
2398 }
2399
Jack Carter873c7242013-01-12 01:03:14 +00002400 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2401
Jack Carterd0bd6422013-04-18 00:41:53 +00002402 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002403
Craig Topper062a2ba2014-04-25 05:30:21 +00002404 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002405 IdVal = MCConstantExpr::Create(0, getContext());
2406
Jack Carterd0bd6422013-04-18 00:41:53 +00002407 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002408 std::unique_ptr<MipsOperand> op(
2409 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002410 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002411 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002412 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002413 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002414 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2415 int64_t Imm;
2416 if (IdVal->EvaluateAsAbsolute(Imm))
2417 IdVal = MCConstantExpr::Create(Imm, getContext());
2418 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2419 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2420 getContext());
2421 }
2422
David Blaikie960ea3f2014-06-08 16:18:35 +00002423 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002424 return MatchOperand_Success;
2425}
2426
David Blaikie960ea3f2014-06-08 16:18:35 +00002427bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002428 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002429 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2430 if (Sym) {
2431 SMLoc S = Parser.getTok().getLoc();
2432 const MCExpr *Expr;
2433 if (Sym->isVariable())
2434 Expr = Sym->getVariableValue();
2435 else
2436 return false;
2437 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002438 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002439 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002440 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002441 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002442 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002443 if (ResTy == MatchOperand_Success) {
2444 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002445 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002446 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447 llvm_unreachable("Should never ParseFail");
2448 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002449 }
2450 } else if (Expr->getKind() == MCExpr::Constant) {
2451 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002452 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002453 Operands.push_back(
2454 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002455 return true;
2456 }
2457 }
2458 return false;
2459}
Jack Carterd0bd6422013-04-18 00:41:53 +00002460
Jack Carter873c7242013-01-12 01:03:14 +00002461MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002462MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002463 StringRef Identifier,
2464 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002465 int Index = matchCPURegisterName(Identifier);
2466 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002467 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2469 return MatchOperand_Success;
2470 }
2471
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002472 Index = matchHWRegsRegisterName(Identifier);
2473 if (Index != -1) {
2474 Operands.push_back(MipsOperand::createHWRegsReg(
2475 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2476 return MatchOperand_Success;
2477 }
2478
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002479 Index = matchFPURegisterName(Identifier);
2480 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002481 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002482 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2483 return MatchOperand_Success;
2484 }
2485
2486 Index = matchFCCRegisterName(Identifier);
2487 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002488 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002489 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2490 return MatchOperand_Success;
2491 }
2492
2493 Index = matchACRegisterName(Identifier);
2494 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002495 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002496 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2497 return MatchOperand_Success;
2498 }
2499
2500 Index = matchMSA128RegisterName(Identifier);
2501 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002502 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002503 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2504 return MatchOperand_Success;
2505 }
2506
2507 Index = matchMSA128CtrlRegisterName(Identifier);
2508 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002509 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002510 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2511 return MatchOperand_Success;
2512 }
2513
2514 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002515}
2516
2517MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002518MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002519 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002520 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002521
2522 if (Token.is(AsmToken::Identifier)) {
2523 DEBUG(dbgs() << ".. identifier\n");
2524 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002525 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002526 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002527 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002528 } else if (Token.is(AsmToken::Integer)) {
2529 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002530 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002531 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2532 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002533 return MatchOperand_Success;
2534 }
2535
2536 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2537
2538 return MatchOperand_NoMatch;
2539}
2540
David Blaikie960ea3f2014-06-08 16:18:35 +00002541MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002542MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002543 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002544 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002545
2546 auto Token = Parser.getTok();
2547
2548 SMLoc S = Token.getLoc();
2549
2550 if (Token.isNot(AsmToken::Dollar)) {
2551 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2552 if (Token.is(AsmToken::Identifier)) {
2553 if (searchSymbolAlias(Operands))
2554 return MatchOperand_Success;
2555 }
2556 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2557 return MatchOperand_NoMatch;
2558 }
2559 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002560
Toma Tabacu13964452014-09-04 13:23:44 +00002561 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002562 if (ResTy == MatchOperand_Success) {
2563 Parser.Lex(); // $
2564 Parser.Lex(); // identifier
2565 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002566 return ResTy;
2567}
2568
2569MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002570MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002571 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002572 switch (getLexer().getKind()) {
2573 default:
2574 return MatchOperand_NoMatch;
2575 case AsmToken::LParen:
2576 case AsmToken::Minus:
2577 case AsmToken::Plus:
2578 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002579 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002580 case AsmToken::String:
2581 break;
2582 }
2583
2584 const MCExpr *IdVal;
2585 SMLoc S = Parser.getTok().getLoc();
2586 if (getParser().parseExpression(IdVal))
2587 return MatchOperand_ParseFail;
2588
2589 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2590 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2591 return MatchOperand_Success;
2592}
2593
David Blaikie960ea3f2014-06-08 16:18:35 +00002594MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002595MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002596 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002597 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002598
2599 SMLoc S = getLexer().getLoc();
2600
2601 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002602 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002603 if (ResTy != MatchOperand_NoMatch)
2604 return ResTy;
2605
Daniel Sanders315386c2014-04-01 10:40:14 +00002606 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002607 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002608 if (ResTy != MatchOperand_NoMatch)
2609 return ResTy;
2610
Daniel Sandersffd84362014-04-01 10:41:48 +00002611 const MCExpr *Expr = nullptr;
2612 if (Parser.parseExpression(Expr)) {
2613 // We have no way of knowing if a symbol was consumed so we must ParseFail
2614 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002615 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002616 Operands.push_back(
2617 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002618 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002619}
2620
Vladimir Medic2b953d02013-10-01 09:48:56 +00002621MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002622MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002624 const MCExpr *IdVal;
2625 // If the first token is '$' we may have register operand.
2626 if (Parser.getTok().is(AsmToken::Dollar))
2627 return MatchOperand_NoMatch;
2628 SMLoc S = Parser.getTok().getLoc();
2629 if (getParser().parseExpression(IdVal))
2630 return MatchOperand_ParseFail;
2631 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002632 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002633 int64_t Val = MCE->getValue();
2634 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2635 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002636 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002637 return MatchOperand_Success;
2638}
2639
Matheus Almeida779c5932013-11-18 12:32:49 +00002640MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002641MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002642 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002643 switch (getLexer().getKind()) {
2644 default:
2645 return MatchOperand_NoMatch;
2646 case AsmToken::LParen:
2647 case AsmToken::Plus:
2648 case AsmToken::Minus:
2649 case AsmToken::Integer:
2650 break;
2651 }
2652
2653 const MCExpr *Expr;
2654 SMLoc S = Parser.getTok().getLoc();
2655
2656 if (getParser().parseExpression(Expr))
2657 return MatchOperand_ParseFail;
2658
2659 int64_t Val;
2660 if (!Expr->EvaluateAsAbsolute(Val)) {
2661 Error(S, "expected immediate value");
2662 return MatchOperand_ParseFail;
2663 }
2664
2665 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2666 // and because the CPU always adds one to the immediate field, the allowed
2667 // range becomes 1..4. We'll only check the range here and will deal
2668 // with the addition/subtraction when actually decoding/encoding
2669 // the instruction.
2670 if (Val < 1 || Val > 4) {
2671 Error(S, "immediate not in range (1..4)");
2672 return MatchOperand_ParseFail;
2673 }
2674
Jack Carter3b2c96e2014-01-22 23:31:38 +00002675 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002676 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002677 return MatchOperand_Success;
2678}
2679
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002680MipsAsmParser::OperandMatchResultTy
2681MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2682 MCAsmParser &Parser = getParser();
2683 SmallVector<unsigned, 10> Regs;
2684 unsigned RegNo;
2685 unsigned PrevReg = Mips::NoRegister;
2686 bool RegRange = false;
2687 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2688
2689 if (Parser.getTok().isNot(AsmToken::Dollar))
2690 return MatchOperand_ParseFail;
2691
2692 SMLoc S = Parser.getTok().getLoc();
2693 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2694 SMLoc E = getLexer().getLoc();
2695 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2696 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2697 if (RegRange) {
2698 // Remove last register operand because registers from register range
2699 // should be inserted first.
2700 if (RegNo == Mips::RA) {
2701 Regs.push_back(RegNo);
2702 } else {
2703 unsigned TmpReg = PrevReg + 1;
2704 while (TmpReg <= RegNo) {
2705 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2706 Error(E, "invalid register operand");
2707 return MatchOperand_ParseFail;
2708 }
2709
2710 PrevReg = TmpReg;
2711 Regs.push_back(TmpReg++);
2712 }
2713 }
2714
2715 RegRange = false;
2716 } else {
2717 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2718 (RegNo != Mips::RA)) {
2719 Error(E, "$16 or $31 expected");
2720 return MatchOperand_ParseFail;
2721 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2722 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2723 Error(E, "invalid register operand");
2724 return MatchOperand_ParseFail;
2725 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2726 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2727 Error(E, "consecutive register numbers expected");
2728 return MatchOperand_ParseFail;
2729 }
2730
2731 Regs.push_back(RegNo);
2732 }
2733
2734 if (Parser.getTok().is(AsmToken::Minus))
2735 RegRange = true;
2736
2737 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2738 !Parser.getTok().isNot(AsmToken::Comma)) {
2739 Error(E, "',' or '-' expected");
2740 return MatchOperand_ParseFail;
2741 }
2742
2743 Lex(); // Consume comma or minus
2744 if (Parser.getTok().isNot(AsmToken::Dollar))
2745 break;
2746
2747 PrevReg = RegNo;
2748 }
2749
2750 SMLoc E = Parser.getTok().getLoc();
2751 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2752 parseMemOperand(Operands);
2753 return MatchOperand_Success;
2754}
2755
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002756MipsAsmParser::OperandMatchResultTy
2757MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2758 MCAsmParser &Parser = getParser();
2759
2760 SMLoc S = Parser.getTok().getLoc();
2761 if (parseAnyRegister(Operands) != MatchOperand_Success)
2762 return MatchOperand_ParseFail;
2763
2764 SMLoc E = Parser.getTok().getLoc();
2765 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2766 unsigned Reg = Op.getGPR32Reg();
2767 Operands.pop_back();
2768 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2769 return MatchOperand_Success;
2770}
2771
Jack Carterdc1e35d2012-09-06 20:00:02 +00002772MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2773
Vladimir Medic4c299852013-11-06 11:27:05 +00002774 MCSymbolRefExpr::VariantKind VK =
2775 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2776 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2777 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2778 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2779 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2780 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2781 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2782 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2783 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2784 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2785 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2786 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2787 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2788 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2789 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2790 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2791 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2792 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002793 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2794 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2795 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2796 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2797 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2798 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002799 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2800 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002801 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002802
Matheus Almeida2852af82014-04-22 10:15:54 +00002803 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002804
Jack Carterdc1e35d2012-09-06 20:00:02 +00002805 return VK;
2806}
Jack Cartera63b16a2012-09-07 00:23:42 +00002807
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002808/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2809/// either this.
2810/// ::= '(', register, ')'
2811/// handle it before we iterate so we don't get tripped up by the lack of
2812/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002813bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002814 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002815 if (getLexer().is(AsmToken::LParen)) {
2816 Operands.push_back(
2817 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2818 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002819 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 SMLoc Loc = getLexer().getLoc();
2821 Parser.eatToEndOfStatement();
2822 return Error(Loc, "unexpected token in argument list");
2823 }
2824 if (Parser.getTok().isNot(AsmToken::RParen)) {
2825 SMLoc Loc = getLexer().getLoc();
2826 Parser.eatToEndOfStatement();
2827 return Error(Loc, "unexpected token, expected ')'");
2828 }
2829 Operands.push_back(
2830 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2831 Parser.Lex();
2832 }
2833 return false;
2834}
2835
2836/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2837/// either one of these.
2838/// ::= '[', register, ']'
2839/// ::= '[', integer, ']'
2840/// handle it before we iterate so we don't get tripped up by the lack of
2841/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002842bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002843 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002844 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845 if (getLexer().is(AsmToken::LBrac)) {
2846 Operands.push_back(
2847 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2848 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002849 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 SMLoc Loc = getLexer().getLoc();
2851 Parser.eatToEndOfStatement();
2852 return Error(Loc, "unexpected token in argument list");
2853 }
2854 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2855 SMLoc Loc = getLexer().getLoc();
2856 Parser.eatToEndOfStatement();
2857 return Error(Loc, "unexpected token, expected ']'");
2858 }
2859 Operands.push_back(
2860 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2861 Parser.Lex();
2862 }
2863 return false;
2864}
2865
David Blaikie960ea3f2014-06-08 16:18:35 +00002866bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2867 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002868 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002869 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002870
2871 // We have reached first instruction, module directive are now forbidden.
2872 getTargetStreamer().forbidModuleDirective();
2873
Vladimir Medic74593e62013-07-17 15:00:42 +00002874 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002875 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002876 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002877 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002878 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002879 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002881
2882 // Read the remaining operands.
2883 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2884 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002885 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002886 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002887 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002888 return Error(Loc, "unexpected token in argument list");
2889 }
Toma Tabacu13964452014-09-04 13:23:44 +00002890 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002891 return true;
2892 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002893
Jack Carterd0bd6422013-04-18 00:41:53 +00002894 while (getLexer().is(AsmToken::Comma)) {
2895 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002896 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002897 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002898 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002899 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002900 return Error(Loc, "unexpected token in argument list");
2901 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002902 // Parse bracket and parenthesis suffixes before we iterate
2903 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002904 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002905 return true;
2906 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002907 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002908 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002909 }
2910 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002911 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2912 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002913 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002914 return Error(Loc, "unexpected token in argument list");
2915 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002916 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002917 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002918}
2919
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002920bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002921 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002922 SMLoc Loc = getLexer().getLoc();
2923 Parser.eatToEndOfStatement();
2924 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002925}
2926
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002927bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002928 return Error(Loc, ErrorMsg);
2929}
2930
Jack Carter0b744b32012-10-04 02:29:46 +00002931bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002932 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002933 // Line should look like: ".set noat".
2934 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002935 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002936 // eat noat
2937 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002938 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002939 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002940 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002941 return false;
2942 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002943 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002944 return false;
2945}
Jack Carterd0bd6422013-04-18 00:41:53 +00002946
Jack Carter0b744b32012-10-04 02:29:46 +00002947bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002948 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002949 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002950 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002951 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002952 getParser().Lex();
2953 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002954 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002955 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002956 return false;
2957 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002958 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002959 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002960 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002961 return false;
2962 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002963 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002964 const AsmToken &Reg = Parser.getTok();
2965 if (Reg.is(AsmToken::Identifier)) {
2966 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2967 } else if (Reg.is(AsmToken::Integer)) {
2968 AtRegNo = Reg.getIntVal();
2969 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002970 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002971 return false;
2972 }
Jack Carter1ac53222013-02-20 23:11:17 +00002973
Daniel Sanders71a89d922014-03-25 13:01:06 +00002974 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002975 reportParseError("unexpected token in statement");
2976 return false;
2977 }
2978
Toma Tabacu9db22db2014-09-09 10:15:38 +00002979 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002980 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002981 return false;
2982 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002983 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002984
2985 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002986 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002987 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002988 }
2989 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002990 return false;
2991 } else {
2992 reportParseError("unexpected token in statement");
2993 return false;
2994 }
2995}
2996
2997bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002998 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002999 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003000 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003001 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003002 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003003 return false;
3004 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003005 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003006 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003007 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003008 return false;
3009}
3010
3011bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003012 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003013 Parser.Lex();
3014 // If this is not the end of the statement, report an error.
3015 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003016 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003017 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003018 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003019 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003020 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003021 Parser.Lex(); // Consume the EndOfStatement.
3022 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003023}
3024
3025bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003026 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003027 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003028 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003029 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003030 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003031 return false;
3032 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003033 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003034 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003035 return false;
3036}
3037
3038bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003039 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003040 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003041 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003042 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003043 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003044 return false;
3045 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003046 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003047 reportParseError("`noreorder' must be set before `nomacro'");
3048 return false;
3049 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003050 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003051 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003052 return false;
3053}
Jack Carterd76b2372013-03-21 21:44:16 +00003054
Daniel Sanders44934432014-08-07 12:03:36 +00003055bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003056 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003057 Parser.Lex();
3058
3059 // If this is not the end of the statement, report an error.
3060 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003061 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003062
3063 setFeatureBits(Mips::FeatureMSA, "msa");
3064 getTargetStreamer().emitDirectiveSetMsa();
3065 return false;
3066}
3067
3068bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003069 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003070 Parser.Lex();
3071
3072 // If this is not the end of the statement, report an error.
3073 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003074 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003075
3076 clearFeatureBits(Mips::FeatureMSA, "msa");
3077 getTargetStreamer().emitDirectiveSetNoMsa();
3078 return false;
3079}
3080
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003081bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003082 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003083 Parser.Lex(); // Eat "nodsp".
3084
3085 // If this is not the end of the statement, report an error.
3086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3087 reportParseError("unexpected token, expected end of statement");
3088 return false;
3089 }
3090
3091 clearFeatureBits(Mips::FeatureDSP, "dsp");
3092 getTargetStreamer().emitDirectiveSetNoDsp();
3093 return false;
3094}
3095
Toma Tabacucc2502d2014-11-04 17:18:07 +00003096bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003097 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003098 Parser.Lex(); // Eat "mips16".
3099
Jack Carter39536722014-01-22 23:08:42 +00003100 // If this is not the end of the statement, report an error.
3101 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003102 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003103 return false;
3104 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003105
3106 setFeatureBits(Mips::FeatureMips16, "mips16");
3107 getTargetStreamer().emitDirectiveSetMips16();
3108 Parser.Lex(); // Consume the EndOfStatement.
3109 return false;
3110}
3111
3112bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003113 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003114 Parser.Lex(); // Eat "nomips16".
3115
3116 // If this is not the end of the statement, report an error.
3117 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3118 reportParseError("unexpected token, expected end of statement");
3119 return false;
3120 }
3121
3122 clearFeatureBits(Mips::FeatureMips16, "mips16");
3123 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003124 Parser.Lex(); // Consume the EndOfStatement.
3125 return false;
3126}
3127
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003128bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003129 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003130 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003131 // Line can be: .set fp=32
3132 // .set fp=xx
3133 // .set fp=64
3134 Parser.Lex(); // Eat fp token
3135 AsmToken Tok = Parser.getTok();
3136 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003137 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003138 return false;
3139 }
3140 Parser.Lex(); // Eat '=' token.
3141 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003142
3143 if (!parseFpABIValue(FpAbiVal, ".set"))
3144 return false;
3145
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003146 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003147 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003148 return false;
3149 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003150 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003151 Parser.Lex(); // Consume the EndOfStatement.
3152 return false;
3153}
3154
Toma Tabacu9db22db2014-09-09 10:15:38 +00003155bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003156 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003157 SMLoc Loc = getLexer().getLoc();
3158
3159 Parser.Lex();
3160 if (getLexer().isNot(AsmToken::EndOfStatement))
3161 return reportParseError("unexpected token, expected end of statement");
3162
3163 // Always keep an element on the options "stack" to prevent the user
3164 // from changing the initial options. This is how we remember them.
3165 if (AssemblerOptions.size() == 2)
3166 return reportParseError(Loc, ".set pop with no .set push");
3167
3168 AssemblerOptions.pop_back();
3169 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3170
3171 getTargetStreamer().emitDirectiveSetPop();
3172 return false;
3173}
3174
3175bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003176 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003177 Parser.Lex();
3178 if (getLexer().isNot(AsmToken::EndOfStatement))
3179 return reportParseError("unexpected token, expected end of statement");
3180
3181 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003182 AssemblerOptions.push_back(
3183 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003184
3185 getTargetStreamer().emitDirectiveSetPush();
3186 return false;
3187}
3188
Jack Carterd76b2372013-03-21 21:44:16 +00003189bool MipsAsmParser::parseSetAssignment() {
3190 StringRef Name;
3191 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003192 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003193
3194 if (Parser.parseIdentifier(Name))
3195 reportParseError("expected identifier after .set");
3196
3197 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003198 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003199 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003200
Jack Carter3b2c96e2014-01-22 23:31:38 +00003201 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003202 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003203
Jack Carterd0bd6422013-04-18 00:41:53 +00003204 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003205 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003206 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003207 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003208 Sym = getContext().GetOrCreateSymbol(Name);
3209 Sym->setVariableValue(Value);
3210
3211 return false;
3212}
Jack Carterd0bd6422013-04-18 00:41:53 +00003213
Toma Tabacu26647792014-09-09 12:52:14 +00003214bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003215 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003216 Parser.Lex();
3217 if (getLexer().isNot(AsmToken::EndOfStatement))
3218 return reportParseError("unexpected token, expected end of statement");
3219
3220 // Reset assembler options to their initial values.
3221 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3222 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3223
3224 getTargetStreamer().emitDirectiveSetMips0();
3225 return false;
3226}
3227
Toma Tabacu85618b32014-08-19 14:22:52 +00003228bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003229 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003230 Parser.Lex();
3231 if (getLexer().isNot(AsmToken::Equal))
3232 return reportParseError("unexpected token, expected equals sign");
3233
3234 Parser.Lex();
3235 StringRef Arch;
3236 if (Parser.parseIdentifier(Arch))
3237 return reportParseError("expected arch identifier");
3238
3239 StringRef ArchFeatureName =
3240 StringSwitch<StringRef>(Arch)
3241 .Case("mips1", "mips1")
3242 .Case("mips2", "mips2")
3243 .Case("mips3", "mips3")
3244 .Case("mips4", "mips4")
3245 .Case("mips5", "mips5")
3246 .Case("mips32", "mips32")
3247 .Case("mips32r2", "mips32r2")
3248 .Case("mips32r6", "mips32r6")
3249 .Case("mips64", "mips64")
3250 .Case("mips64r2", "mips64r2")
3251 .Case("mips64r6", "mips64r6")
3252 .Case("cnmips", "cnmips")
3253 .Case("r4000", "mips3") // This is an implementation of Mips3.
3254 .Default("");
3255
3256 if (ArchFeatureName.empty())
3257 return reportParseError("unsupported architecture");
3258
3259 selectArch(ArchFeatureName);
3260 getTargetStreamer().emitDirectiveSetArch(Arch);
3261 return false;
3262}
3263
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003264bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003265 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003266 Parser.Lex();
3267 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003268 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003269
Matheus Almeida2852af82014-04-22 10:15:54 +00003270 switch (Feature) {
3271 default:
3272 llvm_unreachable("Unimplemented feature");
3273 case Mips::FeatureDSP:
3274 setFeatureBits(Mips::FeatureDSP, "dsp");
3275 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003276 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003277 case Mips::FeatureMicroMips:
3278 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003279 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003280 case Mips::FeatureMips1:
3281 selectArch("mips1");
3282 getTargetStreamer().emitDirectiveSetMips1();
3283 break;
3284 case Mips::FeatureMips2:
3285 selectArch("mips2");
3286 getTargetStreamer().emitDirectiveSetMips2();
3287 break;
3288 case Mips::FeatureMips3:
3289 selectArch("mips3");
3290 getTargetStreamer().emitDirectiveSetMips3();
3291 break;
3292 case Mips::FeatureMips4:
3293 selectArch("mips4");
3294 getTargetStreamer().emitDirectiveSetMips4();
3295 break;
3296 case Mips::FeatureMips5:
3297 selectArch("mips5");
3298 getTargetStreamer().emitDirectiveSetMips5();
3299 break;
3300 case Mips::FeatureMips32:
3301 selectArch("mips32");
3302 getTargetStreamer().emitDirectiveSetMips32();
3303 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003304 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003305 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003306 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003307 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003308 case Mips::FeatureMips32r6:
3309 selectArch("mips32r6");
3310 getTargetStreamer().emitDirectiveSetMips32R6();
3311 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003312 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003313 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003314 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003315 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003316 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003317 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003318 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003319 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003320 case Mips::FeatureMips64r6:
3321 selectArch("mips64r6");
3322 getTargetStreamer().emitDirectiveSetMips64R6();
3323 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003324 }
3325 return false;
3326}
3327
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003328bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003329 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003330 if (getLexer().isNot(AsmToken::Comma)) {
3331 SMLoc Loc = getLexer().getLoc();
3332 Parser.eatToEndOfStatement();
3333 return Error(Loc, ErrorStr);
3334 }
3335
Matheus Almeida2852af82014-04-22 10:15:54 +00003336 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003337 return true;
3338}
3339
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003340bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003341 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003342 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003343
Toma Tabacudde4c462014-11-06 10:02:45 +00003344 if (inMips16Mode()) {
3345 reportParseError(".cpload is not supported in Mips16 mode");
3346 return false;
3347 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003348
David Blaikie960ea3f2014-06-08 16:18:35 +00003349 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003350 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003351 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3352 reportParseError("expected register containing function address");
3353 return false;
3354 }
3355
David Blaikie960ea3f2014-06-08 16:18:35 +00003356 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3357 if (!RegOpnd.isGPRAsmReg()) {
3358 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003359 return false;
3360 }
3361
Toma Tabacudde4c462014-11-06 10:02:45 +00003362 // If this is not the end of the statement, report an error.
3363 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3364 reportParseError("unexpected token, expected end of statement");
3365 return false;
3366 }
3367
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003368 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003369 return false;
3370}
3371
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003372bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003373 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003374 unsigned FuncReg;
3375 unsigned Save;
3376 bool SaveIsReg = true;
3377
Matheus Almeida7e815762014-06-18 13:08:59 +00003378 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003379 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003380 if (ResTy == MatchOperand_NoMatch) {
3381 reportParseError("expected register containing function address");
3382 Parser.eatToEndOfStatement();
3383 return false;
3384 }
3385
3386 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3387 if (!FuncRegOpnd.isGPRAsmReg()) {
3388 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3389 Parser.eatToEndOfStatement();
3390 return false;
3391 }
3392
3393 FuncReg = FuncRegOpnd.getGPR32Reg();
3394 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003395
Toma Tabacu65f10572014-09-16 15:00:52 +00003396 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003397 return true;
3398
Toma Tabacu13964452014-09-04 13:23:44 +00003399 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003400 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003401 const AsmToken &Tok = Parser.getTok();
3402 if (Tok.is(AsmToken::Integer)) {
3403 Save = Tok.getIntVal();
3404 SaveIsReg = false;
3405 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003406 } else {
3407 reportParseError("expected save register or stack offset");
3408 Parser.eatToEndOfStatement();
3409 return false;
3410 }
3411 } else {
3412 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3413 if (!SaveOpnd.isGPRAsmReg()) {
3414 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3415 Parser.eatToEndOfStatement();
3416 return false;
3417 }
3418 Save = SaveOpnd.getGPR32Reg();
3419 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003420
Toma Tabacu65f10572014-09-16 15:00:52 +00003421 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003422 return true;
3423
3424 StringRef Name;
3425 if (Parser.parseIdentifier(Name))
3426 reportParseError("expected identifier");
3427 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003428
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003429 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003430 return false;
3431}
3432
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003433bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003434 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003435 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3436 const AsmToken &Tok = Parser.getTok();
3437
3438 if (Tok.getString() == "2008") {
3439 Parser.Lex();
3440 getTargetStreamer().emitDirectiveNaN2008();
3441 return false;
3442 } else if (Tok.getString() == "legacy") {
3443 Parser.Lex();
3444 getTargetStreamer().emitDirectiveNaNLegacy();
3445 return false;
3446 }
3447 }
3448 // If we don't recognize the option passed to the .nan
3449 // directive (e.g. no option or unknown option), emit an error.
3450 reportParseError("invalid option in .nan directive");
3451 return false;
3452}
3453
Jack Carter0b744b32012-10-04 02:29:46 +00003454bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003455 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003456 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003457 const AsmToken &Tok = Parser.getTok();
3458
3459 if (Tok.getString() == "noat") {
3460 return parseSetNoAtDirective();
3461 } else if (Tok.getString() == "at") {
3462 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003463 } else if (Tok.getString() == "arch") {
3464 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003465 } else if (Tok.getString() == "fp") {
3466 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003467 } else if (Tok.getString() == "pop") {
3468 return parseSetPopDirective();
3469 } else if (Tok.getString() == "push") {
3470 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003471 } else if (Tok.getString() == "reorder") {
3472 return parseSetReorderDirective();
3473 } else if (Tok.getString() == "noreorder") {
3474 return parseSetNoReorderDirective();
3475 } else if (Tok.getString() == "macro") {
3476 return parseSetMacroDirective();
3477 } else if (Tok.getString() == "nomacro") {
3478 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003479 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003480 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003481 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003482 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003483 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003484 getTargetStreamer().emitDirectiveSetNoMicroMips();
3485 Parser.eatToEndOfStatement();
3486 return false;
3487 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003488 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003489 } else if (Tok.getString() == "mips0") {
3490 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003491 } else if (Tok.getString() == "mips1") {
3492 return parseSetFeature(Mips::FeatureMips1);
3493 } else if (Tok.getString() == "mips2") {
3494 return parseSetFeature(Mips::FeatureMips2);
3495 } else if (Tok.getString() == "mips3") {
3496 return parseSetFeature(Mips::FeatureMips3);
3497 } else if (Tok.getString() == "mips4") {
3498 return parseSetFeature(Mips::FeatureMips4);
3499 } else if (Tok.getString() == "mips5") {
3500 return parseSetFeature(Mips::FeatureMips5);
3501 } else if (Tok.getString() == "mips32") {
3502 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003503 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003504 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003505 } else if (Tok.getString() == "mips32r6") {
3506 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003507 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003508 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003509 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003510 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003511 } else if (Tok.getString() == "mips64r6") {
3512 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003513 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003514 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003515 } else if (Tok.getString() == "nodsp") {
3516 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003517 } else if (Tok.getString() == "msa") {
3518 return parseSetMsaDirective();
3519 } else if (Tok.getString() == "nomsa") {
3520 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003521 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003522 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003523 parseSetAssignment();
3524 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003525 }
Jack Carter07c818d2013-01-25 01:31:34 +00003526
Jack Carter0b744b32012-10-04 02:29:46 +00003527 return true;
3528}
3529
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003530/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003531/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003532bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003533 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3535 for (;;) {
3536 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003537 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003538 return true;
3539
3540 getParser().getStreamer().EmitValue(Value, Size);
3541
3542 if (getLexer().is(AsmToken::EndOfStatement))
3543 break;
3544
Jack Carter07c818d2013-01-25 01:31:34 +00003545 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003546 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003547 Parser.Lex();
3548 }
3549 }
3550
3551 Parser.Lex();
3552 return false;
3553}
3554
Vladimir Medic4c299852013-11-06 11:27:05 +00003555/// parseDirectiveGpWord
3556/// ::= .gpword local_sym
3557bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003558 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003559 const MCExpr *Value;
3560 // EmitGPRel32Value requires an expression, so we are using base class
3561 // method to evaluate the expression.
3562 if (getParser().parseExpression(Value))
3563 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003564 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003565
Vladimir Medice10c1122013-11-13 13:18:04 +00003566 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003567 return Error(getLexer().getLoc(),
3568 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003569 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003570 return false;
3571}
3572
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003573/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003574/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003575bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003576 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003577 const MCExpr *Value;
3578 // EmitGPRel64Value requires an expression, so we are using base class
3579 // method to evaluate the expression.
3580 if (getParser().parseExpression(Value))
3581 return true;
3582 getParser().getStreamer().EmitGPRel64Value(Value);
3583
3584 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003585 return Error(getLexer().getLoc(),
3586 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003587 Parser.Lex(); // Eat EndOfStatement token.
3588 return false;
3589}
3590
Jack Carter0cd3c192014-01-06 23:27:31 +00003591bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003592 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003593 // Get the option token.
3594 AsmToken Tok = Parser.getTok();
3595 // At the moment only identifiers are supported.
3596 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003597 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003598 Parser.eatToEndOfStatement();
3599 return false;
3600 }
3601
3602 StringRef Option = Tok.getIdentifier();
3603
3604 if (Option == "pic0") {
3605 getTargetStreamer().emitDirectiveOptionPic0();
3606 Parser.Lex();
3607 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3608 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003609 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003610 Parser.eatToEndOfStatement();
3611 }
3612 return false;
3613 }
3614
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003615 if (Option == "pic2") {
3616 getTargetStreamer().emitDirectiveOptionPic2();
3617 Parser.Lex();
3618 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3619 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003620 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003621 Parser.eatToEndOfStatement();
3622 }
3623 return false;
3624 }
3625
Jack Carter0cd3c192014-01-06 23:27:31 +00003626 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003627 Warning(Parser.getTok().getLoc(),
3628 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003629 Parser.eatToEndOfStatement();
3630 return false;
3631}
3632
Daniel Sanders7e527422014-07-10 13:38:23 +00003633/// parseDirectiveModule
3634/// ::= .module oddspreg
3635/// ::= .module nooddspreg
3636/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003637bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003638 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003639 MCAsmLexer &Lexer = getLexer();
3640 SMLoc L = Lexer.getLoc();
3641
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003642 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003643 // TODO : get a better message.
3644 reportParseError(".module directive must appear before any code");
3645 return false;
3646 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003647
3648 if (Lexer.is(AsmToken::Identifier)) {
3649 StringRef Option = Parser.getTok().getString();
3650 Parser.Lex();
3651
3652 if (Option == "oddspreg") {
3653 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3654 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3655
3656 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003657 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003658 return false;
3659 }
3660
3661 return false;
3662 } else if (Option == "nooddspreg") {
3663 if (!isABI_O32()) {
3664 Error(L, "'.module nooddspreg' requires the O32 ABI");
3665 return false;
3666 }
3667
3668 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3669 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3670
3671 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003672 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003673 return false;
3674 }
3675
3676 return false;
3677 } else if (Option == "fp") {
3678 return parseDirectiveModuleFP();
3679 }
3680
3681 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003682 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003683
3684 return false;
3685}
3686
3687/// parseDirectiveModuleFP
3688/// ::= =32
3689/// ::= =xx
3690/// ::= =64
3691bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003692 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003693 MCAsmLexer &Lexer = getLexer();
3694
3695 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003696 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003697 return false;
3698 }
3699 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003700
Daniel Sanders7e527422014-07-10 13:38:23 +00003701 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003702 if (!parseFpABIValue(FpABI, ".module"))
3703 return false;
3704
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003705 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003706 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003707 return false;
3708 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003709
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003710 // Emit appropriate flags.
3711 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003712 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003713 return false;
3714}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003715
Daniel Sanders7e527422014-07-10 13:38:23 +00003716bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003717 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003718 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003719 MCAsmLexer &Lexer = getLexer();
3720
3721 if (Lexer.is(AsmToken::Identifier)) {
3722 StringRef Value = Parser.getTok().getString();
3723 Parser.Lex();
3724
3725 if (Value != "xx") {
3726 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3727 return false;
3728 }
3729
3730 if (!isABI_O32()) {
3731 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3732 return false;
3733 }
3734
Daniel Sanders7e527422014-07-10 13:38:23 +00003735 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003736 return true;
3737 }
3738
3739 if (Lexer.is(AsmToken::Integer)) {
3740 unsigned Value = Parser.getTok().getIntVal();
3741 Parser.Lex();
3742
3743 if (Value != 32 && Value != 64) {
3744 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3745 return false;
3746 }
3747
3748 if (Value == 32) {
3749 if (!isABI_O32()) {
3750 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3751 return false;
3752 }
3753
Daniel Sanders7e527422014-07-10 13:38:23 +00003754 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3755 } else
3756 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003757
Daniel Sanders7e527422014-07-10 13:38:23 +00003758 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003759 }
3760
3761 return false;
3762}
3763
Jack Carter0b744b32012-10-04 02:29:46 +00003764bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003765 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003766 StringRef IDVal = DirectiveID.getString();
3767
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003768 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003769 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003770 if (IDVal == ".dword") {
3771 parseDataDirective(8, DirectiveID.getLoc());
3772 return false;
3773 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003774 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003775 StringRef SymbolName;
3776
3777 if (Parser.parseIdentifier(SymbolName)) {
3778 reportParseError("expected identifier after .ent");
3779 return false;
3780 }
3781
3782 // There's an undocumented extension that allows an integer to
3783 // follow the name of the procedure which AFAICS is ignored by GAS.
3784 // Example: .ent foo,2
3785 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3786 if (getLexer().isNot(AsmToken::Comma)) {
3787 // Even though we accept this undocumented extension for compatibility
3788 // reasons, the additional integer argument does not actually change
3789 // the behaviour of the '.ent' directive, so we would like to discourage
3790 // its use. We do this by not referring to the extended version in
3791 // error messages which are not directly related to its use.
3792 reportParseError("unexpected token, expected end of statement");
3793 return false;
3794 }
3795 Parser.Lex(); // Eat the comma.
3796 const MCExpr *DummyNumber;
3797 int64_t DummyNumberVal;
3798 // If the user was explicitly trying to use the extended version,
3799 // we still give helpful extension-related error messages.
3800 if (Parser.parseExpression(DummyNumber)) {
3801 reportParseError("expected number after comma");
3802 return false;
3803 }
3804 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3805 reportParseError("expected an absolute expression after comma");
3806 return false;
3807 }
3808 }
3809
3810 // If this is not the end of the statement, report an error.
3811 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3812 reportParseError("unexpected token, expected end of statement");
3813 return false;
3814 }
3815
3816 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3817
3818 getTargetStreamer().emitDirectiveEnt(*Sym);
3819 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003820 return false;
3821 }
3822
Jack Carter07c818d2013-01-25 01:31:34 +00003823 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003824 StringRef SymbolName;
3825
3826 if (Parser.parseIdentifier(SymbolName)) {
3827 reportParseError("expected identifier after .end");
3828 return false;
3829 }
3830
3831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3832 reportParseError("unexpected token, expected end of statement");
3833 return false;
3834 }
3835
3836 if (CurrentFn == nullptr) {
3837 reportParseError(".end used without .ent");
3838 return false;
3839 }
3840
3841 if ((SymbolName != CurrentFn->getName())) {
3842 reportParseError(".end symbol does not match .ent symbol");
3843 return false;
3844 }
3845
3846 getTargetStreamer().emitDirectiveEnd(SymbolName);
3847 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003848 return false;
3849 }
3850
Jack Carter07c818d2013-01-25 01:31:34 +00003851 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003852 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3853 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003854 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003855 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3856 reportParseError("expected stack register");
3857 return false;
3858 }
3859
3860 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3861 if (!StackRegOpnd.isGPRAsmReg()) {
3862 reportParseError(StackRegOpnd.getStartLoc(),
3863 "expected general purpose register");
3864 return false;
3865 }
3866 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3867
3868 if (Parser.getTok().is(AsmToken::Comma))
3869 Parser.Lex();
3870 else {
3871 reportParseError("unexpected token, expected comma");
3872 return false;
3873 }
3874
3875 // Parse the frame size.
3876 const MCExpr *FrameSize;
3877 int64_t FrameSizeVal;
3878
3879 if (Parser.parseExpression(FrameSize)) {
3880 reportParseError("expected frame size value");
3881 return false;
3882 }
3883
3884 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3885 reportParseError("frame size not an absolute expression");
3886 return false;
3887 }
3888
3889 if (Parser.getTok().is(AsmToken::Comma))
3890 Parser.Lex();
3891 else {
3892 reportParseError("unexpected token, expected comma");
3893 return false;
3894 }
3895
3896 // Parse the return register.
3897 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003898 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003899 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3900 reportParseError("expected return register");
3901 return false;
3902 }
3903
3904 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3905 if (!ReturnRegOpnd.isGPRAsmReg()) {
3906 reportParseError(ReturnRegOpnd.getStartLoc(),
3907 "expected general purpose register");
3908 return false;
3909 }
3910
3911 // If this is not the end of the statement, report an error.
3912 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3913 reportParseError("unexpected token, expected end of statement");
3914 return false;
3915 }
3916
3917 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3918 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003919 return false;
3920 }
3921
Jack Carter07c818d2013-01-25 01:31:34 +00003922 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003923 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003924 }
3925
Daniel Sandersd97a6342014-08-13 10:07:34 +00003926 if (IDVal == ".mask" || IDVal == ".fmask") {
3927 // .mask bitmask, frame_offset
3928 // bitmask: One bit for each register used.
3929 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3930 // first register is expected to be saved.
3931 // Examples:
3932 // .mask 0x80000000, -4
3933 // .fmask 0x80000000, -4
3934 //
Jack Carterbe332172012-09-07 00:48:02 +00003935
Daniel Sandersd97a6342014-08-13 10:07:34 +00003936 // Parse the bitmask
3937 const MCExpr *BitMask;
3938 int64_t BitMaskVal;
3939
3940 if (Parser.parseExpression(BitMask)) {
3941 reportParseError("expected bitmask value");
3942 return false;
3943 }
3944
3945 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3946 reportParseError("bitmask not an absolute expression");
3947 return false;
3948 }
3949
3950 if (Parser.getTok().is(AsmToken::Comma))
3951 Parser.Lex();
3952 else {
3953 reportParseError("unexpected token, expected comma");
3954 return false;
3955 }
3956
3957 // Parse the frame_offset
3958 const MCExpr *FrameOffset;
3959 int64_t FrameOffsetVal;
3960
3961 if (Parser.parseExpression(FrameOffset)) {
3962 reportParseError("expected frame offset value");
3963 return false;
3964 }
3965
3966 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3967 reportParseError("frame offset not an absolute expression");
3968 return false;
3969 }
3970
3971 // If this is not the end of the statement, report an error.
3972 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3973 reportParseError("unexpected token, expected end of statement");
3974 return false;
3975 }
3976
3977 if (IDVal == ".mask")
3978 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3979 else
3980 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003981 return false;
3982 }
3983
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003984 if (IDVal == ".nan")
3985 return parseDirectiveNaN();
3986
Jack Carter07c818d2013-01-25 01:31:34 +00003987 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003988 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003989 return false;
3990 }
3991
Rafael Espindolab59fb732014-03-28 18:50:26 +00003992 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003993 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003994 return false;
3995 }
3996
Jack Carter07c818d2013-01-25 01:31:34 +00003997 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003998 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003999 return false;
4000 }
4001
Jack Carter0cd3c192014-01-06 23:27:31 +00004002 if (IDVal == ".option")
4003 return parseDirectiveOption();
4004
4005 if (IDVal == ".abicalls") {
4006 getTargetStreamer().emitDirectiveAbiCalls();
4007 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004008 Error(Parser.getTok().getLoc(),
4009 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004010 // Clear line
4011 Parser.eatToEndOfStatement();
4012 }
4013 return false;
4014 }
4015
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004016 if (IDVal == ".cpsetup")
4017 return parseDirectiveCPSetup();
4018
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004019 if (IDVal == ".module")
4020 return parseDirectiveModule();
4021
Rafael Espindola870c4e92012-01-11 03:56:41 +00004022 return true;
4023}
4024
Rafael Espindola870c4e92012-01-11 03:56:41 +00004025extern "C" void LLVMInitializeMipsAsmParser() {
4026 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4027 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4028 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4029 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4030}
Jack Carterb4dbc172012-09-05 23:34:03 +00004031
4032#define GET_REGISTER_MATCHER
4033#define GET_MATCHER_IMPLEMENTATION
4034#include "MipsGenAsmMatcher.inc"