blob: 1a5aed47b321035b374456f2a037ec15f789cab4 [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"
Toma Tabacu9db22db2014-09-09 10:15:38 +000030#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000031
32using namespace llvm;
33
Chandler Carruthe96dd892014-04-21 22:55:11 +000034#define DEBUG_TYPE "mips-asm-parser"
35
Joey Gouly0e76fa72013-09-12 10:28:05 +000036namespace llvm {
37class MCInstrInfo;
38}
39
Rafael Espindola870c4e92012-01-11 03:56:41 +000040namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000041class MipsAssemblerOptions {
42public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000043 MipsAssemblerOptions(uint64_t Features_) :
44 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000045
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
47 ATReg = Opts->getATRegNum();
48 Reorder = Opts->isReorder();
49 Macro = Opts->isMacro();
50 Features = Opts->getFeatures();
51 }
52
53 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000054 bool setATReg(unsigned Reg);
55
Toma Tabacu9db22db2014-09-09 10:15:38 +000056 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000057 void setReorder() { Reorder = true; }
58 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000059
Toma Tabacu9db22db2014-09-09 10:15:38 +000060 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000061 void setMacro() { Macro = true; }
62 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000063
Toma Tabacu9db22db2014-09-09 10:15:38 +000064 uint64_t getFeatures() const { return Features; }
65 void setFeatures(uint64_t Features_) { Features = Features_; }
66
Daniel Sandersf0df2212014-08-04 12:20:00 +000067 // Set of features that are either architecture features or referenced
68 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
69 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
70 // The reason we need this mask is explained in the selectArch function.
71 // FIXME: Ideally we would like TableGen to generate this information.
72 static const uint64_t AllArchRelatedMask =
73 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
74 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
75 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
76 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
77 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
78 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
79 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
80
Jack Carter0b744b32012-10-04 02:29:46 +000081private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000082 unsigned ATReg;
83 bool Reorder;
84 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000085 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000086};
87}
88
89namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000090class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000091 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000092 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000093 return static_cast<MipsTargetStreamer &>(TS);
94 }
95
Jack Carterb4dbc172012-09-05 23:34:03 +000096 MCSubtargetInfo &STI;
97 MCAsmParser &Parser;
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
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000104#define GET_ASSEMBLER_HEADER
105#include "MipsGenAsmMatcher.inc"
106
Matheus Almeida595fcab2014-06-11 15:05:56 +0000107 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
108
Chad Rosier49963552012-10-13 00:26:04 +0000109 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000110 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000111 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000112 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000113
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000114 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000115 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000116
Toma Tabacu13964452014-09-04 13:23:44 +0000117 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118
Toma Tabacu13964452014-09-04 13:23:44 +0000119 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000120
David Blaikie960ea3f2014-06-08 16:18:35 +0000121 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
122 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000123
Craig Topper56c590a2014-04-29 07:58:02 +0000124 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000125
David Blaikie960ea3f2014-06-08 16:18:35 +0000126 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000127
128 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000129 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
Jack Carter873c7242013-01-12 01:03:14 +0000132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000140
David Blaikie960ea3f2014-06-08 16:18:35 +0000141 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool searchSymbolAlias(OperandVector &Operands);
146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000148
Jack Carter30a59822012-10-04 04:03:53 +0000149 bool needsExpansion(MCInst &Inst);
150
Matheus Almeida3813d572014-06-19 14:39:14 +0000151 // Expands assembly pseudo instructions.
152 // Returns false on success, true otherwise.
153 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000154 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000155
156 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000157 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000158
159 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000160 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000161
162 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000163 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000164
Toma Tabacu0d64b202014-08-14 10:29:17 +0000165 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
166 SmallVectorImpl<MCInst> &Instructions);
167
Jack Carter9e65aa32013-03-22 00:05:30 +0000168 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000169 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
170 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000171 bool reportParseError(Twine ErrorMsg);
172 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000173
Jack Carterb5cf5902013-04-17 00:18:04 +0000174 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000175 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000176
Vladimir Medic4c299852013-11-06 11:27:05 +0000177 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000178
179 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000180 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000181 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000182 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000183 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000184 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000185 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000186 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000187 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000188
189 bool parseSetAtDirective();
190 bool parseSetNoAtDirective();
191 bool parseSetMacroDirective();
192 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000193 bool parseSetMsaDirective();
194 bool parseSetNoMsaDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000195 bool parseSetReorderDirective();
196 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000197 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000198 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000199 bool parseSetPopDirective();
200 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000201
Jack Carterd76b2372013-03-21 21:44:16 +0000202 bool parseSetAssignment();
203
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000204 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000206 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000207 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000208 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000209 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
210 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000211
Jack Carterdc1e35d2012-09-06 20:00:02 +0000212 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000213
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000214 bool eatComma(StringRef ErrorStr);
215
Jack Carter1ac53222013-02-20 23:11:17 +0000216 int matchCPURegisterName(StringRef Symbol);
217
Jack Carter873c7242013-01-12 01:03:14 +0000218 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000219
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000220 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000221
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000222 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000223
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000224 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000225
Jack Carter5dc8ac92013-09-25 23:50:44 +0000226 int matchMSA128RegisterName(StringRef Name);
227
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000228 int matchMSA128CtrlRegisterName(StringRef Name);
229
Jack Carterd0bd6422013-04-18 00:41:53 +0000230 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000231
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000232 unsigned getGPR(int RegNo);
233
Matheus Almeida7de68e72014-06-18 14:46:05 +0000234 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000235
236 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000237 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000238
239 // Helper function that checks if the value of a vector index is within the
240 // boundaries of accepted values for each RegisterKind
241 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
242 bool validateMSAIndex(int Val, int RegKind);
243
Daniel Sandersf0df2212014-08-04 12:20:00 +0000244 // Selects a new architecture by updating the FeatureBits with the necessary
245 // info including implied dependencies.
246 // Internally, it clears all the feature bits related to *any* architecture
247 // and selects the new one using the ToggleFeature functionality of the
248 // MCSubtargetInfo object that handles implied dependencies. The reason we
249 // clear all the arch related bits manually is because ToggleFeature only
250 // clears the features that imply the feature being cleared and not the
251 // features implied by the feature being cleared. This is easier to see
252 // with an example:
253 // --------------------------------------------------
254 // | Feature | Implies |
255 // | -------------------------------------------------|
256 // | FeatureMips1 | None |
257 // | FeatureMips2 | FeatureMips1 |
258 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
259 // | FeatureMips4 | FeatureMips3 |
260 // | ... | |
261 // --------------------------------------------------
262 //
263 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
264 // FeatureMipsGP64 | FeatureMips1)
265 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
266 void selectArch(StringRef ArchFeature) {
267 uint64_t FeatureBits = STI.getFeatureBits();
268 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
269 STI.setFeatureBits(FeatureBits);
270 setAvailableFeatures(
271 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000272 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000273 }
274
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000275 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000276 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000277 setAvailableFeatures(
278 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000279 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000280 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000281 }
282
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000283 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000284 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000285 setAvailableFeatures(
286 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000288 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000289 }
290
Rafael Espindola870c4e92012-01-11 03:56:41 +0000291public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000292 enum MipsMatchResultTy {
293 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
294#define GET_OPERAND_DIAGNOSTIC_TYPES
295#include "MipsGenAsmMatcher.inc"
296#undef GET_OPERAND_DIAGNOSTIC_TYPES
297
298 };
299
Joey Gouly0e76fa72013-09-12 10:28:05 +0000300 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000301 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000302 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000303 // Initialize the set of available features.
304 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000305
306 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000307 AssemblerOptions.push_back(
308 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000309
310 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000311 AssemblerOptions.push_back(
312 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000313
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000314 getTargetStreamer().updateABIInfo(*this);
315
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000316 // Assert exactly one ABI was chosen.
317 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
318 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
319 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
320 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000321
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000322 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000323 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000324
325 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000326 }
327
Jack Carterb4dbc172012-09-05 23:34:03 +0000328 MCAsmParser &getParser() const { return Parser; }
329 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000330
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000331 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
332 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
333
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000334 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
335 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
336 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
337 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
338 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000339 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000340
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000341 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000342 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
343 }
344
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000345 bool inMicroMipsMode() const {
346 return STI.getFeatureBits() & Mips::FeatureMicroMips;
347 }
348 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
349 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
350 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
351 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
352 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
353 bool hasMips32() const {
354 return (STI.getFeatureBits() & Mips::FeatureMips32);
355 }
356 bool hasMips64() const {
357 return (STI.getFeatureBits() & Mips::FeatureMips64);
358 }
359 bool hasMips32r2() const {
360 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
361 }
362 bool hasMips64r2() const {
363 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
364 }
365 bool hasMips32r6() const {
366 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
367 }
368 bool hasMips64r6() const {
369 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
370 }
371 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
372 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
373 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
374
375 bool inMips16Mode() const {
376 return STI.getFeatureBits() & Mips::FeatureMips16;
377 }
378 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000379 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000380
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000381 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000382 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000383};
384}
385
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000386namespace {
387
388/// MipsOperand - Instances of this class represent a parsed Mips machine
389/// instruction.
390class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000391public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000392 /// Broad categories of register classes
393 /// The exact class is finalized by the render method.
394 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000396 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000397 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000398 RegKind_FCC = 4, /// FCC
399 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
400 RegKind_MSACtrl = 16, /// MSA control registers
401 RegKind_COP2 = 32, /// COP2
402 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
403 /// context).
404 RegKind_CCR = 128, /// CCR
405 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000406 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000407
408 /// Potentially any (e.g. $1)
409 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
410 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000411 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000412 };
413
414private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000415 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000416 k_Immediate, /// An immediate (possibly involving symbol references)
417 k_Memory, /// Base + Offset Memory Address
418 k_PhysRegister, /// A physical register from the Mips namespace
419 k_RegisterIndex, /// A register index in one or more RegKind.
420 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000421 } Kind;
422
David Blaikie960ea3f2014-06-08 16:18:35 +0000423public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000424 MipsOperand(KindTy K, MipsAsmParser &Parser)
425 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
426
David Blaikie960ea3f2014-06-08 16:18:35 +0000427private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000428 /// For diagnostics, and checking the assembler temporary
429 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000430
Eric Christopher8996c5d2013-03-15 00:42:55 +0000431 struct Token {
432 const char *Data;
433 unsigned Length;
434 };
435
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000436 struct PhysRegOp {
437 unsigned Num; /// Register Number
438 };
439
440 struct RegIdxOp {
441 unsigned Index; /// Index into the register class
442 RegKind Kind; /// Bitfield of the kinds it could possibly be
443 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000444 };
445
446 struct ImmOp {
447 const MCExpr *Val;
448 };
449
450 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000451 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000452 const MCExpr *Off;
453 };
454
Jack Carterb4dbc172012-09-05 23:34:03 +0000455 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000456 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000457 struct PhysRegOp PhysReg;
458 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000459 struct ImmOp Imm;
460 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000461 };
462
463 SMLoc StartLoc, EndLoc;
464
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000465 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000466 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
467 const MCRegisterInfo *RegInfo,
468 SMLoc S, SMLoc E,
469 MipsAsmParser &Parser) {
470 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000471 Op->RegIdx.Index = Index;
472 Op->RegIdx.RegInfo = RegInfo;
473 Op->RegIdx.Kind = RegKind;
474 Op->StartLoc = S;
475 Op->EndLoc = E;
476 return Op;
477 }
478
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000479public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000480 /// Coerce the register to GPR32 and return the real register for the current
481 /// target.
482 unsigned getGPR32Reg() const {
483 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000484 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000485 unsigned ClassID = Mips::GPR32RegClassID;
486 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000487 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000488
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000489 /// Coerce the register to GPR64 and return the real register for the current
490 /// target.
491 unsigned getGPR64Reg() const {
492 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
493 unsigned ClassID = Mips::GPR64RegClassID;
494 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000495 }
496
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000497private:
498 /// Coerce the register to AFGR64 and return the real register for the current
499 /// target.
500 unsigned getAFGR64Reg() const {
501 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
502 if (RegIdx.Index % 2 != 0)
503 AsmParser.Warning(StartLoc, "Float register should be even.");
504 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
505 .getRegister(RegIdx.Index / 2);
506 }
507
508 /// Coerce the register to FGR64 and return the real register for the current
509 /// target.
510 unsigned getFGR64Reg() const {
511 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
512 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
513 .getRegister(RegIdx.Index);
514 }
515
516 /// Coerce the register to FGR32 and return the real register for the current
517 /// target.
518 unsigned getFGR32Reg() const {
519 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
520 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
521 .getRegister(RegIdx.Index);
522 }
523
524 /// Coerce the register to FGRH32 and return the real register for the current
525 /// target.
526 unsigned getFGRH32Reg() const {
527 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
528 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
529 .getRegister(RegIdx.Index);
530 }
531
532 /// Coerce the register to FCC and return the real register for the current
533 /// target.
534 unsigned getFCCReg() const {
535 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
536 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
537 .getRegister(RegIdx.Index);
538 }
539
540 /// Coerce the register to MSA128 and return the real register for the current
541 /// target.
542 unsigned getMSA128Reg() const {
543 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
544 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
545 // identical
546 unsigned ClassID = Mips::MSA128BRegClassID;
547 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
548 }
549
550 /// Coerce the register to MSACtrl and return the real register for the
551 /// current target.
552 unsigned getMSACtrlReg() const {
553 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
554 unsigned ClassID = Mips::MSACtrlRegClassID;
555 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
556 }
557
558 /// Coerce the register to COP2 and return the real register for the
559 /// current target.
560 unsigned getCOP2Reg() const {
561 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
562 unsigned ClassID = Mips::COP2RegClassID;
563 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
564 }
565
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000566 /// Coerce the register to COP3 and return the real register for the
567 /// current target.
568 unsigned getCOP3Reg() const {
569 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
570 unsigned ClassID = Mips::COP3RegClassID;
571 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
572 }
573
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 /// Coerce the register to ACC64DSP and return the real register for the
575 /// current target.
576 unsigned getACC64DSPReg() const {
577 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
578 unsigned ClassID = Mips::ACC64DSPRegClassID;
579 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
580 }
581
582 /// Coerce the register to HI32DSP and return the real register for the
583 /// current target.
584 unsigned getHI32DSPReg() const {
585 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
586 unsigned ClassID = Mips::HI32DSPRegClassID;
587 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
588 }
589
590 /// Coerce the register to LO32DSP and return the real register for the
591 /// current target.
592 unsigned getLO32DSPReg() const {
593 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
594 unsigned ClassID = Mips::LO32DSPRegClassID;
595 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
596 }
597
598 /// Coerce the register to CCR and return the real register for the
599 /// current target.
600 unsigned getCCRReg() const {
601 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
602 unsigned ClassID = Mips::CCRRegClassID;
603 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
604 }
605
606 /// Coerce the register to HWRegs and return the real register for the
607 /// current target.
608 unsigned getHWRegsReg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
610 unsigned ClassID = Mips::HWRegsRegClassID;
611 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
612 }
613
614public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000615 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000616 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000617 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000618 Inst.addOperand(MCOperand::CreateImm(0));
619 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
620 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
621 else
622 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000623 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000624
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000625 void addRegOperands(MCInst &Inst, unsigned N) const {
626 llvm_unreachable("Use a custom parser instead");
627 }
628
Daniel Sanders21bce302014-04-01 12:35:23 +0000629 /// Render the operand to an MCInst as a GPR32
630 /// Asserts if the wrong number of operands are requested, or the operand
631 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
633 assert(N == 1 && "Invalid number of operands!");
634 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
635 }
636
Daniel Sanders21bce302014-04-01 12:35:23 +0000637 /// Render the operand to an MCInst as a GPR64
638 /// Asserts if the wrong number of operands are requested, or the operand
639 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
641 assert(N == 1 && "Invalid number of operands!");
642 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
643 }
644
645 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
646 assert(N == 1 && "Invalid number of operands!");
647 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
648 }
649
650 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
651 assert(N == 1 && "Invalid number of operands!");
652 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
653 }
654
655 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
656 assert(N == 1 && "Invalid number of operands!");
657 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000658 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000659 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000660 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
661 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000662 }
663
664 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
665 assert(N == 1 && "Invalid number of operands!");
666 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
667 }
668
669 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
670 assert(N == 1 && "Invalid number of operands!");
671 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
672 }
673
674 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
675 assert(N == 1 && "Invalid number of operands!");
676 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
677 }
678
679 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
680 assert(N == 1 && "Invalid number of operands!");
681 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
682 }
683
684 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
685 assert(N == 1 && "Invalid number of operands!");
686 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
687 }
688
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000689 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
692 }
693
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
695 assert(N == 1 && "Invalid number of operands!");
696 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
697 }
698
699 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
700 assert(N == 1 && "Invalid number of operands!");
701 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
702 }
703
704 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
705 assert(N == 1 && "Invalid number of operands!");
706 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
707 }
708
709 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
710 assert(N == 1 && "Invalid number of operands!");
711 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
712 }
713
714 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
715 assert(N == 1 && "Invalid number of operands!");
716 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
717 }
718
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000719 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000720 assert(N == 1 && "Invalid number of operands!");
721 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000722 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000723 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000724
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000725 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000726 assert(N == 2 && "Invalid number of operands!");
727
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000729
730 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000731 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000732 }
733
Craig Topper56c590a2014-04-29 07:58:02 +0000734 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 // As a special case until we sort out the definition of div/divu, pretend
736 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
737 if (isGPRAsmReg() && RegIdx.Index == 0)
738 return true;
739
740 return Kind == k_PhysRegister;
741 }
742 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000743 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 bool isConstantImm() const {
745 return isImm() && dyn_cast<MCConstantExpr>(getImm());
746 }
Craig Topper56c590a2014-04-29 07:58:02 +0000747 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 // Note: It's not possible to pretend that other operand kinds are tokens.
749 // The matcher emitter checks tokens first.
750 return Kind == k_Token;
751 }
Craig Topper56c590a2014-04-29 07:58:02 +0000752 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000753 bool isConstantMemOff() const {
754 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
755 }
756 template <unsigned Bits> bool isMemWithSimmOffset() const {
757 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
758 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000759 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 bool isLSAImm() const {
761 if (!isConstantImm())
762 return false;
763 int64_t Val = getConstantImm();
764 return 1 <= Val && Val <= 4;
765 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000766
767 StringRef getToken() const {
768 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000769 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000770 }
771
Craig Topper56c590a2014-04-29 07:58:02 +0000772 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000773 // As a special case until we sort out the definition of div/divu, pretend
774 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
775 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
776 RegIdx.Kind & RegKind_GPR)
777 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000778
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 assert(Kind == k_PhysRegister && "Invalid access!");
780 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000781 }
782
Jack Carterb4dbc172012-09-05 23:34:03 +0000783 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000785 return Imm.Val;
786 }
787
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 int64_t getConstantImm() const {
789 const MCExpr *Val = getImm();
790 return static_cast<const MCConstantExpr *>(Val)->getValue();
791 }
792
793 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000794 assert((Kind == k_Memory) && "Invalid access!");
795 return Mem.Base;
796 }
797
798 const MCExpr *getMemOff() const {
799 assert((Kind == k_Memory) && "Invalid access!");
800 return Mem.Off;
801 }
802
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000803 int64_t getConstantMemOff() const {
804 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
805 }
806
David Blaikie960ea3f2014-06-08 16:18:35 +0000807 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
808 MipsAsmParser &Parser) {
809 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000810 Op->Tok.Data = Str.data();
811 Op->Tok.Length = Str.size();
812 Op->StartLoc = S;
813 Op->EndLoc = S;
814 return Op;
815 }
816
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 /// Create a numeric register (e.g. $1). The exact register remains
818 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000819 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000820 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000821 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000822 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000824 }
825
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 /// Create a register that is definitely a GPR.
827 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000828 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000829 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000830 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000832 }
833
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000834 /// Create a register that is definitely a FGR.
835 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000836 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000837 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000838 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
840 }
841
842 /// Create a register that is definitely an FCC.
843 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000844 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000845 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000846 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
848 }
849
850 /// Create a register that is definitely an ACC.
851 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000852 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000853 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000854 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
856 }
857
858 /// Create a register that is definitely an MSA128.
859 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000860 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000861 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000862 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
864 }
865
866 /// Create a register that is definitely an MSACtrl.
867 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000868 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000869 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000870 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
872 }
873
David Blaikie960ea3f2014-06-08 16:18:35 +0000874 static std::unique_ptr<MipsOperand>
875 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
876 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000877 Op->Imm.Val = Val;
878 Op->StartLoc = S;
879 Op->EndLoc = E;
880 return Op;
881 }
882
David Blaikie960ea3f2014-06-08 16:18:35 +0000883 static std::unique_ptr<MipsOperand>
884 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
885 SMLoc E, MipsAsmParser &Parser) {
886 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
887 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000888 Op->Mem.Off = Off;
889 Op->StartLoc = S;
890 Op->EndLoc = E;
891 return Op;
892 }
893
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 bool isGPRAsmReg() const {
895 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000896 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 bool isFGRAsmReg() const {
898 // AFGR64 is $0-$15 but we handle this in getAFGR64()
899 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000900 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000901 bool isHWRegsAsmReg() const {
902 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000903 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000904 bool isCCRAsmReg() const {
905 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000906 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000908 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
909 return false;
910 if (!AsmParser.hasEightFccRegisters())
911 return RegIdx.Index == 0;
912 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000913 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 bool isACCAsmReg() const {
915 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000916 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 bool isCOP2AsmReg() const {
918 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000919 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000920 bool isCOP3AsmReg() const {
921 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
922 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 bool isMSA128AsmReg() const {
924 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000925 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 bool isMSACtrlAsmReg() const {
927 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000928 }
929
Jack Carterb4dbc172012-09-05 23:34:03 +0000930 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000931 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000932 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000933 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000934
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000935 virtual ~MipsOperand() {
936 switch (Kind) {
937 case k_Immediate:
938 break;
939 case k_Memory:
940 delete Mem.Base;
941 break;
942 case k_PhysRegister:
943 case k_RegisterIndex:
944 case k_Token:
945 break;
946 }
947 }
948
Craig Topper56c590a2014-04-29 07:58:02 +0000949 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000950 switch (Kind) {
951 case k_Immediate:
952 OS << "Imm<";
953 Imm.Val->print(OS);
954 OS << ">";
955 break;
956 case k_Memory:
957 OS << "Mem<";
958 Mem.Base->print(OS);
959 OS << ", ";
960 Mem.Off->print(OS);
961 OS << ">";
962 break;
963 case k_PhysRegister:
964 OS << "PhysReg<" << PhysReg.Num << ">";
965 break;
966 case k_RegisterIndex:
967 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
968 break;
969 case k_Token:
970 OS << Tok.Data;
971 break;
972 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000973 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000974}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000975} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000976
Jack Carter9e65aa32013-03-22 00:05:30 +0000977namespace llvm {
978extern const MCInstrDesc MipsInsts[];
979}
980static const MCInstrDesc &getInstDesc(unsigned Opcode) {
981 return MipsInsts[Opcode];
982}
983
Zoran Jovanovicac9ef122014-09-12 13:43:41 +0000984static bool hasShortDelaySlot(unsigned Opcode) {
985 switch (Opcode) {
986 case Mips::JALS_MM:
987 case Mips::JALRS_MM:
988 return true;
989 default:
990 return false;
991 }
992}
993
Jack Carter9e65aa32013-03-22 00:05:30 +0000994bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000995 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000996 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000997
Jack Carter9e65aa32013-03-22 00:05:30 +0000998 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000999
1000 if (MCID.isBranch() || MCID.isCall()) {
1001 const unsigned Opcode = Inst.getOpcode();
1002 MCOperand Offset;
1003
1004 switch (Opcode) {
1005 default:
1006 break;
1007 case Mips::BEQ:
1008 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001009 case Mips::BEQ_MM:
1010 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001011 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001012 Offset = Inst.getOperand(2);
1013 if (!Offset.isImm())
1014 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001015 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001016 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001017 if (OffsetToAlignment(Offset.getImm(),
1018 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001019 return Error(IDLoc, "branch to misaligned address");
1020 break;
1021 case Mips::BGEZ:
1022 case Mips::BGTZ:
1023 case Mips::BLEZ:
1024 case Mips::BLTZ:
1025 case Mips::BGEZAL:
1026 case Mips::BLTZAL:
1027 case Mips::BC1F:
1028 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 case Mips::BGEZ_MM:
1030 case Mips::BGTZ_MM:
1031 case Mips::BLEZ_MM:
1032 case Mips::BLTZ_MM:
1033 case Mips::BGEZAL_MM:
1034 case Mips::BLTZAL_MM:
1035 case Mips::BC1F_MM:
1036 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001037 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001038 Offset = Inst.getOperand(1);
1039 if (!Offset.isImm())
1040 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001041 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001042 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001043 if (OffsetToAlignment(Offset.getImm(),
1044 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001045 return Error(IDLoc, "branch to misaligned address");
1046 break;
1047 }
1048 }
1049
Daniel Sandersa84989a2014-06-16 13:25:35 +00001050 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1051 // We still accept it but it is a normal nop.
1052 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1053 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1054 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1055 "nop instruction");
1056 }
1057
Toma Tabacu9db22db2014-09-09 10:15:38 +00001058 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001059 // If this instruction has a delay slot and .set reorder is active,
1060 // emit a NOP after it.
1061 Instructions.push_back(Inst);
1062 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001063 if (hasShortDelaySlot(Inst.getOpcode())) {
1064 NopInst.setOpcode(Mips::MOVE16_MM);
1065 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1066 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1067 } else {
1068 NopInst.setOpcode(Mips::SLL);
1069 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1070 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1071 NopInst.addOperand(MCOperand::CreateImm(0));
1072 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001073 Instructions.push_back(NopInst);
1074 return false;
1075 }
1076
Jack Carter9e65aa32013-03-22 00:05:30 +00001077 if (MCID.mayLoad() || MCID.mayStore()) {
1078 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001079 // reference or immediate we may have to expand instructions.
1080 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001081 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001082 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1083 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001084 MCOperand &Op = Inst.getOperand(i);
1085 if (Op.isImm()) {
1086 int MemOffset = Op.getImm();
1087 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 // Offset can't exceed 16bit value.
1089 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001090 return false;
1091 }
1092 } else if (Op.isExpr()) {
1093 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001095 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001096 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001097 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001098 // Expand symbol.
1099 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001100 return false;
1101 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001102 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001104 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001105 }
1106 }
1107 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001108 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001109 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001110
1111 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001112 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001113 else
1114 Instructions.push_back(Inst);
1115
1116 return false;
1117}
1118
Jack Carter30a59822012-10-04 04:03:53 +00001119bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1120
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 switch (Inst.getOpcode()) {
1122 case Mips::LoadImm32Reg:
1123 case Mips::LoadAddr32Imm:
1124 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001125 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001126 return true;
1127 default:
1128 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001129 }
1130}
Jack Carter92995f12012-10-06 00:53:28 +00001131
Matheus Almeida3813d572014-06-19 14:39:14 +00001132bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001133 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001134 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001135 default:
1136 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001137 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001138 case Mips::LoadImm32Reg:
1139 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001140 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001141 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001142 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1143 return true;
1144 }
1145 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001146 case Mips::LoadAddr32Imm:
1147 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1148 case Mips::LoadAddr32Reg:
1149 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1150 }
Jack Carter30a59822012-10-04 04:03:53 +00001151}
Jack Carter92995f12012-10-06 00:53:28 +00001152
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001153namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001154template <bool PerformShift>
1155void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001156 SmallVectorImpl<MCInst> &Instructions) {
1157 MCInst tmpInst;
1158 if (PerformShift) {
1159 tmpInst.setOpcode(Mips::DSLL);
1160 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1161 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1162 tmpInst.addOperand(MCOperand::CreateImm(16));
1163 tmpInst.setLoc(IDLoc);
1164 Instructions.push_back(tmpInst);
1165 tmpInst.clear();
1166 }
1167 tmpInst.setOpcode(Mips::ORi);
1168 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1169 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001170 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001171 tmpInst.setLoc(IDLoc);
1172 Instructions.push_back(tmpInst);
1173}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001174
1175template <int Shift, bool PerformShift>
1176void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1177 SmallVectorImpl<MCInst> &Instructions) {
1178 createShiftOr<PerformShift>(
1179 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1180 IDLoc, Instructions);
1181}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001182}
1183
Matheus Almeida3813d572014-06-19 14:39:14 +00001184bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001185 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001186 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001187 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001188 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001189 const MCOperand &RegOp = Inst.getOperand(0);
1190 assert(RegOp.isReg() && "expected register operand kind");
1191
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001192 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001193 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001194 // FIXME: gas has a special case for values that are 000...1111, which
1195 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001196 if (0 <= ImmValue && ImmValue <= 65535) {
1197 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001198 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001199 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001200 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001201 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001202 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001203 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 } else if (ImmValue < 0 && ImmValue >= -32768) {
1205 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001206 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001207 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001208 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001209 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001210 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001211 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001212 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1213 // For any value of j that is representable as a 32-bit integer, create
1214 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001215 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001216 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001217 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001218 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1219 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001220 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001221 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1222 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001223 if (!isGP64bit()) {
1224 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001225 return true;
1226 }
1227
1228 // <------- lo32 ------>
1229 // <------- hi32 ------>
1230 // <- hi16 -> <- lo16 ->
1231 // _________________________________
1232 // | | | |
1233 // | 16-bytes | 16-bytes | 16-bytes |
1234 // |__________|__________|__________|
1235 //
1236 // For any value of j that is representable as a 48-bit integer, create
1237 // a sequence of:
1238 // li d,j => lui d,hi16(j)
1239 // ori d,d,hi16(lo32(j))
1240 // dsll d,d,16
1241 // ori d,d,lo16(lo32(j))
1242 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001243 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001244 tmpInst.addOperand(
1245 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001246 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001247 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1248 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1249 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001250 if (!isGP64bit()) {
1251 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001252 return true;
1253 }
1254
1255 // <------- hi32 ------> <------- lo32 ------>
1256 // <- hi16 -> <- lo16 ->
1257 // ___________________________________________
1258 // | | | | |
1259 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1260 // |__________|__________|__________|__________|
1261 //
1262 // For any value of j that isn't representable as a 48-bit integer.
1263 // li d,j => lui d,hi16(j)
1264 // ori d,d,lo16(hi32(j))
1265 // dsll d,d,16
1266 // ori d,d,hi16(lo32(j))
1267 // dsll d,d,16
1268 // ori d,d,lo16(lo32(j))
1269 tmpInst.setOpcode(Mips::LUi);
1270 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1271 tmpInst.addOperand(
1272 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1273 Instructions.push_back(tmpInst);
1274 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1275 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1276 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001277 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001278 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001279}
Jack Carter92995f12012-10-06 00:53:28 +00001280
Matheus Almeida3813d572014-06-19 14:39:14 +00001281bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001282MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1283 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001284 MCInst tmpInst;
1285 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001286 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1287 "expected immediate operand kind");
1288 if (!ImmOp.isImm()) {
1289 expandLoadAddressSym(Inst, IDLoc, Instructions);
1290 return false;
1291 }
Jack Carter543fdf82012-10-09 23:29:45 +00001292 const MCOperand &SrcRegOp = Inst.getOperand(1);
1293 assert(SrcRegOp.isReg() && "expected register operand kind");
1294 const MCOperand &DstRegOp = Inst.getOperand(0);
1295 assert(DstRegOp.isReg() && "expected register operand kind");
1296 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001297 if (-32768 <= ImmValue && ImmValue <= 65535) {
1298 // For -32768 <= j <= 65535.
1299 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001300 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001301 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1302 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1303 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1304 Instructions.push_back(tmpInst);
1305 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001306 // For any other value of j that is representable as a 32-bit integer.
1307 // la d,j(s) => lui d,hi16(j)
1308 // ori d,d,lo16(j)
1309 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001310 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001311 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1312 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1313 Instructions.push_back(tmpInst);
1314 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001315 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001316 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1317 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1318 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1319 Instructions.push_back(tmpInst);
1320 tmpInst.clear();
1321 tmpInst.setOpcode(Mips::ADDu);
1322 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1323 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1324 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1325 Instructions.push_back(tmpInst);
1326 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001327 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001328}
1329
Matheus Almeida3813d572014-06-19 14:39:14 +00001330bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001331MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1332 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001333 MCInst tmpInst;
1334 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001335 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1336 "expected immediate operand kind");
1337 if (!ImmOp.isImm()) {
1338 expandLoadAddressSym(Inst, IDLoc, Instructions);
1339 return false;
1340 }
Jack Carter543fdf82012-10-09 23:29:45 +00001341 const MCOperand &RegOp = Inst.getOperand(0);
1342 assert(RegOp.isReg() && "expected register operand kind");
1343 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001344 if (-32768 <= ImmValue && ImmValue <= 65535) {
1345 // For -32768 <= j <= 65535.
1346 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001347 tmpInst.setOpcode(Mips::ADDiu);
1348 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001349 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001350 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1351 Instructions.push_back(tmpInst);
1352 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001353 // For any other value of j that is representable as a 32-bit integer.
1354 // la d,j => lui d,hi16(j)
1355 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001356 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001357 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1358 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1359 Instructions.push_back(tmpInst);
1360 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001361 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001362 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1363 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1364 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1365 Instructions.push_back(tmpInst);
1366 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001367 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001368}
1369
Toma Tabacu0d64b202014-08-14 10:29:17 +00001370void
1371MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1372 SmallVectorImpl<MCInst> &Instructions) {
1373 // FIXME: If we do have a valid at register to use, we should generate a
1374 // slightly shorter sequence here.
1375 MCInst tmpInst;
1376 int ExprOperandNo = 1;
1377 // Sometimes the assembly parser will get the immediate expression as
1378 // a $zero + an immediate.
1379 if (Inst.getNumOperands() == 3) {
1380 assert(Inst.getOperand(1).getReg() ==
1381 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1382 ExprOperandNo = 2;
1383 }
1384 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1385 assert(SymOp.isExpr() && "expected symbol operand kind");
1386 const MCOperand &RegOp = Inst.getOperand(0);
1387 unsigned RegNo = RegOp.getReg();
1388 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1389 const MCSymbolRefExpr *HiExpr =
1390 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1391 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1392 const MCSymbolRefExpr *LoExpr =
1393 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1394 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1395 if (isGP64bit()) {
1396 // If it's a 64-bit architecture, expand to:
1397 // la d,sym => lui d,highest(sym)
1398 // ori d,d,higher(sym)
1399 // dsll d,d,16
1400 // ori d,d,hi16(sym)
1401 // dsll d,d,16
1402 // ori d,d,lo16(sym)
1403 const MCSymbolRefExpr *HighestExpr =
1404 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1405 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1406 const MCSymbolRefExpr *HigherExpr =
1407 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1408 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1409
1410 tmpInst.setOpcode(Mips::LUi);
1411 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1412 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1413 Instructions.push_back(tmpInst);
1414
1415 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1416 Instructions);
1417 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1418 Instructions);
1419 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1420 Instructions);
1421 } else {
1422 // Otherwise, expand to:
1423 // la d,sym => lui d,hi16(sym)
1424 // ori d,d,lo16(sym)
1425 tmpInst.setOpcode(Mips::LUi);
1426 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1427 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1428 Instructions.push_back(tmpInst);
1429
1430 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1431 Instructions);
1432 }
1433}
1434
Jack Carter9e65aa32013-03-22 00:05:30 +00001435void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001436 SmallVectorImpl<MCInst> &Instructions,
1437 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001438 const MCSymbolRefExpr *SR;
1439 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001440 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001441 const MCExpr *ExprOffset;
1442 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001443 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001444 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1445 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001446 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001447 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1448 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001449 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001450 if (isImmOpnd) {
1451 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1452 ImmOffset = Inst.getOperand(2).getImm();
1453 LoOffset = ImmOffset & 0x0000ffff;
1454 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001455 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001456 if (LoOffset & 0x8000)
1457 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001458 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001459 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001460 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001461 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001462 // These are some of the types of expansions we perform here:
1463 // 1) lw $8, sym => lui $8, %hi(sym)
1464 // lw $8, %lo(sym)($8)
1465 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1466 // add $8, $8, $9
1467 // lw $8, %lo(offset)($9)
1468 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1469 // add $at, $at, $8
1470 // lw $8, %lo(offset)($at)
1471 // 4) sw $8, sym => lui $at, %hi(sym)
1472 // sw $8, %lo(sym)($at)
1473 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1474 // add $at, $at, $8
1475 // sw $8, %lo(offset)($at)
1476 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1477 // ldc1 $f0, %lo(sym)($at)
1478 //
1479 // For load instructions we can use the destination register as a temporary
1480 // if base and dst are different (examples 1 and 2) and if the base register
1481 // is general purpose otherwise we must use $at (example 6) and error if it's
1482 // not available. For stores we must use $at (examples 4 and 5) because we
1483 // must not clobber the source register setting up the offset.
1484 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1485 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1486 unsigned RegClassIDOp0 =
1487 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1488 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1489 (RegClassIDOp0 == Mips::GPR64RegClassID);
1490 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001491 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001492 else {
1493 int AT = getATReg(IDLoc);
1494 // At this point we need AT to perform the expansions and we exit if it is
1495 // not available.
1496 if (!AT)
1497 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001498 TmpRegNum = getReg(
1499 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001500 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001501
Jack Carter9e65aa32013-03-22 00:05:30 +00001502 TempInst.setOpcode(Mips::LUi);
1503 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1504 if (isImmOpnd)
1505 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1506 else {
1507 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001508 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001509 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1510 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1511 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001512 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001513 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001514 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001515 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001516 }
1517 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001518 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001519 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001520 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001521 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001522 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001523 TempInst.setOpcode(Mips::ADDu);
1524 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1525 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1526 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1527 Instructions.push_back(TempInst);
1528 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001529 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001530 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001531 TempInst.setOpcode(Inst.getOpcode());
1532 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1533 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1534 if (isImmOpnd)
1535 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1536 else {
1537 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1539 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1540 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001541 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001542 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001543 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001544 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001545 }
1546 }
1547 Instructions.push_back(TempInst);
1548 TempInst.clear();
1549}
1550
Matheus Almeida595fcab2014-06-11 15:05:56 +00001551unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1552 // As described by the Mips32r2 spec, the registers Rd and Rs for
1553 // jalr.hb must be different.
1554 unsigned Opcode = Inst.getOpcode();
1555
1556 if (Opcode == Mips::JALR_HB &&
1557 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1558 return Match_RequiresDifferentSrcAndDst;
1559
1560 return Match_Success;
1561}
1562
David Blaikie960ea3f2014-06-08 16:18:35 +00001563bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1564 OperandVector &Operands,
1565 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001566 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001567 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001568
Jack Carterb4dbc172012-09-05 23:34:03 +00001569 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001570 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001571 unsigned MatchResult =
1572 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001573
1574 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001575 default:
1576 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001577 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001578 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001579 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001581 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001582 return false;
1583 }
1584 case Match_MissingFeature:
1585 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1586 return true;
1587 case Match_InvalidOperand: {
1588 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001589 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001590 if (ErrorInfo >= Operands.size())
1591 return Error(IDLoc, "too few operands for instruction");
1592
David Blaikie960ea3f2014-06-08 16:18:35 +00001593 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001594 if (ErrorLoc == SMLoc())
1595 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001596 }
1597
1598 return Error(ErrorLoc, "invalid operand for instruction");
1599 }
1600 case Match_MnemonicFail:
1601 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001602 case Match_RequiresDifferentSrcAndDst:
1603 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001604 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001605 return true;
1606}
1607
Toma Tabacu13964452014-09-04 13:23:44 +00001608void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001609 if ((RegIndex != 0) &&
1610 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001611 if (RegIndex == 1)
1612 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001613 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001614 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1615 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001616 }
1617}
1618
Jack Carter1ac53222013-02-20 23:11:17 +00001619int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001620 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001621
Vladimir Medic4c299852013-11-06 11:27:05 +00001622 CC = StringSwitch<unsigned>(Name)
1623 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001624 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001625 .Case("a0", 4)
1626 .Case("a1", 5)
1627 .Case("a2", 6)
1628 .Case("a3", 7)
1629 .Case("v0", 2)
1630 .Case("v1", 3)
1631 .Case("s0", 16)
1632 .Case("s1", 17)
1633 .Case("s2", 18)
1634 .Case("s3", 19)
1635 .Case("s4", 20)
1636 .Case("s5", 21)
1637 .Case("s6", 22)
1638 .Case("s7", 23)
1639 .Case("k0", 26)
1640 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001641 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001642 .Case("sp", 29)
1643 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001644 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001645 .Case("ra", 31)
1646 .Case("t0", 8)
1647 .Case("t1", 9)
1648 .Case("t2", 10)
1649 .Case("t3", 11)
1650 .Case("t4", 12)
1651 .Case("t5", 13)
1652 .Case("t6", 14)
1653 .Case("t7", 15)
1654 .Case("t8", 24)
1655 .Case("t9", 25)
1656 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001657
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001658 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001659 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1660 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1661 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1662 if (8 <= CC && CC <= 11)
1663 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001664
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001665 if (CC == -1)
1666 CC = StringSwitch<unsigned>(Name)
1667 .Case("a4", 8)
1668 .Case("a5", 9)
1669 .Case("a6", 10)
1670 .Case("a7", 11)
1671 .Case("kt0", 26)
1672 .Case("kt1", 27)
1673 .Default(-1);
1674 }
Jack Carter1ac53222013-02-20 23:11:17 +00001675
1676 return CC;
1677}
Jack Carterd0bd6422013-04-18 00:41:53 +00001678
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001679int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001680
Jack Cartera63b16a2012-09-07 00:23:42 +00001681 if (Name[0] == 'f') {
1682 StringRef NumString = Name.substr(1);
1683 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001684 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001685 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001686 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001687 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001688 return IntVal;
1689 }
1690 return -1;
1691}
Jack Cartera63b16a2012-09-07 00:23:42 +00001692
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001693int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1694
1695 if (Name.startswith("fcc")) {
1696 StringRef NumString = Name.substr(3);
1697 unsigned IntVal;
1698 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001699 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001700 if (IntVal > 7) // There are only 8 fcc registers.
1701 return -1;
1702 return IntVal;
1703 }
1704 return -1;
1705}
1706
1707int MipsAsmParser::matchACRegisterName(StringRef Name) {
1708
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001709 if (Name.startswith("ac")) {
1710 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001711 unsigned IntVal;
1712 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001713 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001714 if (IntVal > 3) // There are only 3 acc registers.
1715 return -1;
1716 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001717 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001718 return -1;
1719}
Jack Carterd0bd6422013-04-18 00:41:53 +00001720
Jack Carter5dc8ac92013-09-25 23:50:44 +00001721int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1722 unsigned IntVal;
1723
1724 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1725 return -1;
1726
1727 if (IntVal > 31)
1728 return -1;
1729
1730 return IntVal;
1731}
1732
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001733int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1734 int CC;
1735
1736 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001737 .Case("msair", 0)
1738 .Case("msacsr", 1)
1739 .Case("msaaccess", 2)
1740 .Case("msasave", 3)
1741 .Case("msamodify", 4)
1742 .Case("msarequest", 5)
1743 .Case("msamap", 6)
1744 .Case("msaunmap", 7)
1745 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001746
1747 return CC;
1748}
1749
Jack Carter0b744b32012-10-04 02:29:46 +00001750bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1751 if (Reg > 31)
1752 return false;
1753
Toma Tabacu3c24b042014-09-05 15:43:21 +00001754 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001755 return true;
1756}
1757
Matheus Almeida7de68e72014-06-18 14:46:05 +00001758int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001759 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001760 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001761 reportParseError(Loc,
1762 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001763 return AT;
1764}
Jack Carter0b744b32012-10-04 02:29:46 +00001765
Jack Carterd0bd6422013-04-18 00:41:53 +00001766unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001767 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001768}
1769
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001770unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001771 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001772 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001773}
1774
Jack Carter873c7242013-01-12 01:03:14 +00001775int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001776 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001777 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001778 return -1;
1779
Jack Carter873c7242013-01-12 01:03:14 +00001780 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001781}
1782
Toma Tabacu13964452014-09-04 13:23:44 +00001783bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1784 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001785
Jack Carter30a59822012-10-04 04:03:53 +00001786 // Check if the current operand has a custom associated parser, if so, try to
1787 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001788 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1789 if (ResTy == MatchOperand_Success)
1790 return false;
1791 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1792 // there was a match, but an error occurred, in which case, just return that
1793 // the operand parsing failed.
1794 if (ResTy == MatchOperand_ParseFail)
1795 return true;
1796
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001797 DEBUG(dbgs() << ".. Generic Parser\n");
1798
Jack Carterb4dbc172012-09-05 23:34:03 +00001799 switch (getLexer().getKind()) {
1800 default:
1801 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1802 return true;
1803 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001805 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001806
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001807 // Almost all registers have been parsed by custom parsers. There is only
1808 // one exception to this. $zero (and it's alias $0) will reach this point
1809 // for div, divu, and similar instructions because it is not an operand
1810 // to the instruction definition but an explicit register. Special case
1811 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001812 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001813 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001814
Jack Carterd0bd6422013-04-18 00:41:53 +00001815 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001816 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001817 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001818 return true;
1819
Jack Carter873c7242013-01-12 01:03:14 +00001820 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001821 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001822 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001823 const MCExpr *Res =
1824 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001825
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001826 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001827 return false;
1828 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001829 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001830 case AsmToken::LParen:
1831 case AsmToken::Minus:
1832 case AsmToken::Plus:
1833 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001834 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001835 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001836 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001837 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001838 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001839 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001840 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001841 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001842 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001844 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001845 return true;
1846
Jack Carter873c7242013-01-12 01:03:14 +00001847 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1848
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001849 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001850 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001851 } // case AsmToken::Percent
1852 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001853 return true;
1854}
1855
Vladimir Medic4c299852013-11-06 11:27:05 +00001856const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001857 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001858 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001859 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001860 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001861 // It's a constant, evaluate reloc value.
1862 int16_t Val;
1863 switch (getVariantKind(RelocStr)) {
1864 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1865 // Get the 1st 16-bits.
1866 Val = MCE->getValue() & 0xffff;
1867 break;
1868 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1869 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1870 // 16 bits being negative.
1871 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1872 break;
1873 case MCSymbolRefExpr::VK_Mips_HIGHER:
1874 // Get the 3rd 16-bits.
1875 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1876 break;
1877 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1878 // Get the 4th 16-bits.
1879 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1880 break;
1881 default:
1882 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001883 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001884 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001885 }
1886
Jack Carterb5cf5902013-04-17 00:18:04 +00001887 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001888 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001889 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001890 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001891 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001892 return Res;
1893 }
1894
1895 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001896 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1897
Sasa Stankovic06c47802014-04-03 10:37:45 +00001898 // Try to create target expression.
1899 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1900 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001901
Jack Carterd0bd6422013-04-18 00:41:53 +00001902 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1903 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001904 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1905 return Res;
1906 }
1907
1908 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001909 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1910 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1911 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001912 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001913 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001914 return Expr;
1915}
1916
1917bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1918
1919 switch (Expr->getKind()) {
1920 case MCExpr::Constant:
1921 return true;
1922 case MCExpr::SymbolRef:
1923 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1924 case MCExpr::Binary:
1925 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1926 if (!isEvaluated(BE->getLHS()))
1927 return false;
1928 return isEvaluated(BE->getRHS());
1929 }
1930 case MCExpr::Unary:
1931 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001932 case MCExpr::Target:
1933 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001934 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001935 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001936}
Jack Carterd0bd6422013-04-18 00:41:53 +00001937
Jack Carterb5cf5902013-04-17 00:18:04 +00001938bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001939 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001940 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001941 if (Tok.isNot(AsmToken::Identifier))
1942 return true;
1943
1944 std::string Str = Tok.getIdentifier().str();
1945
Jack Carterd0bd6422013-04-18 00:41:53 +00001946 Parser.Lex(); // Eat the identifier.
1947 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001948 const MCExpr *IdVal;
1949 SMLoc EndLoc;
1950
1951 if (getLexer().getKind() == AsmToken::LParen) {
1952 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001953 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001954 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001955 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001956 const AsmToken &nextTok = Parser.getTok();
1957 if (nextTok.isNot(AsmToken::Identifier))
1958 return true;
1959 Str += "(%";
1960 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001961 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001962 if (getLexer().getKind() != AsmToken::LParen)
1963 return true;
1964 } else
1965 break;
1966 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001968 return true;
1969
1970 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001971 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001972
1973 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001974 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001975
Jack Carterd0bd6422013-04-18 00:41:53 +00001976 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001977 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001978}
1979
Jack Carterb4dbc172012-09-05 23:34:03 +00001980bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1981 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001982 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00001983 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001984 if (ResTy == MatchOperand_Success) {
1985 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001986 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001987 StartLoc = Operand.getStartLoc();
1988 EndLoc = Operand.getEndLoc();
1989
1990 // AFAIK, we only support numeric registers and named GPR's in CFI
1991 // directives.
1992 // Don't worry about eating tokens before failing. Using an unrecognised
1993 // register is a parse error.
1994 if (Operand.isGPRAsmReg()) {
1995 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001996 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001997 }
1998
1999 return (RegNo == (unsigned)-1);
2000 }
2001
2002 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002003 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002004}
2005
Jack Carterb5cf5902013-04-17 00:18:04 +00002006bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00002007 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002008 bool Result = true;
2009
2010 while (getLexer().getKind() == AsmToken::LParen)
2011 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002012
Jack Carterd0bd6422013-04-18 00:41:53 +00002013 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002014 default:
2015 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002016 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002017 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002018 case AsmToken::Integer:
2019 case AsmToken::Minus:
2020 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002021 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002022 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002023 else
2024 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002025 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002026 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002027 break;
Jack Carter873c7242013-01-12 01:03:14 +00002028 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002029 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002030 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002031 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002032}
2033
David Blaikie960ea3f2014-06-08 16:18:35 +00002034MipsAsmParser::OperandMatchResultTy
2035MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002036 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002037 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002038 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002039 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002040 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002041 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002042 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002043
Jack Carterb5cf5902013-04-17 00:18:04 +00002044 if (getLexer().getKind() == AsmToken::LParen) {
2045 Parser.Lex();
2046 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002047 }
2048
Jack Carterb5cf5902013-04-17 00:18:04 +00002049 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002050 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002051 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002052
Jack Carterd0bd6422013-04-18 00:41:53 +00002053 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002054 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002055 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2056 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002057 SMLoc E =
2058 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002059 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002060 return MatchOperand_Success;
2061 }
2062 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002063 SMLoc E =
2064 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002065
Jack Carterd0bd6422013-04-18 00:41:53 +00002066 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002067 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002068 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002069 S, E, *this);
2070 Operands.push_back(
2071 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002072 return MatchOperand_Success;
2073 }
2074 Error(Parser.getTok().getLoc(), "'(' expected");
2075 return MatchOperand_ParseFail;
2076 }
2077
Jack Carterd0bd6422013-04-18 00:41:53 +00002078 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002079 }
2080
Toma Tabacu13964452014-09-04 13:23:44 +00002081 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002082 if (Res != MatchOperand_Success)
2083 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002084
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002085 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002086 Error(Parser.getTok().getLoc(), "')' expected");
2087 return MatchOperand_ParseFail;
2088 }
2089
Jack Carter873c7242013-01-12 01:03:14 +00002090 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2091
Jack Carterd0bd6422013-04-18 00:41:53 +00002092 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002093
Craig Topper062a2ba2014-04-25 05:30:21 +00002094 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002095 IdVal = MCConstantExpr::Create(0, getContext());
2096
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002098 std::unique_ptr<MipsOperand> op(
2099 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002100 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002101 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002102 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002104 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2105 int64_t Imm;
2106 if (IdVal->EvaluateAsAbsolute(Imm))
2107 IdVal = MCConstantExpr::Create(Imm, getContext());
2108 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2109 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2110 getContext());
2111 }
2112
David Blaikie960ea3f2014-06-08 16:18:35 +00002113 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002114 return MatchOperand_Success;
2115}
2116
David Blaikie960ea3f2014-06-08 16:18:35 +00002117bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002118
Jack Carterd76b2372013-03-21 21:44:16 +00002119 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2120 if (Sym) {
2121 SMLoc S = Parser.getTok().getLoc();
2122 const MCExpr *Expr;
2123 if (Sym->isVariable())
2124 Expr = Sym->getVariableValue();
2125 else
2126 return false;
2127 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002128 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002129 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002130 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002131 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002132 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002133 if (ResTy == MatchOperand_Success) {
2134 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002135 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002136 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002137 llvm_unreachable("Should never ParseFail");
2138 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002139 }
2140 } else if (Expr->getKind() == MCExpr::Constant) {
2141 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002142 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002143 Operands.push_back(
2144 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002145 return true;
2146 }
2147 }
2148 return false;
2149}
Jack Carterd0bd6422013-04-18 00:41:53 +00002150
Jack Carter873c7242013-01-12 01:03:14 +00002151MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002152MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002153 StringRef Identifier,
2154 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002155 int Index = matchCPURegisterName(Identifier);
2156 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002157 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002158 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2159 return MatchOperand_Success;
2160 }
2161
2162 Index = matchFPURegisterName(Identifier);
2163 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002164 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002165 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2166 return MatchOperand_Success;
2167 }
2168
2169 Index = matchFCCRegisterName(Identifier);
2170 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002171 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002172 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2173 return MatchOperand_Success;
2174 }
2175
2176 Index = matchACRegisterName(Identifier);
2177 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002178 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002179 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2180 return MatchOperand_Success;
2181 }
2182
2183 Index = matchMSA128RegisterName(Identifier);
2184 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002185 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002186 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2187 return MatchOperand_Success;
2188 }
2189
2190 Index = matchMSA128CtrlRegisterName(Identifier);
2191 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002192 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002193 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2194 return MatchOperand_Success;
2195 }
2196
2197 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002198}
2199
2200MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002201MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002202 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002203
2204 if (Token.is(AsmToken::Identifier)) {
2205 DEBUG(dbgs() << ".. identifier\n");
2206 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002207 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002208 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002209 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002210 } else if (Token.is(AsmToken::Integer)) {
2211 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002212 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002213 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2214 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002215 return MatchOperand_Success;
2216 }
2217
2218 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2219
2220 return MatchOperand_NoMatch;
2221}
2222
David Blaikie960ea3f2014-06-08 16:18:35 +00002223MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002224MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2225 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002226
2227 auto Token = Parser.getTok();
2228
2229 SMLoc S = Token.getLoc();
2230
2231 if (Token.isNot(AsmToken::Dollar)) {
2232 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2233 if (Token.is(AsmToken::Identifier)) {
2234 if (searchSymbolAlias(Operands))
2235 return MatchOperand_Success;
2236 }
2237 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2238 return MatchOperand_NoMatch;
2239 }
2240 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002241
Toma Tabacu13964452014-09-04 13:23:44 +00002242 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002243 if (ResTy == MatchOperand_Success) {
2244 Parser.Lex(); // $
2245 Parser.Lex(); // identifier
2246 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002247 return ResTy;
2248}
2249
2250MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002251MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002252 switch (getLexer().getKind()) {
2253 default:
2254 return MatchOperand_NoMatch;
2255 case AsmToken::LParen:
2256 case AsmToken::Minus:
2257 case AsmToken::Plus:
2258 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002259 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002260 case AsmToken::String:
2261 break;
2262 }
2263
2264 const MCExpr *IdVal;
2265 SMLoc S = Parser.getTok().getLoc();
2266 if (getParser().parseExpression(IdVal))
2267 return MatchOperand_ParseFail;
2268
2269 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2270 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2271 return MatchOperand_Success;
2272}
2273
David Blaikie960ea3f2014-06-08 16:18:35 +00002274MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002275MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2276 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002277
2278 SMLoc S = getLexer().getLoc();
2279
2280 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002281 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002282 if (ResTy != MatchOperand_NoMatch)
2283 return ResTy;
2284
Daniel Sanders315386c2014-04-01 10:40:14 +00002285 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002286 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002287 if (ResTy != MatchOperand_NoMatch)
2288 return ResTy;
2289
Daniel Sandersffd84362014-04-01 10:41:48 +00002290 const MCExpr *Expr = nullptr;
2291 if (Parser.parseExpression(Expr)) {
2292 // We have no way of knowing if a symbol was consumed so we must ParseFail
2293 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002294 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002295 Operands.push_back(
2296 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002297 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002298}
2299
Vladimir Medic2b953d02013-10-01 09:48:56 +00002300MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002301MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002302 const MCExpr *IdVal;
2303 // If the first token is '$' we may have register operand.
2304 if (Parser.getTok().is(AsmToken::Dollar))
2305 return MatchOperand_NoMatch;
2306 SMLoc S = Parser.getTok().getLoc();
2307 if (getParser().parseExpression(IdVal))
2308 return MatchOperand_ParseFail;
2309 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002310 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002311 int64_t Val = MCE->getValue();
2312 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2313 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002314 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002315 return MatchOperand_Success;
2316}
2317
Matheus Almeida779c5932013-11-18 12:32:49 +00002318MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002319MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002320 switch (getLexer().getKind()) {
2321 default:
2322 return MatchOperand_NoMatch;
2323 case AsmToken::LParen:
2324 case AsmToken::Plus:
2325 case AsmToken::Minus:
2326 case AsmToken::Integer:
2327 break;
2328 }
2329
2330 const MCExpr *Expr;
2331 SMLoc S = Parser.getTok().getLoc();
2332
2333 if (getParser().parseExpression(Expr))
2334 return MatchOperand_ParseFail;
2335
2336 int64_t Val;
2337 if (!Expr->EvaluateAsAbsolute(Val)) {
2338 Error(S, "expected immediate value");
2339 return MatchOperand_ParseFail;
2340 }
2341
2342 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2343 // and because the CPU always adds one to the immediate field, the allowed
2344 // range becomes 1..4. We'll only check the range here and will deal
2345 // with the addition/subtraction when actually decoding/encoding
2346 // the instruction.
2347 if (Val < 1 || Val > 4) {
2348 Error(S, "immediate not in range (1..4)");
2349 return MatchOperand_ParseFail;
2350 }
2351
Jack Carter3b2c96e2014-01-22 23:31:38 +00002352 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002353 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002354 return MatchOperand_Success;
2355}
2356
Jack Carterdc1e35d2012-09-06 20:00:02 +00002357MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2358
Vladimir Medic4c299852013-11-06 11:27:05 +00002359 MCSymbolRefExpr::VariantKind VK =
2360 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2361 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2362 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2363 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2364 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2365 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2366 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2367 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2368 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2369 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2370 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2371 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2372 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2373 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2374 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2375 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2376 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2377 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002378 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2379 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2380 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2381 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2382 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2383 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002384 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2385 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002386 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002387
Matheus Almeida2852af82014-04-22 10:15:54 +00002388 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002389
Jack Carterdc1e35d2012-09-06 20:00:02 +00002390 return VK;
2391}
Jack Cartera63b16a2012-09-07 00:23:42 +00002392
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002393/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2394/// either this.
2395/// ::= '(', register, ')'
2396/// handle it before we iterate so we don't get tripped up by the lack of
2397/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002398bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002399 if (getLexer().is(AsmToken::LParen)) {
2400 Operands.push_back(
2401 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2402 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002403 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002404 SMLoc Loc = getLexer().getLoc();
2405 Parser.eatToEndOfStatement();
2406 return Error(Loc, "unexpected token in argument list");
2407 }
2408 if (Parser.getTok().isNot(AsmToken::RParen)) {
2409 SMLoc Loc = getLexer().getLoc();
2410 Parser.eatToEndOfStatement();
2411 return Error(Loc, "unexpected token, expected ')'");
2412 }
2413 Operands.push_back(
2414 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2415 Parser.Lex();
2416 }
2417 return false;
2418}
2419
2420/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2421/// either one of these.
2422/// ::= '[', register, ']'
2423/// ::= '[', integer, ']'
2424/// handle it before we iterate so we don't get tripped up by the lack of
2425/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002426bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002427 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002428 if (getLexer().is(AsmToken::LBrac)) {
2429 Operands.push_back(
2430 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2431 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002432 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002433 SMLoc Loc = getLexer().getLoc();
2434 Parser.eatToEndOfStatement();
2435 return Error(Loc, "unexpected token in argument list");
2436 }
2437 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2438 SMLoc Loc = getLexer().getLoc();
2439 Parser.eatToEndOfStatement();
2440 return Error(Loc, "unexpected token, expected ']'");
2441 }
2442 Operands.push_back(
2443 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2444 Parser.Lex();
2445 }
2446 return false;
2447}
2448
David Blaikie960ea3f2014-06-08 16:18:35 +00002449bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2450 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002451 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002452
2453 // We have reached first instruction, module directive are now forbidden.
2454 getTargetStreamer().forbidModuleDirective();
2455
Vladimir Medic74593e62013-07-17 15:00:42 +00002456 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002457 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002458 Parser.eatToEndOfStatement();
2459 return Error(NameLoc, "Unknown instruction");
2460 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002461 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002463
2464 // Read the remaining operands.
2465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2466 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002467 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002468 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002469 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002470 return Error(Loc, "unexpected token in argument list");
2471 }
Toma Tabacu13964452014-09-04 13:23:44 +00002472 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 return true;
2474 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002475
Jack Carterd0bd6422013-04-18 00:41:53 +00002476 while (getLexer().is(AsmToken::Comma)) {
2477 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002478 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002479 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002480 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002481 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002482 return Error(Loc, "unexpected token in argument list");
2483 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002484 // Parse bracket and parenthesis suffixes before we iterate
2485 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002486 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002487 return true;
2488 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002489 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002490 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002491 }
2492 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002493 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2494 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002495 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002496 return Error(Loc, "unexpected token in argument list");
2497 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002498 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002499 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002500}
2501
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002502bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002503 SMLoc Loc = getLexer().getLoc();
2504 Parser.eatToEndOfStatement();
2505 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002506}
2507
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002508bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002509 return Error(Loc, ErrorMsg);
2510}
2511
Jack Carter0b744b32012-10-04 02:29:46 +00002512bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002513 // Line should look like: ".set noat".
2514 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002515 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002516 // eat noat
2517 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2520 reportParseError("unexpected token in statement");
2521 return false;
2522 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002523 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002524 return false;
2525}
Jack Carterd0bd6422013-04-18 00:41:53 +00002526
Jack Carter0b744b32012-10-04 02:29:46 +00002527bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002529 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002530 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002531 getParser().Lex();
2532 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002533 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002534 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002535 return false;
2536 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002537 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002538 if (getLexer().isNot(AsmToken::Dollar)) {
2539 reportParseError("unexpected token in statement");
2540 return false;
2541 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002543 const AsmToken &Reg = Parser.getTok();
2544 if (Reg.is(AsmToken::Identifier)) {
2545 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2546 } else if (Reg.is(AsmToken::Integer)) {
2547 AtRegNo = Reg.getIntVal();
2548 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002549 reportParseError("unexpected token in statement");
2550 return false;
2551 }
Jack Carter1ac53222013-02-20 23:11:17 +00002552
Daniel Sanders71a89d922014-03-25 13:01:06 +00002553 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002554 reportParseError("unexpected token in statement");
2555 return false;
2556 }
2557
Toma Tabacu9db22db2014-09-09 10:15:38 +00002558 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002559 reportParseError("unexpected token in statement");
2560 return false;
2561 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002562 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002563
2564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2565 reportParseError("unexpected token in statement");
2566 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 }
2568 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002569 return false;
2570 } else {
2571 reportParseError("unexpected token in statement");
2572 return false;
2573 }
2574}
2575
2576bool MipsAsmParser::parseSetReorderDirective() {
2577 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002579 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2580 reportParseError("unexpected token in statement");
2581 return false;
2582 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002583 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002584 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002585 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002586 return false;
2587}
2588
2589bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 Parser.Lex();
2591 // If this is not the end of the statement, report an error.
2592 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2593 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002594 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002595 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002596 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002597 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002598 Parser.Lex(); // Consume the EndOfStatement.
2599 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002600}
2601
2602bool MipsAsmParser::parseSetMacroDirective() {
2603 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002604 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002605 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2606 reportParseError("unexpected token in statement");
2607 return false;
2608 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002609 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002610 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002611 return false;
2612}
2613
2614bool MipsAsmParser::parseSetNoMacroDirective() {
2615 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002617 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2618 reportParseError("`noreorder' must be set before `nomacro'");
2619 return false;
2620 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002621 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002622 reportParseError("`noreorder' must be set before `nomacro'");
2623 return false;
2624 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002625 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002626 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002627 return false;
2628}
Jack Carterd76b2372013-03-21 21:44:16 +00002629
Daniel Sanders44934432014-08-07 12:03:36 +00002630bool MipsAsmParser::parseSetMsaDirective() {
2631 Parser.Lex();
2632
2633 // If this is not the end of the statement, report an error.
2634 if (getLexer().isNot(AsmToken::EndOfStatement))
2635 return reportParseError("unexpected token in statement");
2636
2637 setFeatureBits(Mips::FeatureMSA, "msa");
2638 getTargetStreamer().emitDirectiveSetMsa();
2639 return false;
2640}
2641
2642bool MipsAsmParser::parseSetNoMsaDirective() {
2643 Parser.Lex();
2644
2645 // If this is not the end of the statement, report an error.
2646 if (getLexer().isNot(AsmToken::EndOfStatement))
2647 return reportParseError("unexpected token in statement");
2648
2649 clearFeatureBits(Mips::FeatureMSA, "msa");
2650 getTargetStreamer().emitDirectiveSetNoMsa();
2651 return false;
2652}
2653
Jack Carter39536722014-01-22 23:08:42 +00002654bool MipsAsmParser::parseSetNoMips16Directive() {
2655 Parser.Lex();
2656 // If this is not the end of the statement, report an error.
2657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2658 reportParseError("unexpected token in statement");
2659 return false;
2660 }
2661 // For now do nothing.
2662 Parser.Lex(); // Consume the EndOfStatement.
2663 return false;
2664}
2665
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002666bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002667 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002668 // Line can be: .set fp=32
2669 // .set fp=xx
2670 // .set fp=64
2671 Parser.Lex(); // Eat fp token
2672 AsmToken Tok = Parser.getTok();
2673 if (Tok.isNot(AsmToken::Equal)) {
2674 reportParseError("unexpected token in statement");
2675 return false;
2676 }
2677 Parser.Lex(); // Eat '=' token.
2678 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002679
2680 if (!parseFpABIValue(FpAbiVal, ".set"))
2681 return false;
2682
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002683 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2684 reportParseError("unexpected token in statement");
2685 return false;
2686 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002687 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002688 Parser.Lex(); // Consume the EndOfStatement.
2689 return false;
2690}
2691
Toma Tabacu9db22db2014-09-09 10:15:38 +00002692bool MipsAsmParser::parseSetPopDirective() {
2693 SMLoc Loc = getLexer().getLoc();
2694
2695 Parser.Lex();
2696 if (getLexer().isNot(AsmToken::EndOfStatement))
2697 return reportParseError("unexpected token, expected end of statement");
2698
2699 // Always keep an element on the options "stack" to prevent the user
2700 // from changing the initial options. This is how we remember them.
2701 if (AssemblerOptions.size() == 2)
2702 return reportParseError(Loc, ".set pop with no .set push");
2703
2704 AssemblerOptions.pop_back();
2705 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2706
2707 getTargetStreamer().emitDirectiveSetPop();
2708 return false;
2709}
2710
2711bool MipsAsmParser::parseSetPushDirective() {
2712 Parser.Lex();
2713 if (getLexer().isNot(AsmToken::EndOfStatement))
2714 return reportParseError("unexpected token, expected end of statement");
2715
2716 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002717 AssemblerOptions.push_back(
2718 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002719
2720 getTargetStreamer().emitDirectiveSetPush();
2721 return false;
2722}
2723
Jack Carterd76b2372013-03-21 21:44:16 +00002724bool MipsAsmParser::parseSetAssignment() {
2725 StringRef Name;
2726 const MCExpr *Value;
2727
2728 if (Parser.parseIdentifier(Name))
2729 reportParseError("expected identifier after .set");
2730
2731 if (getLexer().isNot(AsmToken::Comma))
2732 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002733 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002734
Jack Carter3b2c96e2014-01-22 23:31:38 +00002735 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002736 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002737
Jack Carterd0bd6422013-04-18 00:41:53 +00002738 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002739 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002740 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002741 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002742 Sym = getContext().GetOrCreateSymbol(Name);
2743 Sym->setVariableValue(Value);
2744
2745 return false;
2746}
Jack Carterd0bd6422013-04-18 00:41:53 +00002747
Toma Tabacu26647792014-09-09 12:52:14 +00002748bool MipsAsmParser::parseSetMips0Directive() {
2749 Parser.Lex();
2750 if (getLexer().isNot(AsmToken::EndOfStatement))
2751 return reportParseError("unexpected token, expected end of statement");
2752
2753 // Reset assembler options to their initial values.
2754 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2755 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2756
2757 getTargetStreamer().emitDirectiveSetMips0();
2758 return false;
2759}
2760
Toma Tabacu85618b32014-08-19 14:22:52 +00002761bool MipsAsmParser::parseSetArchDirective() {
2762 Parser.Lex();
2763 if (getLexer().isNot(AsmToken::Equal))
2764 return reportParseError("unexpected token, expected equals sign");
2765
2766 Parser.Lex();
2767 StringRef Arch;
2768 if (Parser.parseIdentifier(Arch))
2769 return reportParseError("expected arch identifier");
2770
2771 StringRef ArchFeatureName =
2772 StringSwitch<StringRef>(Arch)
2773 .Case("mips1", "mips1")
2774 .Case("mips2", "mips2")
2775 .Case("mips3", "mips3")
2776 .Case("mips4", "mips4")
2777 .Case("mips5", "mips5")
2778 .Case("mips32", "mips32")
2779 .Case("mips32r2", "mips32r2")
2780 .Case("mips32r6", "mips32r6")
2781 .Case("mips64", "mips64")
2782 .Case("mips64r2", "mips64r2")
2783 .Case("mips64r6", "mips64r6")
2784 .Case("cnmips", "cnmips")
2785 .Case("r4000", "mips3") // This is an implementation of Mips3.
2786 .Default("");
2787
2788 if (ArchFeatureName.empty())
2789 return reportParseError("unsupported architecture");
2790
2791 selectArch(ArchFeatureName);
2792 getTargetStreamer().emitDirectiveSetArch(Arch);
2793 return false;
2794}
2795
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002796bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2797 Parser.Lex();
2798 if (getLexer().isNot(AsmToken::EndOfStatement))
2799 return reportParseError("unexpected token in .set directive");
2800
Matheus Almeida2852af82014-04-22 10:15:54 +00002801 switch (Feature) {
2802 default:
2803 llvm_unreachable("Unimplemented feature");
2804 case Mips::FeatureDSP:
2805 setFeatureBits(Mips::FeatureDSP, "dsp");
2806 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002807 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002808 case Mips::FeatureMicroMips:
2809 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002810 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002811 case Mips::FeatureMips16:
2812 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002813 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002814 case Mips::FeatureMips1:
2815 selectArch("mips1");
2816 getTargetStreamer().emitDirectiveSetMips1();
2817 break;
2818 case Mips::FeatureMips2:
2819 selectArch("mips2");
2820 getTargetStreamer().emitDirectiveSetMips2();
2821 break;
2822 case Mips::FeatureMips3:
2823 selectArch("mips3");
2824 getTargetStreamer().emitDirectiveSetMips3();
2825 break;
2826 case Mips::FeatureMips4:
2827 selectArch("mips4");
2828 getTargetStreamer().emitDirectiveSetMips4();
2829 break;
2830 case Mips::FeatureMips5:
2831 selectArch("mips5");
2832 getTargetStreamer().emitDirectiveSetMips5();
2833 break;
2834 case Mips::FeatureMips32:
2835 selectArch("mips32");
2836 getTargetStreamer().emitDirectiveSetMips32();
2837 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002838 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002839 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002840 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002841 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002842 case Mips::FeatureMips32r6:
2843 selectArch("mips32r6");
2844 getTargetStreamer().emitDirectiveSetMips32R6();
2845 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002846 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002847 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002848 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002849 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002850 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002851 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002852 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002853 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002854 case Mips::FeatureMips64r6:
2855 selectArch("mips64r6");
2856 getTargetStreamer().emitDirectiveSetMips64R6();
2857 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002858 }
2859 return false;
2860}
2861
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002862bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2863 if (getLexer().isNot(AsmToken::Comma)) {
2864 SMLoc Loc = getLexer().getLoc();
2865 Parser.eatToEndOfStatement();
2866 return Error(Loc, ErrorStr);
2867 }
2868
Matheus Almeida2852af82014-04-22 10:15:54 +00002869 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002870 return true;
2871}
2872
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002873bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002874 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002875 Warning(Loc, ".cpload in reorder section");
2876
2877 // FIXME: Warn if cpload is used in Mips16 mode.
2878
David Blaikie960ea3f2014-06-08 16:18:35 +00002879 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002880 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002881 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2882 reportParseError("expected register containing function address");
2883 return false;
2884 }
2885
David Blaikie960ea3f2014-06-08 16:18:35 +00002886 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2887 if (!RegOpnd.isGPRAsmReg()) {
2888 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002889 return false;
2890 }
2891
David Blaikie960ea3f2014-06-08 16:18:35 +00002892 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002893 return false;
2894}
2895
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002896bool MipsAsmParser::parseDirectiveCPSetup() {
2897 unsigned FuncReg;
2898 unsigned Save;
2899 bool SaveIsReg = true;
2900
Matheus Almeida7e815762014-06-18 13:08:59 +00002901 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002902 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002903 if (ResTy == MatchOperand_NoMatch) {
2904 reportParseError("expected register containing function address");
2905 Parser.eatToEndOfStatement();
2906 return false;
2907 }
2908
2909 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2910 if (!FuncRegOpnd.isGPRAsmReg()) {
2911 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2912 Parser.eatToEndOfStatement();
2913 return false;
2914 }
2915
2916 FuncReg = FuncRegOpnd.getGPR32Reg();
2917 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002918
2919 if (!eatComma("expected comma parsing directive"))
2920 return true;
2921
Toma Tabacu13964452014-09-04 13:23:44 +00002922 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002923 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002924 const AsmToken &Tok = Parser.getTok();
2925 if (Tok.is(AsmToken::Integer)) {
2926 Save = Tok.getIntVal();
2927 SaveIsReg = false;
2928 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002929 } else {
2930 reportParseError("expected save register or stack offset");
2931 Parser.eatToEndOfStatement();
2932 return false;
2933 }
2934 } else {
2935 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2936 if (!SaveOpnd.isGPRAsmReg()) {
2937 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2938 Parser.eatToEndOfStatement();
2939 return false;
2940 }
2941 Save = SaveOpnd.getGPR32Reg();
2942 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002943
2944 if (!eatComma("expected comma parsing directive"))
2945 return true;
2946
2947 StringRef Name;
2948 if (Parser.parseIdentifier(Name))
2949 reportParseError("expected identifier");
2950 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002951
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002952 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002953 return false;
2954}
2955
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002956bool MipsAsmParser::parseDirectiveNaN() {
2957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2958 const AsmToken &Tok = Parser.getTok();
2959
2960 if (Tok.getString() == "2008") {
2961 Parser.Lex();
2962 getTargetStreamer().emitDirectiveNaN2008();
2963 return false;
2964 } else if (Tok.getString() == "legacy") {
2965 Parser.Lex();
2966 getTargetStreamer().emitDirectiveNaNLegacy();
2967 return false;
2968 }
2969 }
2970 // If we don't recognize the option passed to the .nan
2971 // directive (e.g. no option or unknown option), emit an error.
2972 reportParseError("invalid option in .nan directive");
2973 return false;
2974}
2975
Jack Carter0b744b32012-10-04 02:29:46 +00002976bool MipsAsmParser::parseDirectiveSet() {
2977
Jack Carterd0bd6422013-04-18 00:41:53 +00002978 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002979 const AsmToken &Tok = Parser.getTok();
2980
2981 if (Tok.getString() == "noat") {
2982 return parseSetNoAtDirective();
2983 } else if (Tok.getString() == "at") {
2984 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00002985 } else if (Tok.getString() == "arch") {
2986 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002987 } else if (Tok.getString() == "fp") {
2988 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002989 } else if (Tok.getString() == "pop") {
2990 return parseSetPopDirective();
2991 } else if (Tok.getString() == "push") {
2992 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002993 } else if (Tok.getString() == "reorder") {
2994 return parseSetReorderDirective();
2995 } else if (Tok.getString() == "noreorder") {
2996 return parseSetNoReorderDirective();
2997 } else if (Tok.getString() == "macro") {
2998 return parseSetMacroDirective();
2999 } else if (Tok.getString() == "nomacro") {
3000 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003001 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003002 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00003003 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003004 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003005 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003006 getTargetStreamer().emitDirectiveSetNoMicroMips();
3007 Parser.eatToEndOfStatement();
3008 return false;
3009 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003010 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003011 } else if (Tok.getString() == "mips0") {
3012 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003013 } else if (Tok.getString() == "mips1") {
3014 return parseSetFeature(Mips::FeatureMips1);
3015 } else if (Tok.getString() == "mips2") {
3016 return parseSetFeature(Mips::FeatureMips2);
3017 } else if (Tok.getString() == "mips3") {
3018 return parseSetFeature(Mips::FeatureMips3);
3019 } else if (Tok.getString() == "mips4") {
3020 return parseSetFeature(Mips::FeatureMips4);
3021 } else if (Tok.getString() == "mips5") {
3022 return parseSetFeature(Mips::FeatureMips5);
3023 } else if (Tok.getString() == "mips32") {
3024 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003025 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003026 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003027 } else if (Tok.getString() == "mips32r6") {
3028 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003029 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003030 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003031 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003032 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003033 } else if (Tok.getString() == "mips64r6") {
3034 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003035 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003036 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00003037 } else if (Tok.getString() == "msa") {
3038 return parseSetMsaDirective();
3039 } else if (Tok.getString() == "nomsa") {
3040 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003041 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003042 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003043 parseSetAssignment();
3044 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003045 }
Jack Carter07c818d2013-01-25 01:31:34 +00003046
Jack Carter0b744b32012-10-04 02:29:46 +00003047 return true;
3048}
3049
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003050/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003051/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003052bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3054 for (;;) {
3055 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003056 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003057 return true;
3058
3059 getParser().getStreamer().EmitValue(Value, Size);
3060
3061 if (getLexer().is(AsmToken::EndOfStatement))
3062 break;
3063
3064 // FIXME: Improve diagnostic.
3065 if (getLexer().isNot(AsmToken::Comma))
3066 return Error(L, "unexpected token in directive");
3067 Parser.Lex();
3068 }
3069 }
3070
3071 Parser.Lex();
3072 return false;
3073}
3074
Vladimir Medic4c299852013-11-06 11:27:05 +00003075/// parseDirectiveGpWord
3076/// ::= .gpword local_sym
3077bool MipsAsmParser::parseDirectiveGpWord() {
3078 const MCExpr *Value;
3079 // EmitGPRel32Value requires an expression, so we are using base class
3080 // method to evaluate the expression.
3081 if (getParser().parseExpression(Value))
3082 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003083 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003084
Vladimir Medice10c1122013-11-13 13:18:04 +00003085 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00003086 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00003087 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003088 return false;
3089}
3090
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003091/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003092/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003093bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003094 const MCExpr *Value;
3095 // EmitGPRel64Value requires an expression, so we are using base class
3096 // method to evaluate the expression.
3097 if (getParser().parseExpression(Value))
3098 return true;
3099 getParser().getStreamer().EmitGPRel64Value(Value);
3100
3101 if (getLexer().isNot(AsmToken::EndOfStatement))
3102 return Error(getLexer().getLoc(), "unexpected token in directive");
3103 Parser.Lex(); // Eat EndOfStatement token.
3104 return false;
3105}
3106
Jack Carter0cd3c192014-01-06 23:27:31 +00003107bool MipsAsmParser::parseDirectiveOption() {
3108 // Get the option token.
3109 AsmToken Tok = Parser.getTok();
3110 // At the moment only identifiers are supported.
3111 if (Tok.isNot(AsmToken::Identifier)) {
3112 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
3113 Parser.eatToEndOfStatement();
3114 return false;
3115 }
3116
3117 StringRef Option = Tok.getIdentifier();
3118
3119 if (Option == "pic0") {
3120 getTargetStreamer().emitDirectiveOptionPic0();
3121 Parser.Lex();
3122 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3123 Error(Parser.getTok().getLoc(),
3124 "unexpected token in .option pic0 directive");
3125 Parser.eatToEndOfStatement();
3126 }
3127 return false;
3128 }
3129
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003130 if (Option == "pic2") {
3131 getTargetStreamer().emitDirectiveOptionPic2();
3132 Parser.Lex();
3133 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3134 Error(Parser.getTok().getLoc(),
3135 "unexpected token in .option pic2 directive");
3136 Parser.eatToEndOfStatement();
3137 }
3138 return false;
3139 }
3140
Jack Carter0cd3c192014-01-06 23:27:31 +00003141 // Unknown option.
3142 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
3143 Parser.eatToEndOfStatement();
3144 return false;
3145}
3146
Daniel Sanders7e527422014-07-10 13:38:23 +00003147/// parseDirectiveModule
3148/// ::= .module oddspreg
3149/// ::= .module nooddspreg
3150/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003151bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003152 MCAsmLexer &Lexer = getLexer();
3153 SMLoc L = Lexer.getLoc();
3154
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003155 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003156 // TODO : get a better message.
3157 reportParseError(".module directive must appear before any code");
3158 return false;
3159 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003160
3161 if (Lexer.is(AsmToken::Identifier)) {
3162 StringRef Option = Parser.getTok().getString();
3163 Parser.Lex();
3164
3165 if (Option == "oddspreg") {
3166 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3167 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3168
3169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3170 reportParseError("Expected end of statement");
3171 return false;
3172 }
3173
3174 return false;
3175 } else if (Option == "nooddspreg") {
3176 if (!isABI_O32()) {
3177 Error(L, "'.module nooddspreg' requires the O32 ABI");
3178 return false;
3179 }
3180
3181 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3182 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3183
3184 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3185 reportParseError("Expected end of statement");
3186 return false;
3187 }
3188
3189 return false;
3190 } else if (Option == "fp") {
3191 return parseDirectiveModuleFP();
3192 }
3193
3194 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003195 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003196
3197 return false;
3198}
3199
3200/// parseDirectiveModuleFP
3201/// ::= =32
3202/// ::= =xx
3203/// ::= =64
3204bool MipsAsmParser::parseDirectiveModuleFP() {
3205 MCAsmLexer &Lexer = getLexer();
3206
3207 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003208 reportParseError("unexpected token in statement");
3209 return false;
3210 }
3211 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003212
Daniel Sanders7e527422014-07-10 13:38:23 +00003213 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003214 if (!parseFpABIValue(FpABI, ".module"))
3215 return false;
3216
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003217 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3218 reportParseError("unexpected token in statement");
3219 return false;
3220 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003221
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003222 // Emit appropriate flags.
3223 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003224 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003225 return false;
3226}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003227
Daniel Sanders7e527422014-07-10 13:38:23 +00003228bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003229 StringRef Directive) {
3230 MCAsmLexer &Lexer = getLexer();
3231
3232 if (Lexer.is(AsmToken::Identifier)) {
3233 StringRef Value = Parser.getTok().getString();
3234 Parser.Lex();
3235
3236 if (Value != "xx") {
3237 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3238 return false;
3239 }
3240
3241 if (!isABI_O32()) {
3242 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3243 return false;
3244 }
3245
Daniel Sanders7e527422014-07-10 13:38:23 +00003246 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003247 return true;
3248 }
3249
3250 if (Lexer.is(AsmToken::Integer)) {
3251 unsigned Value = Parser.getTok().getIntVal();
3252 Parser.Lex();
3253
3254 if (Value != 32 && Value != 64) {
3255 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3256 return false;
3257 }
3258
3259 if (Value == 32) {
3260 if (!isABI_O32()) {
3261 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3262 return false;
3263 }
3264
Daniel Sanders7e527422014-07-10 13:38:23 +00003265 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3266 } else
3267 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003268
Daniel Sanders7e527422014-07-10 13:38:23 +00003269 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003270 }
3271
3272 return false;
3273}
3274
Jack Carter0b744b32012-10-04 02:29:46 +00003275bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003276 StringRef IDVal = DirectiveID.getString();
3277
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003278 if (IDVal == ".cpload")
3279 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003280 if (IDVal == ".dword") {
3281 parseDataDirective(8, DirectiveID.getLoc());
3282 return false;
3283 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003284 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003285 StringRef SymbolName;
3286
3287 if (Parser.parseIdentifier(SymbolName)) {
3288 reportParseError("expected identifier after .ent");
3289 return false;
3290 }
3291
3292 // There's an undocumented extension that allows an integer to
3293 // follow the name of the procedure which AFAICS is ignored by GAS.
3294 // Example: .ent foo,2
3295 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3296 if (getLexer().isNot(AsmToken::Comma)) {
3297 // Even though we accept this undocumented extension for compatibility
3298 // reasons, the additional integer argument does not actually change
3299 // the behaviour of the '.ent' directive, so we would like to discourage
3300 // its use. We do this by not referring to the extended version in
3301 // error messages which are not directly related to its use.
3302 reportParseError("unexpected token, expected end of statement");
3303 return false;
3304 }
3305 Parser.Lex(); // Eat the comma.
3306 const MCExpr *DummyNumber;
3307 int64_t DummyNumberVal;
3308 // If the user was explicitly trying to use the extended version,
3309 // we still give helpful extension-related error messages.
3310 if (Parser.parseExpression(DummyNumber)) {
3311 reportParseError("expected number after comma");
3312 return false;
3313 }
3314 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3315 reportParseError("expected an absolute expression after comma");
3316 return false;
3317 }
3318 }
3319
3320 // If this is not the end of the statement, report an error.
3321 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3322 reportParseError("unexpected token, expected end of statement");
3323 return false;
3324 }
3325
3326 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3327
3328 getTargetStreamer().emitDirectiveEnt(*Sym);
3329 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003330 return false;
3331 }
3332
Jack Carter07c818d2013-01-25 01:31:34 +00003333 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003334 StringRef SymbolName;
3335
3336 if (Parser.parseIdentifier(SymbolName)) {
3337 reportParseError("expected identifier after .end");
3338 return false;
3339 }
3340
3341 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3342 reportParseError("unexpected token, expected end of statement");
3343 return false;
3344 }
3345
3346 if (CurrentFn == nullptr) {
3347 reportParseError(".end used without .ent");
3348 return false;
3349 }
3350
3351 if ((SymbolName != CurrentFn->getName())) {
3352 reportParseError(".end symbol does not match .ent symbol");
3353 return false;
3354 }
3355
3356 getTargetStreamer().emitDirectiveEnd(SymbolName);
3357 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003358 return false;
3359 }
3360
Jack Carter07c818d2013-01-25 01:31:34 +00003361 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003362 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3363 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003364 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003365 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3366 reportParseError("expected stack register");
3367 return false;
3368 }
3369
3370 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3371 if (!StackRegOpnd.isGPRAsmReg()) {
3372 reportParseError(StackRegOpnd.getStartLoc(),
3373 "expected general purpose register");
3374 return false;
3375 }
3376 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3377
3378 if (Parser.getTok().is(AsmToken::Comma))
3379 Parser.Lex();
3380 else {
3381 reportParseError("unexpected token, expected comma");
3382 return false;
3383 }
3384
3385 // Parse the frame size.
3386 const MCExpr *FrameSize;
3387 int64_t FrameSizeVal;
3388
3389 if (Parser.parseExpression(FrameSize)) {
3390 reportParseError("expected frame size value");
3391 return false;
3392 }
3393
3394 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3395 reportParseError("frame size not an absolute expression");
3396 return false;
3397 }
3398
3399 if (Parser.getTok().is(AsmToken::Comma))
3400 Parser.Lex();
3401 else {
3402 reportParseError("unexpected token, expected comma");
3403 return false;
3404 }
3405
3406 // Parse the return register.
3407 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003408 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003409 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3410 reportParseError("expected return register");
3411 return false;
3412 }
3413
3414 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3415 if (!ReturnRegOpnd.isGPRAsmReg()) {
3416 reportParseError(ReturnRegOpnd.getStartLoc(),
3417 "expected general purpose register");
3418 return false;
3419 }
3420
3421 // If this is not the end of the statement, report an error.
3422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3423 reportParseError("unexpected token, expected end of statement");
3424 return false;
3425 }
3426
3427 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3428 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003429 return false;
3430 }
3431
Jack Carter07c818d2013-01-25 01:31:34 +00003432 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003433 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003434 }
3435
Daniel Sandersd97a6342014-08-13 10:07:34 +00003436 if (IDVal == ".mask" || IDVal == ".fmask") {
3437 // .mask bitmask, frame_offset
3438 // bitmask: One bit for each register used.
3439 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3440 // first register is expected to be saved.
3441 // Examples:
3442 // .mask 0x80000000, -4
3443 // .fmask 0x80000000, -4
3444 //
Jack Carterbe332172012-09-07 00:48:02 +00003445
Daniel Sandersd97a6342014-08-13 10:07:34 +00003446 // Parse the bitmask
3447 const MCExpr *BitMask;
3448 int64_t BitMaskVal;
3449
3450 if (Parser.parseExpression(BitMask)) {
3451 reportParseError("expected bitmask value");
3452 return false;
3453 }
3454
3455 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3456 reportParseError("bitmask not an absolute expression");
3457 return false;
3458 }
3459
3460 if (Parser.getTok().is(AsmToken::Comma))
3461 Parser.Lex();
3462 else {
3463 reportParseError("unexpected token, expected comma");
3464 return false;
3465 }
3466
3467 // Parse the frame_offset
3468 const MCExpr *FrameOffset;
3469 int64_t FrameOffsetVal;
3470
3471 if (Parser.parseExpression(FrameOffset)) {
3472 reportParseError("expected frame offset value");
3473 return false;
3474 }
3475
3476 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3477 reportParseError("frame offset not an absolute expression");
3478 return false;
3479 }
3480
3481 // If this is not the end of the statement, report an error.
3482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3483 reportParseError("unexpected token, expected end of statement");
3484 return false;
3485 }
3486
3487 if (IDVal == ".mask")
3488 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3489 else
3490 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003491 return false;
3492 }
3493
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003494 if (IDVal == ".nan")
3495 return parseDirectiveNaN();
3496
Jack Carter07c818d2013-01-25 01:31:34 +00003497 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003498 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003499 return false;
3500 }
3501
Rafael Espindolab59fb732014-03-28 18:50:26 +00003502 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003503 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003504 return false;
3505 }
3506
Jack Carter07c818d2013-01-25 01:31:34 +00003507 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003508 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003509 return false;
3510 }
3511
Jack Carter0cd3c192014-01-06 23:27:31 +00003512 if (IDVal == ".option")
3513 return parseDirectiveOption();
3514
3515 if (IDVal == ".abicalls") {
3516 getTargetStreamer().emitDirectiveAbiCalls();
3517 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3518 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3519 // Clear line
3520 Parser.eatToEndOfStatement();
3521 }
3522 return false;
3523 }
3524
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003525 if (IDVal == ".cpsetup")
3526 return parseDirectiveCPSetup();
3527
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003528 if (IDVal == ".module")
3529 return parseDirectiveModule();
3530
Rafael Espindola870c4e92012-01-11 03:56:41 +00003531 return true;
3532}
3533
Rafael Espindola870c4e92012-01-11 03:56:41 +00003534extern "C" void LLVMInitializeMipsAsmParser() {
3535 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3536 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3537 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3538 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3539}
Jack Carterb4dbc172012-09-05 23:34:03 +00003540
3541#define GET_REGISTER_MATCHER
3542#define GET_MATCHER_IMPLEMENTATION
3543#include "MipsGenAsmMatcher.inc"