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