blob: ec7d5074d391b1b22db8ea671bea33c29da23536 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000017#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000020#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCParser/MCAsmLexer.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000026#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000027#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000028#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000029#include "llvm/Support/TargetRegistry.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000031#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000032
33using namespace llvm;
34
Chandler Carruthe96dd892014-04-21 22:55:11 +000035#define DEBUG_TYPE "mips-asm-parser"
36
Joey Gouly0e76fa72013-09-12 10:28:05 +000037namespace llvm {
38class MCInstrInfo;
39}
40
Rafael Espindola870c4e92012-01-11 03:56:41 +000041namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000042class MipsAssemblerOptions {
43public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000044 MipsAssemblerOptions(uint64_t Features_) :
45 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000046
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48 ATReg = Opts->getATRegNum();
49 Reorder = Opts->isReorder();
50 Macro = Opts->isMacro();
51 Features = Opts->getFeatures();
52 }
53
54 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000055 bool setATReg(unsigned Reg);
56
Toma Tabacu9db22db2014-09-09 10:15:38 +000057 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000058 void setReorder() { Reorder = true; }
59 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000060
Toma Tabacu9db22db2014-09-09 10:15:38 +000061 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000062 void setMacro() { Macro = true; }
63 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 uint64_t getFeatures() const { return Features; }
66 void setFeatures(uint64_t Features_) { Features = Features_; }
67
Daniel Sandersf0df2212014-08-04 12:20:00 +000068 // Set of features that are either architecture features or referenced
69 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71 // The reason we need this mask is explained in the selectArch function.
72 // FIXME: Ideally we would like TableGen to generate this information.
73 static const uint64_t AllArchRelatedMask =
74 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81
Jack Carter0b744b32012-10-04 02:29:46 +000082private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000083 unsigned ATReg;
84 bool Reorder;
85 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000086 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000087};
88}
89
90namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000091class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000092 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000093 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 return static_cast<MipsTargetStreamer &>(TS);
95 }
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 MCSubtargetInfo &STI;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Daniel Sandersef638fe2014-10-03 15:37:37 +0000104 // Print a warning along with its fix-it message at the given range.
105 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
106 SMRange Range, bool ShowColors = true);
107
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000108#define GET_ASSEMBLER_HEADER
109#include "MipsGenAsmMatcher.inc"
110
Matheus Almeida595fcab2014-06-11 15:05:56 +0000111 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
112
Chad Rosier49963552012-10-13 00:26:04 +0000113 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000114 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000115 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000116 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000117
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Toma Tabacu13964452014-09-04 13:23:44 +0000121 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
David Blaikie960ea3f2014-06-08 16:18:35 +0000125 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
126 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Craig Topper56c590a2014-04-29 07:58:02 +0000128 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000135
Jack Carter873c7242013-01-12 01:03:14 +0000136 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000137 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000149 MipsAsmParser::OperandMatchResultTy
150 parseRegisterList (OperandVector &Operands);
151
David Blaikie960ea3f2014-06-08 16:18:35 +0000152 bool searchSymbolAlias(OperandVector &Operands);
153
Toma Tabacu13964452014-09-04 13:23:44 +0000154 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000155
Jack Carter30a59822012-10-04 04:03:53 +0000156 bool needsExpansion(MCInst &Inst);
157
Matheus Almeida3813d572014-06-19 14:39:14 +0000158 // Expands assembly pseudo instructions.
159 // Returns false on success, true otherwise.
160 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000161 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000162
163 bool expandLoadImm(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 expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000167 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000168
169 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
Toma Tabacu0d64b202014-08-14 10:29:17 +0000172 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
173 SmallVectorImpl<MCInst> &Instructions);
174
Jack Carter9e65aa32013-03-22 00:05:30 +0000175 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000176 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
177 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000178 bool reportParseError(Twine ErrorMsg);
179 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000180
Jack Carterb5cf5902013-04-17 00:18:04 +0000181 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000182 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000183
Vladimir Medic4c299852013-11-06 11:27:05 +0000184 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000185
186 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000187 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000188 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000189 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000190 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000191 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000192 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000193 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000194 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000195
196 bool parseSetAtDirective();
197 bool parseSetNoAtDirective();
198 bool parseSetMacroDirective();
199 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000200 bool parseSetMsaDirective();
201 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000202 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000203 bool parseSetReorderDirective();
204 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000205 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000206 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000207 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000208 bool parseSetPopDirective();
209 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000210
Jack Carterd76b2372013-03-21 21:44:16 +0000211 bool parseSetAssignment();
212
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000213 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000214 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000215 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000216 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000217 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000218 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
219 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000220
Jack Carterdc1e35d2012-09-06 20:00:02 +0000221 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000222
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000223 bool eatComma(StringRef ErrorStr);
224
Jack Carter1ac53222013-02-20 23:11:17 +0000225 int matchCPURegisterName(StringRef Symbol);
226
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000227 int matchHWRegsRegisterName(StringRef Symbol);
228
Jack Carter873c7242013-01-12 01:03:14 +0000229 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000230
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000231 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000232
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000233 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000234
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000235 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000236
Jack Carter5dc8ac92013-09-25 23:50:44 +0000237 int matchMSA128RegisterName(StringRef Name);
238
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000239 int matchMSA128CtrlRegisterName(StringRef Name);
240
Jack Carterd0bd6422013-04-18 00:41:53 +0000241 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000242
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000243 unsigned getGPR(int RegNo);
244
Matheus Almeida7de68e72014-06-18 14:46:05 +0000245 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000246
247 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000248 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000249
250 // Helper function that checks if the value of a vector index is within the
251 // boundaries of accepted values for each RegisterKind
252 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
253 bool validateMSAIndex(int Val, int RegKind);
254
Daniel Sandersf0df2212014-08-04 12:20:00 +0000255 // Selects a new architecture by updating the FeatureBits with the necessary
256 // info including implied dependencies.
257 // Internally, it clears all the feature bits related to *any* architecture
258 // and selects the new one using the ToggleFeature functionality of the
259 // MCSubtargetInfo object that handles implied dependencies. The reason we
260 // clear all the arch related bits manually is because ToggleFeature only
261 // clears the features that imply the feature being cleared and not the
262 // features implied by the feature being cleared. This is easier to see
263 // with an example:
264 // --------------------------------------------------
265 // | Feature | Implies |
266 // | -------------------------------------------------|
267 // | FeatureMips1 | None |
268 // | FeatureMips2 | FeatureMips1 |
269 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
270 // | FeatureMips4 | FeatureMips3 |
271 // | ... | |
272 // --------------------------------------------------
273 //
274 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
275 // FeatureMipsGP64 | FeatureMips1)
276 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
277 void selectArch(StringRef ArchFeature) {
278 uint64_t FeatureBits = STI.getFeatureBits();
279 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
280 STI.setFeatureBits(FeatureBits);
281 setAvailableFeatures(
282 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000283 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000284 }
285
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000286 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000288 setAvailableFeatures(
289 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000291 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000292 }
293
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000294 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000296 setAvailableFeatures(
297 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000298 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000299 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000300 }
301
Rafael Espindola870c4e92012-01-11 03:56:41 +0000302public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000303 enum MipsMatchResultTy {
304 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
305#define GET_OPERAND_DIAGNOSTIC_TYPES
306#include "MipsGenAsmMatcher.inc"
307#undef GET_OPERAND_DIAGNOSTIC_TYPES
308
309 };
310
Joey Gouly0e76fa72013-09-12 10:28:05 +0000311 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000312 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000313 : MCTargetAsmParser(), STI(sti) {
314 MCAsmParserExtension::Initialize(parser);
315
Jack Carterb4dbc172012-09-05 23:34:03 +0000316 // Initialize the set of available features.
317 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000318
319 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000320 AssemblerOptions.push_back(
321 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000322
323 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000324 AssemblerOptions.push_back(
325 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000326
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000327 getTargetStreamer().updateABIInfo(*this);
328
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000329 // Assert exactly one ABI was chosen.
330 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
331 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
332 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
333 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000334
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000335 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000336 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000337
338 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000339 }
340
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000341 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
342 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
343
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000344 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
345 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
346 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
347 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
348 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000349 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000350
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000351 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000352 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
353 }
354
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000355 bool inMicroMipsMode() const {
356 return STI.getFeatureBits() & Mips::FeatureMicroMips;
357 }
358 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
359 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
360 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
361 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
362 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
363 bool hasMips32() const {
364 return (STI.getFeatureBits() & Mips::FeatureMips32);
365 }
366 bool hasMips64() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips64);
368 }
369 bool hasMips32r2() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
371 }
372 bool hasMips64r2() const {
373 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
374 }
375 bool hasMips32r6() const {
376 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
377 }
378 bool hasMips64r6() const {
379 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
380 }
381 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
382 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
383 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
384
385 bool inMips16Mode() const {
386 return STI.getFeatureBits() & Mips::FeatureMips16;
387 }
388 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000389 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000391 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000392 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000393};
394}
395
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000396namespace {
397
398/// MipsOperand - Instances of this class represent a parsed Mips machine
399/// instruction.
400class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000401public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000402 /// Broad categories of register classes
403 /// The exact class is finalized by the render method.
404 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000405 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000406 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000408 RegKind_FCC = 4, /// FCC
409 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
410 RegKind_MSACtrl = 16, /// MSA control registers
411 RegKind_COP2 = 32, /// COP2
412 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
413 /// context).
414 RegKind_CCR = 128, /// CCR
415 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000416 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000417
418 /// Potentially any (e.g. $1)
419 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
420 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000421 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000422 };
423
424private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000425 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000426 k_Immediate, /// An immediate (possibly involving symbol references)
427 k_Memory, /// Base + Offset Memory Address
428 k_PhysRegister, /// A physical register from the Mips namespace
429 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000430 k_Token, /// A simple token
431 k_RegList /// A physical register list
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000432 } Kind;
433
David Blaikie960ea3f2014-06-08 16:18:35 +0000434public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000435 MipsOperand(KindTy K, MipsAsmParser &Parser)
436 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
437
David Blaikie960ea3f2014-06-08 16:18:35 +0000438private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000439 /// For diagnostics, and checking the assembler temporary
440 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000441
Eric Christopher8996c5d2013-03-15 00:42:55 +0000442 struct Token {
443 const char *Data;
444 unsigned Length;
445 };
446
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000447 struct PhysRegOp {
448 unsigned Num; /// Register Number
449 };
450
451 struct RegIdxOp {
452 unsigned Index; /// Index into the register class
453 RegKind Kind; /// Bitfield of the kinds it could possibly be
454 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000455 };
456
457 struct ImmOp {
458 const MCExpr *Val;
459 };
460
461 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000462 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000463 const MCExpr *Off;
464 };
465
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000466 struct RegListOp {
467 SmallVector<unsigned, 10> *List;
468 };
469
Jack Carterb4dbc172012-09-05 23:34:03 +0000470 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000471 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000472 struct PhysRegOp PhysReg;
473 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000474 struct ImmOp Imm;
475 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000476 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000477 };
478
479 SMLoc StartLoc, EndLoc;
480
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000481 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000482 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
483 const MCRegisterInfo *RegInfo,
484 SMLoc S, SMLoc E,
485 MipsAsmParser &Parser) {
486 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000487 Op->RegIdx.Index = Index;
488 Op->RegIdx.RegInfo = RegInfo;
489 Op->RegIdx.Kind = RegKind;
490 Op->StartLoc = S;
491 Op->EndLoc = E;
492 return Op;
493 }
494
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000495public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000496 /// Coerce the register to GPR32 and return the real register for the current
497 /// target.
498 unsigned getGPR32Reg() const {
499 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000500 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000501 unsigned ClassID = Mips::GPR32RegClassID;
502 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000503 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000504
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000505 /// Coerce the register to GPR32 and return the real register for the current
506 /// target.
507 unsigned getGPRMM16Reg() const {
508 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
509 unsigned ClassID = Mips::GPR32RegClassID;
510 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
511 }
512
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000513 /// Coerce the register to GPR64 and return the real register for the current
514 /// target.
515 unsigned getGPR64Reg() const {
516 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
517 unsigned ClassID = Mips::GPR64RegClassID;
518 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000519 }
520
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521private:
522 /// Coerce the register to AFGR64 and return the real register for the current
523 /// target.
524 unsigned getAFGR64Reg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
526 if (RegIdx.Index % 2 != 0)
527 AsmParser.Warning(StartLoc, "Float register should be even.");
528 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
529 .getRegister(RegIdx.Index / 2);
530 }
531
532 /// Coerce the register to FGR64 and return the real register for the current
533 /// target.
534 unsigned getFGR64Reg() const {
535 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
536 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
537 .getRegister(RegIdx.Index);
538 }
539
540 /// Coerce the register to FGR32 and return the real register for the current
541 /// target.
542 unsigned getFGR32Reg() const {
543 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
544 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
545 .getRegister(RegIdx.Index);
546 }
547
548 /// Coerce the register to FGRH32 and return the real register for the current
549 /// target.
550 unsigned getFGRH32Reg() const {
551 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
552 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
553 .getRegister(RegIdx.Index);
554 }
555
556 /// Coerce the register to FCC and return the real register for the current
557 /// target.
558 unsigned getFCCReg() const {
559 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
560 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
561 .getRegister(RegIdx.Index);
562 }
563
564 /// Coerce the register to MSA128 and return the real register for the current
565 /// target.
566 unsigned getMSA128Reg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
568 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
569 // identical
570 unsigned ClassID = Mips::MSA128BRegClassID;
571 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
572 }
573
574 /// Coerce the register to MSACtrl and return the real register for the
575 /// current target.
576 unsigned getMSACtrlReg() const {
577 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
578 unsigned ClassID = Mips::MSACtrlRegClassID;
579 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
580 }
581
582 /// Coerce the register to COP2 and return the real register for the
583 /// current target.
584 unsigned getCOP2Reg() const {
585 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
586 unsigned ClassID = Mips::COP2RegClassID;
587 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
588 }
589
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000590 /// Coerce the register to COP3 and return the real register for the
591 /// current target.
592 unsigned getCOP3Reg() const {
593 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
594 unsigned ClassID = Mips::COP3RegClassID;
595 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
596 }
597
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 /// Coerce the register to ACC64DSP and return the real register for the
599 /// current target.
600 unsigned getACC64DSPReg() const {
601 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
602 unsigned ClassID = Mips::ACC64DSPRegClassID;
603 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
604 }
605
606 /// Coerce the register to HI32DSP and return the real register for the
607 /// current target.
608 unsigned getHI32DSPReg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
610 unsigned ClassID = Mips::HI32DSPRegClassID;
611 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
612 }
613
614 /// Coerce the register to LO32DSP and return the real register for the
615 /// current target.
616 unsigned getLO32DSPReg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
618 unsigned ClassID = Mips::LO32DSPRegClassID;
619 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
620 }
621
622 /// Coerce the register to CCR and return the real register for the
623 /// current target.
624 unsigned getCCRReg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
626 unsigned ClassID = Mips::CCRRegClassID;
627 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
628 }
629
630 /// Coerce the register to HWRegs and return the real register for the
631 /// current target.
632 unsigned getHWRegsReg() const {
633 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
634 unsigned ClassID = Mips::HWRegsRegClassID;
635 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
636 }
637
638public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000639 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000640 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000641 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000642 Inst.addOperand(MCOperand::CreateImm(0));
643 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
644 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
645 else
646 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000647 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 void addRegOperands(MCInst &Inst, unsigned N) const {
650 llvm_unreachable("Use a custom parser instead");
651 }
652
Daniel Sanders21bce302014-04-01 12:35:23 +0000653 /// Render the operand to an MCInst as a GPR32
654 /// Asserts if the wrong number of operands are requested, or the operand
655 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
657 assert(N == 1 && "Invalid number of operands!");
658 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
659 }
660
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000661 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
662 assert(N == 1 && "Invalid number of operands!");
663 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
664 }
665
Jozef Kolek1904fa22014-11-24 14:25:53 +0000666 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
667 assert(N == 1 && "Invalid number of operands!");
668 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
669 }
670
Daniel Sanders21bce302014-04-01 12:35:23 +0000671 /// Render the operand to an MCInst as a GPR64
672 /// Asserts if the wrong number of operands are requested, or the operand
673 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000674 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
675 assert(N == 1 && "Invalid number of operands!");
676 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
677 }
678
679 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
680 assert(N == 1 && "Invalid number of operands!");
681 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
682 }
683
684 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
685 assert(N == 1 && "Invalid number of operands!");
686 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
687 }
688
689 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000692 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000693 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000694 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
695 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000696 }
697
698 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
699 assert(N == 1 && "Invalid number of operands!");
700 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
701 }
702
703 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
704 assert(N == 1 && "Invalid number of operands!");
705 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
706 }
707
708 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
709 assert(N == 1 && "Invalid number of operands!");
710 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
711 }
712
713 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
714 assert(N == 1 && "Invalid number of operands!");
715 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
716 }
717
718 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
719 assert(N == 1 && "Invalid number of operands!");
720 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
721 }
722
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000723 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
724 assert(N == 1 && "Invalid number of operands!");
725 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
726 }
727
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
729 assert(N == 1 && "Invalid number of operands!");
730 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
731 }
732
733 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
734 assert(N == 1 && "Invalid number of operands!");
735 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
736 }
737
738 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
740 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
741 }
742
743 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
745 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
746 }
747
748 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
749 assert(N == 1 && "Invalid number of operands!");
750 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
751 }
752
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000753 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 assert(N == 1 && "Invalid number of operands!");
755 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000756 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000758
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000760 assert(N == 2 && "Invalid number of operands!");
761
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000762 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000763
764 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000765 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000766 }
767
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000768 void addRegListOperands(MCInst &Inst, unsigned N) const {
769 assert(N == 1 && "Invalid number of operands!");
770
771 for (auto RegNo : getRegList())
772 Inst.addOperand(MCOperand::CreateReg(RegNo));
773 }
774
Craig Topper56c590a2014-04-29 07:58:02 +0000775 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 // As a special case until we sort out the definition of div/divu, pretend
777 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
778 if (isGPRAsmReg() && RegIdx.Index == 0)
779 return true;
780
781 return Kind == k_PhysRegister;
782 }
783 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000784 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 bool isConstantImm() const {
786 return isImm() && dyn_cast<MCConstantExpr>(getImm());
787 }
Craig Topper56c590a2014-04-29 07:58:02 +0000788 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 // Note: It's not possible to pretend that other operand kinds are tokens.
790 // The matcher emitter checks tokens first.
791 return Kind == k_Token;
792 }
Craig Topper56c590a2014-04-29 07:58:02 +0000793 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000794 bool isConstantMemOff() const {
795 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
796 }
797 template <unsigned Bits> bool isMemWithSimmOffset() const {
798 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
799 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000800 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 bool isLSAImm() const {
802 if (!isConstantImm())
803 return false;
804 int64_t Val = getConstantImm();
805 return 1 <= Val && Val <= 4;
806 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000807 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000808
809 StringRef getToken() const {
810 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000811 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000812 }
813
Craig Topper56c590a2014-04-29 07:58:02 +0000814 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 // As a special case until we sort out the definition of div/divu, pretend
816 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
817 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
818 RegIdx.Kind & RegKind_GPR)
819 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000820
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 assert(Kind == k_PhysRegister && "Invalid access!");
822 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000823 }
824
Jack Carterb4dbc172012-09-05 23:34:03 +0000825 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000827 return Imm.Val;
828 }
829
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 int64_t getConstantImm() const {
831 const MCExpr *Val = getImm();
832 return static_cast<const MCConstantExpr *>(Val)->getValue();
833 }
834
835 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000836 assert((Kind == k_Memory) && "Invalid access!");
837 return Mem.Base;
838 }
839
840 const MCExpr *getMemOff() const {
841 assert((Kind == k_Memory) && "Invalid access!");
842 return Mem.Off;
843 }
844
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000845 int64_t getConstantMemOff() const {
846 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
847 }
848
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000849 const SmallVectorImpl<unsigned> &getRegList() const {
850 assert((Kind == k_RegList) && "Invalid access!");
851 return *(RegList.List);
852 }
853
David Blaikie960ea3f2014-06-08 16:18:35 +0000854 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
855 MipsAsmParser &Parser) {
856 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000857 Op->Tok.Data = Str.data();
858 Op->Tok.Length = Str.size();
859 Op->StartLoc = S;
860 Op->EndLoc = S;
861 return Op;
862 }
863
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 /// Create a numeric register (e.g. $1). The exact register remains
865 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000866 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000867 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000868 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000869 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000871 }
872
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 /// Create a register that is definitely a GPR.
874 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000875 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000876 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000877 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000879 }
880
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 /// Create a register that is definitely a FGR.
882 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000883 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000884 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000885 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000886 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
887 }
888
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000889 /// Create a register that is definitely a HWReg.
890 /// This is typically only used for named registers such as $hwr_cpunum.
891 static std::unique_ptr<MipsOperand>
892 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
893 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
894 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
895 }
896
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 /// Create a register that is definitely an FCC.
898 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000899 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000900 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000901 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
903 }
904
905 /// Create a register that is definitely an ACC.
906 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000907 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000908 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000909 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000910 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
911 }
912
913 /// Create a register that is definitely an MSA128.
914 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000915 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000916 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000917 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
919 }
920
921 /// Create a register that is definitely an MSACtrl.
922 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000923 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000924 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000925 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
927 }
928
David Blaikie960ea3f2014-06-08 16:18:35 +0000929 static std::unique_ptr<MipsOperand>
930 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
931 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000932 Op->Imm.Val = Val;
933 Op->StartLoc = S;
934 Op->EndLoc = E;
935 return Op;
936 }
937
David Blaikie960ea3f2014-06-08 16:18:35 +0000938 static std::unique_ptr<MipsOperand>
939 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
940 SMLoc E, MipsAsmParser &Parser) {
941 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
942 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000943 Op->Mem.Off = Off;
944 Op->StartLoc = S;
945 Op->EndLoc = E;
946 return Op;
947 }
948
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000949 static std::unique_ptr<MipsOperand>
950 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
951 MipsAsmParser &Parser) {
952 assert (Regs.size() > 0 && "Empty list not allowed");
953
954 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
955 Op->RegList.List = new SmallVector<unsigned, 10>();
956 for (auto Reg : Regs)
957 Op->RegList.List->push_back(Reg);
958 Op->StartLoc = StartLoc;
959 Op->EndLoc = EndLoc;
960 return Op;
961 }
962
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000963 bool isGPRAsmReg() const {
964 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000965 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000966 bool isMM16AsmReg() const {
967 if (!(isRegIdx() && RegIdx.Kind))
968 return false;
969 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
970 || RegIdx.Index == 16 || RegIdx.Index == 17);
971 }
Jozef Kolek1904fa22014-11-24 14:25:53 +0000972 bool isMM16AsmRegZero() const {
973 if (!(isRegIdx() && RegIdx.Kind))
974 return false;
975 return (RegIdx.Index == 0 ||
976 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
977 RegIdx.Index == 17);
978 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000979 bool isFGRAsmReg() const {
980 // AFGR64 is $0-$15 but we handle this in getAFGR64()
981 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000982 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000983 bool isHWRegsAsmReg() const {
984 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000985 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 bool isCCRAsmReg() const {
987 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000988 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000989 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000990 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
991 return false;
992 if (!AsmParser.hasEightFccRegisters())
993 return RegIdx.Index == 0;
994 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000995 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 bool isACCAsmReg() const {
997 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000998 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000999 bool isCOP2AsmReg() const {
1000 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001001 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001002 bool isCOP3AsmReg() const {
1003 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1004 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001005 bool isMSA128AsmReg() const {
1006 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001007 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001008 bool isMSACtrlAsmReg() const {
1009 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001010 }
1011
Jack Carterb4dbc172012-09-05 23:34:03 +00001012 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001013 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001014 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001015 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001016
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001017 virtual ~MipsOperand() {
1018 switch (Kind) {
1019 case k_Immediate:
1020 break;
1021 case k_Memory:
1022 delete Mem.Base;
1023 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001024 case k_RegList:
1025 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001026 case k_PhysRegister:
1027 case k_RegisterIndex:
1028 case k_Token:
1029 break;
1030 }
1031 }
1032
Craig Topper56c590a2014-04-29 07:58:02 +00001033 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 switch (Kind) {
1035 case k_Immediate:
1036 OS << "Imm<";
1037 Imm.Val->print(OS);
1038 OS << ">";
1039 break;
1040 case k_Memory:
1041 OS << "Mem<";
1042 Mem.Base->print(OS);
1043 OS << ", ";
1044 Mem.Off->print(OS);
1045 OS << ">";
1046 break;
1047 case k_PhysRegister:
1048 OS << "PhysReg<" << PhysReg.Num << ">";
1049 break;
1050 case k_RegisterIndex:
1051 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1052 break;
1053 case k_Token:
1054 OS << Tok.Data;
1055 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001056 case k_RegList:
1057 OS << "RegList< ";
1058 for (auto Reg : (*RegList.List))
1059 OS << Reg << " ";
1060 OS << ">";
1061 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001063 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001064}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001065} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001066
Jack Carter9e65aa32013-03-22 00:05:30 +00001067namespace llvm {
1068extern const MCInstrDesc MipsInsts[];
1069}
1070static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1071 return MipsInsts[Opcode];
1072}
1073
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001074static bool hasShortDelaySlot(unsigned Opcode) {
1075 switch (Opcode) {
1076 case Mips::JALS_MM:
1077 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001078 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001079 case Mips::BGEZALS_MM:
1080 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001081 return true;
1082 default:
1083 return false;
1084 }
1085}
1086
Jack Carter9e65aa32013-03-22 00:05:30 +00001087bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001088 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001089 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001090
Jack Carter9e65aa32013-03-22 00:05:30 +00001091 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001092
1093 if (MCID.isBranch() || MCID.isCall()) {
1094 const unsigned Opcode = Inst.getOpcode();
1095 MCOperand Offset;
1096
1097 switch (Opcode) {
1098 default:
1099 break;
1100 case Mips::BEQ:
1101 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 case Mips::BEQ_MM:
1103 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001104 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001105 Offset = Inst.getOperand(2);
1106 if (!Offset.isImm())
1107 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001108 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001109 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001110 if (OffsetToAlignment(Offset.getImm(),
1111 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001112 return Error(IDLoc, "branch to misaligned address");
1113 break;
1114 case Mips::BGEZ:
1115 case Mips::BGTZ:
1116 case Mips::BLEZ:
1117 case Mips::BLTZ:
1118 case Mips::BGEZAL:
1119 case Mips::BLTZAL:
1120 case Mips::BC1F:
1121 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 case Mips::BGEZ_MM:
1123 case Mips::BGTZ_MM:
1124 case Mips::BLEZ_MM:
1125 case Mips::BLTZ_MM:
1126 case Mips::BGEZAL_MM:
1127 case Mips::BLTZAL_MM:
1128 case Mips::BC1F_MM:
1129 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001130 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001131 Offset = Inst.getOperand(1);
1132 if (!Offset.isImm())
1133 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001134 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001135 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001136 if (OffsetToAlignment(Offset.getImm(),
1137 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001138 return Error(IDLoc, "branch to misaligned address");
1139 break;
1140 }
1141 }
1142
Daniel Sandersa84989a2014-06-16 13:25:35 +00001143 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1144 // We still accept it but it is a normal nop.
1145 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1146 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1147 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1148 "nop instruction");
1149 }
1150
Toma Tabacu9db22db2014-09-09 10:15:38 +00001151 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001152 // If this instruction has a delay slot and .set reorder is active,
1153 // emit a NOP after it.
1154 Instructions.push_back(Inst);
1155 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001156 if (hasShortDelaySlot(Inst.getOpcode())) {
1157 NopInst.setOpcode(Mips::MOVE16_MM);
1158 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1159 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1160 } else {
1161 NopInst.setOpcode(Mips::SLL);
1162 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1163 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1164 NopInst.addOperand(MCOperand::CreateImm(0));
1165 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001166 Instructions.push_back(NopInst);
1167 return false;
1168 }
1169
Jack Carter9e65aa32013-03-22 00:05:30 +00001170 if (MCID.mayLoad() || MCID.mayStore()) {
1171 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 // reference or immediate we may have to expand instructions.
1173 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001174 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001175 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1176 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001177 MCOperand &Op = Inst.getOperand(i);
1178 if (Op.isImm()) {
1179 int MemOffset = Op.getImm();
1180 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 // Offset can't exceed 16bit value.
1182 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001183 return false;
1184 }
1185 } else if (Op.isExpr()) {
1186 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001187 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001188 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001189 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001190 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001191 // Expand symbol.
1192 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001193 return false;
1194 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001195 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001196 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001197 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001198 }
1199 }
1200 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001201 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001202 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001203
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001204 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1205 if (inMicroMipsMode()) {
1206 MCOperand Opnd;
1207 int Imm;
1208
1209 switch (Inst.getOpcode()) {
1210 default:
1211 break;
1212 case Mips::ADDIUS5_MM:
1213 Opnd = Inst.getOperand(2);
1214 if (!Opnd.isImm())
1215 return Error(IDLoc, "expected immediate operand kind");
1216 Imm = Opnd.getImm();
1217 if (Imm < -8 || Imm > 7)
1218 return Error(IDLoc, "immediate operand value out of range");
1219 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001220 case Mips::ADDIUSP_MM:
1221 Opnd = Inst.getOperand(0);
1222 if (!Opnd.isImm())
1223 return Error(IDLoc, "expected immediate operand kind");
1224 Imm = Opnd.getImm();
1225 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1226 Imm % 4 != 0)
1227 return Error(IDLoc, "immediate operand value out of range");
1228 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001229 case Mips::SLL16_MM:
1230 case Mips::SRL16_MM:
1231 Opnd = Inst.getOperand(2);
1232 if (!Opnd.isImm())
1233 return Error(IDLoc, "expected immediate operand kind");
1234 Imm = Opnd.getImm();
1235 if (Imm < 1 || Imm > 8)
1236 return Error(IDLoc, "immediate operand value out of range");
1237 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001238 case Mips::LI16_MM:
1239 Opnd = Inst.getOperand(1);
1240 if (!Opnd.isImm())
1241 return Error(IDLoc, "expected immediate operand kind");
1242 Imm = Opnd.getImm();
1243 if (Imm < -1 || Imm > 126)
1244 return Error(IDLoc, "immediate operand value out of range");
1245 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001246 case Mips::ADDIUR2_MM:
1247 Opnd = Inst.getOperand(2);
1248 if (!Opnd.isImm())
1249 return Error(IDLoc, "expected immediate operand kind");
1250 Imm = Opnd.getImm();
1251 if (!(Imm == 1 || Imm == -1 ||
1252 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1253 return Error(IDLoc, "immediate operand value out of range");
1254 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001255 case Mips::ADDIUR1SP_MM:
1256 Opnd = Inst.getOperand(1);
1257 if (!Opnd.isImm())
1258 return Error(IDLoc, "expected immediate operand kind");
1259 Imm = Opnd.getImm();
1260 if (OffsetToAlignment(Imm, 4LL))
1261 return Error(IDLoc, "misaligned immediate operand value");
1262 if (Imm < 0 || Imm > 255)
1263 return Error(IDLoc, "immediate operand value out of range");
1264 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001265 case Mips::ANDI16_MM:
1266 Opnd = Inst.getOperand(2);
1267 if (!Opnd.isImm())
1268 return Error(IDLoc, "expected immediate operand kind");
1269 Imm = Opnd.getImm();
1270 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1271 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1272 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1273 return Error(IDLoc, "immediate operand value out of range");
1274 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001275 }
1276 }
1277
Jack Carter9e65aa32013-03-22 00:05:30 +00001278 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001279 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001280 else
1281 Instructions.push_back(Inst);
1282
1283 return false;
1284}
1285
Jack Carter30a59822012-10-04 04:03:53 +00001286bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1287
Jack Carterd0bd6422013-04-18 00:41:53 +00001288 switch (Inst.getOpcode()) {
1289 case Mips::LoadImm32Reg:
1290 case Mips::LoadAddr32Imm:
1291 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001292 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001293 return true;
1294 default:
1295 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001296 }
1297}
Jack Carter92995f12012-10-06 00:53:28 +00001298
Matheus Almeida3813d572014-06-19 14:39:14 +00001299bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001300 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001301 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001302 default:
1303 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001304 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001305 case Mips::LoadImm32Reg:
1306 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001307 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001308 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001309 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001310 return true;
1311 }
1312 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001313 case Mips::LoadAddr32Imm:
1314 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1315 case Mips::LoadAddr32Reg:
1316 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1317 }
Jack Carter30a59822012-10-04 04:03:53 +00001318}
Jack Carter92995f12012-10-06 00:53:28 +00001319
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001320namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001321template <bool PerformShift>
1322void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001323 SmallVectorImpl<MCInst> &Instructions) {
1324 MCInst tmpInst;
1325 if (PerformShift) {
1326 tmpInst.setOpcode(Mips::DSLL);
1327 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1328 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1329 tmpInst.addOperand(MCOperand::CreateImm(16));
1330 tmpInst.setLoc(IDLoc);
1331 Instructions.push_back(tmpInst);
1332 tmpInst.clear();
1333 }
1334 tmpInst.setOpcode(Mips::ORi);
1335 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1336 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001337 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001338 tmpInst.setLoc(IDLoc);
1339 Instructions.push_back(tmpInst);
1340}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001341
1342template <int Shift, bool PerformShift>
1343void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1344 SmallVectorImpl<MCInst> &Instructions) {
1345 createShiftOr<PerformShift>(
1346 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1347 IDLoc, Instructions);
1348}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001349}
1350
Matheus Almeida3813d572014-06-19 14:39:14 +00001351bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001352 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001353 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001354 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001355 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001356 const MCOperand &RegOp = Inst.getOperand(0);
1357 assert(RegOp.isReg() && "expected register operand kind");
1358
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001359 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001360 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001361 // FIXME: gas has a special case for values that are 000...1111, which
1362 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001363 if (0 <= ImmValue && ImmValue <= 65535) {
1364 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001365 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001366 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001367 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001368 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001369 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001370 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001371 } else if (ImmValue < 0 && ImmValue >= -32768) {
1372 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001373 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001374 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001375 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001376 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001377 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001378 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001379 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1380 // For any value of j that is representable as a 32-bit integer, create
1381 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001382 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001383 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001384 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001385 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1386 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001387 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001388 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1389 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001390 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001391 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001392 return true;
1393 }
1394
1395 // <------- lo32 ------>
1396 // <------- hi32 ------>
1397 // <- hi16 -> <- lo16 ->
1398 // _________________________________
1399 // | | | |
1400 // | 16-bytes | 16-bytes | 16-bytes |
1401 // |__________|__________|__________|
1402 //
1403 // For any value of j that is representable as a 48-bit integer, create
1404 // a sequence of:
1405 // li d,j => lui d,hi16(j)
1406 // ori d,d,hi16(lo32(j))
1407 // dsll d,d,16
1408 // ori d,d,lo16(lo32(j))
1409 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001410 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001411 tmpInst.addOperand(
1412 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001413 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001414 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1415 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1416 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001417 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001418 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001419 return true;
1420 }
1421
1422 // <------- hi32 ------> <------- lo32 ------>
1423 // <- hi16 -> <- lo16 ->
1424 // ___________________________________________
1425 // | | | | |
1426 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1427 // |__________|__________|__________|__________|
1428 //
1429 // For any value of j that isn't representable as a 48-bit integer.
1430 // li d,j => lui d,hi16(j)
1431 // ori d,d,lo16(hi32(j))
1432 // dsll d,d,16
1433 // ori d,d,hi16(lo32(j))
1434 // dsll d,d,16
1435 // ori d,d,lo16(lo32(j))
1436 tmpInst.setOpcode(Mips::LUi);
1437 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1438 tmpInst.addOperand(
1439 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1440 Instructions.push_back(tmpInst);
1441 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1442 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1443 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001444 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001445 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001446}
Jack Carter92995f12012-10-06 00:53:28 +00001447
Matheus Almeida3813d572014-06-19 14:39:14 +00001448bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001449MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1450 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001451 MCInst tmpInst;
1452 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001453 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1454 "expected immediate operand kind");
1455 if (!ImmOp.isImm()) {
1456 expandLoadAddressSym(Inst, IDLoc, Instructions);
1457 return false;
1458 }
Jack Carter543fdf82012-10-09 23:29:45 +00001459 const MCOperand &SrcRegOp = Inst.getOperand(1);
1460 assert(SrcRegOp.isReg() && "expected register operand kind");
1461 const MCOperand &DstRegOp = Inst.getOperand(0);
1462 assert(DstRegOp.isReg() && "expected register operand kind");
1463 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 if (-32768 <= ImmValue && ImmValue <= 65535) {
1465 // For -32768 <= j <= 65535.
1466 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001467 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001468 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1469 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1470 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1471 Instructions.push_back(tmpInst);
1472 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 // For any other value of j that is representable as a 32-bit integer.
1474 // la d,j(s) => lui d,hi16(j)
1475 // ori d,d,lo16(j)
1476 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001477 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001478 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1479 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1480 Instructions.push_back(tmpInst);
1481 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001482 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001483 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1484 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1485 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1486 Instructions.push_back(tmpInst);
1487 tmpInst.clear();
1488 tmpInst.setOpcode(Mips::ADDu);
1489 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1490 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1491 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1492 Instructions.push_back(tmpInst);
1493 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001494 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001495}
1496
Matheus Almeida3813d572014-06-19 14:39:14 +00001497bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001498MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1499 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001500 MCInst tmpInst;
1501 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001502 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1503 "expected immediate operand kind");
1504 if (!ImmOp.isImm()) {
1505 expandLoadAddressSym(Inst, IDLoc, Instructions);
1506 return false;
1507 }
Jack Carter543fdf82012-10-09 23:29:45 +00001508 const MCOperand &RegOp = Inst.getOperand(0);
1509 assert(RegOp.isReg() && "expected register operand kind");
1510 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001511 if (-32768 <= ImmValue && ImmValue <= 65535) {
1512 // For -32768 <= j <= 65535.
1513 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001514 tmpInst.setOpcode(Mips::ADDiu);
1515 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001516 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001517 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1518 Instructions.push_back(tmpInst);
1519 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001520 // For any other value of j that is representable as a 32-bit integer.
1521 // la d,j => lui d,hi16(j)
1522 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001523 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001524 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1525 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1526 Instructions.push_back(tmpInst);
1527 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001528 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001529 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1530 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1531 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1532 Instructions.push_back(tmpInst);
1533 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001534 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001535}
1536
Toma Tabacu0d64b202014-08-14 10:29:17 +00001537void
1538MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1539 SmallVectorImpl<MCInst> &Instructions) {
1540 // FIXME: If we do have a valid at register to use, we should generate a
1541 // slightly shorter sequence here.
1542 MCInst tmpInst;
1543 int ExprOperandNo = 1;
1544 // Sometimes the assembly parser will get the immediate expression as
1545 // a $zero + an immediate.
1546 if (Inst.getNumOperands() == 3) {
1547 assert(Inst.getOperand(1).getReg() ==
1548 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1549 ExprOperandNo = 2;
1550 }
1551 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1552 assert(SymOp.isExpr() && "expected symbol operand kind");
1553 const MCOperand &RegOp = Inst.getOperand(0);
1554 unsigned RegNo = RegOp.getReg();
1555 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1556 const MCSymbolRefExpr *HiExpr =
1557 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1558 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1559 const MCSymbolRefExpr *LoExpr =
1560 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1561 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1562 if (isGP64bit()) {
1563 // If it's a 64-bit architecture, expand to:
1564 // la d,sym => lui d,highest(sym)
1565 // ori d,d,higher(sym)
1566 // dsll d,d,16
1567 // ori d,d,hi16(sym)
1568 // dsll d,d,16
1569 // ori d,d,lo16(sym)
1570 const MCSymbolRefExpr *HighestExpr =
1571 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1572 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1573 const MCSymbolRefExpr *HigherExpr =
1574 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1575 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1576
1577 tmpInst.setOpcode(Mips::LUi);
1578 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1579 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1580 Instructions.push_back(tmpInst);
1581
1582 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1583 Instructions);
1584 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1585 Instructions);
1586 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1587 Instructions);
1588 } else {
1589 // Otherwise, expand to:
1590 // la d,sym => lui d,hi16(sym)
1591 // ori d,d,lo16(sym)
1592 tmpInst.setOpcode(Mips::LUi);
1593 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1594 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1595 Instructions.push_back(tmpInst);
1596
1597 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1598 Instructions);
1599 }
1600}
1601
Jack Carter9e65aa32013-03-22 00:05:30 +00001602void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001603 SmallVectorImpl<MCInst> &Instructions,
1604 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001605 const MCSymbolRefExpr *SR;
1606 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001608 const MCExpr *ExprOffset;
1609 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001611 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1612 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001613 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001614 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1615 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001617 if (isImmOpnd) {
1618 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1619 ImmOffset = Inst.getOperand(2).getImm();
1620 LoOffset = ImmOffset & 0x0000ffff;
1621 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001623 if (LoOffset & 0x8000)
1624 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001625 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001626 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001628 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001629 // These are some of the types of expansions we perform here:
1630 // 1) lw $8, sym => lui $8, %hi(sym)
1631 // lw $8, %lo(sym)($8)
1632 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1633 // add $8, $8, $9
1634 // lw $8, %lo(offset)($9)
1635 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1636 // add $at, $at, $8
1637 // lw $8, %lo(offset)($at)
1638 // 4) sw $8, sym => lui $at, %hi(sym)
1639 // sw $8, %lo(sym)($at)
1640 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1641 // add $at, $at, $8
1642 // sw $8, %lo(offset)($at)
1643 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1644 // ldc1 $f0, %lo(sym)($at)
1645 //
1646 // For load instructions we can use the destination register as a temporary
1647 // if base and dst are different (examples 1 and 2) and if the base register
1648 // is general purpose otherwise we must use $at (example 6) and error if it's
1649 // not available. For stores we must use $at (examples 4 and 5) because we
1650 // must not clobber the source register setting up the offset.
1651 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1652 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1653 unsigned RegClassIDOp0 =
1654 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1655 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1656 (RegClassIDOp0 == Mips::GPR64RegClassID);
1657 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001658 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001659 else {
1660 int AT = getATReg(IDLoc);
1661 // At this point we need AT to perform the expansions and we exit if it is
1662 // not available.
1663 if (!AT)
1664 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001665 TmpRegNum = getReg(
1666 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001667 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001668
Jack Carter9e65aa32013-03-22 00:05:30 +00001669 TempInst.setOpcode(Mips::LUi);
1670 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1671 if (isImmOpnd)
1672 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1673 else {
1674 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001675 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1677 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1678 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001679 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001680 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001681 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001682 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001683 }
1684 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001685 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001686 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001687 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001688 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001689 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001690 TempInst.setOpcode(Mips::ADDu);
1691 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1692 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1693 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1694 Instructions.push_back(TempInst);
1695 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001696 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001697 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001698 TempInst.setOpcode(Inst.getOpcode());
1699 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1700 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1701 if (isImmOpnd)
1702 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1703 else {
1704 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1706 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1707 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001708 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001709 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001710 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001711 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001712 }
1713 }
1714 Instructions.push_back(TempInst);
1715 TempInst.clear();
1716}
1717
Matheus Almeida595fcab2014-06-11 15:05:56 +00001718unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1719 // As described by the Mips32r2 spec, the registers Rd and Rs for
1720 // jalr.hb must be different.
1721 unsigned Opcode = Inst.getOpcode();
1722
1723 if (Opcode == Mips::JALR_HB &&
1724 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1725 return Match_RequiresDifferentSrcAndDst;
1726
1727 return Match_Success;
1728}
1729
David Blaikie960ea3f2014-06-08 16:18:35 +00001730bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1731 OperandVector &Operands,
1732 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001733 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001735
Jack Carterb4dbc172012-09-05 23:34:03 +00001736 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001738 unsigned MatchResult =
1739 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001740
1741 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 default:
1743 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001744 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001746 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001747 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001748 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001749 return false;
1750 }
1751 case Match_MissingFeature:
1752 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1753 return true;
1754 case Match_InvalidOperand: {
1755 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001756 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001757 if (ErrorInfo >= Operands.size())
1758 return Error(IDLoc, "too few operands for instruction");
1759
David Blaikie960ea3f2014-06-08 16:18:35 +00001760 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001761 if (ErrorLoc == SMLoc())
1762 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001763 }
1764
1765 return Error(ErrorLoc, "invalid operand for instruction");
1766 }
1767 case Match_MnemonicFail:
1768 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001769 case Match_RequiresDifferentSrcAndDst:
1770 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001771 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001772 return true;
1773}
1774
Toma Tabacu13964452014-09-04 13:23:44 +00001775void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001776 if ((RegIndex != 0) &&
1777 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001778 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001779 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001780 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001781 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001782 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001783 }
1784}
1785
Daniel Sandersef638fe2014-10-03 15:37:37 +00001786void
1787MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1788 SMRange Range, bool ShowColors) {
1789 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001790 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001791 ShowColors);
1792}
1793
Jack Carter1ac53222013-02-20 23:11:17 +00001794int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001795 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001796
Vladimir Medic4c299852013-11-06 11:27:05 +00001797 CC = StringSwitch<unsigned>(Name)
1798 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001799 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001800 .Case("a0", 4)
1801 .Case("a1", 5)
1802 .Case("a2", 6)
1803 .Case("a3", 7)
1804 .Case("v0", 2)
1805 .Case("v1", 3)
1806 .Case("s0", 16)
1807 .Case("s1", 17)
1808 .Case("s2", 18)
1809 .Case("s3", 19)
1810 .Case("s4", 20)
1811 .Case("s5", 21)
1812 .Case("s6", 22)
1813 .Case("s7", 23)
1814 .Case("k0", 26)
1815 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001816 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001817 .Case("sp", 29)
1818 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001819 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001820 .Case("ra", 31)
1821 .Case("t0", 8)
1822 .Case("t1", 9)
1823 .Case("t2", 10)
1824 .Case("t3", 11)
1825 .Case("t4", 12)
1826 .Case("t5", 13)
1827 .Case("t6", 14)
1828 .Case("t7", 15)
1829 .Case("t8", 24)
1830 .Case("t9", 25)
1831 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001832
Toma Tabacufda445c2014-09-15 15:33:01 +00001833 if (!(isABI_N32() || isABI_N64()))
1834 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001835
Daniel Sandersef638fe2014-10-03 15:37:37 +00001836 if (12 <= CC && CC <= 15) {
1837 // Name is one of t4-t7
1838 AsmToken RegTok = getLexer().peekTok();
1839 SMRange RegRange = RegTok.getLocRange();
1840
1841 StringRef FixedName = StringSwitch<StringRef>(Name)
1842 .Case("t4", "t0")
1843 .Case("t5", "t1")
1844 .Case("t6", "t2")
1845 .Case("t7", "t3")
1846 .Default("");
1847 assert(FixedName != "" && "Register name is not one of t4-t7.");
1848
1849 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1850 "Did you mean $" + FixedName + "?", RegRange);
1851 }
1852
Toma Tabacufda445c2014-09-15 15:33:01 +00001853 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1854 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1855 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1856 if (8 <= CC && CC <= 11)
1857 CC += 4;
1858
1859 if (CC == -1)
1860 CC = StringSwitch<unsigned>(Name)
1861 .Case("a4", 8)
1862 .Case("a5", 9)
1863 .Case("a6", 10)
1864 .Case("a7", 11)
1865 .Case("kt0", 26)
1866 .Case("kt1", 27)
1867 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001868
1869 return CC;
1870}
Jack Carterd0bd6422013-04-18 00:41:53 +00001871
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001872int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1873 int CC;
1874
1875 CC = StringSwitch<unsigned>(Name)
1876 .Case("hwr_cpunum", 0)
1877 .Case("hwr_synci_step", 1)
1878 .Case("hwr_cc", 2)
1879 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001880 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001881 .Default(-1);
1882
1883 return CC;
1884}
1885
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001886int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001887
Jack Cartera63b16a2012-09-07 00:23:42 +00001888 if (Name[0] == 'f') {
1889 StringRef NumString = Name.substr(1);
1890 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001891 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001892 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001893 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001894 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001895 return IntVal;
1896 }
1897 return -1;
1898}
Jack Cartera63b16a2012-09-07 00:23:42 +00001899
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001900int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1901
1902 if (Name.startswith("fcc")) {
1903 StringRef NumString = Name.substr(3);
1904 unsigned IntVal;
1905 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001906 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001907 if (IntVal > 7) // There are only 8 fcc registers.
1908 return -1;
1909 return IntVal;
1910 }
1911 return -1;
1912}
1913
1914int MipsAsmParser::matchACRegisterName(StringRef Name) {
1915
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001916 if (Name.startswith("ac")) {
1917 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001918 unsigned IntVal;
1919 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001920 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001921 if (IntVal > 3) // There are only 3 acc registers.
1922 return -1;
1923 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001924 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001925 return -1;
1926}
Jack Carterd0bd6422013-04-18 00:41:53 +00001927
Jack Carter5dc8ac92013-09-25 23:50:44 +00001928int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1929 unsigned IntVal;
1930
1931 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1932 return -1;
1933
1934 if (IntVal > 31)
1935 return -1;
1936
1937 return IntVal;
1938}
1939
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001940int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1941 int CC;
1942
1943 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001944 .Case("msair", 0)
1945 .Case("msacsr", 1)
1946 .Case("msaaccess", 2)
1947 .Case("msasave", 3)
1948 .Case("msamodify", 4)
1949 .Case("msarequest", 5)
1950 .Case("msamap", 6)
1951 .Case("msaunmap", 7)
1952 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001953
1954 return CC;
1955}
1956
Jack Carter0b744b32012-10-04 02:29:46 +00001957bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1958 if (Reg > 31)
1959 return false;
1960
Toma Tabacu3c24b042014-09-05 15:43:21 +00001961 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001962 return true;
1963}
1964
Matheus Almeida7de68e72014-06-18 14:46:05 +00001965int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001966 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001967 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001968 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001969 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001970 return AT;
1971}
Jack Carter0b744b32012-10-04 02:29:46 +00001972
Jack Carterd0bd6422013-04-18 00:41:53 +00001973unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001974 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001975}
1976
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001977unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001978 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001979 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001980}
1981
Jack Carter873c7242013-01-12 01:03:14 +00001982int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001983 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001984 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001985 return -1;
1986
Jack Carter873c7242013-01-12 01:03:14 +00001987 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001988}
1989
Toma Tabacu13964452014-09-04 13:23:44 +00001990bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001991 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00001992 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001993
Jack Carter30a59822012-10-04 04:03:53 +00001994 // Check if the current operand has a custom associated parser, if so, try to
1995 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001996 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1997 if (ResTy == MatchOperand_Success)
1998 return false;
1999 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2000 // there was a match, but an error occurred, in which case, just return that
2001 // the operand parsing failed.
2002 if (ResTy == MatchOperand_ParseFail)
2003 return true;
2004
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002005 DEBUG(dbgs() << ".. Generic Parser\n");
2006
Jack Carterb4dbc172012-09-05 23:34:03 +00002007 switch (getLexer().getKind()) {
2008 default:
2009 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2010 return true;
2011 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002012 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002013 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002014
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002015 // Almost all registers have been parsed by custom parsers. There is only
2016 // one exception to this. $zero (and it's alias $0) will reach this point
2017 // for div, divu, and similar instructions because it is not an operand
2018 // to the instruction definition but an explicit register. Special case
2019 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002020 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002021 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002022
Jack Carterd0bd6422013-04-18 00:41:53 +00002023 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002024 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002025 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002026 return true;
2027
Jack Carter873c7242013-01-12 01:03:14 +00002028 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002029 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002030 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002031 const MCExpr *Res =
2032 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002033
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002034 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002035 return false;
2036 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002037 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002038 case AsmToken::LParen:
2039 case AsmToken::Minus:
2040 case AsmToken::Plus:
2041 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002042 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002043 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002044 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002045 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002046 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002047 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002048 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002049 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002050 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002051 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002052 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002053 return true;
2054
Jack Carter873c7242013-01-12 01:03:14 +00002055 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2056
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002057 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002058 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002059 } // case AsmToken::Percent
2060 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002061 return true;
2062}
2063
Vladimir Medic4c299852013-11-06 11:27:05 +00002064const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002065 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002066 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002068 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002069 // It's a constant, evaluate reloc value.
2070 int16_t Val;
2071 switch (getVariantKind(RelocStr)) {
2072 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2073 // Get the 1st 16-bits.
2074 Val = MCE->getValue() & 0xffff;
2075 break;
2076 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2077 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2078 // 16 bits being negative.
2079 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2080 break;
2081 case MCSymbolRefExpr::VK_Mips_HIGHER:
2082 // Get the 3rd 16-bits.
2083 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2084 break;
2085 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2086 // Get the 4th 16-bits.
2087 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2088 break;
2089 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002090 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002091 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002092 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002093 }
2094
Jack Carterb5cf5902013-04-17 00:18:04 +00002095 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002097 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002098 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002100 return Res;
2101 }
2102
2103 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002104 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2105
Sasa Stankovic06c47802014-04-03 10:37:45 +00002106 // Try to create target expression.
2107 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2108 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002109
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2111 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002112 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2113 return Res;
2114 }
2115
2116 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002117 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2118 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2119 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002120 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002121 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002122 return Expr;
2123}
2124
2125bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2126
2127 switch (Expr->getKind()) {
2128 case MCExpr::Constant:
2129 return true;
2130 case MCExpr::SymbolRef:
2131 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2132 case MCExpr::Binary:
2133 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2134 if (!isEvaluated(BE->getLHS()))
2135 return false;
2136 return isEvaluated(BE->getRHS());
2137 }
2138 case MCExpr::Unary:
2139 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002140 case MCExpr::Target:
2141 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002142 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002143 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002144}
Jack Carterd0bd6422013-04-18 00:41:53 +00002145
Jack Carterb5cf5902013-04-17 00:18:04 +00002146bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002147 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002148 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002149 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002150 if (Tok.isNot(AsmToken::Identifier))
2151 return true;
2152
2153 std::string Str = Tok.getIdentifier().str();
2154
Jack Carterd0bd6422013-04-18 00:41:53 +00002155 Parser.Lex(); // Eat the identifier.
2156 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002157 const MCExpr *IdVal;
2158 SMLoc EndLoc;
2159
2160 if (getLexer().getKind() == AsmToken::LParen) {
2161 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002163 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002164 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002165 const AsmToken &nextTok = Parser.getTok();
2166 if (nextTok.isNot(AsmToken::Identifier))
2167 return true;
2168 Str += "(%";
2169 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002170 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002171 if (getLexer().getKind() != AsmToken::LParen)
2172 return true;
2173 } else
2174 break;
2175 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002177 return true;
2178
2179 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002181
2182 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002183 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002184
Jack Carterd0bd6422013-04-18 00:41:53 +00002185 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002186 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002187}
2188
Jack Carterb4dbc172012-09-05 23:34:03 +00002189bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2190 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002191 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002192 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002193 if (ResTy == MatchOperand_Success) {
2194 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002195 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002196 StartLoc = Operand.getStartLoc();
2197 EndLoc = Operand.getEndLoc();
2198
2199 // AFAIK, we only support numeric registers and named GPR's in CFI
2200 // directives.
2201 // Don't worry about eating tokens before failing. Using an unrecognised
2202 // register is a parse error.
2203 if (Operand.isGPRAsmReg()) {
2204 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002205 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002206 }
2207
2208 return (RegNo == (unsigned)-1);
2209 }
2210
2211 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002212 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002213}
2214
Jack Carterb5cf5902013-04-17 00:18:04 +00002215bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002216 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002217 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002218 bool Result = true;
2219
2220 while (getLexer().getKind() == AsmToken::LParen)
2221 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002222
Jack Carterd0bd6422013-04-18 00:41:53 +00002223 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002224 default:
2225 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002226 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002227 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002228 case AsmToken::Integer:
2229 case AsmToken::Minus:
2230 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002231 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002232 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002233 else
2234 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002235 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002236 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002237 break;
Jack Carter873c7242013-01-12 01:03:14 +00002238 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002239 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002240 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002241 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002242}
2243
David Blaikie960ea3f2014-06-08 16:18:35 +00002244MipsAsmParser::OperandMatchResultTy
2245MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002246 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002247 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002248 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002249 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002250 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002251 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002252 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002253 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002254
Jack Carterb5cf5902013-04-17 00:18:04 +00002255 if (getLexer().getKind() == AsmToken::LParen) {
2256 Parser.Lex();
2257 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002258 }
2259
Jack Carterb5cf5902013-04-17 00:18:04 +00002260 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002261 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002262 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002263
Jack Carterd0bd6422013-04-18 00:41:53 +00002264 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002265 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002266 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2267 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002268 SMLoc E =
2269 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002270 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002271 return MatchOperand_Success;
2272 }
2273 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002274 SMLoc E =
2275 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002276
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002278 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002279 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002280 S, E, *this);
2281 Operands.push_back(
2282 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002283 return MatchOperand_Success;
2284 }
2285 Error(Parser.getTok().getLoc(), "'(' expected");
2286 return MatchOperand_ParseFail;
2287 }
2288
Jack Carterd0bd6422013-04-18 00:41:53 +00002289 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002290 }
2291
Toma Tabacu13964452014-09-04 13:23:44 +00002292 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002293 if (Res != MatchOperand_Success)
2294 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002295
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002296 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002297 Error(Parser.getTok().getLoc(), "')' expected");
2298 return MatchOperand_ParseFail;
2299 }
2300
Jack Carter873c7242013-01-12 01:03:14 +00002301 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2302
Jack Carterd0bd6422013-04-18 00:41:53 +00002303 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002304
Craig Topper062a2ba2014-04-25 05:30:21 +00002305 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002306 IdVal = MCConstantExpr::Create(0, getContext());
2307
Jack Carterd0bd6422013-04-18 00:41:53 +00002308 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002309 std::unique_ptr<MipsOperand> op(
2310 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002311 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002312 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002313 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002314 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002315 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2316 int64_t Imm;
2317 if (IdVal->EvaluateAsAbsolute(Imm))
2318 IdVal = MCConstantExpr::Create(Imm, getContext());
2319 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2320 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2321 getContext());
2322 }
2323
David Blaikie960ea3f2014-06-08 16:18:35 +00002324 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002325 return MatchOperand_Success;
2326}
2327
David Blaikie960ea3f2014-06-08 16:18:35 +00002328bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002329 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002330 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2331 if (Sym) {
2332 SMLoc S = Parser.getTok().getLoc();
2333 const MCExpr *Expr;
2334 if (Sym->isVariable())
2335 Expr = Sym->getVariableValue();
2336 else
2337 return false;
2338 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002339 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002340 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002341 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002342 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002343 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002344 if (ResTy == MatchOperand_Success) {
2345 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002346 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002347 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002348 llvm_unreachable("Should never ParseFail");
2349 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002350 }
2351 } else if (Expr->getKind() == MCExpr::Constant) {
2352 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002353 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002354 Operands.push_back(
2355 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002356 return true;
2357 }
2358 }
2359 return false;
2360}
Jack Carterd0bd6422013-04-18 00:41:53 +00002361
Jack Carter873c7242013-01-12 01:03:14 +00002362MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002363MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002364 StringRef Identifier,
2365 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002366 int Index = matchCPURegisterName(Identifier);
2367 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002368 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002369 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2370 return MatchOperand_Success;
2371 }
2372
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002373 Index = matchHWRegsRegisterName(Identifier);
2374 if (Index != -1) {
2375 Operands.push_back(MipsOperand::createHWRegsReg(
2376 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2377 return MatchOperand_Success;
2378 }
2379
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002380 Index = matchFPURegisterName(Identifier);
2381 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002382 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002383 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2384 return MatchOperand_Success;
2385 }
2386
2387 Index = matchFCCRegisterName(Identifier);
2388 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002389 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002390 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2391 return MatchOperand_Success;
2392 }
2393
2394 Index = matchACRegisterName(Identifier);
2395 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002396 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002397 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2398 return MatchOperand_Success;
2399 }
2400
2401 Index = matchMSA128RegisterName(Identifier);
2402 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002403 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002404 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2405 return MatchOperand_Success;
2406 }
2407
2408 Index = matchMSA128CtrlRegisterName(Identifier);
2409 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002410 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002411 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2412 return MatchOperand_Success;
2413 }
2414
2415 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002416}
2417
2418MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002419MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002420 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002421 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002422
2423 if (Token.is(AsmToken::Identifier)) {
2424 DEBUG(dbgs() << ".. identifier\n");
2425 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002426 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002427 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002428 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002429 } else if (Token.is(AsmToken::Integer)) {
2430 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002431 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002432 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2433 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002434 return MatchOperand_Success;
2435 }
2436
2437 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2438
2439 return MatchOperand_NoMatch;
2440}
2441
David Blaikie960ea3f2014-06-08 16:18:35 +00002442MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002443MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002444 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002445 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002446
2447 auto Token = Parser.getTok();
2448
2449 SMLoc S = Token.getLoc();
2450
2451 if (Token.isNot(AsmToken::Dollar)) {
2452 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2453 if (Token.is(AsmToken::Identifier)) {
2454 if (searchSymbolAlias(Operands))
2455 return MatchOperand_Success;
2456 }
2457 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2458 return MatchOperand_NoMatch;
2459 }
2460 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002461
Toma Tabacu13964452014-09-04 13:23:44 +00002462 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002463 if (ResTy == MatchOperand_Success) {
2464 Parser.Lex(); // $
2465 Parser.Lex(); // identifier
2466 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002467 return ResTy;
2468}
2469
2470MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002471MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002472 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 switch (getLexer().getKind()) {
2474 default:
2475 return MatchOperand_NoMatch;
2476 case AsmToken::LParen:
2477 case AsmToken::Minus:
2478 case AsmToken::Plus:
2479 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002480 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002481 case AsmToken::String:
2482 break;
2483 }
2484
2485 const MCExpr *IdVal;
2486 SMLoc S = Parser.getTok().getLoc();
2487 if (getParser().parseExpression(IdVal))
2488 return MatchOperand_ParseFail;
2489
2490 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2491 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2492 return MatchOperand_Success;
2493}
2494
David Blaikie960ea3f2014-06-08 16:18:35 +00002495MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002496MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002497 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002498 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002499
2500 SMLoc S = getLexer().getLoc();
2501
2502 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002503 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002504 if (ResTy != MatchOperand_NoMatch)
2505 return ResTy;
2506
Daniel Sanders315386c2014-04-01 10:40:14 +00002507 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002508 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002509 if (ResTy != MatchOperand_NoMatch)
2510 return ResTy;
2511
Daniel Sandersffd84362014-04-01 10:41:48 +00002512 const MCExpr *Expr = nullptr;
2513 if (Parser.parseExpression(Expr)) {
2514 // We have no way of knowing if a symbol was consumed so we must ParseFail
2515 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002516 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002517 Operands.push_back(
2518 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002519 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002520}
2521
Vladimir Medic2b953d02013-10-01 09:48:56 +00002522MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002523MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002524 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002525 const MCExpr *IdVal;
2526 // If the first token is '$' we may have register operand.
2527 if (Parser.getTok().is(AsmToken::Dollar))
2528 return MatchOperand_NoMatch;
2529 SMLoc S = Parser.getTok().getLoc();
2530 if (getParser().parseExpression(IdVal))
2531 return MatchOperand_ParseFail;
2532 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002533 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002534 int64_t Val = MCE->getValue();
2535 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2536 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002537 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002538 return MatchOperand_Success;
2539}
2540
Matheus Almeida779c5932013-11-18 12:32:49 +00002541MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002542MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002543 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002544 switch (getLexer().getKind()) {
2545 default:
2546 return MatchOperand_NoMatch;
2547 case AsmToken::LParen:
2548 case AsmToken::Plus:
2549 case AsmToken::Minus:
2550 case AsmToken::Integer:
2551 break;
2552 }
2553
2554 const MCExpr *Expr;
2555 SMLoc S = Parser.getTok().getLoc();
2556
2557 if (getParser().parseExpression(Expr))
2558 return MatchOperand_ParseFail;
2559
2560 int64_t Val;
2561 if (!Expr->EvaluateAsAbsolute(Val)) {
2562 Error(S, "expected immediate value");
2563 return MatchOperand_ParseFail;
2564 }
2565
2566 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2567 // and because the CPU always adds one to the immediate field, the allowed
2568 // range becomes 1..4. We'll only check the range here and will deal
2569 // with the addition/subtraction when actually decoding/encoding
2570 // the instruction.
2571 if (Val < 1 || Val > 4) {
2572 Error(S, "immediate not in range (1..4)");
2573 return MatchOperand_ParseFail;
2574 }
2575
Jack Carter3b2c96e2014-01-22 23:31:38 +00002576 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002577 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002578 return MatchOperand_Success;
2579}
2580
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002581MipsAsmParser::OperandMatchResultTy
2582MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2583 MCAsmParser &Parser = getParser();
2584 SmallVector<unsigned, 10> Regs;
2585 unsigned RegNo;
2586 unsigned PrevReg = Mips::NoRegister;
2587 bool RegRange = false;
2588 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2589
2590 if (Parser.getTok().isNot(AsmToken::Dollar))
2591 return MatchOperand_ParseFail;
2592
2593 SMLoc S = Parser.getTok().getLoc();
2594 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2595 SMLoc E = getLexer().getLoc();
2596 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2597 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2598 if (RegRange) {
2599 // Remove last register operand because registers from register range
2600 // should be inserted first.
2601 if (RegNo == Mips::RA) {
2602 Regs.push_back(RegNo);
2603 } else {
2604 unsigned TmpReg = PrevReg + 1;
2605 while (TmpReg <= RegNo) {
2606 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2607 Error(E, "invalid register operand");
2608 return MatchOperand_ParseFail;
2609 }
2610
2611 PrevReg = TmpReg;
2612 Regs.push_back(TmpReg++);
2613 }
2614 }
2615
2616 RegRange = false;
2617 } else {
2618 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2619 (RegNo != Mips::RA)) {
2620 Error(E, "$16 or $31 expected");
2621 return MatchOperand_ParseFail;
2622 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2623 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2624 Error(E, "invalid register operand");
2625 return MatchOperand_ParseFail;
2626 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2627 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2628 Error(E, "consecutive register numbers expected");
2629 return MatchOperand_ParseFail;
2630 }
2631
2632 Regs.push_back(RegNo);
2633 }
2634
2635 if (Parser.getTok().is(AsmToken::Minus))
2636 RegRange = true;
2637
2638 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2639 !Parser.getTok().isNot(AsmToken::Comma)) {
2640 Error(E, "',' or '-' expected");
2641 return MatchOperand_ParseFail;
2642 }
2643
2644 Lex(); // Consume comma or minus
2645 if (Parser.getTok().isNot(AsmToken::Dollar))
2646 break;
2647
2648 PrevReg = RegNo;
2649 }
2650
2651 SMLoc E = Parser.getTok().getLoc();
2652 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2653 parseMemOperand(Operands);
2654 return MatchOperand_Success;
2655}
2656
Jack Carterdc1e35d2012-09-06 20:00:02 +00002657MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2658
Vladimir Medic4c299852013-11-06 11:27:05 +00002659 MCSymbolRefExpr::VariantKind VK =
2660 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2661 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2662 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2663 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2664 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2665 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2666 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2667 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2668 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2669 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2670 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2671 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2672 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2673 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2674 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2675 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2676 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2677 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002678 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2679 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2680 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2681 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2682 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2683 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002684 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2685 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002686 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002687
Matheus Almeida2852af82014-04-22 10:15:54 +00002688 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002689
Jack Carterdc1e35d2012-09-06 20:00:02 +00002690 return VK;
2691}
Jack Cartera63b16a2012-09-07 00:23:42 +00002692
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002693/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2694/// either this.
2695/// ::= '(', register, ')'
2696/// handle it before we iterate so we don't get tripped up by the lack of
2697/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002698bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002699 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002700 if (getLexer().is(AsmToken::LParen)) {
2701 Operands.push_back(
2702 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2703 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002704 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002705 SMLoc Loc = getLexer().getLoc();
2706 Parser.eatToEndOfStatement();
2707 return Error(Loc, "unexpected token in argument list");
2708 }
2709 if (Parser.getTok().isNot(AsmToken::RParen)) {
2710 SMLoc Loc = getLexer().getLoc();
2711 Parser.eatToEndOfStatement();
2712 return Error(Loc, "unexpected token, expected ')'");
2713 }
2714 Operands.push_back(
2715 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2716 Parser.Lex();
2717 }
2718 return false;
2719}
2720
2721/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2722/// either one of these.
2723/// ::= '[', register, ']'
2724/// ::= '[', integer, ']'
2725/// handle it before we iterate so we don't get tripped up by the lack of
2726/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002727bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002728 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002729 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002730 if (getLexer().is(AsmToken::LBrac)) {
2731 Operands.push_back(
2732 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2733 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002734 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002735 SMLoc Loc = getLexer().getLoc();
2736 Parser.eatToEndOfStatement();
2737 return Error(Loc, "unexpected token in argument list");
2738 }
2739 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2740 SMLoc Loc = getLexer().getLoc();
2741 Parser.eatToEndOfStatement();
2742 return Error(Loc, "unexpected token, expected ']'");
2743 }
2744 Operands.push_back(
2745 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2746 Parser.Lex();
2747 }
2748 return false;
2749}
2750
David Blaikie960ea3f2014-06-08 16:18:35 +00002751bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2752 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002753 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002754 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002755
2756 // We have reached first instruction, module directive are now forbidden.
2757 getTargetStreamer().forbidModuleDirective();
2758
Vladimir Medic74593e62013-07-17 15:00:42 +00002759 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002760 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002761 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002762 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002763 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002764 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002765 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002766
2767 // Read the remaining operands.
2768 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2769 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002770 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002771 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002772 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002773 return Error(Loc, "unexpected token in argument list");
2774 }
Toma Tabacu13964452014-09-04 13:23:44 +00002775 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002776 return true;
2777 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002778
Jack Carterd0bd6422013-04-18 00:41:53 +00002779 while (getLexer().is(AsmToken::Comma)) {
2780 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002781 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002782 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002783 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002784 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002785 return Error(Loc, "unexpected token in argument list");
2786 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002787 // Parse bracket and parenthesis suffixes before we iterate
2788 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002789 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002790 return true;
2791 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002792 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002793 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002794 }
2795 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002796 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2797 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002798 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002799 return Error(Loc, "unexpected token in argument list");
2800 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002801 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002802 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002803}
2804
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002805bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002806 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002807 SMLoc Loc = getLexer().getLoc();
2808 Parser.eatToEndOfStatement();
2809 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002810}
2811
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002812bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002813 return Error(Loc, ErrorMsg);
2814}
2815
Jack Carter0b744b32012-10-04 02:29:46 +00002816bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002817 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002818 // Line should look like: ".set noat".
2819 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002820 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002821 // eat noat
2822 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002823 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002824 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002825 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002826 return false;
2827 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002828 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002829 return false;
2830}
Jack Carterd0bd6422013-04-18 00:41:53 +00002831
Jack Carter0b744b32012-10-04 02:29:46 +00002832bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002833 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002834 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002835 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002836 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002837 getParser().Lex();
2838 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002839 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002840 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002841 return false;
2842 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002843 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002844 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002845 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002846 return false;
2847 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002848 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002849 const AsmToken &Reg = Parser.getTok();
2850 if (Reg.is(AsmToken::Identifier)) {
2851 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2852 } else if (Reg.is(AsmToken::Integer)) {
2853 AtRegNo = Reg.getIntVal();
2854 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002855 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002856 return false;
2857 }
Jack Carter1ac53222013-02-20 23:11:17 +00002858
Daniel Sanders71a89d922014-03-25 13:01:06 +00002859 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002860 reportParseError("unexpected token in statement");
2861 return false;
2862 }
2863
Toma Tabacu9db22db2014-09-09 10:15:38 +00002864 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002865 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002866 return false;
2867 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002868 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002869
2870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002871 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002872 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002873 }
2874 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002875 return false;
2876 } else {
2877 reportParseError("unexpected token in statement");
2878 return false;
2879 }
2880}
2881
2882bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002883 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002884 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002885 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002886 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002887 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002888 return false;
2889 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002890 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002891 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002892 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002893 return false;
2894}
2895
2896bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002897 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002898 Parser.Lex();
2899 // If this is not the end of the statement, report an error.
2900 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002901 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002902 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002903 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002904 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002905 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002906 Parser.Lex(); // Consume the EndOfStatement.
2907 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002908}
2909
2910bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002911 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002912 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002913 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002914 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002915 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002916 return false;
2917 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002918 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002919 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002920 return false;
2921}
2922
2923bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002924 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002925 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002926 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002927 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002928 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002929 return false;
2930 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002931 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002932 reportParseError("`noreorder' must be set before `nomacro'");
2933 return false;
2934 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002935 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002936 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002937 return false;
2938}
Jack Carterd76b2372013-03-21 21:44:16 +00002939
Daniel Sanders44934432014-08-07 12:03:36 +00002940bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002941 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002942 Parser.Lex();
2943
2944 // If this is not the end of the statement, report an error.
2945 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002946 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002947
2948 setFeatureBits(Mips::FeatureMSA, "msa");
2949 getTargetStreamer().emitDirectiveSetMsa();
2950 return false;
2951}
2952
2953bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002954 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002955 Parser.Lex();
2956
2957 // If this is not the end of the statement, report an error.
2958 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002959 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002960
2961 clearFeatureBits(Mips::FeatureMSA, "msa");
2962 getTargetStreamer().emitDirectiveSetNoMsa();
2963 return false;
2964}
2965
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002966bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002967 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002968 Parser.Lex(); // Eat "nodsp".
2969
2970 // If this is not the end of the statement, report an error.
2971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2972 reportParseError("unexpected token, expected end of statement");
2973 return false;
2974 }
2975
2976 clearFeatureBits(Mips::FeatureDSP, "dsp");
2977 getTargetStreamer().emitDirectiveSetNoDsp();
2978 return false;
2979}
2980
Toma Tabacucc2502d2014-11-04 17:18:07 +00002981bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002982 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00002983 Parser.Lex(); // Eat "mips16".
2984
Jack Carter39536722014-01-22 23:08:42 +00002985 // If this is not the end of the statement, report an error.
2986 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002987 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002988 return false;
2989 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00002990
2991 setFeatureBits(Mips::FeatureMips16, "mips16");
2992 getTargetStreamer().emitDirectiveSetMips16();
2993 Parser.Lex(); // Consume the EndOfStatement.
2994 return false;
2995}
2996
2997bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002998 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00002999 Parser.Lex(); // Eat "nomips16".
3000
3001 // If this is not the end of the statement, report an error.
3002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3003 reportParseError("unexpected token, expected end of statement");
3004 return false;
3005 }
3006
3007 clearFeatureBits(Mips::FeatureMips16, "mips16");
3008 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003009 Parser.Lex(); // Consume the EndOfStatement.
3010 return false;
3011}
3012
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003013bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003014 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003015 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003016 // Line can be: .set fp=32
3017 // .set fp=xx
3018 // .set fp=64
3019 Parser.Lex(); // Eat fp token
3020 AsmToken Tok = Parser.getTok();
3021 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003022 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003023 return false;
3024 }
3025 Parser.Lex(); // Eat '=' token.
3026 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003027
3028 if (!parseFpABIValue(FpAbiVal, ".set"))
3029 return false;
3030
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003031 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003032 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003033 return false;
3034 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003035 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003036 Parser.Lex(); // Consume the EndOfStatement.
3037 return false;
3038}
3039
Toma Tabacu9db22db2014-09-09 10:15:38 +00003040bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003041 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003042 SMLoc Loc = getLexer().getLoc();
3043
3044 Parser.Lex();
3045 if (getLexer().isNot(AsmToken::EndOfStatement))
3046 return reportParseError("unexpected token, expected end of statement");
3047
3048 // Always keep an element on the options "stack" to prevent the user
3049 // from changing the initial options. This is how we remember them.
3050 if (AssemblerOptions.size() == 2)
3051 return reportParseError(Loc, ".set pop with no .set push");
3052
3053 AssemblerOptions.pop_back();
3054 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3055
3056 getTargetStreamer().emitDirectiveSetPop();
3057 return false;
3058}
3059
3060bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003061 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003062 Parser.Lex();
3063 if (getLexer().isNot(AsmToken::EndOfStatement))
3064 return reportParseError("unexpected token, expected end of statement");
3065
3066 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003067 AssemblerOptions.push_back(
3068 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003069
3070 getTargetStreamer().emitDirectiveSetPush();
3071 return false;
3072}
3073
Jack Carterd76b2372013-03-21 21:44:16 +00003074bool MipsAsmParser::parseSetAssignment() {
3075 StringRef Name;
3076 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003077 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003078
3079 if (Parser.parseIdentifier(Name))
3080 reportParseError("expected identifier after .set");
3081
3082 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003083 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003084 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003085
Jack Carter3b2c96e2014-01-22 23:31:38 +00003086 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003087 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003088
Jack Carterd0bd6422013-04-18 00:41:53 +00003089 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003090 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003091 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003092 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003093 Sym = getContext().GetOrCreateSymbol(Name);
3094 Sym->setVariableValue(Value);
3095
3096 return false;
3097}
Jack Carterd0bd6422013-04-18 00:41:53 +00003098
Toma Tabacu26647792014-09-09 12:52:14 +00003099bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003100 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003101 Parser.Lex();
3102 if (getLexer().isNot(AsmToken::EndOfStatement))
3103 return reportParseError("unexpected token, expected end of statement");
3104
3105 // Reset assembler options to their initial values.
3106 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3107 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3108
3109 getTargetStreamer().emitDirectiveSetMips0();
3110 return false;
3111}
3112
Toma Tabacu85618b32014-08-19 14:22:52 +00003113bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003114 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003115 Parser.Lex();
3116 if (getLexer().isNot(AsmToken::Equal))
3117 return reportParseError("unexpected token, expected equals sign");
3118
3119 Parser.Lex();
3120 StringRef Arch;
3121 if (Parser.parseIdentifier(Arch))
3122 return reportParseError("expected arch identifier");
3123
3124 StringRef ArchFeatureName =
3125 StringSwitch<StringRef>(Arch)
3126 .Case("mips1", "mips1")
3127 .Case("mips2", "mips2")
3128 .Case("mips3", "mips3")
3129 .Case("mips4", "mips4")
3130 .Case("mips5", "mips5")
3131 .Case("mips32", "mips32")
3132 .Case("mips32r2", "mips32r2")
3133 .Case("mips32r6", "mips32r6")
3134 .Case("mips64", "mips64")
3135 .Case("mips64r2", "mips64r2")
3136 .Case("mips64r6", "mips64r6")
3137 .Case("cnmips", "cnmips")
3138 .Case("r4000", "mips3") // This is an implementation of Mips3.
3139 .Default("");
3140
3141 if (ArchFeatureName.empty())
3142 return reportParseError("unsupported architecture");
3143
3144 selectArch(ArchFeatureName);
3145 getTargetStreamer().emitDirectiveSetArch(Arch);
3146 return false;
3147}
3148
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003149bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003150 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003151 Parser.Lex();
3152 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003153 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003154
Matheus Almeida2852af82014-04-22 10:15:54 +00003155 switch (Feature) {
3156 default:
3157 llvm_unreachable("Unimplemented feature");
3158 case Mips::FeatureDSP:
3159 setFeatureBits(Mips::FeatureDSP, "dsp");
3160 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003161 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003162 case Mips::FeatureMicroMips:
3163 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003164 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003165 case Mips::FeatureMips1:
3166 selectArch("mips1");
3167 getTargetStreamer().emitDirectiveSetMips1();
3168 break;
3169 case Mips::FeatureMips2:
3170 selectArch("mips2");
3171 getTargetStreamer().emitDirectiveSetMips2();
3172 break;
3173 case Mips::FeatureMips3:
3174 selectArch("mips3");
3175 getTargetStreamer().emitDirectiveSetMips3();
3176 break;
3177 case Mips::FeatureMips4:
3178 selectArch("mips4");
3179 getTargetStreamer().emitDirectiveSetMips4();
3180 break;
3181 case Mips::FeatureMips5:
3182 selectArch("mips5");
3183 getTargetStreamer().emitDirectiveSetMips5();
3184 break;
3185 case Mips::FeatureMips32:
3186 selectArch("mips32");
3187 getTargetStreamer().emitDirectiveSetMips32();
3188 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003189 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003190 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003191 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003192 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003193 case Mips::FeatureMips32r6:
3194 selectArch("mips32r6");
3195 getTargetStreamer().emitDirectiveSetMips32R6();
3196 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003197 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003198 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003199 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003200 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003201 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003202 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003203 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003204 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003205 case Mips::FeatureMips64r6:
3206 selectArch("mips64r6");
3207 getTargetStreamer().emitDirectiveSetMips64R6();
3208 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003209 }
3210 return false;
3211}
3212
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003213bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003214 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003215 if (getLexer().isNot(AsmToken::Comma)) {
3216 SMLoc Loc = getLexer().getLoc();
3217 Parser.eatToEndOfStatement();
3218 return Error(Loc, ErrorStr);
3219 }
3220
Matheus Almeida2852af82014-04-22 10:15:54 +00003221 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003222 return true;
3223}
3224
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003225bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003226 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003227 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003228
Toma Tabacudde4c462014-11-06 10:02:45 +00003229 if (inMips16Mode()) {
3230 reportParseError(".cpload is not supported in Mips16 mode");
3231 return false;
3232 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003233
David Blaikie960ea3f2014-06-08 16:18:35 +00003234 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003235 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003236 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3237 reportParseError("expected register containing function address");
3238 return false;
3239 }
3240
David Blaikie960ea3f2014-06-08 16:18:35 +00003241 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3242 if (!RegOpnd.isGPRAsmReg()) {
3243 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003244 return false;
3245 }
3246
Toma Tabacudde4c462014-11-06 10:02:45 +00003247 // If this is not the end of the statement, report an error.
3248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3249 reportParseError("unexpected token, expected end of statement");
3250 return false;
3251 }
3252
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003253 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003254 return false;
3255}
3256
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003257bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003258 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003259 unsigned FuncReg;
3260 unsigned Save;
3261 bool SaveIsReg = true;
3262
Matheus Almeida7e815762014-06-18 13:08:59 +00003263 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003264 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003265 if (ResTy == MatchOperand_NoMatch) {
3266 reportParseError("expected register containing function address");
3267 Parser.eatToEndOfStatement();
3268 return false;
3269 }
3270
3271 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3272 if (!FuncRegOpnd.isGPRAsmReg()) {
3273 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3274 Parser.eatToEndOfStatement();
3275 return false;
3276 }
3277
3278 FuncReg = FuncRegOpnd.getGPR32Reg();
3279 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003280
Toma Tabacu65f10572014-09-16 15:00:52 +00003281 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003282 return true;
3283
Toma Tabacu13964452014-09-04 13:23:44 +00003284 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003285 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003286 const AsmToken &Tok = Parser.getTok();
3287 if (Tok.is(AsmToken::Integer)) {
3288 Save = Tok.getIntVal();
3289 SaveIsReg = false;
3290 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003291 } else {
3292 reportParseError("expected save register or stack offset");
3293 Parser.eatToEndOfStatement();
3294 return false;
3295 }
3296 } else {
3297 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3298 if (!SaveOpnd.isGPRAsmReg()) {
3299 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3300 Parser.eatToEndOfStatement();
3301 return false;
3302 }
3303 Save = SaveOpnd.getGPR32Reg();
3304 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003305
Toma Tabacu65f10572014-09-16 15:00:52 +00003306 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003307 return true;
3308
3309 StringRef Name;
3310 if (Parser.parseIdentifier(Name))
3311 reportParseError("expected identifier");
3312 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003313
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003314 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003315 return false;
3316}
3317
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003318bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003319 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003320 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3321 const AsmToken &Tok = Parser.getTok();
3322
3323 if (Tok.getString() == "2008") {
3324 Parser.Lex();
3325 getTargetStreamer().emitDirectiveNaN2008();
3326 return false;
3327 } else if (Tok.getString() == "legacy") {
3328 Parser.Lex();
3329 getTargetStreamer().emitDirectiveNaNLegacy();
3330 return false;
3331 }
3332 }
3333 // If we don't recognize the option passed to the .nan
3334 // directive (e.g. no option or unknown option), emit an error.
3335 reportParseError("invalid option in .nan directive");
3336 return false;
3337}
3338
Jack Carter0b744b32012-10-04 02:29:46 +00003339bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003340 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003341 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003342 const AsmToken &Tok = Parser.getTok();
3343
3344 if (Tok.getString() == "noat") {
3345 return parseSetNoAtDirective();
3346 } else if (Tok.getString() == "at") {
3347 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003348 } else if (Tok.getString() == "arch") {
3349 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003350 } else if (Tok.getString() == "fp") {
3351 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003352 } else if (Tok.getString() == "pop") {
3353 return parseSetPopDirective();
3354 } else if (Tok.getString() == "push") {
3355 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003356 } else if (Tok.getString() == "reorder") {
3357 return parseSetReorderDirective();
3358 } else if (Tok.getString() == "noreorder") {
3359 return parseSetNoReorderDirective();
3360 } else if (Tok.getString() == "macro") {
3361 return parseSetMacroDirective();
3362 } else if (Tok.getString() == "nomacro") {
3363 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003364 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003365 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003366 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003367 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003368 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003369 getTargetStreamer().emitDirectiveSetNoMicroMips();
3370 Parser.eatToEndOfStatement();
3371 return false;
3372 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003373 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003374 } else if (Tok.getString() == "mips0") {
3375 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003376 } else if (Tok.getString() == "mips1") {
3377 return parseSetFeature(Mips::FeatureMips1);
3378 } else if (Tok.getString() == "mips2") {
3379 return parseSetFeature(Mips::FeatureMips2);
3380 } else if (Tok.getString() == "mips3") {
3381 return parseSetFeature(Mips::FeatureMips3);
3382 } else if (Tok.getString() == "mips4") {
3383 return parseSetFeature(Mips::FeatureMips4);
3384 } else if (Tok.getString() == "mips5") {
3385 return parseSetFeature(Mips::FeatureMips5);
3386 } else if (Tok.getString() == "mips32") {
3387 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003388 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003389 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003390 } else if (Tok.getString() == "mips32r6") {
3391 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003392 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003393 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003394 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003395 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003396 } else if (Tok.getString() == "mips64r6") {
3397 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003398 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003399 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003400 } else if (Tok.getString() == "nodsp") {
3401 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003402 } else if (Tok.getString() == "msa") {
3403 return parseSetMsaDirective();
3404 } else if (Tok.getString() == "nomsa") {
3405 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003406 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003407 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003408 parseSetAssignment();
3409 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003410 }
Jack Carter07c818d2013-01-25 01:31:34 +00003411
Jack Carter0b744b32012-10-04 02:29:46 +00003412 return true;
3413}
3414
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003415/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003416/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003417bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003418 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3420 for (;;) {
3421 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003422 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003423 return true;
3424
3425 getParser().getStreamer().EmitValue(Value, Size);
3426
3427 if (getLexer().is(AsmToken::EndOfStatement))
3428 break;
3429
Jack Carter07c818d2013-01-25 01:31:34 +00003430 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003431 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003432 Parser.Lex();
3433 }
3434 }
3435
3436 Parser.Lex();
3437 return false;
3438}
3439
Vladimir Medic4c299852013-11-06 11:27:05 +00003440/// parseDirectiveGpWord
3441/// ::= .gpword local_sym
3442bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003443 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003444 const MCExpr *Value;
3445 // EmitGPRel32Value requires an expression, so we are using base class
3446 // method to evaluate the expression.
3447 if (getParser().parseExpression(Value))
3448 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003449 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003450
Vladimir Medice10c1122013-11-13 13:18:04 +00003451 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003452 return Error(getLexer().getLoc(),
3453 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003454 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003455 return false;
3456}
3457
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003458/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003459/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003460bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003461 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003462 const MCExpr *Value;
3463 // EmitGPRel64Value requires an expression, so we are using base class
3464 // method to evaluate the expression.
3465 if (getParser().parseExpression(Value))
3466 return true;
3467 getParser().getStreamer().EmitGPRel64Value(Value);
3468
3469 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003470 return Error(getLexer().getLoc(),
3471 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003472 Parser.Lex(); // Eat EndOfStatement token.
3473 return false;
3474}
3475
Jack Carter0cd3c192014-01-06 23:27:31 +00003476bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003477 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003478 // Get the option token.
3479 AsmToken Tok = Parser.getTok();
3480 // At the moment only identifiers are supported.
3481 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003482 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003483 Parser.eatToEndOfStatement();
3484 return false;
3485 }
3486
3487 StringRef Option = Tok.getIdentifier();
3488
3489 if (Option == "pic0") {
3490 getTargetStreamer().emitDirectiveOptionPic0();
3491 Parser.Lex();
3492 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3493 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003494 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003495 Parser.eatToEndOfStatement();
3496 }
3497 return false;
3498 }
3499
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003500 if (Option == "pic2") {
3501 getTargetStreamer().emitDirectiveOptionPic2();
3502 Parser.Lex();
3503 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3504 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003505 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003506 Parser.eatToEndOfStatement();
3507 }
3508 return false;
3509 }
3510
Jack Carter0cd3c192014-01-06 23:27:31 +00003511 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003512 Warning(Parser.getTok().getLoc(),
3513 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003514 Parser.eatToEndOfStatement();
3515 return false;
3516}
3517
Daniel Sanders7e527422014-07-10 13:38:23 +00003518/// parseDirectiveModule
3519/// ::= .module oddspreg
3520/// ::= .module nooddspreg
3521/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003522bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003523 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003524 MCAsmLexer &Lexer = getLexer();
3525 SMLoc L = Lexer.getLoc();
3526
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003527 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003528 // TODO : get a better message.
3529 reportParseError(".module directive must appear before any code");
3530 return false;
3531 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003532
3533 if (Lexer.is(AsmToken::Identifier)) {
3534 StringRef Option = Parser.getTok().getString();
3535 Parser.Lex();
3536
3537 if (Option == "oddspreg") {
3538 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3539 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3540
3541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003542 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003543 return false;
3544 }
3545
3546 return false;
3547 } else if (Option == "nooddspreg") {
3548 if (!isABI_O32()) {
3549 Error(L, "'.module nooddspreg' requires the O32 ABI");
3550 return false;
3551 }
3552
3553 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3554 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3555
3556 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003557 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003558 return false;
3559 }
3560
3561 return false;
3562 } else if (Option == "fp") {
3563 return parseDirectiveModuleFP();
3564 }
3565
3566 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003567 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003568
3569 return false;
3570}
3571
3572/// parseDirectiveModuleFP
3573/// ::= =32
3574/// ::= =xx
3575/// ::= =64
3576bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003577 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003578 MCAsmLexer &Lexer = getLexer();
3579
3580 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003581 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003582 return false;
3583 }
3584 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003585
Daniel Sanders7e527422014-07-10 13:38:23 +00003586 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003587 if (!parseFpABIValue(FpABI, ".module"))
3588 return false;
3589
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003591 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003592 return false;
3593 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003594
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003595 // Emit appropriate flags.
3596 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003597 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003598 return false;
3599}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003600
Daniel Sanders7e527422014-07-10 13:38:23 +00003601bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003602 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003603 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003604 MCAsmLexer &Lexer = getLexer();
3605
3606 if (Lexer.is(AsmToken::Identifier)) {
3607 StringRef Value = Parser.getTok().getString();
3608 Parser.Lex();
3609
3610 if (Value != "xx") {
3611 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3612 return false;
3613 }
3614
3615 if (!isABI_O32()) {
3616 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3617 return false;
3618 }
3619
Daniel Sanders7e527422014-07-10 13:38:23 +00003620 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003621 return true;
3622 }
3623
3624 if (Lexer.is(AsmToken::Integer)) {
3625 unsigned Value = Parser.getTok().getIntVal();
3626 Parser.Lex();
3627
3628 if (Value != 32 && Value != 64) {
3629 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3630 return false;
3631 }
3632
3633 if (Value == 32) {
3634 if (!isABI_O32()) {
3635 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3636 return false;
3637 }
3638
Daniel Sanders7e527422014-07-10 13:38:23 +00003639 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3640 } else
3641 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003642
Daniel Sanders7e527422014-07-10 13:38:23 +00003643 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003644 }
3645
3646 return false;
3647}
3648
Jack Carter0b744b32012-10-04 02:29:46 +00003649bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003650 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003651 StringRef IDVal = DirectiveID.getString();
3652
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003653 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003654 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003655 if (IDVal == ".dword") {
3656 parseDataDirective(8, DirectiveID.getLoc());
3657 return false;
3658 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003659 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003660 StringRef SymbolName;
3661
3662 if (Parser.parseIdentifier(SymbolName)) {
3663 reportParseError("expected identifier after .ent");
3664 return false;
3665 }
3666
3667 // There's an undocumented extension that allows an integer to
3668 // follow the name of the procedure which AFAICS is ignored by GAS.
3669 // Example: .ent foo,2
3670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3671 if (getLexer().isNot(AsmToken::Comma)) {
3672 // Even though we accept this undocumented extension for compatibility
3673 // reasons, the additional integer argument does not actually change
3674 // the behaviour of the '.ent' directive, so we would like to discourage
3675 // its use. We do this by not referring to the extended version in
3676 // error messages which are not directly related to its use.
3677 reportParseError("unexpected token, expected end of statement");
3678 return false;
3679 }
3680 Parser.Lex(); // Eat the comma.
3681 const MCExpr *DummyNumber;
3682 int64_t DummyNumberVal;
3683 // If the user was explicitly trying to use the extended version,
3684 // we still give helpful extension-related error messages.
3685 if (Parser.parseExpression(DummyNumber)) {
3686 reportParseError("expected number after comma");
3687 return false;
3688 }
3689 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3690 reportParseError("expected an absolute expression after comma");
3691 return false;
3692 }
3693 }
3694
3695 // If this is not the end of the statement, report an error.
3696 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3697 reportParseError("unexpected token, expected end of statement");
3698 return false;
3699 }
3700
3701 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3702
3703 getTargetStreamer().emitDirectiveEnt(*Sym);
3704 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003705 return false;
3706 }
3707
Jack Carter07c818d2013-01-25 01:31:34 +00003708 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003709 StringRef SymbolName;
3710
3711 if (Parser.parseIdentifier(SymbolName)) {
3712 reportParseError("expected identifier after .end");
3713 return false;
3714 }
3715
3716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3717 reportParseError("unexpected token, expected end of statement");
3718 return false;
3719 }
3720
3721 if (CurrentFn == nullptr) {
3722 reportParseError(".end used without .ent");
3723 return false;
3724 }
3725
3726 if ((SymbolName != CurrentFn->getName())) {
3727 reportParseError(".end symbol does not match .ent symbol");
3728 return false;
3729 }
3730
3731 getTargetStreamer().emitDirectiveEnd(SymbolName);
3732 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003733 return false;
3734 }
3735
Jack Carter07c818d2013-01-25 01:31:34 +00003736 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003737 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3738 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003739 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003740 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3741 reportParseError("expected stack register");
3742 return false;
3743 }
3744
3745 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3746 if (!StackRegOpnd.isGPRAsmReg()) {
3747 reportParseError(StackRegOpnd.getStartLoc(),
3748 "expected general purpose register");
3749 return false;
3750 }
3751 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3752
3753 if (Parser.getTok().is(AsmToken::Comma))
3754 Parser.Lex();
3755 else {
3756 reportParseError("unexpected token, expected comma");
3757 return false;
3758 }
3759
3760 // Parse the frame size.
3761 const MCExpr *FrameSize;
3762 int64_t FrameSizeVal;
3763
3764 if (Parser.parseExpression(FrameSize)) {
3765 reportParseError("expected frame size value");
3766 return false;
3767 }
3768
3769 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3770 reportParseError("frame size not an absolute expression");
3771 return false;
3772 }
3773
3774 if (Parser.getTok().is(AsmToken::Comma))
3775 Parser.Lex();
3776 else {
3777 reportParseError("unexpected token, expected comma");
3778 return false;
3779 }
3780
3781 // Parse the return register.
3782 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003783 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003784 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3785 reportParseError("expected return register");
3786 return false;
3787 }
3788
3789 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3790 if (!ReturnRegOpnd.isGPRAsmReg()) {
3791 reportParseError(ReturnRegOpnd.getStartLoc(),
3792 "expected general purpose register");
3793 return false;
3794 }
3795
3796 // If this is not the end of the statement, report an error.
3797 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3798 reportParseError("unexpected token, expected end of statement");
3799 return false;
3800 }
3801
3802 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3803 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003804 return false;
3805 }
3806
Jack Carter07c818d2013-01-25 01:31:34 +00003807 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003808 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003809 }
3810
Daniel Sandersd97a6342014-08-13 10:07:34 +00003811 if (IDVal == ".mask" || IDVal == ".fmask") {
3812 // .mask bitmask, frame_offset
3813 // bitmask: One bit for each register used.
3814 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3815 // first register is expected to be saved.
3816 // Examples:
3817 // .mask 0x80000000, -4
3818 // .fmask 0x80000000, -4
3819 //
Jack Carterbe332172012-09-07 00:48:02 +00003820
Daniel Sandersd97a6342014-08-13 10:07:34 +00003821 // Parse the bitmask
3822 const MCExpr *BitMask;
3823 int64_t BitMaskVal;
3824
3825 if (Parser.parseExpression(BitMask)) {
3826 reportParseError("expected bitmask value");
3827 return false;
3828 }
3829
3830 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3831 reportParseError("bitmask not an absolute expression");
3832 return false;
3833 }
3834
3835 if (Parser.getTok().is(AsmToken::Comma))
3836 Parser.Lex();
3837 else {
3838 reportParseError("unexpected token, expected comma");
3839 return false;
3840 }
3841
3842 // Parse the frame_offset
3843 const MCExpr *FrameOffset;
3844 int64_t FrameOffsetVal;
3845
3846 if (Parser.parseExpression(FrameOffset)) {
3847 reportParseError("expected frame offset value");
3848 return false;
3849 }
3850
3851 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3852 reportParseError("frame offset not an absolute expression");
3853 return false;
3854 }
3855
3856 // If this is not the end of the statement, report an error.
3857 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3858 reportParseError("unexpected token, expected end of statement");
3859 return false;
3860 }
3861
3862 if (IDVal == ".mask")
3863 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3864 else
3865 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003866 return false;
3867 }
3868
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003869 if (IDVal == ".nan")
3870 return parseDirectiveNaN();
3871
Jack Carter07c818d2013-01-25 01:31:34 +00003872 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003873 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003874 return false;
3875 }
3876
Rafael Espindolab59fb732014-03-28 18:50:26 +00003877 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003878 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003879 return false;
3880 }
3881
Jack Carter07c818d2013-01-25 01:31:34 +00003882 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003883 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003884 return false;
3885 }
3886
Jack Carter0cd3c192014-01-06 23:27:31 +00003887 if (IDVal == ".option")
3888 return parseDirectiveOption();
3889
3890 if (IDVal == ".abicalls") {
3891 getTargetStreamer().emitDirectiveAbiCalls();
3892 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003893 Error(Parser.getTok().getLoc(),
3894 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003895 // Clear line
3896 Parser.eatToEndOfStatement();
3897 }
3898 return false;
3899 }
3900
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003901 if (IDVal == ".cpsetup")
3902 return parseDirectiveCPSetup();
3903
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003904 if (IDVal == ".module")
3905 return parseDirectiveModule();
3906
Rafael Espindola870c4e92012-01-11 03:56:41 +00003907 return true;
3908}
3909
Rafael Espindola870c4e92012-01-11 03:56:41 +00003910extern "C" void LLVMInitializeMipsAsmParser() {
3911 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3912 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3913 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3914 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3915}
Jack Carterb4dbc172012-09-05 23:34:03 +00003916
3917#define GET_REGISTER_MATCHER
3918#define GET_MATCHER_IMPLEMENTATION
3919#include "MipsGenAsmMatcher.inc"