blob: 14e98494b1e9822626c056a99197e3413ca9bea9 [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
984bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000985 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000986 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000987
Jack Carter9e65aa32013-03-22 00:05:30 +0000988 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000989
990 if (MCID.isBranch() || MCID.isCall()) {
991 const unsigned Opcode = Inst.getOpcode();
992 MCOperand Offset;
993
994 switch (Opcode) {
995 default:
996 break;
997 case Mips::BEQ:
998 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000999 case Mips::BEQ_MM:
1000 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001001 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001002 Offset = Inst.getOperand(2);
1003 if (!Offset.isImm())
1004 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001005 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001006 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001007 if (OffsetToAlignment(Offset.getImm(),
1008 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001009 return Error(IDLoc, "branch to misaligned address");
1010 break;
1011 case Mips::BGEZ:
1012 case Mips::BGTZ:
1013 case Mips::BLEZ:
1014 case Mips::BLTZ:
1015 case Mips::BGEZAL:
1016 case Mips::BLTZAL:
1017 case Mips::BC1F:
1018 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001019 case Mips::BGEZ_MM:
1020 case Mips::BGTZ_MM:
1021 case Mips::BLEZ_MM:
1022 case Mips::BLTZ_MM:
1023 case Mips::BGEZAL_MM:
1024 case Mips::BLTZAL_MM:
1025 case Mips::BC1F_MM:
1026 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001027 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001028 Offset = Inst.getOperand(1);
1029 if (!Offset.isImm())
1030 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001031 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001032 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001033 if (OffsetToAlignment(Offset.getImm(),
1034 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001035 return Error(IDLoc, "branch to misaligned address");
1036 break;
1037 }
1038 }
1039
Daniel Sandersa84989a2014-06-16 13:25:35 +00001040 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1041 // We still accept it but it is a normal nop.
1042 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1043 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1044 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1045 "nop instruction");
1046 }
1047
Toma Tabacu9db22db2014-09-09 10:15:38 +00001048 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001049 // If this instruction has a delay slot and .set reorder is active,
1050 // emit a NOP after it.
1051 Instructions.push_back(Inst);
1052 MCInst NopInst;
1053 NopInst.setOpcode(Mips::SLL);
1054 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1055 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1056 NopInst.addOperand(MCOperand::CreateImm(0));
1057 Instructions.push_back(NopInst);
1058 return false;
1059 }
1060
Jack Carter9e65aa32013-03-22 00:05:30 +00001061 if (MCID.mayLoad() || MCID.mayStore()) {
1062 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001063 // reference or immediate we may have to expand instructions.
1064 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001065 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001066 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1067 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001068 MCOperand &Op = Inst.getOperand(i);
1069 if (Op.isImm()) {
1070 int MemOffset = Op.getImm();
1071 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001072 // Offset can't exceed 16bit value.
1073 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001074 return false;
1075 }
1076 } else if (Op.isExpr()) {
1077 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001079 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001080 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001081 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001082 // Expand symbol.
1083 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001084 return false;
1085 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001086 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001087 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001088 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001089 }
1090 }
1091 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001092 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001093 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001094
1095 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001096 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001097 else
1098 Instructions.push_back(Inst);
1099
1100 return false;
1101}
1102
Jack Carter30a59822012-10-04 04:03:53 +00001103bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1104
Jack Carterd0bd6422013-04-18 00:41:53 +00001105 switch (Inst.getOpcode()) {
1106 case Mips::LoadImm32Reg:
1107 case Mips::LoadAddr32Imm:
1108 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001109 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 return true;
1111 default:
1112 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001113 }
1114}
Jack Carter92995f12012-10-06 00:53:28 +00001115
Matheus Almeida3813d572014-06-19 14:39:14 +00001116bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001117 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001119 default:
1120 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001121 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001122 case Mips::LoadImm32Reg:
1123 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001124 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001125 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001126 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1127 return true;
1128 }
1129 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 case Mips::LoadAddr32Imm:
1131 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1132 case Mips::LoadAddr32Reg:
1133 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1134 }
Jack Carter30a59822012-10-04 04:03:53 +00001135}
Jack Carter92995f12012-10-06 00:53:28 +00001136
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001137namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001138template <bool PerformShift>
1139void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001140 SmallVectorImpl<MCInst> &Instructions) {
1141 MCInst tmpInst;
1142 if (PerformShift) {
1143 tmpInst.setOpcode(Mips::DSLL);
1144 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1145 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1146 tmpInst.addOperand(MCOperand::CreateImm(16));
1147 tmpInst.setLoc(IDLoc);
1148 Instructions.push_back(tmpInst);
1149 tmpInst.clear();
1150 }
1151 tmpInst.setOpcode(Mips::ORi);
1152 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1153 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001154 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001155 tmpInst.setLoc(IDLoc);
1156 Instructions.push_back(tmpInst);
1157}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001158
1159template <int Shift, bool PerformShift>
1160void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1161 SmallVectorImpl<MCInst> &Instructions) {
1162 createShiftOr<PerformShift>(
1163 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1164 IDLoc, Instructions);
1165}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001166}
1167
Matheus Almeida3813d572014-06-19 14:39:14 +00001168bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001170 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001171 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001172 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001173 const MCOperand &RegOp = Inst.getOperand(0);
1174 assert(RegOp.isReg() && "expected register operand kind");
1175
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001176 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001177 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001178 // FIXME: gas has a special case for values that are 000...1111, which
1179 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001180 if (0 <= ImmValue && ImmValue <= 65535) {
1181 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001182 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001183 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001184 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001185 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001186 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001187 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001188 } else if (ImmValue < 0 && ImmValue >= -32768) {
1189 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001190 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001191 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001192 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001193 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001194 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001195 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001196 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1197 // For any value of j that is representable as a 32-bit integer, create
1198 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001199 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001200 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001201 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001202 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1203 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001204 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001205 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1206 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001207 if (!isGP64bit()) {
1208 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001209 return true;
1210 }
1211
1212 // <------- lo32 ------>
1213 // <------- hi32 ------>
1214 // <- hi16 -> <- lo16 ->
1215 // _________________________________
1216 // | | | |
1217 // | 16-bytes | 16-bytes | 16-bytes |
1218 // |__________|__________|__________|
1219 //
1220 // For any value of j that is representable as a 48-bit integer, create
1221 // a sequence of:
1222 // li d,j => lui d,hi16(j)
1223 // ori d,d,hi16(lo32(j))
1224 // dsll d,d,16
1225 // ori d,d,lo16(lo32(j))
1226 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001227 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001228 tmpInst.addOperand(
1229 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001230 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001231 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1232 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1233 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001234 if (!isGP64bit()) {
1235 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001236 return true;
1237 }
1238
1239 // <------- hi32 ------> <------- lo32 ------>
1240 // <- hi16 -> <- lo16 ->
1241 // ___________________________________________
1242 // | | | | |
1243 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1244 // |__________|__________|__________|__________|
1245 //
1246 // For any value of j that isn't representable as a 48-bit integer.
1247 // li d,j => lui d,hi16(j)
1248 // ori d,d,lo16(hi32(j))
1249 // dsll d,d,16
1250 // ori d,d,hi16(lo32(j))
1251 // dsll d,d,16
1252 // ori d,d,lo16(lo32(j))
1253 tmpInst.setOpcode(Mips::LUi);
1254 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1255 tmpInst.addOperand(
1256 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1257 Instructions.push_back(tmpInst);
1258 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1259 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1260 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001261 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001262 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001263}
Jack Carter92995f12012-10-06 00:53:28 +00001264
Matheus Almeida3813d572014-06-19 14:39:14 +00001265bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001266MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1267 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001268 MCInst tmpInst;
1269 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001270 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1271 "expected immediate operand kind");
1272 if (!ImmOp.isImm()) {
1273 expandLoadAddressSym(Inst, IDLoc, Instructions);
1274 return false;
1275 }
Jack Carter543fdf82012-10-09 23:29:45 +00001276 const MCOperand &SrcRegOp = Inst.getOperand(1);
1277 assert(SrcRegOp.isReg() && "expected register operand kind");
1278 const MCOperand &DstRegOp = Inst.getOperand(0);
1279 assert(DstRegOp.isReg() && "expected register operand kind");
1280 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001281 if (-32768 <= ImmValue && ImmValue <= 65535) {
1282 // For -32768 <= j <= 65535.
1283 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001284 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001285 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1286 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1287 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1288 Instructions.push_back(tmpInst);
1289 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001290 // For any other value of j that is representable as a 32-bit integer.
1291 // la d,j(s) => lui d,hi16(j)
1292 // ori d,d,lo16(j)
1293 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001294 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001295 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1296 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1297 Instructions.push_back(tmpInst);
1298 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001299 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001300 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1301 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1302 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1303 Instructions.push_back(tmpInst);
1304 tmpInst.clear();
1305 tmpInst.setOpcode(Mips::ADDu);
1306 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1307 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1308 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1309 Instructions.push_back(tmpInst);
1310 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001311 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001312}
1313
Matheus Almeida3813d572014-06-19 14:39:14 +00001314bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001315MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1316 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001317 MCInst tmpInst;
1318 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001319 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1320 "expected immediate operand kind");
1321 if (!ImmOp.isImm()) {
1322 expandLoadAddressSym(Inst, IDLoc, Instructions);
1323 return false;
1324 }
Jack Carter543fdf82012-10-09 23:29:45 +00001325 const MCOperand &RegOp = Inst.getOperand(0);
1326 assert(RegOp.isReg() && "expected register operand kind");
1327 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001328 if (-32768 <= ImmValue && ImmValue <= 65535) {
1329 // For -32768 <= j <= 65535.
1330 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001331 tmpInst.setOpcode(Mips::ADDiu);
1332 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001333 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001334 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1335 Instructions.push_back(tmpInst);
1336 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001337 // For any other value of j that is representable as a 32-bit integer.
1338 // la d,j => lui d,hi16(j)
1339 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001340 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001341 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1342 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1343 Instructions.push_back(tmpInst);
1344 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001345 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001346 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1347 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1348 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1349 Instructions.push_back(tmpInst);
1350 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001351 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001352}
1353
Toma Tabacu0d64b202014-08-14 10:29:17 +00001354void
1355MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1356 SmallVectorImpl<MCInst> &Instructions) {
1357 // FIXME: If we do have a valid at register to use, we should generate a
1358 // slightly shorter sequence here.
1359 MCInst tmpInst;
1360 int ExprOperandNo = 1;
1361 // Sometimes the assembly parser will get the immediate expression as
1362 // a $zero + an immediate.
1363 if (Inst.getNumOperands() == 3) {
1364 assert(Inst.getOperand(1).getReg() ==
1365 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1366 ExprOperandNo = 2;
1367 }
1368 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1369 assert(SymOp.isExpr() && "expected symbol operand kind");
1370 const MCOperand &RegOp = Inst.getOperand(0);
1371 unsigned RegNo = RegOp.getReg();
1372 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1373 const MCSymbolRefExpr *HiExpr =
1374 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1375 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1376 const MCSymbolRefExpr *LoExpr =
1377 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1378 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1379 if (isGP64bit()) {
1380 // If it's a 64-bit architecture, expand to:
1381 // la d,sym => lui d,highest(sym)
1382 // ori d,d,higher(sym)
1383 // dsll d,d,16
1384 // ori d,d,hi16(sym)
1385 // dsll d,d,16
1386 // ori d,d,lo16(sym)
1387 const MCSymbolRefExpr *HighestExpr =
1388 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1389 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1390 const MCSymbolRefExpr *HigherExpr =
1391 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1392 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1393
1394 tmpInst.setOpcode(Mips::LUi);
1395 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1396 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1397 Instructions.push_back(tmpInst);
1398
1399 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1400 Instructions);
1401 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1402 Instructions);
1403 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1404 Instructions);
1405 } else {
1406 // Otherwise, expand to:
1407 // la d,sym => lui d,hi16(sym)
1408 // ori d,d,lo16(sym)
1409 tmpInst.setOpcode(Mips::LUi);
1410 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1411 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1412 Instructions.push_back(tmpInst);
1413
1414 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1415 Instructions);
1416 }
1417}
1418
Jack Carter9e65aa32013-03-22 00:05:30 +00001419void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001420 SmallVectorImpl<MCInst> &Instructions,
1421 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001422 const MCSymbolRefExpr *SR;
1423 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001424 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001425 const MCExpr *ExprOffset;
1426 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001428 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1429 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001430 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001431 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1432 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001433 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001434 if (isImmOpnd) {
1435 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1436 ImmOffset = Inst.getOperand(2).getImm();
1437 LoOffset = ImmOffset & 0x0000ffff;
1438 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001439 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001440 if (LoOffset & 0x8000)
1441 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001442 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001443 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001444 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001445 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001446 // These are some of the types of expansions we perform here:
1447 // 1) lw $8, sym => lui $8, %hi(sym)
1448 // lw $8, %lo(sym)($8)
1449 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1450 // add $8, $8, $9
1451 // lw $8, %lo(offset)($9)
1452 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1453 // add $at, $at, $8
1454 // lw $8, %lo(offset)($at)
1455 // 4) sw $8, sym => lui $at, %hi(sym)
1456 // sw $8, %lo(sym)($at)
1457 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1458 // add $at, $at, $8
1459 // sw $8, %lo(offset)($at)
1460 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1461 // ldc1 $f0, %lo(sym)($at)
1462 //
1463 // For load instructions we can use the destination register as a temporary
1464 // if base and dst are different (examples 1 and 2) and if the base register
1465 // is general purpose otherwise we must use $at (example 6) and error if it's
1466 // not available. For stores we must use $at (examples 4 and 5) because we
1467 // must not clobber the source register setting up the offset.
1468 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1469 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1470 unsigned RegClassIDOp0 =
1471 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1472 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1473 (RegClassIDOp0 == Mips::GPR64RegClassID);
1474 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001475 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001476 else {
1477 int AT = getATReg(IDLoc);
1478 // At this point we need AT to perform the expansions and we exit if it is
1479 // not available.
1480 if (!AT)
1481 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001482 TmpRegNum = getReg(
1483 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001484 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001485
Jack Carter9e65aa32013-03-22 00:05:30 +00001486 TempInst.setOpcode(Mips::LUi);
1487 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1488 if (isImmOpnd)
1489 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1490 else {
1491 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001492 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1494 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1495 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001496 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001497 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001499 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001500 }
1501 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001502 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001503 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001504 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001505 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001506 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001507 TempInst.setOpcode(Mips::ADDu);
1508 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1509 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1510 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1511 Instructions.push_back(TempInst);
1512 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001513 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001514 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001515 TempInst.setOpcode(Inst.getOpcode());
1516 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1517 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1518 if (isImmOpnd)
1519 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1520 else {
1521 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001522 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1523 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1524 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001525 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001526 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001527 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001528 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001529 }
1530 }
1531 Instructions.push_back(TempInst);
1532 TempInst.clear();
1533}
1534
Matheus Almeida595fcab2014-06-11 15:05:56 +00001535unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1536 // As described by the Mips32r2 spec, the registers Rd and Rs for
1537 // jalr.hb must be different.
1538 unsigned Opcode = Inst.getOpcode();
1539
1540 if (Opcode == Mips::JALR_HB &&
1541 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1542 return Match_RequiresDifferentSrcAndDst;
1543
1544 return Match_Success;
1545}
1546
David Blaikie960ea3f2014-06-08 16:18:35 +00001547bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1548 OperandVector &Operands,
1549 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001550 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001551 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001552
Jack Carterb4dbc172012-09-05 23:34:03 +00001553 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001554 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001555 unsigned MatchResult =
1556 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001557
1558 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001559 default:
1560 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001561 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001562 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001563 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001564 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001565 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001566 return false;
1567 }
1568 case Match_MissingFeature:
1569 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1570 return true;
1571 case Match_InvalidOperand: {
1572 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001573 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001574 if (ErrorInfo >= Operands.size())
1575 return Error(IDLoc, "too few operands for instruction");
1576
David Blaikie960ea3f2014-06-08 16:18:35 +00001577 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001578 if (ErrorLoc == SMLoc())
1579 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001580 }
1581
1582 return Error(ErrorLoc, "invalid operand for instruction");
1583 }
1584 case Match_MnemonicFail:
1585 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001586 case Match_RequiresDifferentSrcAndDst:
1587 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001588 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001589 return true;
1590}
1591
Toma Tabacu13964452014-09-04 13:23:44 +00001592void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001593 if ((RegIndex != 0) &&
1594 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001595 if (RegIndex == 1)
1596 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001597 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001598 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1599 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001600 }
1601}
1602
Jack Carter1ac53222013-02-20 23:11:17 +00001603int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001604 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001605
Vladimir Medic4c299852013-11-06 11:27:05 +00001606 CC = StringSwitch<unsigned>(Name)
1607 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001608 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001609 .Case("a0", 4)
1610 .Case("a1", 5)
1611 .Case("a2", 6)
1612 .Case("a3", 7)
1613 .Case("v0", 2)
1614 .Case("v1", 3)
1615 .Case("s0", 16)
1616 .Case("s1", 17)
1617 .Case("s2", 18)
1618 .Case("s3", 19)
1619 .Case("s4", 20)
1620 .Case("s5", 21)
1621 .Case("s6", 22)
1622 .Case("s7", 23)
1623 .Case("k0", 26)
1624 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001625 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001626 .Case("sp", 29)
1627 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001628 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001629 .Case("ra", 31)
1630 .Case("t0", 8)
1631 .Case("t1", 9)
1632 .Case("t2", 10)
1633 .Case("t3", 11)
1634 .Case("t4", 12)
1635 .Case("t5", 13)
1636 .Case("t6", 14)
1637 .Case("t7", 15)
1638 .Case("t8", 24)
1639 .Case("t9", 25)
1640 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001641
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001642 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001643 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1644 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1645 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1646 if (8 <= CC && CC <= 11)
1647 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001648
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001649 if (CC == -1)
1650 CC = StringSwitch<unsigned>(Name)
1651 .Case("a4", 8)
1652 .Case("a5", 9)
1653 .Case("a6", 10)
1654 .Case("a7", 11)
1655 .Case("kt0", 26)
1656 .Case("kt1", 27)
1657 .Default(-1);
1658 }
Jack Carter1ac53222013-02-20 23:11:17 +00001659
1660 return CC;
1661}
Jack Carterd0bd6422013-04-18 00:41:53 +00001662
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001663int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001664
Jack Cartera63b16a2012-09-07 00:23:42 +00001665 if (Name[0] == 'f') {
1666 StringRef NumString = Name.substr(1);
1667 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001668 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001669 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001670 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001671 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001672 return IntVal;
1673 }
1674 return -1;
1675}
Jack Cartera63b16a2012-09-07 00:23:42 +00001676
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001677int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1678
1679 if (Name.startswith("fcc")) {
1680 StringRef NumString = Name.substr(3);
1681 unsigned IntVal;
1682 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001683 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001684 if (IntVal > 7) // There are only 8 fcc registers.
1685 return -1;
1686 return IntVal;
1687 }
1688 return -1;
1689}
1690
1691int MipsAsmParser::matchACRegisterName(StringRef Name) {
1692
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001693 if (Name.startswith("ac")) {
1694 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001695 unsigned IntVal;
1696 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001697 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001698 if (IntVal > 3) // There are only 3 acc registers.
1699 return -1;
1700 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001701 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001702 return -1;
1703}
Jack Carterd0bd6422013-04-18 00:41:53 +00001704
Jack Carter5dc8ac92013-09-25 23:50:44 +00001705int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1706 unsigned IntVal;
1707
1708 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1709 return -1;
1710
1711 if (IntVal > 31)
1712 return -1;
1713
1714 return IntVal;
1715}
1716
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001717int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1718 int CC;
1719
1720 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001721 .Case("msair", 0)
1722 .Case("msacsr", 1)
1723 .Case("msaaccess", 2)
1724 .Case("msasave", 3)
1725 .Case("msamodify", 4)
1726 .Case("msarequest", 5)
1727 .Case("msamap", 6)
1728 .Case("msaunmap", 7)
1729 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001730
1731 return CC;
1732}
1733
Jack Carter0b744b32012-10-04 02:29:46 +00001734bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1735 if (Reg > 31)
1736 return false;
1737
Toma Tabacu3c24b042014-09-05 15:43:21 +00001738 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001739 return true;
1740}
1741
Matheus Almeida7de68e72014-06-18 14:46:05 +00001742int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001743 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001744 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001745 reportParseError(Loc,
1746 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001747 return AT;
1748}
Jack Carter0b744b32012-10-04 02:29:46 +00001749
Jack Carterd0bd6422013-04-18 00:41:53 +00001750unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001751 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001752}
1753
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001754unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001755 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001756 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001757}
1758
Jack Carter873c7242013-01-12 01:03:14 +00001759int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001760 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001761 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001762 return -1;
1763
Jack Carter873c7242013-01-12 01:03:14 +00001764 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001765}
1766
Toma Tabacu13964452014-09-04 13:23:44 +00001767bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1768 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001769
Jack Carter30a59822012-10-04 04:03:53 +00001770 // Check if the current operand has a custom associated parser, if so, try to
1771 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001772 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1773 if (ResTy == MatchOperand_Success)
1774 return false;
1775 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1776 // there was a match, but an error occurred, in which case, just return that
1777 // the operand parsing failed.
1778 if (ResTy == MatchOperand_ParseFail)
1779 return true;
1780
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001781 DEBUG(dbgs() << ".. Generic Parser\n");
1782
Jack Carterb4dbc172012-09-05 23:34:03 +00001783 switch (getLexer().getKind()) {
1784 default:
1785 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1786 return true;
1787 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001788 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001789 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001790
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001791 // Almost all registers have been parsed by custom parsers. There is only
1792 // one exception to this. $zero (and it's alias $0) will reach this point
1793 // for div, divu, and similar instructions because it is not an operand
1794 // to the instruction definition but an explicit register. Special case
1795 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001796 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001797 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001798
Jack Carterd0bd6422013-04-18 00:41:53 +00001799 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001800 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001801 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001802 return true;
1803
Jack Carter873c7242013-01-12 01:03:14 +00001804 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001805 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001806 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001807 const MCExpr *Res =
1808 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001809
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001810 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001811 return false;
1812 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001813 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001814 case AsmToken::LParen:
1815 case AsmToken::Minus:
1816 case AsmToken::Plus:
1817 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001818 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001819 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001820 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001821 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001822 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001823 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001824 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001825 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001826 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001827 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001828 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001829 return true;
1830
Jack Carter873c7242013-01-12 01:03:14 +00001831 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1832
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001833 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001834 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001835 } // case AsmToken::Percent
1836 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001837 return true;
1838}
1839
Vladimir Medic4c299852013-11-06 11:27:05 +00001840const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001841 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001842 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001844 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001845 // It's a constant, evaluate reloc value.
1846 int16_t Val;
1847 switch (getVariantKind(RelocStr)) {
1848 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1849 // Get the 1st 16-bits.
1850 Val = MCE->getValue() & 0xffff;
1851 break;
1852 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1853 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1854 // 16 bits being negative.
1855 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1856 break;
1857 case MCSymbolRefExpr::VK_Mips_HIGHER:
1858 // Get the 3rd 16-bits.
1859 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1860 break;
1861 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1862 // Get the 4th 16-bits.
1863 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1864 break;
1865 default:
1866 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001867 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001868 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001869 }
1870
Jack Carterb5cf5902013-04-17 00:18:04 +00001871 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001872 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001873 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001874 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001876 return Res;
1877 }
1878
1879 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001880 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1881
Sasa Stankovic06c47802014-04-03 10:37:45 +00001882 // Try to create target expression.
1883 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1884 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001885
Jack Carterd0bd6422013-04-18 00:41:53 +00001886 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1887 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001888 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1889 return Res;
1890 }
1891
1892 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001893 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1894 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1895 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001896 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001897 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001898 return Expr;
1899}
1900
1901bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1902
1903 switch (Expr->getKind()) {
1904 case MCExpr::Constant:
1905 return true;
1906 case MCExpr::SymbolRef:
1907 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1908 case MCExpr::Binary:
1909 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1910 if (!isEvaluated(BE->getLHS()))
1911 return false;
1912 return isEvaluated(BE->getRHS());
1913 }
1914 case MCExpr::Unary:
1915 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001916 case MCExpr::Target:
1917 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001918 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001919 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001920}
Jack Carterd0bd6422013-04-18 00:41:53 +00001921
Jack Carterb5cf5902013-04-17 00:18:04 +00001922bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001923 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001924 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001925 if (Tok.isNot(AsmToken::Identifier))
1926 return true;
1927
1928 std::string Str = Tok.getIdentifier().str();
1929
Jack Carterd0bd6422013-04-18 00:41:53 +00001930 Parser.Lex(); // Eat the identifier.
1931 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001932 const MCExpr *IdVal;
1933 SMLoc EndLoc;
1934
1935 if (getLexer().getKind() == AsmToken::LParen) {
1936 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001937 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001938 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001939 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001940 const AsmToken &nextTok = Parser.getTok();
1941 if (nextTok.isNot(AsmToken::Identifier))
1942 return true;
1943 Str += "(%";
1944 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001945 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001946 if (getLexer().getKind() != AsmToken::LParen)
1947 return true;
1948 } else
1949 break;
1950 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001951 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001952 return true;
1953
1954 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001955 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001956
1957 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001958 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001959
Jack Carterd0bd6422013-04-18 00:41:53 +00001960 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001961 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001962}
1963
Jack Carterb4dbc172012-09-05 23:34:03 +00001964bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1965 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001966 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00001967 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001968 if (ResTy == MatchOperand_Success) {
1969 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001970 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001971 StartLoc = Operand.getStartLoc();
1972 EndLoc = Operand.getEndLoc();
1973
1974 // AFAIK, we only support numeric registers and named GPR's in CFI
1975 // directives.
1976 // Don't worry about eating tokens before failing. Using an unrecognised
1977 // register is a parse error.
1978 if (Operand.isGPRAsmReg()) {
1979 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001980 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001981 }
1982
1983 return (RegNo == (unsigned)-1);
1984 }
1985
1986 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001987 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001988}
1989
Jack Carterb5cf5902013-04-17 00:18:04 +00001990bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001991 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001992 bool Result = true;
1993
1994 while (getLexer().getKind() == AsmToken::LParen)
1995 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001996
Jack Carterd0bd6422013-04-18 00:41:53 +00001997 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001998 default:
1999 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002000 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002001 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002002 case AsmToken::Integer:
2003 case AsmToken::Minus:
2004 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002005 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002006 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002007 else
2008 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002010 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 break;
Jack Carter873c7242013-01-12 01:03:14 +00002012 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002013 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002014 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002015 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002016}
2017
David Blaikie960ea3f2014-06-08 16:18:35 +00002018MipsAsmParser::OperandMatchResultTy
2019MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002020 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002021 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002022 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002023 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002024 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002025 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002026 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002027
Jack Carterb5cf5902013-04-17 00:18:04 +00002028 if (getLexer().getKind() == AsmToken::LParen) {
2029 Parser.Lex();
2030 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002031 }
2032
Jack Carterb5cf5902013-04-17 00:18:04 +00002033 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002034 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002035 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002036
Jack Carterd0bd6422013-04-18 00:41:53 +00002037 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002038 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002039 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2040 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002041 SMLoc E =
2042 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002043 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002044 return MatchOperand_Success;
2045 }
2046 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002047 SMLoc E =
2048 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002049
Jack Carterd0bd6422013-04-18 00:41:53 +00002050 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002051 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002052 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002053 S, E, *this);
2054 Operands.push_back(
2055 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002056 return MatchOperand_Success;
2057 }
2058 Error(Parser.getTok().getLoc(), "'(' expected");
2059 return MatchOperand_ParseFail;
2060 }
2061
Jack Carterd0bd6422013-04-18 00:41:53 +00002062 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002063 }
2064
Toma Tabacu13964452014-09-04 13:23:44 +00002065 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002066 if (Res != MatchOperand_Success)
2067 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002068
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002069 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002070 Error(Parser.getTok().getLoc(), "')' expected");
2071 return MatchOperand_ParseFail;
2072 }
2073
Jack Carter873c7242013-01-12 01:03:14 +00002074 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2075
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002077
Craig Topper062a2ba2014-04-25 05:30:21 +00002078 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002079 IdVal = MCConstantExpr::Create(0, getContext());
2080
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002082 std::unique_ptr<MipsOperand> op(
2083 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002084 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002085 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002086 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002087 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002088 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2089 int64_t Imm;
2090 if (IdVal->EvaluateAsAbsolute(Imm))
2091 IdVal = MCConstantExpr::Create(Imm, getContext());
2092 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2093 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2094 getContext());
2095 }
2096
David Blaikie960ea3f2014-06-08 16:18:35 +00002097 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002098 return MatchOperand_Success;
2099}
2100
David Blaikie960ea3f2014-06-08 16:18:35 +00002101bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002102
Jack Carterd76b2372013-03-21 21:44:16 +00002103 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2104 if (Sym) {
2105 SMLoc S = Parser.getTok().getLoc();
2106 const MCExpr *Expr;
2107 if (Sym->isVariable())
2108 Expr = Sym->getVariableValue();
2109 else
2110 return false;
2111 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002112 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002113 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002114 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002115 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002116 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002117 if (ResTy == MatchOperand_Success) {
2118 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002119 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002120 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002121 llvm_unreachable("Should never ParseFail");
2122 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002123 }
2124 } else if (Expr->getKind() == MCExpr::Constant) {
2125 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002126 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002127 Operands.push_back(
2128 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002129 return true;
2130 }
2131 }
2132 return false;
2133}
Jack Carterd0bd6422013-04-18 00:41:53 +00002134
Jack Carter873c7242013-01-12 01:03:14 +00002135MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002136MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002137 StringRef Identifier,
2138 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002139 int Index = matchCPURegisterName(Identifier);
2140 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002141 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002142 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2143 return MatchOperand_Success;
2144 }
2145
2146 Index = matchFPURegisterName(Identifier);
2147 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002148 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002149 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2150 return MatchOperand_Success;
2151 }
2152
2153 Index = matchFCCRegisterName(Identifier);
2154 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002155 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002156 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2157 return MatchOperand_Success;
2158 }
2159
2160 Index = matchACRegisterName(Identifier);
2161 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002162 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002163 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2164 return MatchOperand_Success;
2165 }
2166
2167 Index = matchMSA128RegisterName(Identifier);
2168 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002169 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002170 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2171 return MatchOperand_Success;
2172 }
2173
2174 Index = matchMSA128CtrlRegisterName(Identifier);
2175 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002176 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002177 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2178 return MatchOperand_Success;
2179 }
2180
2181 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002182}
2183
2184MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002185MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002186 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002187
2188 if (Token.is(AsmToken::Identifier)) {
2189 DEBUG(dbgs() << ".. identifier\n");
2190 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002191 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002192 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002193 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002194 } else if (Token.is(AsmToken::Integer)) {
2195 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002196 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002197 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2198 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002199 return MatchOperand_Success;
2200 }
2201
2202 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2203
2204 return MatchOperand_NoMatch;
2205}
2206
David Blaikie960ea3f2014-06-08 16:18:35 +00002207MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002208MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2209 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002210
2211 auto Token = Parser.getTok();
2212
2213 SMLoc S = Token.getLoc();
2214
2215 if (Token.isNot(AsmToken::Dollar)) {
2216 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2217 if (Token.is(AsmToken::Identifier)) {
2218 if (searchSymbolAlias(Operands))
2219 return MatchOperand_Success;
2220 }
2221 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2222 return MatchOperand_NoMatch;
2223 }
2224 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002225
Toma Tabacu13964452014-09-04 13:23:44 +00002226 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002227 if (ResTy == MatchOperand_Success) {
2228 Parser.Lex(); // $
2229 Parser.Lex(); // identifier
2230 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002231 return ResTy;
2232}
2233
2234MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002235MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002236 switch (getLexer().getKind()) {
2237 default:
2238 return MatchOperand_NoMatch;
2239 case AsmToken::LParen:
2240 case AsmToken::Minus:
2241 case AsmToken::Plus:
2242 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002243 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002244 case AsmToken::String:
2245 break;
2246 }
2247
2248 const MCExpr *IdVal;
2249 SMLoc S = Parser.getTok().getLoc();
2250 if (getParser().parseExpression(IdVal))
2251 return MatchOperand_ParseFail;
2252
2253 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2254 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2255 return MatchOperand_Success;
2256}
2257
David Blaikie960ea3f2014-06-08 16:18:35 +00002258MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002259MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2260 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002261
2262 SMLoc S = getLexer().getLoc();
2263
2264 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002265 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002266 if (ResTy != MatchOperand_NoMatch)
2267 return ResTy;
2268
Daniel Sanders315386c2014-04-01 10:40:14 +00002269 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002270 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002271 if (ResTy != MatchOperand_NoMatch)
2272 return ResTy;
2273
Daniel Sandersffd84362014-04-01 10:41:48 +00002274 const MCExpr *Expr = nullptr;
2275 if (Parser.parseExpression(Expr)) {
2276 // We have no way of knowing if a symbol was consumed so we must ParseFail
2277 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002278 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002279 Operands.push_back(
2280 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002281 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002282}
2283
Vladimir Medic2b953d02013-10-01 09:48:56 +00002284MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002285MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002286 const MCExpr *IdVal;
2287 // If the first token is '$' we may have register operand.
2288 if (Parser.getTok().is(AsmToken::Dollar))
2289 return MatchOperand_NoMatch;
2290 SMLoc S = Parser.getTok().getLoc();
2291 if (getParser().parseExpression(IdVal))
2292 return MatchOperand_ParseFail;
2293 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002294 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002295 int64_t Val = MCE->getValue();
2296 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2297 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002298 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002299 return MatchOperand_Success;
2300}
2301
Matheus Almeida779c5932013-11-18 12:32:49 +00002302MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002303MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002304 switch (getLexer().getKind()) {
2305 default:
2306 return MatchOperand_NoMatch;
2307 case AsmToken::LParen:
2308 case AsmToken::Plus:
2309 case AsmToken::Minus:
2310 case AsmToken::Integer:
2311 break;
2312 }
2313
2314 const MCExpr *Expr;
2315 SMLoc S = Parser.getTok().getLoc();
2316
2317 if (getParser().parseExpression(Expr))
2318 return MatchOperand_ParseFail;
2319
2320 int64_t Val;
2321 if (!Expr->EvaluateAsAbsolute(Val)) {
2322 Error(S, "expected immediate value");
2323 return MatchOperand_ParseFail;
2324 }
2325
2326 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2327 // and because the CPU always adds one to the immediate field, the allowed
2328 // range becomes 1..4. We'll only check the range here and will deal
2329 // with the addition/subtraction when actually decoding/encoding
2330 // the instruction.
2331 if (Val < 1 || Val > 4) {
2332 Error(S, "immediate not in range (1..4)");
2333 return MatchOperand_ParseFail;
2334 }
2335
Jack Carter3b2c96e2014-01-22 23:31:38 +00002336 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002337 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002338 return MatchOperand_Success;
2339}
2340
Jack Carterdc1e35d2012-09-06 20:00:02 +00002341MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2342
Vladimir Medic4c299852013-11-06 11:27:05 +00002343 MCSymbolRefExpr::VariantKind VK =
2344 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2345 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2346 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2347 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2348 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2349 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2350 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2351 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2352 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2353 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2354 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2355 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2356 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2357 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2358 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2359 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2360 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2361 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002362 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2363 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2364 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2365 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2366 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2367 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002368 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2369 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002370 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002371
Matheus Almeida2852af82014-04-22 10:15:54 +00002372 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002373
Jack Carterdc1e35d2012-09-06 20:00:02 +00002374 return VK;
2375}
Jack Cartera63b16a2012-09-07 00:23:42 +00002376
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002377/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2378/// either this.
2379/// ::= '(', register, ')'
2380/// handle it before we iterate so we don't get tripped up by the lack of
2381/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002382bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002383 if (getLexer().is(AsmToken::LParen)) {
2384 Operands.push_back(
2385 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2386 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002387 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002388 SMLoc Loc = getLexer().getLoc();
2389 Parser.eatToEndOfStatement();
2390 return Error(Loc, "unexpected token in argument list");
2391 }
2392 if (Parser.getTok().isNot(AsmToken::RParen)) {
2393 SMLoc Loc = getLexer().getLoc();
2394 Parser.eatToEndOfStatement();
2395 return Error(Loc, "unexpected token, expected ')'");
2396 }
2397 Operands.push_back(
2398 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2399 Parser.Lex();
2400 }
2401 return false;
2402}
2403
2404/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2405/// either one of these.
2406/// ::= '[', register, ']'
2407/// ::= '[', integer, ']'
2408/// handle it before we iterate so we don't get tripped up by the lack of
2409/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002410bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002411 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002412 if (getLexer().is(AsmToken::LBrac)) {
2413 Operands.push_back(
2414 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2415 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002416 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002417 SMLoc Loc = getLexer().getLoc();
2418 Parser.eatToEndOfStatement();
2419 return Error(Loc, "unexpected token in argument list");
2420 }
2421 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2422 SMLoc Loc = getLexer().getLoc();
2423 Parser.eatToEndOfStatement();
2424 return Error(Loc, "unexpected token, expected ']'");
2425 }
2426 Operands.push_back(
2427 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2428 Parser.Lex();
2429 }
2430 return false;
2431}
2432
David Blaikie960ea3f2014-06-08 16:18:35 +00002433bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2434 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002435 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002436
2437 // We have reached first instruction, module directive are now forbidden.
2438 getTargetStreamer().forbidModuleDirective();
2439
Vladimir Medic74593e62013-07-17 15:00:42 +00002440 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002441 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002442 Parser.eatToEndOfStatement();
2443 return Error(NameLoc, "Unknown instruction");
2444 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002445 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002446 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002447
2448 // Read the remaining operands.
2449 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2450 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002451 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002452 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002453 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 return Error(Loc, "unexpected token in argument list");
2455 }
Toma Tabacu13964452014-09-04 13:23:44 +00002456 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002457 return true;
2458 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002459
Jack Carterd0bd6422013-04-18 00:41:53 +00002460 while (getLexer().is(AsmToken::Comma)) {
2461 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002462 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002463 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002464 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002465 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002466 return Error(Loc, "unexpected token in argument list");
2467 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468 // Parse bracket and parenthesis suffixes before we iterate
2469 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002470 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002471 return true;
2472 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002473 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002474 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002475 }
2476 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002477 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2478 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002479 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002480 return Error(Loc, "unexpected token in argument list");
2481 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002482 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002483 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002484}
2485
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002486bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002487 SMLoc Loc = getLexer().getLoc();
2488 Parser.eatToEndOfStatement();
2489 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002490}
2491
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002492bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002493 return Error(Loc, ErrorMsg);
2494}
2495
Jack Carter0b744b32012-10-04 02:29:46 +00002496bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002497 // Line should look like: ".set noat".
2498 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002499 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002500 // eat noat
2501 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002502 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2504 reportParseError("unexpected token in statement");
2505 return false;
2506 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002507 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002508 return false;
2509}
Jack Carterd0bd6422013-04-18 00:41:53 +00002510
Jack Carter0b744b32012-10-04 02:29:46 +00002511bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002512 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002513 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002514 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002515 getParser().Lex();
2516 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002517 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002519 return false;
2520 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002522 if (getLexer().isNot(AsmToken::Dollar)) {
2523 reportParseError("unexpected token in statement");
2524 return false;
2525 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002526 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002527 const AsmToken &Reg = Parser.getTok();
2528 if (Reg.is(AsmToken::Identifier)) {
2529 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2530 } else if (Reg.is(AsmToken::Integer)) {
2531 AtRegNo = Reg.getIntVal();
2532 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002533 reportParseError("unexpected token in statement");
2534 return false;
2535 }
Jack Carter1ac53222013-02-20 23:11:17 +00002536
Daniel Sanders71a89d922014-03-25 13:01:06 +00002537 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002538 reportParseError("unexpected token in statement");
2539 return false;
2540 }
2541
Toma Tabacu9db22db2014-09-09 10:15:38 +00002542 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002543 reportParseError("unexpected token in statement");
2544 return false;
2545 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002546 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002547
2548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2549 reportParseError("unexpected token in statement");
2550 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002551 }
2552 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002553 return false;
2554 } else {
2555 reportParseError("unexpected token in statement");
2556 return false;
2557 }
2558}
2559
2560bool MipsAsmParser::parseSetReorderDirective() {
2561 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002562 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002563 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2564 reportParseError("unexpected token in statement");
2565 return false;
2566 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002567 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002568 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002570 return false;
2571}
2572
2573bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002574 Parser.Lex();
2575 // If this is not the end of the statement, report an error.
2576 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2577 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002578 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002579 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002580 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002581 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002582 Parser.Lex(); // Consume the EndOfStatement.
2583 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002584}
2585
2586bool MipsAsmParser::parseSetMacroDirective() {
2587 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002589 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2590 reportParseError("unexpected token in statement");
2591 return false;
2592 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002593 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002594 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002595 return false;
2596}
2597
2598bool MipsAsmParser::parseSetNoMacroDirective() {
2599 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002600 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002601 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2602 reportParseError("`noreorder' must be set before `nomacro'");
2603 return false;
2604 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002605 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002606 reportParseError("`noreorder' must be set before `nomacro'");
2607 return false;
2608 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002609 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002610 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002611 return false;
2612}
Jack Carterd76b2372013-03-21 21:44:16 +00002613
Daniel Sanders44934432014-08-07 12:03:36 +00002614bool MipsAsmParser::parseSetMsaDirective() {
2615 Parser.Lex();
2616
2617 // If this is not the end of the statement, report an error.
2618 if (getLexer().isNot(AsmToken::EndOfStatement))
2619 return reportParseError("unexpected token in statement");
2620
2621 setFeatureBits(Mips::FeatureMSA, "msa");
2622 getTargetStreamer().emitDirectiveSetMsa();
2623 return false;
2624}
2625
2626bool MipsAsmParser::parseSetNoMsaDirective() {
2627 Parser.Lex();
2628
2629 // If this is not the end of the statement, report an error.
2630 if (getLexer().isNot(AsmToken::EndOfStatement))
2631 return reportParseError("unexpected token in statement");
2632
2633 clearFeatureBits(Mips::FeatureMSA, "msa");
2634 getTargetStreamer().emitDirectiveSetNoMsa();
2635 return false;
2636}
2637
Jack Carter39536722014-01-22 23:08:42 +00002638bool MipsAsmParser::parseSetNoMips16Directive() {
2639 Parser.Lex();
2640 // If this is not the end of the statement, report an error.
2641 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2642 reportParseError("unexpected token in statement");
2643 return false;
2644 }
2645 // For now do nothing.
2646 Parser.Lex(); // Consume the EndOfStatement.
2647 return false;
2648}
2649
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002650bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002651 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002652 // Line can be: .set fp=32
2653 // .set fp=xx
2654 // .set fp=64
2655 Parser.Lex(); // Eat fp token
2656 AsmToken Tok = Parser.getTok();
2657 if (Tok.isNot(AsmToken::Equal)) {
2658 reportParseError("unexpected token in statement");
2659 return false;
2660 }
2661 Parser.Lex(); // Eat '=' token.
2662 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002663
2664 if (!parseFpABIValue(FpAbiVal, ".set"))
2665 return false;
2666
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002667 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2668 reportParseError("unexpected token in statement");
2669 return false;
2670 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002671 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002672 Parser.Lex(); // Consume the EndOfStatement.
2673 return false;
2674}
2675
Toma Tabacu9db22db2014-09-09 10:15:38 +00002676bool MipsAsmParser::parseSetPopDirective() {
2677 SMLoc Loc = getLexer().getLoc();
2678
2679 Parser.Lex();
2680 if (getLexer().isNot(AsmToken::EndOfStatement))
2681 return reportParseError("unexpected token, expected end of statement");
2682
2683 // Always keep an element on the options "stack" to prevent the user
2684 // from changing the initial options. This is how we remember them.
2685 if (AssemblerOptions.size() == 2)
2686 return reportParseError(Loc, ".set pop with no .set push");
2687
2688 AssemblerOptions.pop_back();
2689 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2690
2691 getTargetStreamer().emitDirectiveSetPop();
2692 return false;
2693}
2694
2695bool MipsAsmParser::parseSetPushDirective() {
2696 Parser.Lex();
2697 if (getLexer().isNot(AsmToken::EndOfStatement))
2698 return reportParseError("unexpected token, expected end of statement");
2699
2700 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002701 AssemblerOptions.push_back(
2702 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002703
2704 getTargetStreamer().emitDirectiveSetPush();
2705 return false;
2706}
2707
Jack Carterd76b2372013-03-21 21:44:16 +00002708bool MipsAsmParser::parseSetAssignment() {
2709 StringRef Name;
2710 const MCExpr *Value;
2711
2712 if (Parser.parseIdentifier(Name))
2713 reportParseError("expected identifier after .set");
2714
2715 if (getLexer().isNot(AsmToken::Comma))
2716 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002717 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002718
Jack Carter3b2c96e2014-01-22 23:31:38 +00002719 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002720 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002721
Jack Carterd0bd6422013-04-18 00:41:53 +00002722 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002723 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002724 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002725 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002726 Sym = getContext().GetOrCreateSymbol(Name);
2727 Sym->setVariableValue(Value);
2728
2729 return false;
2730}
Jack Carterd0bd6422013-04-18 00:41:53 +00002731
Toma Tabacu26647792014-09-09 12:52:14 +00002732bool MipsAsmParser::parseSetMips0Directive() {
2733 Parser.Lex();
2734 if (getLexer().isNot(AsmToken::EndOfStatement))
2735 return reportParseError("unexpected token, expected end of statement");
2736
2737 // Reset assembler options to their initial values.
2738 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2739 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2740
2741 getTargetStreamer().emitDirectiveSetMips0();
2742 return false;
2743}
2744
Toma Tabacu85618b32014-08-19 14:22:52 +00002745bool MipsAsmParser::parseSetArchDirective() {
2746 Parser.Lex();
2747 if (getLexer().isNot(AsmToken::Equal))
2748 return reportParseError("unexpected token, expected equals sign");
2749
2750 Parser.Lex();
2751 StringRef Arch;
2752 if (Parser.parseIdentifier(Arch))
2753 return reportParseError("expected arch identifier");
2754
2755 StringRef ArchFeatureName =
2756 StringSwitch<StringRef>(Arch)
2757 .Case("mips1", "mips1")
2758 .Case("mips2", "mips2")
2759 .Case("mips3", "mips3")
2760 .Case("mips4", "mips4")
2761 .Case("mips5", "mips5")
2762 .Case("mips32", "mips32")
2763 .Case("mips32r2", "mips32r2")
2764 .Case("mips32r6", "mips32r6")
2765 .Case("mips64", "mips64")
2766 .Case("mips64r2", "mips64r2")
2767 .Case("mips64r6", "mips64r6")
2768 .Case("cnmips", "cnmips")
2769 .Case("r4000", "mips3") // This is an implementation of Mips3.
2770 .Default("");
2771
2772 if (ArchFeatureName.empty())
2773 return reportParseError("unsupported architecture");
2774
2775 selectArch(ArchFeatureName);
2776 getTargetStreamer().emitDirectiveSetArch(Arch);
2777 return false;
2778}
2779
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002780bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2781 Parser.Lex();
2782 if (getLexer().isNot(AsmToken::EndOfStatement))
2783 return reportParseError("unexpected token in .set directive");
2784
Matheus Almeida2852af82014-04-22 10:15:54 +00002785 switch (Feature) {
2786 default:
2787 llvm_unreachable("Unimplemented feature");
2788 case Mips::FeatureDSP:
2789 setFeatureBits(Mips::FeatureDSP, "dsp");
2790 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002791 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002792 case Mips::FeatureMicroMips:
2793 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002794 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002795 case Mips::FeatureMips16:
2796 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002797 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002798 case Mips::FeatureMips1:
2799 selectArch("mips1");
2800 getTargetStreamer().emitDirectiveSetMips1();
2801 break;
2802 case Mips::FeatureMips2:
2803 selectArch("mips2");
2804 getTargetStreamer().emitDirectiveSetMips2();
2805 break;
2806 case Mips::FeatureMips3:
2807 selectArch("mips3");
2808 getTargetStreamer().emitDirectiveSetMips3();
2809 break;
2810 case Mips::FeatureMips4:
2811 selectArch("mips4");
2812 getTargetStreamer().emitDirectiveSetMips4();
2813 break;
2814 case Mips::FeatureMips5:
2815 selectArch("mips5");
2816 getTargetStreamer().emitDirectiveSetMips5();
2817 break;
2818 case Mips::FeatureMips32:
2819 selectArch("mips32");
2820 getTargetStreamer().emitDirectiveSetMips32();
2821 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002822 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002823 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002824 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002825 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002826 case Mips::FeatureMips32r6:
2827 selectArch("mips32r6");
2828 getTargetStreamer().emitDirectiveSetMips32R6();
2829 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002830 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002831 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002832 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002833 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002834 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002835 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002836 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002837 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002838 case Mips::FeatureMips64r6:
2839 selectArch("mips64r6");
2840 getTargetStreamer().emitDirectiveSetMips64R6();
2841 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002842 }
2843 return false;
2844}
2845
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002846bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2847 if (getLexer().isNot(AsmToken::Comma)) {
2848 SMLoc Loc = getLexer().getLoc();
2849 Parser.eatToEndOfStatement();
2850 return Error(Loc, ErrorStr);
2851 }
2852
Matheus Almeida2852af82014-04-22 10:15:54 +00002853 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002854 return true;
2855}
2856
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002857bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002858 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002859 Warning(Loc, ".cpload in reorder section");
2860
2861 // FIXME: Warn if cpload is used in Mips16 mode.
2862
David Blaikie960ea3f2014-06-08 16:18:35 +00002863 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002864 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002865 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2866 reportParseError("expected register containing function address");
2867 return false;
2868 }
2869
David Blaikie960ea3f2014-06-08 16:18:35 +00002870 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2871 if (!RegOpnd.isGPRAsmReg()) {
2872 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002873 return false;
2874 }
2875
David Blaikie960ea3f2014-06-08 16:18:35 +00002876 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002877 return false;
2878}
2879
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002880bool MipsAsmParser::parseDirectiveCPSetup() {
2881 unsigned FuncReg;
2882 unsigned Save;
2883 bool SaveIsReg = true;
2884
Matheus Almeida7e815762014-06-18 13:08:59 +00002885 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002886 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002887 if (ResTy == MatchOperand_NoMatch) {
2888 reportParseError("expected register containing function address");
2889 Parser.eatToEndOfStatement();
2890 return false;
2891 }
2892
2893 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2894 if (!FuncRegOpnd.isGPRAsmReg()) {
2895 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2896 Parser.eatToEndOfStatement();
2897 return false;
2898 }
2899
2900 FuncReg = FuncRegOpnd.getGPR32Reg();
2901 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002902
2903 if (!eatComma("expected comma parsing directive"))
2904 return true;
2905
Toma Tabacu13964452014-09-04 13:23:44 +00002906 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002907 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002908 const AsmToken &Tok = Parser.getTok();
2909 if (Tok.is(AsmToken::Integer)) {
2910 Save = Tok.getIntVal();
2911 SaveIsReg = false;
2912 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002913 } else {
2914 reportParseError("expected save register or stack offset");
2915 Parser.eatToEndOfStatement();
2916 return false;
2917 }
2918 } else {
2919 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2920 if (!SaveOpnd.isGPRAsmReg()) {
2921 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2922 Parser.eatToEndOfStatement();
2923 return false;
2924 }
2925 Save = SaveOpnd.getGPR32Reg();
2926 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002927
2928 if (!eatComma("expected comma parsing directive"))
2929 return true;
2930
2931 StringRef Name;
2932 if (Parser.parseIdentifier(Name))
2933 reportParseError("expected identifier");
2934 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002935
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002936 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002937 return false;
2938}
2939
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002940bool MipsAsmParser::parseDirectiveNaN() {
2941 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2942 const AsmToken &Tok = Parser.getTok();
2943
2944 if (Tok.getString() == "2008") {
2945 Parser.Lex();
2946 getTargetStreamer().emitDirectiveNaN2008();
2947 return false;
2948 } else if (Tok.getString() == "legacy") {
2949 Parser.Lex();
2950 getTargetStreamer().emitDirectiveNaNLegacy();
2951 return false;
2952 }
2953 }
2954 // If we don't recognize the option passed to the .nan
2955 // directive (e.g. no option or unknown option), emit an error.
2956 reportParseError("invalid option in .nan directive");
2957 return false;
2958}
2959
Jack Carter0b744b32012-10-04 02:29:46 +00002960bool MipsAsmParser::parseDirectiveSet() {
2961
Jack Carterd0bd6422013-04-18 00:41:53 +00002962 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002963 const AsmToken &Tok = Parser.getTok();
2964
2965 if (Tok.getString() == "noat") {
2966 return parseSetNoAtDirective();
2967 } else if (Tok.getString() == "at") {
2968 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00002969 } else if (Tok.getString() == "arch") {
2970 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002971 } else if (Tok.getString() == "fp") {
2972 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002973 } else if (Tok.getString() == "pop") {
2974 return parseSetPopDirective();
2975 } else if (Tok.getString() == "push") {
2976 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002977 } else if (Tok.getString() == "reorder") {
2978 return parseSetReorderDirective();
2979 } else if (Tok.getString() == "noreorder") {
2980 return parseSetNoReorderDirective();
2981 } else if (Tok.getString() == "macro") {
2982 return parseSetMacroDirective();
2983 } else if (Tok.getString() == "nomacro") {
2984 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002985 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002986 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002987 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002988 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002989 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002990 getTargetStreamer().emitDirectiveSetNoMicroMips();
2991 Parser.eatToEndOfStatement();
2992 return false;
2993 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002994 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00002995 } else if (Tok.getString() == "mips0") {
2996 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00002997 } else if (Tok.getString() == "mips1") {
2998 return parseSetFeature(Mips::FeatureMips1);
2999 } else if (Tok.getString() == "mips2") {
3000 return parseSetFeature(Mips::FeatureMips2);
3001 } else if (Tok.getString() == "mips3") {
3002 return parseSetFeature(Mips::FeatureMips3);
3003 } else if (Tok.getString() == "mips4") {
3004 return parseSetFeature(Mips::FeatureMips4);
3005 } else if (Tok.getString() == "mips5") {
3006 return parseSetFeature(Mips::FeatureMips5);
3007 } else if (Tok.getString() == "mips32") {
3008 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003009 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003010 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003011 } else if (Tok.getString() == "mips32r6") {
3012 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003013 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003014 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003015 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003016 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003017 } else if (Tok.getString() == "mips64r6") {
3018 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003019 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003020 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00003021 } else if (Tok.getString() == "msa") {
3022 return parseSetMsaDirective();
3023 } else if (Tok.getString() == "nomsa") {
3024 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003025 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003026 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003027 parseSetAssignment();
3028 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003029 }
Jack Carter07c818d2013-01-25 01:31:34 +00003030
Jack Carter0b744b32012-10-04 02:29:46 +00003031 return true;
3032}
3033
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003034/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003035/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003036bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003037 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3038 for (;;) {
3039 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003040 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003041 return true;
3042
3043 getParser().getStreamer().EmitValue(Value, Size);
3044
3045 if (getLexer().is(AsmToken::EndOfStatement))
3046 break;
3047
3048 // FIXME: Improve diagnostic.
3049 if (getLexer().isNot(AsmToken::Comma))
3050 return Error(L, "unexpected token in directive");
3051 Parser.Lex();
3052 }
3053 }
3054
3055 Parser.Lex();
3056 return false;
3057}
3058
Vladimir Medic4c299852013-11-06 11:27:05 +00003059/// parseDirectiveGpWord
3060/// ::= .gpword local_sym
3061bool MipsAsmParser::parseDirectiveGpWord() {
3062 const MCExpr *Value;
3063 // EmitGPRel32Value requires an expression, so we are using base class
3064 // method to evaluate the expression.
3065 if (getParser().parseExpression(Value))
3066 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003067 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003068
Vladimir Medice10c1122013-11-13 13:18:04 +00003069 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00003070 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00003071 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003072 return false;
3073}
3074
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003075/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003076/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003077bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003078 const MCExpr *Value;
3079 // EmitGPRel64Value requires an expression, so we are using base class
3080 // method to evaluate the expression.
3081 if (getParser().parseExpression(Value))
3082 return true;
3083 getParser().getStreamer().EmitGPRel64Value(Value);
3084
3085 if (getLexer().isNot(AsmToken::EndOfStatement))
3086 return Error(getLexer().getLoc(), "unexpected token in directive");
3087 Parser.Lex(); // Eat EndOfStatement token.
3088 return false;
3089}
3090
Jack Carter0cd3c192014-01-06 23:27:31 +00003091bool MipsAsmParser::parseDirectiveOption() {
3092 // Get the option token.
3093 AsmToken Tok = Parser.getTok();
3094 // At the moment only identifiers are supported.
3095 if (Tok.isNot(AsmToken::Identifier)) {
3096 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
3097 Parser.eatToEndOfStatement();
3098 return false;
3099 }
3100
3101 StringRef Option = Tok.getIdentifier();
3102
3103 if (Option == "pic0") {
3104 getTargetStreamer().emitDirectiveOptionPic0();
3105 Parser.Lex();
3106 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3107 Error(Parser.getTok().getLoc(),
3108 "unexpected token in .option pic0 directive");
3109 Parser.eatToEndOfStatement();
3110 }
3111 return false;
3112 }
3113
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003114 if (Option == "pic2") {
3115 getTargetStreamer().emitDirectiveOptionPic2();
3116 Parser.Lex();
3117 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3118 Error(Parser.getTok().getLoc(),
3119 "unexpected token in .option pic2 directive");
3120 Parser.eatToEndOfStatement();
3121 }
3122 return false;
3123 }
3124
Jack Carter0cd3c192014-01-06 23:27:31 +00003125 // Unknown option.
3126 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
3127 Parser.eatToEndOfStatement();
3128 return false;
3129}
3130
Daniel Sanders7e527422014-07-10 13:38:23 +00003131/// parseDirectiveModule
3132/// ::= .module oddspreg
3133/// ::= .module nooddspreg
3134/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003135bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003136 MCAsmLexer &Lexer = getLexer();
3137 SMLoc L = Lexer.getLoc();
3138
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003139 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003140 // TODO : get a better message.
3141 reportParseError(".module directive must appear before any code");
3142 return false;
3143 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003144
3145 if (Lexer.is(AsmToken::Identifier)) {
3146 StringRef Option = Parser.getTok().getString();
3147 Parser.Lex();
3148
3149 if (Option == "oddspreg") {
3150 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3151 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3152
3153 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3154 reportParseError("Expected end of statement");
3155 return false;
3156 }
3157
3158 return false;
3159 } else if (Option == "nooddspreg") {
3160 if (!isABI_O32()) {
3161 Error(L, "'.module nooddspreg' requires the O32 ABI");
3162 return false;
3163 }
3164
3165 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3166 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3167
3168 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3169 reportParseError("Expected end of statement");
3170 return false;
3171 }
3172
3173 return false;
3174 } else if (Option == "fp") {
3175 return parseDirectiveModuleFP();
3176 }
3177
3178 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003179 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003180
3181 return false;
3182}
3183
3184/// parseDirectiveModuleFP
3185/// ::= =32
3186/// ::= =xx
3187/// ::= =64
3188bool MipsAsmParser::parseDirectiveModuleFP() {
3189 MCAsmLexer &Lexer = getLexer();
3190
3191 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003192 reportParseError("unexpected token in statement");
3193 return false;
3194 }
3195 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003196
Daniel Sanders7e527422014-07-10 13:38:23 +00003197 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003198 if (!parseFpABIValue(FpABI, ".module"))
3199 return false;
3200
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003201 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3202 reportParseError("unexpected token in statement");
3203 return false;
3204 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003205
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003206 // Emit appropriate flags.
3207 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003208 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003209 return false;
3210}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003211
Daniel Sanders7e527422014-07-10 13:38:23 +00003212bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003213 StringRef Directive) {
3214 MCAsmLexer &Lexer = getLexer();
3215
3216 if (Lexer.is(AsmToken::Identifier)) {
3217 StringRef Value = Parser.getTok().getString();
3218 Parser.Lex();
3219
3220 if (Value != "xx") {
3221 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3222 return false;
3223 }
3224
3225 if (!isABI_O32()) {
3226 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3227 return false;
3228 }
3229
Daniel Sanders7e527422014-07-10 13:38:23 +00003230 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003231 return true;
3232 }
3233
3234 if (Lexer.is(AsmToken::Integer)) {
3235 unsigned Value = Parser.getTok().getIntVal();
3236 Parser.Lex();
3237
3238 if (Value != 32 && Value != 64) {
3239 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3240 return false;
3241 }
3242
3243 if (Value == 32) {
3244 if (!isABI_O32()) {
3245 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3246 return false;
3247 }
3248
Daniel Sanders7e527422014-07-10 13:38:23 +00003249 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3250 } else
3251 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003252
Daniel Sanders7e527422014-07-10 13:38:23 +00003253 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003254 }
3255
3256 return false;
3257}
3258
Jack Carter0b744b32012-10-04 02:29:46 +00003259bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003260 StringRef IDVal = DirectiveID.getString();
3261
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003262 if (IDVal == ".cpload")
3263 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003264 if (IDVal == ".dword") {
3265 parseDataDirective(8, DirectiveID.getLoc());
3266 return false;
3267 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003268 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003269 StringRef SymbolName;
3270
3271 if (Parser.parseIdentifier(SymbolName)) {
3272 reportParseError("expected identifier after .ent");
3273 return false;
3274 }
3275
3276 // There's an undocumented extension that allows an integer to
3277 // follow the name of the procedure which AFAICS is ignored by GAS.
3278 // Example: .ent foo,2
3279 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3280 if (getLexer().isNot(AsmToken::Comma)) {
3281 // Even though we accept this undocumented extension for compatibility
3282 // reasons, the additional integer argument does not actually change
3283 // the behaviour of the '.ent' directive, so we would like to discourage
3284 // its use. We do this by not referring to the extended version in
3285 // error messages which are not directly related to its use.
3286 reportParseError("unexpected token, expected end of statement");
3287 return false;
3288 }
3289 Parser.Lex(); // Eat the comma.
3290 const MCExpr *DummyNumber;
3291 int64_t DummyNumberVal;
3292 // If the user was explicitly trying to use the extended version,
3293 // we still give helpful extension-related error messages.
3294 if (Parser.parseExpression(DummyNumber)) {
3295 reportParseError("expected number after comma");
3296 return false;
3297 }
3298 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3299 reportParseError("expected an absolute expression after comma");
3300 return false;
3301 }
3302 }
3303
3304 // If this is not the end of the statement, report an error.
3305 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3306 reportParseError("unexpected token, expected end of statement");
3307 return false;
3308 }
3309
3310 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3311
3312 getTargetStreamer().emitDirectiveEnt(*Sym);
3313 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003314 return false;
3315 }
3316
Jack Carter07c818d2013-01-25 01:31:34 +00003317 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003318 StringRef SymbolName;
3319
3320 if (Parser.parseIdentifier(SymbolName)) {
3321 reportParseError("expected identifier after .end");
3322 return false;
3323 }
3324
3325 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3326 reportParseError("unexpected token, expected end of statement");
3327 return false;
3328 }
3329
3330 if (CurrentFn == nullptr) {
3331 reportParseError(".end used without .ent");
3332 return false;
3333 }
3334
3335 if ((SymbolName != CurrentFn->getName())) {
3336 reportParseError(".end symbol does not match .ent symbol");
3337 return false;
3338 }
3339
3340 getTargetStreamer().emitDirectiveEnd(SymbolName);
3341 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003342 return false;
3343 }
3344
Jack Carter07c818d2013-01-25 01:31:34 +00003345 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003346 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3347 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003348 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003349 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3350 reportParseError("expected stack register");
3351 return false;
3352 }
3353
3354 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3355 if (!StackRegOpnd.isGPRAsmReg()) {
3356 reportParseError(StackRegOpnd.getStartLoc(),
3357 "expected general purpose register");
3358 return false;
3359 }
3360 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3361
3362 if (Parser.getTok().is(AsmToken::Comma))
3363 Parser.Lex();
3364 else {
3365 reportParseError("unexpected token, expected comma");
3366 return false;
3367 }
3368
3369 // Parse the frame size.
3370 const MCExpr *FrameSize;
3371 int64_t FrameSizeVal;
3372
3373 if (Parser.parseExpression(FrameSize)) {
3374 reportParseError("expected frame size value");
3375 return false;
3376 }
3377
3378 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3379 reportParseError("frame size not an absolute expression");
3380 return false;
3381 }
3382
3383 if (Parser.getTok().is(AsmToken::Comma))
3384 Parser.Lex();
3385 else {
3386 reportParseError("unexpected token, expected comma");
3387 return false;
3388 }
3389
3390 // Parse the return register.
3391 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003392 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003393 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3394 reportParseError("expected return register");
3395 return false;
3396 }
3397
3398 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3399 if (!ReturnRegOpnd.isGPRAsmReg()) {
3400 reportParseError(ReturnRegOpnd.getStartLoc(),
3401 "expected general purpose register");
3402 return false;
3403 }
3404
3405 // If this is not the end of the statement, report an error.
3406 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3407 reportParseError("unexpected token, expected end of statement");
3408 return false;
3409 }
3410
3411 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3412 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003413 return false;
3414 }
3415
Jack Carter07c818d2013-01-25 01:31:34 +00003416 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003417 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003418 }
3419
Daniel Sandersd97a6342014-08-13 10:07:34 +00003420 if (IDVal == ".mask" || IDVal == ".fmask") {
3421 // .mask bitmask, frame_offset
3422 // bitmask: One bit for each register used.
3423 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3424 // first register is expected to be saved.
3425 // Examples:
3426 // .mask 0x80000000, -4
3427 // .fmask 0x80000000, -4
3428 //
Jack Carterbe332172012-09-07 00:48:02 +00003429
Daniel Sandersd97a6342014-08-13 10:07:34 +00003430 // Parse the bitmask
3431 const MCExpr *BitMask;
3432 int64_t BitMaskVal;
3433
3434 if (Parser.parseExpression(BitMask)) {
3435 reportParseError("expected bitmask value");
3436 return false;
3437 }
3438
3439 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3440 reportParseError("bitmask not an absolute expression");
3441 return false;
3442 }
3443
3444 if (Parser.getTok().is(AsmToken::Comma))
3445 Parser.Lex();
3446 else {
3447 reportParseError("unexpected token, expected comma");
3448 return false;
3449 }
3450
3451 // Parse the frame_offset
3452 const MCExpr *FrameOffset;
3453 int64_t FrameOffsetVal;
3454
3455 if (Parser.parseExpression(FrameOffset)) {
3456 reportParseError("expected frame offset value");
3457 return false;
3458 }
3459
3460 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3461 reportParseError("frame offset not an absolute expression");
3462 return false;
3463 }
3464
3465 // If this is not the end of the statement, report an error.
3466 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3467 reportParseError("unexpected token, expected end of statement");
3468 return false;
3469 }
3470
3471 if (IDVal == ".mask")
3472 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3473 else
3474 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003475 return false;
3476 }
3477
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003478 if (IDVal == ".nan")
3479 return parseDirectiveNaN();
3480
Jack Carter07c818d2013-01-25 01:31:34 +00003481 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003482 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003483 return false;
3484 }
3485
Rafael Espindolab59fb732014-03-28 18:50:26 +00003486 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003487 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003488 return false;
3489 }
3490
Jack Carter07c818d2013-01-25 01:31:34 +00003491 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003492 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003493 return false;
3494 }
3495
Jack Carter0cd3c192014-01-06 23:27:31 +00003496 if (IDVal == ".option")
3497 return parseDirectiveOption();
3498
3499 if (IDVal == ".abicalls") {
3500 getTargetStreamer().emitDirectiveAbiCalls();
3501 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3502 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3503 // Clear line
3504 Parser.eatToEndOfStatement();
3505 }
3506 return false;
3507 }
3508
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003509 if (IDVal == ".cpsetup")
3510 return parseDirectiveCPSetup();
3511
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003512 if (IDVal == ".module")
3513 return parseDirectiveModule();
3514
Rafael Espindola870c4e92012-01-11 03:56:41 +00003515 return true;
3516}
3517
Rafael Espindola870c4e92012-01-11 03:56:41 +00003518extern "C" void LLVMInitializeMipsAsmParser() {
3519 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3520 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3521 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3522 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3523}
Jack Carterb4dbc172012-09-05 23:34:03 +00003524
3525#define GET_REGISTER_MATCHER
3526#define GET_MATCHER_IMPLEMENTATION
3527#include "MipsGenAsmMatcher.inc"