blob: 67725cb7ffa03b61deb0f681fceafc37aeeb5b5b [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000017#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000020#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCParser/MCAsmLexer.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000026#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000027#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000028#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000029#include "llvm/Support/TargetRegistry.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000031#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000032
33using namespace llvm;
34
Chandler Carruthe96dd892014-04-21 22:55:11 +000035#define DEBUG_TYPE "mips-asm-parser"
36
Joey Gouly0e76fa72013-09-12 10:28:05 +000037namespace llvm {
38class MCInstrInfo;
39}
40
Rafael Espindola870c4e92012-01-11 03:56:41 +000041namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000042class MipsAssemblerOptions {
43public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000044 MipsAssemblerOptions(uint64_t Features_) :
45 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000046
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48 ATReg = Opts->getATRegNum();
49 Reorder = Opts->isReorder();
50 Macro = Opts->isMacro();
51 Features = Opts->getFeatures();
52 }
53
54 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000055 bool setATReg(unsigned Reg);
56
Toma Tabacu9db22db2014-09-09 10:15:38 +000057 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000058 void setReorder() { Reorder = true; }
59 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000060
Toma Tabacu9db22db2014-09-09 10:15:38 +000061 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000062 void setMacro() { Macro = true; }
63 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 uint64_t getFeatures() const { return Features; }
66 void setFeatures(uint64_t Features_) { Features = Features_; }
67
Daniel Sandersf0df2212014-08-04 12:20:00 +000068 // Set of features that are either architecture features or referenced
69 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71 // The reason we need this mask is explained in the selectArch function.
72 // FIXME: Ideally we would like TableGen to generate this information.
73 static const uint64_t AllArchRelatedMask =
74 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81
Jack Carter0b744b32012-10-04 02:29:46 +000082private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000083 unsigned ATReg;
84 bool Reorder;
85 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000086 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000087};
88}
89
90namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000091class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000092 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000093 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 return static_cast<MipsTargetStreamer &>(TS);
95 }
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 MCSubtargetInfo &STI;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Daniel Sandersef638fe2014-10-03 15:37:37 +0000104 // Print a warning along with its fix-it message at the given range.
105 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
106 SMRange Range, bool ShowColors = true);
107
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000108#define GET_ASSEMBLER_HEADER
109#include "MipsGenAsmMatcher.inc"
110
Matheus Almeida595fcab2014-06-11 15:05:56 +0000111 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
112
Chad Rosier49963552012-10-13 00:26:04 +0000113 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000114 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000115 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000116 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000117
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Toma Tabacu13964452014-09-04 13:23:44 +0000121 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
David Blaikie960ea3f2014-06-08 16:18:35 +0000125 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
126 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Craig Topper56c590a2014-04-29 07:58:02 +0000128 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000135
Jack Carter873c7242013-01-12 01:03:14 +0000136 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000137 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000149 MipsAsmParser::OperandMatchResultTy
150 parseRegisterList (OperandVector &Operands);
151
David Blaikie960ea3f2014-06-08 16:18:35 +0000152 bool searchSymbolAlias(OperandVector &Operands);
153
Toma Tabacu13964452014-09-04 13:23:44 +0000154 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000155
Jack Carter30a59822012-10-04 04:03:53 +0000156 bool needsExpansion(MCInst &Inst);
157
Matheus Almeida3813d572014-06-19 14:39:14 +0000158 // Expands assembly pseudo instructions.
159 // Returns false on success, true otherwise.
160 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000161 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000162
163 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000164 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000165
166 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000167 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000168
169 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
Toma Tabacu0d64b202014-08-14 10:29:17 +0000172 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
173 SmallVectorImpl<MCInst> &Instructions);
174
Jack Carter9e65aa32013-03-22 00:05:30 +0000175 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000176 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
177 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000178 bool reportParseError(Twine ErrorMsg);
179 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000180
Jack Carterb5cf5902013-04-17 00:18:04 +0000181 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000182 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000183
Vladimir Medic4c299852013-11-06 11:27:05 +0000184 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000185
186 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000187 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000188 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000189 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000190 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000191 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000192 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000193 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000194 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000195
196 bool parseSetAtDirective();
197 bool parseSetNoAtDirective();
198 bool parseSetMacroDirective();
199 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000200 bool parseSetMsaDirective();
201 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000202 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000203 bool parseSetReorderDirective();
204 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000205 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000206 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000207 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000208 bool parseSetPopDirective();
209 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000210
Jack Carterd76b2372013-03-21 21:44:16 +0000211 bool parseSetAssignment();
212
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000213 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000214 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000215 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000216 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000217 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000218 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
219 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000220
Jack Carterdc1e35d2012-09-06 20:00:02 +0000221 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000222
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000223 bool eatComma(StringRef ErrorStr);
224
Jack Carter1ac53222013-02-20 23:11:17 +0000225 int matchCPURegisterName(StringRef Symbol);
226
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000227 int matchHWRegsRegisterName(StringRef Symbol);
228
Jack Carter873c7242013-01-12 01:03:14 +0000229 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000230
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000231 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000232
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000233 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000234
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000235 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000236
Jack Carter5dc8ac92013-09-25 23:50:44 +0000237 int matchMSA128RegisterName(StringRef Name);
238
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000239 int matchMSA128CtrlRegisterName(StringRef Name);
240
Jack Carterd0bd6422013-04-18 00:41:53 +0000241 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000242
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000243 unsigned getGPR(int RegNo);
244
Matheus Almeida7de68e72014-06-18 14:46:05 +0000245 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000246
247 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000248 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000249
250 // Helper function that checks if the value of a vector index is within the
251 // boundaries of accepted values for each RegisterKind
252 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
253 bool validateMSAIndex(int Val, int RegKind);
254
Daniel Sandersf0df2212014-08-04 12:20:00 +0000255 // Selects a new architecture by updating the FeatureBits with the necessary
256 // info including implied dependencies.
257 // Internally, it clears all the feature bits related to *any* architecture
258 // and selects the new one using the ToggleFeature functionality of the
259 // MCSubtargetInfo object that handles implied dependencies. The reason we
260 // clear all the arch related bits manually is because ToggleFeature only
261 // clears the features that imply the feature being cleared and not the
262 // features implied by the feature being cleared. This is easier to see
263 // with an example:
264 // --------------------------------------------------
265 // | Feature | Implies |
266 // | -------------------------------------------------|
267 // | FeatureMips1 | None |
268 // | FeatureMips2 | FeatureMips1 |
269 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
270 // | FeatureMips4 | FeatureMips3 |
271 // | ... | |
272 // --------------------------------------------------
273 //
274 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
275 // FeatureMipsGP64 | FeatureMips1)
276 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
277 void selectArch(StringRef ArchFeature) {
278 uint64_t FeatureBits = STI.getFeatureBits();
279 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
280 STI.setFeatureBits(FeatureBits);
281 setAvailableFeatures(
282 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000283 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000284 }
285
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000286 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000288 setAvailableFeatures(
289 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000291 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000292 }
293
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000294 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000296 setAvailableFeatures(
297 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000298 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000299 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000300 }
301
Rafael Espindola870c4e92012-01-11 03:56:41 +0000302public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000303 enum MipsMatchResultTy {
304 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
305#define GET_OPERAND_DIAGNOSTIC_TYPES
306#include "MipsGenAsmMatcher.inc"
307#undef GET_OPERAND_DIAGNOSTIC_TYPES
308
309 };
310
Joey Gouly0e76fa72013-09-12 10:28:05 +0000311 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000312 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000313 : MCTargetAsmParser(), STI(sti) {
314 MCAsmParserExtension::Initialize(parser);
315
Jack Carterb4dbc172012-09-05 23:34:03 +0000316 // Initialize the set of available features.
317 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000318
319 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000320 AssemblerOptions.push_back(
321 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000322
323 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000324 AssemblerOptions.push_back(
325 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000326
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000327 getTargetStreamer().updateABIInfo(*this);
328
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000329 // Assert exactly one ABI was chosen.
330 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
331 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
332 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
333 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000334
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000335 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000336 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000337
338 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000339 }
340
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000341 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
342 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
343
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000344 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
345 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
346 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
347 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
348 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000349 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000350
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000351 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000352 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
353 }
354
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000355 bool inMicroMipsMode() const {
356 return STI.getFeatureBits() & Mips::FeatureMicroMips;
357 }
358 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
359 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
360 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
361 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
362 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
363 bool hasMips32() const {
364 return (STI.getFeatureBits() & Mips::FeatureMips32);
365 }
366 bool hasMips64() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips64);
368 }
369 bool hasMips32r2() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
371 }
372 bool hasMips64r2() const {
373 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
374 }
375 bool hasMips32r6() const {
376 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
377 }
378 bool hasMips64r6() const {
379 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
380 }
381 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
382 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
383 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
384
385 bool inMips16Mode() const {
386 return STI.getFeatureBits() & Mips::FeatureMips16;
387 }
388 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000389 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000391 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000392 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000393};
394}
395
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000396namespace {
397
398/// MipsOperand - Instances of this class represent a parsed Mips machine
399/// instruction.
400class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000401public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000402 /// Broad categories of register classes
403 /// The exact class is finalized by the render method.
404 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000405 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000406 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000408 RegKind_FCC = 4, /// FCC
409 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
410 RegKind_MSACtrl = 16, /// MSA control registers
411 RegKind_COP2 = 32, /// COP2
412 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
413 /// context).
414 RegKind_CCR = 128, /// CCR
415 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000416 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000417
418 /// Potentially any (e.g. $1)
419 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
420 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000421 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000422 };
423
424private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000425 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000426 k_Immediate, /// An immediate (possibly involving symbol references)
427 k_Memory, /// Base + Offset Memory Address
428 k_PhysRegister, /// A physical register from the Mips namespace
429 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000430 k_Token, /// A simple token
431 k_RegList /// A physical register list
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000432 } Kind;
433
David Blaikie960ea3f2014-06-08 16:18:35 +0000434public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000435 MipsOperand(KindTy K, MipsAsmParser &Parser)
436 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
437
David Blaikie960ea3f2014-06-08 16:18:35 +0000438private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000439 /// For diagnostics, and checking the assembler temporary
440 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000441
Eric Christopher8996c5d2013-03-15 00:42:55 +0000442 struct Token {
443 const char *Data;
444 unsigned Length;
445 };
446
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000447 struct PhysRegOp {
448 unsigned Num; /// Register Number
449 };
450
451 struct RegIdxOp {
452 unsigned Index; /// Index into the register class
453 RegKind Kind; /// Bitfield of the kinds it could possibly be
454 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000455 };
456
457 struct ImmOp {
458 const MCExpr *Val;
459 };
460
461 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000462 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000463 const MCExpr *Off;
464 };
465
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000466 struct RegListOp {
467 SmallVector<unsigned, 10> *List;
468 };
469
Jack Carterb4dbc172012-09-05 23:34:03 +0000470 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000471 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000472 struct PhysRegOp PhysReg;
473 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000474 struct ImmOp Imm;
475 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000476 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000477 };
478
479 SMLoc StartLoc, EndLoc;
480
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000481 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000482 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
483 const MCRegisterInfo *RegInfo,
484 SMLoc S, SMLoc E,
485 MipsAsmParser &Parser) {
486 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000487 Op->RegIdx.Index = Index;
488 Op->RegIdx.RegInfo = RegInfo;
489 Op->RegIdx.Kind = RegKind;
490 Op->StartLoc = S;
491 Op->EndLoc = E;
492 return Op;
493 }
494
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000495public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000496 /// Coerce the register to GPR32 and return the real register for the current
497 /// target.
498 unsigned getGPR32Reg() const {
499 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000500 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000501 unsigned ClassID = Mips::GPR32RegClassID;
502 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000503 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000504
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000505 /// Coerce the register to GPR32 and return the real register for the current
506 /// target.
507 unsigned getGPRMM16Reg() const {
508 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
509 unsigned ClassID = Mips::GPR32RegClassID;
510 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
511 }
512
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000513 /// Coerce the register to GPR64 and return the real register for the current
514 /// target.
515 unsigned getGPR64Reg() const {
516 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
517 unsigned ClassID = Mips::GPR64RegClassID;
518 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000519 }
520
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521private:
522 /// Coerce the register to AFGR64 and return the real register for the current
523 /// target.
524 unsigned getAFGR64Reg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
526 if (RegIdx.Index % 2 != 0)
527 AsmParser.Warning(StartLoc, "Float register should be even.");
528 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
529 .getRegister(RegIdx.Index / 2);
530 }
531
532 /// Coerce the register to FGR64 and return the real register for the current
533 /// target.
534 unsigned getFGR64Reg() const {
535 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
536 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
537 .getRegister(RegIdx.Index);
538 }
539
540 /// Coerce the register to FGR32 and return the real register for the current
541 /// target.
542 unsigned getFGR32Reg() const {
543 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
544 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
545 .getRegister(RegIdx.Index);
546 }
547
548 /// Coerce the register to FGRH32 and return the real register for the current
549 /// target.
550 unsigned getFGRH32Reg() const {
551 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
552 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
553 .getRegister(RegIdx.Index);
554 }
555
556 /// Coerce the register to FCC and return the real register for the current
557 /// target.
558 unsigned getFCCReg() const {
559 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
560 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
561 .getRegister(RegIdx.Index);
562 }
563
564 /// Coerce the register to MSA128 and return the real register for the current
565 /// target.
566 unsigned getMSA128Reg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
568 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
569 // identical
570 unsigned ClassID = Mips::MSA128BRegClassID;
571 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
572 }
573
574 /// Coerce the register to MSACtrl and return the real register for the
575 /// current target.
576 unsigned getMSACtrlReg() const {
577 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
578 unsigned ClassID = Mips::MSACtrlRegClassID;
579 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
580 }
581
582 /// Coerce the register to COP2 and return the real register for the
583 /// current target.
584 unsigned getCOP2Reg() const {
585 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
586 unsigned ClassID = Mips::COP2RegClassID;
587 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
588 }
589
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000590 /// Coerce the register to COP3 and return the real register for the
591 /// current target.
592 unsigned getCOP3Reg() const {
593 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
594 unsigned ClassID = Mips::COP3RegClassID;
595 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
596 }
597
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 /// Coerce the register to ACC64DSP and return the real register for the
599 /// current target.
600 unsigned getACC64DSPReg() const {
601 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
602 unsigned ClassID = Mips::ACC64DSPRegClassID;
603 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
604 }
605
606 /// Coerce the register to HI32DSP and return the real register for the
607 /// current target.
608 unsigned getHI32DSPReg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
610 unsigned ClassID = Mips::HI32DSPRegClassID;
611 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
612 }
613
614 /// Coerce the register to LO32DSP and return the real register for the
615 /// current target.
616 unsigned getLO32DSPReg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
618 unsigned ClassID = Mips::LO32DSPRegClassID;
619 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
620 }
621
622 /// Coerce the register to CCR and return the real register for the
623 /// current target.
624 unsigned getCCRReg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
626 unsigned ClassID = Mips::CCRRegClassID;
627 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
628 }
629
630 /// Coerce the register to HWRegs and return the real register for the
631 /// current target.
632 unsigned getHWRegsReg() const {
633 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
634 unsigned ClassID = Mips::HWRegsRegClassID;
635 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
636 }
637
638public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000639 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000640 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000641 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000642 Inst.addOperand(MCOperand::CreateImm(0));
643 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
644 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
645 else
646 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000647 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 void addRegOperands(MCInst &Inst, unsigned N) const {
650 llvm_unreachable("Use a custom parser instead");
651 }
652
Daniel Sanders21bce302014-04-01 12:35:23 +0000653 /// Render the operand to an MCInst as a GPR32
654 /// Asserts if the wrong number of operands are requested, or the operand
655 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
657 assert(N == 1 && "Invalid number of operands!");
658 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
659 }
660
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000661 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
662 assert(N == 1 && "Invalid number of operands!");
663 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
664 }
665
Jozef Kolek1904fa22014-11-24 14:25:53 +0000666 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
667 assert(N == 1 && "Invalid number of operands!");
668 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
669 }
670
Daniel Sanders21bce302014-04-01 12:35:23 +0000671 /// Render the operand to an MCInst as a GPR64
672 /// Asserts if the wrong number of operands are requested, or the operand
673 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000674 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
675 assert(N == 1 && "Invalid number of operands!");
676 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
677 }
678
679 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
680 assert(N == 1 && "Invalid number of operands!");
681 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
682 }
683
684 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
685 assert(N == 1 && "Invalid number of operands!");
686 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
687 }
688
689 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000692 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000693 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000694 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
695 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000696 }
697
698 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
699 assert(N == 1 && "Invalid number of operands!");
700 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
701 }
702
703 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
704 assert(N == 1 && "Invalid number of operands!");
705 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
706 }
707
708 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
709 assert(N == 1 && "Invalid number of operands!");
710 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
711 }
712
713 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
714 assert(N == 1 && "Invalid number of operands!");
715 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
716 }
717
718 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
719 assert(N == 1 && "Invalid number of operands!");
720 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
721 }
722
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000723 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
724 assert(N == 1 && "Invalid number of operands!");
725 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
726 }
727
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
729 assert(N == 1 && "Invalid number of operands!");
730 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
731 }
732
733 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
734 assert(N == 1 && "Invalid number of operands!");
735 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
736 }
737
738 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
740 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
741 }
742
743 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
745 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
746 }
747
748 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
749 assert(N == 1 && "Invalid number of operands!");
750 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
751 }
752
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000753 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 assert(N == 1 && "Invalid number of operands!");
755 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000756 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000758
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000760 assert(N == 2 && "Invalid number of operands!");
761
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000762 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000763
764 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000765 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000766 }
767
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000768 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
769 assert(N == 2 && "Invalid number of operands!");
770
771 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
772
773 const MCExpr *Expr = getMemOff();
774 addExpr(Inst, Expr);
775 }
776
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000777 void addRegListOperands(MCInst &Inst, unsigned N) const {
778 assert(N == 1 && "Invalid number of operands!");
779
780 for (auto RegNo : getRegList())
781 Inst.addOperand(MCOperand::CreateReg(RegNo));
782 }
783
Craig Topper56c590a2014-04-29 07:58:02 +0000784 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 // As a special case until we sort out the definition of div/divu, pretend
786 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
787 if (isGPRAsmReg() && RegIdx.Index == 0)
788 return true;
789
790 return Kind == k_PhysRegister;
791 }
792 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000793 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 bool isConstantImm() const {
795 return isImm() && dyn_cast<MCConstantExpr>(getImm());
796 }
Craig Topper56c590a2014-04-29 07:58:02 +0000797 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 // Note: It's not possible to pretend that other operand kinds are tokens.
799 // The matcher emitter checks tokens first.
800 return Kind == k_Token;
801 }
Craig Topper56c590a2014-04-29 07:58:02 +0000802 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000803 bool isConstantMemOff() const {
804 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
805 }
806 template <unsigned Bits> bool isMemWithSimmOffset() const {
807 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
808 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000809 bool isMemWithGRPMM16Base() const {
810 return isMem() && getMemBase()->isMM16AsmReg();
811 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000812 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
813 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
814 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
815 }
816 bool isRegList16() const {
817 if (!isRegList())
818 return false;
819
820 int Size = RegList.List->size();
821 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
822 RegList.List->back() != Mips::RA)
823 return false;
824
825 int PrevReg = *RegList.List->begin();
826 for (int i = 1; i < Size - 1; i++) {
827 int Reg = (*(RegList.List))[i];
828 if ( Reg != PrevReg + 1)
829 return false;
830 PrevReg = Reg;
831 }
832
833 return true;
834 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000835 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 bool isLSAImm() const {
837 if (!isConstantImm())
838 return false;
839 int64_t Val = getConstantImm();
840 return 1 <= Val && Val <= 4;
841 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000842 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000843
844 StringRef getToken() const {
845 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000846 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000847 }
848
Craig Topper56c590a2014-04-29 07:58:02 +0000849 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 // As a special case until we sort out the definition of div/divu, pretend
851 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
852 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
853 RegIdx.Kind & RegKind_GPR)
854 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000855
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 assert(Kind == k_PhysRegister && "Invalid access!");
857 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000858 }
859
Jack Carterb4dbc172012-09-05 23:34:03 +0000860 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000862 return Imm.Val;
863 }
864
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 int64_t getConstantImm() const {
866 const MCExpr *Val = getImm();
867 return static_cast<const MCConstantExpr *>(Val)->getValue();
868 }
869
870 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000871 assert((Kind == k_Memory) && "Invalid access!");
872 return Mem.Base;
873 }
874
875 const MCExpr *getMemOff() const {
876 assert((Kind == k_Memory) && "Invalid access!");
877 return Mem.Off;
878 }
879
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000880 int64_t getConstantMemOff() const {
881 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
882 }
883
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000884 const SmallVectorImpl<unsigned> &getRegList() const {
885 assert((Kind == k_RegList) && "Invalid access!");
886 return *(RegList.List);
887 }
888
David Blaikie960ea3f2014-06-08 16:18:35 +0000889 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
890 MipsAsmParser &Parser) {
891 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000892 Op->Tok.Data = Str.data();
893 Op->Tok.Length = Str.size();
894 Op->StartLoc = S;
895 Op->EndLoc = S;
896 return Op;
897 }
898
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 /// Create a numeric register (e.g. $1). The exact register remains
900 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000901 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000902 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000903 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000904 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000906 }
907
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 /// Create a register that is definitely a GPR.
909 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000910 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000911 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000912 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000913 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000914 }
915
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000916 /// Create a register that is definitely a FGR.
917 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000918 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000919 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000920 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
922 }
923
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000924 /// Create a register that is definitely a HWReg.
925 /// This is typically only used for named registers such as $hwr_cpunum.
926 static std::unique_ptr<MipsOperand>
927 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
928 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
929 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
930 }
931
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 /// Create a register that is definitely an FCC.
933 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000934 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000935 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000936 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000937 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
938 }
939
940 /// Create a register that is definitely an ACC.
941 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000942 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000943 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000944 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000945 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
946 }
947
948 /// Create a register that is definitely an MSA128.
949 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000950 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000951 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000952 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000953 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
954 }
955
956 /// Create a register that is definitely an MSACtrl.
957 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000958 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000959 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000960 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000961 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
962 }
963
David Blaikie960ea3f2014-06-08 16:18:35 +0000964 static std::unique_ptr<MipsOperand>
965 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
966 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000967 Op->Imm.Val = Val;
968 Op->StartLoc = S;
969 Op->EndLoc = E;
970 return Op;
971 }
972
David Blaikie960ea3f2014-06-08 16:18:35 +0000973 static std::unique_ptr<MipsOperand>
974 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
975 SMLoc E, MipsAsmParser &Parser) {
976 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
977 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000978 Op->Mem.Off = Off;
979 Op->StartLoc = S;
980 Op->EndLoc = E;
981 return Op;
982 }
983
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000984 static std::unique_ptr<MipsOperand>
985 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
986 MipsAsmParser &Parser) {
987 assert (Regs.size() > 0 && "Empty list not allowed");
988
989 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
990 Op->RegList.List = new SmallVector<unsigned, 10>();
991 for (auto Reg : Regs)
992 Op->RegList.List->push_back(Reg);
993 Op->StartLoc = StartLoc;
994 Op->EndLoc = EndLoc;
995 return Op;
996 }
997
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000998 bool isGPRAsmReg() const {
999 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001000 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001001 bool isMM16AsmReg() const {
1002 if (!(isRegIdx() && RegIdx.Kind))
1003 return false;
1004 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1005 || RegIdx.Index == 16 || RegIdx.Index == 17);
1006 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001007 bool isMM16AsmRegZero() const {
1008 if (!(isRegIdx() && RegIdx.Kind))
1009 return false;
1010 return (RegIdx.Index == 0 ||
1011 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1012 RegIdx.Index == 17);
1013 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001014 bool isFGRAsmReg() const {
1015 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1016 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001017 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 bool isHWRegsAsmReg() const {
1019 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001020 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 bool isCCRAsmReg() const {
1022 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001023 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001025 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1026 return false;
1027 if (!AsmParser.hasEightFccRegisters())
1028 return RegIdx.Index == 0;
1029 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001030 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 bool isACCAsmReg() const {
1032 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001033 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 bool isCOP2AsmReg() const {
1035 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001036 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001037 bool isCOP3AsmReg() const {
1038 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1039 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 bool isMSA128AsmReg() const {
1041 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001042 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 bool isMSACtrlAsmReg() const {
1044 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001045 }
1046
Jack Carterb4dbc172012-09-05 23:34:03 +00001047 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001048 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001049 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001050 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001051
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001052 virtual ~MipsOperand() {
1053 switch (Kind) {
1054 case k_Immediate:
1055 break;
1056 case k_Memory:
1057 delete Mem.Base;
1058 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001059 case k_RegList:
1060 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001061 case k_PhysRegister:
1062 case k_RegisterIndex:
1063 case k_Token:
1064 break;
1065 }
1066 }
1067
Craig Topper56c590a2014-04-29 07:58:02 +00001068 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 switch (Kind) {
1070 case k_Immediate:
1071 OS << "Imm<";
1072 Imm.Val->print(OS);
1073 OS << ">";
1074 break;
1075 case k_Memory:
1076 OS << "Mem<";
1077 Mem.Base->print(OS);
1078 OS << ", ";
1079 Mem.Off->print(OS);
1080 OS << ">";
1081 break;
1082 case k_PhysRegister:
1083 OS << "PhysReg<" << PhysReg.Num << ">";
1084 break;
1085 case k_RegisterIndex:
1086 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1087 break;
1088 case k_Token:
1089 OS << Tok.Data;
1090 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001091 case k_RegList:
1092 OS << "RegList< ";
1093 for (auto Reg : (*RegList.List))
1094 OS << Reg << " ";
1095 OS << ">";
1096 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001098 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001099}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001100} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001101
Jack Carter9e65aa32013-03-22 00:05:30 +00001102namespace llvm {
1103extern const MCInstrDesc MipsInsts[];
1104}
1105static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1106 return MipsInsts[Opcode];
1107}
1108
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001109static bool hasShortDelaySlot(unsigned Opcode) {
1110 switch (Opcode) {
1111 case Mips::JALS_MM:
1112 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001113 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001114 case Mips::BGEZALS_MM:
1115 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001116 return true;
1117 default:
1118 return false;
1119 }
1120}
1121
Jack Carter9e65aa32013-03-22 00:05:30 +00001122bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001123 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001124 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001125
Jack Carter9e65aa32013-03-22 00:05:30 +00001126 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001127
1128 if (MCID.isBranch() || MCID.isCall()) {
1129 const unsigned Opcode = Inst.getOpcode();
1130 MCOperand Offset;
1131
1132 switch (Opcode) {
1133 default:
1134 break;
1135 case Mips::BEQ:
1136 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 case Mips::BEQ_MM:
1138 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001139 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001140 Offset = Inst.getOperand(2);
1141 if (!Offset.isImm())
1142 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001143 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001144 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001145 if (OffsetToAlignment(Offset.getImm(),
1146 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001147 return Error(IDLoc, "branch to misaligned address");
1148 break;
1149 case Mips::BGEZ:
1150 case Mips::BGTZ:
1151 case Mips::BLEZ:
1152 case Mips::BLTZ:
1153 case Mips::BGEZAL:
1154 case Mips::BLTZAL:
1155 case Mips::BC1F:
1156 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001157 case Mips::BGEZ_MM:
1158 case Mips::BGTZ_MM:
1159 case Mips::BLEZ_MM:
1160 case Mips::BLTZ_MM:
1161 case Mips::BGEZAL_MM:
1162 case Mips::BLTZAL_MM:
1163 case Mips::BC1F_MM:
1164 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001165 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001166 Offset = Inst.getOperand(1);
1167 if (!Offset.isImm())
1168 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001169 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001170 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001171 if (OffsetToAlignment(Offset.getImm(),
1172 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001173 return Error(IDLoc, "branch to misaligned address");
1174 break;
1175 }
1176 }
1177
Daniel Sandersa84989a2014-06-16 13:25:35 +00001178 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1179 // We still accept it but it is a normal nop.
1180 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1181 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1182 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1183 "nop instruction");
1184 }
1185
Toma Tabacu9db22db2014-09-09 10:15:38 +00001186 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001187 // If this instruction has a delay slot and .set reorder is active,
1188 // emit a NOP after it.
1189 Instructions.push_back(Inst);
1190 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001191 if (hasShortDelaySlot(Inst.getOpcode())) {
1192 NopInst.setOpcode(Mips::MOVE16_MM);
1193 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1194 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1195 } else {
1196 NopInst.setOpcode(Mips::SLL);
1197 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1198 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1199 NopInst.addOperand(MCOperand::CreateImm(0));
1200 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001201 Instructions.push_back(NopInst);
1202 return false;
1203 }
1204
Jack Carter9e65aa32013-03-22 00:05:30 +00001205 if (MCID.mayLoad() || MCID.mayStore()) {
1206 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001207 // reference or immediate we may have to expand instructions.
1208 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001209 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001210 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1211 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001212 MCOperand &Op = Inst.getOperand(i);
1213 if (Op.isImm()) {
1214 int MemOffset = Op.getImm();
1215 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001216 // Offset can't exceed 16bit value.
1217 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001218 return false;
1219 }
1220 } else if (Op.isExpr()) {
1221 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001222 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001223 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001224 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001225 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001226 // Expand symbol.
1227 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001228 return false;
1229 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001230 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001231 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001232 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001233 }
1234 }
1235 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001236 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001237 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001238
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001239 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1240 if (inMicroMipsMode()) {
1241 MCOperand Opnd;
1242 int Imm;
1243
1244 switch (Inst.getOpcode()) {
1245 default:
1246 break;
1247 case Mips::ADDIUS5_MM:
1248 Opnd = Inst.getOperand(2);
1249 if (!Opnd.isImm())
1250 return Error(IDLoc, "expected immediate operand kind");
1251 Imm = Opnd.getImm();
1252 if (Imm < -8 || Imm > 7)
1253 return Error(IDLoc, "immediate operand value out of range");
1254 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001255 case Mips::ADDIUSP_MM:
1256 Opnd = Inst.getOperand(0);
1257 if (!Opnd.isImm())
1258 return Error(IDLoc, "expected immediate operand kind");
1259 Imm = Opnd.getImm();
1260 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1261 Imm % 4 != 0)
1262 return Error(IDLoc, "immediate operand value out of range");
1263 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001264 case Mips::SLL16_MM:
1265 case Mips::SRL16_MM:
1266 Opnd = Inst.getOperand(2);
1267 if (!Opnd.isImm())
1268 return Error(IDLoc, "expected immediate operand kind");
1269 Imm = Opnd.getImm();
1270 if (Imm < 1 || Imm > 8)
1271 return Error(IDLoc, "immediate operand value out of range");
1272 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001273 case Mips::LI16_MM:
1274 Opnd = Inst.getOperand(1);
1275 if (!Opnd.isImm())
1276 return Error(IDLoc, "expected immediate operand kind");
1277 Imm = Opnd.getImm();
1278 if (Imm < -1 || Imm > 126)
1279 return Error(IDLoc, "immediate operand value out of range");
1280 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001281 case Mips::ADDIUR2_MM:
1282 Opnd = Inst.getOperand(2);
1283 if (!Opnd.isImm())
1284 return Error(IDLoc, "expected immediate operand kind");
1285 Imm = Opnd.getImm();
1286 if (!(Imm == 1 || Imm == -1 ||
1287 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1288 return Error(IDLoc, "immediate operand value out of range");
1289 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001290 case Mips::ADDIUR1SP_MM:
1291 Opnd = Inst.getOperand(1);
1292 if (!Opnd.isImm())
1293 return Error(IDLoc, "expected immediate operand kind");
1294 Imm = Opnd.getImm();
1295 if (OffsetToAlignment(Imm, 4LL))
1296 return Error(IDLoc, "misaligned immediate operand value");
1297 if (Imm < 0 || Imm > 255)
1298 return Error(IDLoc, "immediate operand value out of range");
1299 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001300 case Mips::ANDI16_MM:
1301 Opnd = Inst.getOperand(2);
1302 if (!Opnd.isImm())
1303 return Error(IDLoc, "expected immediate operand kind");
1304 Imm = Opnd.getImm();
1305 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1306 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1307 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1308 return Error(IDLoc, "immediate operand value out of range");
1309 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001310 case Mips::LBU16_MM:
1311 Opnd = Inst.getOperand(2);
1312 if (!Opnd.isImm())
1313 return Error(IDLoc, "expected immediate operand kind");
1314 Imm = Opnd.getImm();
1315 if (Imm < -1 || Imm > 14)
1316 return Error(IDLoc, "immediate operand value out of range");
1317 break;
1318 case Mips::SB16_MM:
1319 Opnd = Inst.getOperand(2);
1320 if (!Opnd.isImm())
1321 return Error(IDLoc, "expected immediate operand kind");
1322 Imm = Opnd.getImm();
1323 if (Imm < 0 || Imm > 15)
1324 return Error(IDLoc, "immediate operand value out of range");
1325 break;
1326 case Mips::LHU16_MM:
1327 case Mips::SH16_MM:
1328 Opnd = Inst.getOperand(2);
1329 if (!Opnd.isImm())
1330 return Error(IDLoc, "expected immediate operand kind");
1331 Imm = Opnd.getImm();
1332 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1333 return Error(IDLoc, "immediate operand value out of range");
1334 break;
1335 case Mips::LW16_MM:
1336 case Mips::SW16_MM:
1337 Opnd = Inst.getOperand(2);
1338 if (!Opnd.isImm())
1339 return Error(IDLoc, "expected immediate operand kind");
1340 Imm = Opnd.getImm();
1341 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1342 return Error(IDLoc, "immediate operand value out of range");
1343 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001344 }
1345 }
1346
Jack Carter9e65aa32013-03-22 00:05:30 +00001347 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001348 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001349 else
1350 Instructions.push_back(Inst);
1351
1352 return false;
1353}
1354
Jack Carter30a59822012-10-04 04:03:53 +00001355bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1356
Jack Carterd0bd6422013-04-18 00:41:53 +00001357 switch (Inst.getOpcode()) {
1358 case Mips::LoadImm32Reg:
1359 case Mips::LoadAddr32Imm:
1360 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001361 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001362 return true;
1363 default:
1364 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001365 }
1366}
Jack Carter92995f12012-10-06 00:53:28 +00001367
Matheus Almeida3813d572014-06-19 14:39:14 +00001368bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001369 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001370 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001371 default:
1372 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001373 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001374 case Mips::LoadImm32Reg:
1375 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001376 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001377 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001378 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001379 return true;
1380 }
1381 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001382 case Mips::LoadAddr32Imm:
1383 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1384 case Mips::LoadAddr32Reg:
1385 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1386 }
Jack Carter30a59822012-10-04 04:03:53 +00001387}
Jack Carter92995f12012-10-06 00:53:28 +00001388
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001389namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001390template <bool PerformShift>
1391void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001392 SmallVectorImpl<MCInst> &Instructions) {
1393 MCInst tmpInst;
1394 if (PerformShift) {
1395 tmpInst.setOpcode(Mips::DSLL);
1396 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1397 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1398 tmpInst.addOperand(MCOperand::CreateImm(16));
1399 tmpInst.setLoc(IDLoc);
1400 Instructions.push_back(tmpInst);
1401 tmpInst.clear();
1402 }
1403 tmpInst.setOpcode(Mips::ORi);
1404 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1405 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001406 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001407 tmpInst.setLoc(IDLoc);
1408 Instructions.push_back(tmpInst);
1409}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001410
1411template <int Shift, bool PerformShift>
1412void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1413 SmallVectorImpl<MCInst> &Instructions) {
1414 createShiftOr<PerformShift>(
1415 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1416 IDLoc, Instructions);
1417}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001418}
1419
Matheus Almeida3813d572014-06-19 14:39:14 +00001420bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001422 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001423 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001424 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001425 const MCOperand &RegOp = Inst.getOperand(0);
1426 assert(RegOp.isReg() && "expected register operand kind");
1427
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001428 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001429 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001430 // FIXME: gas has a special case for values that are 000...1111, which
1431 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001432 if (0 <= ImmValue && ImmValue <= 65535) {
1433 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001434 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001435 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001436 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001437 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001438 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001439 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001440 } else if (ImmValue < 0 && ImmValue >= -32768) {
1441 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001442 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001443 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001444 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001445 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001446 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001447 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001448 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1449 // For any value of j that is representable as a 32-bit integer, create
1450 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001451 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001452 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001453 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001454 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1455 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001456 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001457 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1458 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001459 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001460 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001461 return true;
1462 }
1463
1464 // <------- lo32 ------>
1465 // <------- hi32 ------>
1466 // <- hi16 -> <- lo16 ->
1467 // _________________________________
1468 // | | | |
1469 // | 16-bytes | 16-bytes | 16-bytes |
1470 // |__________|__________|__________|
1471 //
1472 // For any value of j that is representable as a 48-bit integer, create
1473 // a sequence of:
1474 // li d,j => lui d,hi16(j)
1475 // ori d,d,hi16(lo32(j))
1476 // dsll d,d,16
1477 // ori d,d,lo16(lo32(j))
1478 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001479 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001480 tmpInst.addOperand(
1481 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001482 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001483 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1484 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1485 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001486 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001487 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001488 return true;
1489 }
1490
1491 // <------- hi32 ------> <------- lo32 ------>
1492 // <- hi16 -> <- lo16 ->
1493 // ___________________________________________
1494 // | | | | |
1495 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1496 // |__________|__________|__________|__________|
1497 //
1498 // For any value of j that isn't representable as a 48-bit integer.
1499 // li d,j => lui d,hi16(j)
1500 // ori d,d,lo16(hi32(j))
1501 // dsll d,d,16
1502 // ori d,d,hi16(lo32(j))
1503 // dsll d,d,16
1504 // ori d,d,lo16(lo32(j))
1505 tmpInst.setOpcode(Mips::LUi);
1506 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1507 tmpInst.addOperand(
1508 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1509 Instructions.push_back(tmpInst);
1510 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1511 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1512 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001513 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001514 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001515}
Jack Carter92995f12012-10-06 00:53:28 +00001516
Matheus Almeida3813d572014-06-19 14:39:14 +00001517bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001518MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1519 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001520 MCInst tmpInst;
1521 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001522 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1523 "expected immediate operand kind");
1524 if (!ImmOp.isImm()) {
1525 expandLoadAddressSym(Inst, IDLoc, Instructions);
1526 return false;
1527 }
Jack Carter543fdf82012-10-09 23:29:45 +00001528 const MCOperand &SrcRegOp = Inst.getOperand(1);
1529 assert(SrcRegOp.isReg() && "expected register operand kind");
1530 const MCOperand &DstRegOp = Inst.getOperand(0);
1531 assert(DstRegOp.isReg() && "expected register operand kind");
1532 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001533 if (-32768 <= ImmValue && ImmValue <= 65535) {
1534 // For -32768 <= j <= 65535.
1535 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001536 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001537 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1538 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1539 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1540 Instructions.push_back(tmpInst);
1541 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001542 // For any other value of j that is representable as a 32-bit integer.
1543 // la d,j(s) => lui d,hi16(j)
1544 // ori d,d,lo16(j)
1545 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001546 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001547 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1548 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1549 Instructions.push_back(tmpInst);
1550 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001551 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001552 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1553 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1554 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1555 Instructions.push_back(tmpInst);
1556 tmpInst.clear();
1557 tmpInst.setOpcode(Mips::ADDu);
1558 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1559 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1560 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1561 Instructions.push_back(tmpInst);
1562 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001563 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001564}
1565
Matheus Almeida3813d572014-06-19 14:39:14 +00001566bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001567MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1568 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001569 MCInst tmpInst;
1570 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001571 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1572 "expected immediate operand kind");
1573 if (!ImmOp.isImm()) {
1574 expandLoadAddressSym(Inst, IDLoc, Instructions);
1575 return false;
1576 }
Jack Carter543fdf82012-10-09 23:29:45 +00001577 const MCOperand &RegOp = Inst.getOperand(0);
1578 assert(RegOp.isReg() && "expected register operand kind");
1579 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 if (-32768 <= ImmValue && ImmValue <= 65535) {
1581 // For -32768 <= j <= 65535.
1582 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001583 tmpInst.setOpcode(Mips::ADDiu);
1584 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001585 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001586 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1587 Instructions.push_back(tmpInst);
1588 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 // For any other value of j that is representable as a 32-bit integer.
1590 // la d,j => lui d,hi16(j)
1591 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001592 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001593 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1594 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1595 Instructions.push_back(tmpInst);
1596 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001597 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001598 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1599 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1600 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1601 Instructions.push_back(tmpInst);
1602 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001603 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001604}
1605
Toma Tabacu0d64b202014-08-14 10:29:17 +00001606void
1607MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1608 SmallVectorImpl<MCInst> &Instructions) {
1609 // FIXME: If we do have a valid at register to use, we should generate a
1610 // slightly shorter sequence here.
1611 MCInst tmpInst;
1612 int ExprOperandNo = 1;
1613 // Sometimes the assembly parser will get the immediate expression as
1614 // a $zero + an immediate.
1615 if (Inst.getNumOperands() == 3) {
1616 assert(Inst.getOperand(1).getReg() ==
1617 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1618 ExprOperandNo = 2;
1619 }
1620 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1621 assert(SymOp.isExpr() && "expected symbol operand kind");
1622 const MCOperand &RegOp = Inst.getOperand(0);
1623 unsigned RegNo = RegOp.getReg();
1624 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1625 const MCSymbolRefExpr *HiExpr =
1626 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1627 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1628 const MCSymbolRefExpr *LoExpr =
1629 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1630 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1631 if (isGP64bit()) {
1632 // If it's a 64-bit architecture, expand to:
1633 // la d,sym => lui d,highest(sym)
1634 // ori d,d,higher(sym)
1635 // dsll d,d,16
1636 // ori d,d,hi16(sym)
1637 // dsll d,d,16
1638 // ori d,d,lo16(sym)
1639 const MCSymbolRefExpr *HighestExpr =
1640 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1641 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1642 const MCSymbolRefExpr *HigherExpr =
1643 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1644 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1645
1646 tmpInst.setOpcode(Mips::LUi);
1647 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1648 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1649 Instructions.push_back(tmpInst);
1650
1651 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1652 Instructions);
1653 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1654 Instructions);
1655 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1656 Instructions);
1657 } else {
1658 // Otherwise, expand to:
1659 // la d,sym => lui d,hi16(sym)
1660 // ori d,d,lo16(sym)
1661 tmpInst.setOpcode(Mips::LUi);
1662 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1663 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1664 Instructions.push_back(tmpInst);
1665
1666 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1667 Instructions);
1668 }
1669}
1670
Jack Carter9e65aa32013-03-22 00:05:30 +00001671void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001672 SmallVectorImpl<MCInst> &Instructions,
1673 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001674 const MCSymbolRefExpr *SR;
1675 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001677 const MCExpr *ExprOffset;
1678 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001679 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001680 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1681 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001682 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001683 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1684 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001685 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001686 if (isImmOpnd) {
1687 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1688 ImmOffset = Inst.getOperand(2).getImm();
1689 LoOffset = ImmOffset & 0x0000ffff;
1690 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001691 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001692 if (LoOffset & 0x8000)
1693 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001695 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001696 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001697 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001698 // These are some of the types of expansions we perform here:
1699 // 1) lw $8, sym => lui $8, %hi(sym)
1700 // lw $8, %lo(sym)($8)
1701 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1702 // add $8, $8, $9
1703 // lw $8, %lo(offset)($9)
1704 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1705 // add $at, $at, $8
1706 // lw $8, %lo(offset)($at)
1707 // 4) sw $8, sym => lui $at, %hi(sym)
1708 // sw $8, %lo(sym)($at)
1709 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1710 // add $at, $at, $8
1711 // sw $8, %lo(offset)($at)
1712 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1713 // ldc1 $f0, %lo(sym)($at)
1714 //
1715 // For load instructions we can use the destination register as a temporary
1716 // if base and dst are different (examples 1 and 2) and if the base register
1717 // is general purpose otherwise we must use $at (example 6) and error if it's
1718 // not available. For stores we must use $at (examples 4 and 5) because we
1719 // must not clobber the source register setting up the offset.
1720 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1721 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1722 unsigned RegClassIDOp0 =
1723 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1724 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1725 (RegClassIDOp0 == Mips::GPR64RegClassID);
1726 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001727 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001728 else {
1729 int AT = getATReg(IDLoc);
1730 // At this point we need AT to perform the expansions and we exit if it is
1731 // not available.
1732 if (!AT)
1733 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001734 TmpRegNum = getReg(
1735 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001736 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001737
Jack Carter9e65aa32013-03-22 00:05:30 +00001738 TempInst.setOpcode(Mips::LUi);
1739 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1740 if (isImmOpnd)
1741 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1742 else {
1743 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001744 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1746 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1747 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001748 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001749 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001750 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001751 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001752 }
1753 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001754 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001755 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001756 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001757 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001758 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001759 TempInst.setOpcode(Mips::ADDu);
1760 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1761 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1762 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1763 Instructions.push_back(TempInst);
1764 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001765 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001766 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001767 TempInst.setOpcode(Inst.getOpcode());
1768 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1769 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1770 if (isImmOpnd)
1771 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1772 else {
1773 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001774 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1775 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1776 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001778 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001779 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001780 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001781 }
1782 }
1783 Instructions.push_back(TempInst);
1784 TempInst.clear();
1785}
1786
Matheus Almeida595fcab2014-06-11 15:05:56 +00001787unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1788 // As described by the Mips32r2 spec, the registers Rd and Rs for
1789 // jalr.hb must be different.
1790 unsigned Opcode = Inst.getOpcode();
1791
1792 if (Opcode == Mips::JALR_HB &&
1793 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1794 return Match_RequiresDifferentSrcAndDst;
1795
1796 return Match_Success;
1797}
1798
David Blaikie960ea3f2014-06-08 16:18:35 +00001799bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1800 OperandVector &Operands,
1801 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001802 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001803 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001804
Jack Carterb4dbc172012-09-05 23:34:03 +00001805 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001806 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001807 unsigned MatchResult =
1808 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001809
1810 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001811 default:
1812 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001813 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001814 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001815 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001816 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001817 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001818 return false;
1819 }
1820 case Match_MissingFeature:
1821 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1822 return true;
1823 case Match_InvalidOperand: {
1824 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001825 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001826 if (ErrorInfo >= Operands.size())
1827 return Error(IDLoc, "too few operands for instruction");
1828
David Blaikie960ea3f2014-06-08 16:18:35 +00001829 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 if (ErrorLoc == SMLoc())
1831 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001832 }
1833
1834 return Error(ErrorLoc, "invalid operand for instruction");
1835 }
1836 case Match_MnemonicFail:
1837 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001838 case Match_RequiresDifferentSrcAndDst:
1839 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001840 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001841 return true;
1842}
1843
Toma Tabacu13964452014-09-04 13:23:44 +00001844void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001845 if ((RegIndex != 0) &&
1846 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001847 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001848 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001849 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001850 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001851 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001852 }
1853}
1854
Daniel Sandersef638fe2014-10-03 15:37:37 +00001855void
1856MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1857 SMRange Range, bool ShowColors) {
1858 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001859 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001860 ShowColors);
1861}
1862
Jack Carter1ac53222013-02-20 23:11:17 +00001863int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001864 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001865
Vladimir Medic4c299852013-11-06 11:27:05 +00001866 CC = StringSwitch<unsigned>(Name)
1867 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001868 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001869 .Case("a0", 4)
1870 .Case("a1", 5)
1871 .Case("a2", 6)
1872 .Case("a3", 7)
1873 .Case("v0", 2)
1874 .Case("v1", 3)
1875 .Case("s0", 16)
1876 .Case("s1", 17)
1877 .Case("s2", 18)
1878 .Case("s3", 19)
1879 .Case("s4", 20)
1880 .Case("s5", 21)
1881 .Case("s6", 22)
1882 .Case("s7", 23)
1883 .Case("k0", 26)
1884 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001885 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001886 .Case("sp", 29)
1887 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001888 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001889 .Case("ra", 31)
1890 .Case("t0", 8)
1891 .Case("t1", 9)
1892 .Case("t2", 10)
1893 .Case("t3", 11)
1894 .Case("t4", 12)
1895 .Case("t5", 13)
1896 .Case("t6", 14)
1897 .Case("t7", 15)
1898 .Case("t8", 24)
1899 .Case("t9", 25)
1900 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001901
Toma Tabacufda445c2014-09-15 15:33:01 +00001902 if (!(isABI_N32() || isABI_N64()))
1903 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001904
Daniel Sandersef638fe2014-10-03 15:37:37 +00001905 if (12 <= CC && CC <= 15) {
1906 // Name is one of t4-t7
1907 AsmToken RegTok = getLexer().peekTok();
1908 SMRange RegRange = RegTok.getLocRange();
1909
1910 StringRef FixedName = StringSwitch<StringRef>(Name)
1911 .Case("t4", "t0")
1912 .Case("t5", "t1")
1913 .Case("t6", "t2")
1914 .Case("t7", "t3")
1915 .Default("");
1916 assert(FixedName != "" && "Register name is not one of t4-t7.");
1917
1918 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1919 "Did you mean $" + FixedName + "?", RegRange);
1920 }
1921
Toma Tabacufda445c2014-09-15 15:33:01 +00001922 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1923 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1924 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1925 if (8 <= CC && CC <= 11)
1926 CC += 4;
1927
1928 if (CC == -1)
1929 CC = StringSwitch<unsigned>(Name)
1930 .Case("a4", 8)
1931 .Case("a5", 9)
1932 .Case("a6", 10)
1933 .Case("a7", 11)
1934 .Case("kt0", 26)
1935 .Case("kt1", 27)
1936 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001937
1938 return CC;
1939}
Jack Carterd0bd6422013-04-18 00:41:53 +00001940
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001941int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1942 int CC;
1943
1944 CC = StringSwitch<unsigned>(Name)
1945 .Case("hwr_cpunum", 0)
1946 .Case("hwr_synci_step", 1)
1947 .Case("hwr_cc", 2)
1948 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001949 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001950 .Default(-1);
1951
1952 return CC;
1953}
1954
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001955int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001956
Jack Cartera63b16a2012-09-07 00:23:42 +00001957 if (Name[0] == 'f') {
1958 StringRef NumString = Name.substr(1);
1959 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001960 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001961 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001962 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001963 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001964 return IntVal;
1965 }
1966 return -1;
1967}
Jack Cartera63b16a2012-09-07 00:23:42 +00001968
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001969int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1970
1971 if (Name.startswith("fcc")) {
1972 StringRef NumString = Name.substr(3);
1973 unsigned IntVal;
1974 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001975 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001976 if (IntVal > 7) // There are only 8 fcc registers.
1977 return -1;
1978 return IntVal;
1979 }
1980 return -1;
1981}
1982
1983int MipsAsmParser::matchACRegisterName(StringRef Name) {
1984
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001985 if (Name.startswith("ac")) {
1986 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001987 unsigned IntVal;
1988 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001989 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001990 if (IntVal > 3) // There are only 3 acc registers.
1991 return -1;
1992 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001993 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001994 return -1;
1995}
Jack Carterd0bd6422013-04-18 00:41:53 +00001996
Jack Carter5dc8ac92013-09-25 23:50:44 +00001997int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1998 unsigned IntVal;
1999
2000 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2001 return -1;
2002
2003 if (IntVal > 31)
2004 return -1;
2005
2006 return IntVal;
2007}
2008
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002009int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2010 int CC;
2011
2012 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002013 .Case("msair", 0)
2014 .Case("msacsr", 1)
2015 .Case("msaaccess", 2)
2016 .Case("msasave", 3)
2017 .Case("msamodify", 4)
2018 .Case("msarequest", 5)
2019 .Case("msamap", 6)
2020 .Case("msaunmap", 7)
2021 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002022
2023 return CC;
2024}
2025
Jack Carter0b744b32012-10-04 02:29:46 +00002026bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2027 if (Reg > 31)
2028 return false;
2029
Toma Tabacu3c24b042014-09-05 15:43:21 +00002030 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002031 return true;
2032}
2033
Matheus Almeida7de68e72014-06-18 14:46:05 +00002034int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002035 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002036 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002037 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002038 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002039 return AT;
2040}
Jack Carter0b744b32012-10-04 02:29:46 +00002041
Jack Carterd0bd6422013-04-18 00:41:53 +00002042unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002043 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002044}
2045
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002046unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002047 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002048 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002049}
2050
Jack Carter873c7242013-01-12 01:03:14 +00002051int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002052 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002053 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002054 return -1;
2055
Jack Carter873c7242013-01-12 01:03:14 +00002056 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002057}
2058
Toma Tabacu13964452014-09-04 13:23:44 +00002059bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002060 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002061 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002062
Jack Carter30a59822012-10-04 04:03:53 +00002063 // Check if the current operand has a custom associated parser, if so, try to
2064 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002065 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2066 if (ResTy == MatchOperand_Success)
2067 return false;
2068 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2069 // there was a match, but an error occurred, in which case, just return that
2070 // the operand parsing failed.
2071 if (ResTy == MatchOperand_ParseFail)
2072 return true;
2073
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002074 DEBUG(dbgs() << ".. Generic Parser\n");
2075
Jack Carterb4dbc172012-09-05 23:34:03 +00002076 switch (getLexer().getKind()) {
2077 default:
2078 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2079 return true;
2080 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002082 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002083
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002084 // Almost all registers have been parsed by custom parsers. There is only
2085 // one exception to this. $zero (and it's alias $0) will reach this point
2086 // for div, divu, and similar instructions because it is not an operand
2087 // to the instruction definition but an explicit register. Special case
2088 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002089 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002090 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002091
Jack Carterd0bd6422013-04-18 00:41:53 +00002092 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002093 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002094 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002095 return true;
2096
Jack Carter873c7242013-01-12 01:03:14 +00002097 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002098 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002100 const MCExpr *Res =
2101 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002103 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002104 return false;
2105 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002106 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002107 case AsmToken::LParen:
2108 case AsmToken::Minus:
2109 case AsmToken::Plus:
2110 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002111 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002112 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002113 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002114 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002115 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002116 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002117 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002119 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002121 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002122 return true;
2123
Jack Carter873c7242013-01-12 01:03:14 +00002124 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2125
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002126 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002127 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002128 } // case AsmToken::Percent
2129 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002130 return true;
2131}
2132
Vladimir Medic4c299852013-11-06 11:27:05 +00002133const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002134 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002135 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002136 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002137 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002138 // It's a constant, evaluate reloc value.
2139 int16_t Val;
2140 switch (getVariantKind(RelocStr)) {
2141 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2142 // Get the 1st 16-bits.
2143 Val = MCE->getValue() & 0xffff;
2144 break;
2145 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2146 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2147 // 16 bits being negative.
2148 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2149 break;
2150 case MCSymbolRefExpr::VK_Mips_HIGHER:
2151 // Get the 3rd 16-bits.
2152 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2153 break;
2154 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2155 // Get the 4th 16-bits.
2156 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2157 break;
2158 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002159 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002160 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002161 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002162 }
2163
Jack Carterb5cf5902013-04-17 00:18:04 +00002164 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002165 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002166 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002167 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002169 return Res;
2170 }
2171
2172 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002173 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2174
Sasa Stankovic06c47802014-04-03 10:37:45 +00002175 // Try to create target expression.
2176 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2177 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002178
Jack Carterd0bd6422013-04-18 00:41:53 +00002179 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2180 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002181 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2182 return Res;
2183 }
2184
2185 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002186 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2187 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2188 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002189 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002191 return Expr;
2192}
2193
2194bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2195
2196 switch (Expr->getKind()) {
2197 case MCExpr::Constant:
2198 return true;
2199 case MCExpr::SymbolRef:
2200 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2201 case MCExpr::Binary:
2202 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2203 if (!isEvaluated(BE->getLHS()))
2204 return false;
2205 return isEvaluated(BE->getRHS());
2206 }
2207 case MCExpr::Unary:
2208 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002209 case MCExpr::Target:
2210 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002211 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002212 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002213}
Jack Carterd0bd6422013-04-18 00:41:53 +00002214
Jack Carterb5cf5902013-04-17 00:18:04 +00002215bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002216 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002217 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002218 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002219 if (Tok.isNot(AsmToken::Identifier))
2220 return true;
2221
2222 std::string Str = Tok.getIdentifier().str();
2223
Jack Carterd0bd6422013-04-18 00:41:53 +00002224 Parser.Lex(); // Eat the identifier.
2225 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002226 const MCExpr *IdVal;
2227 SMLoc EndLoc;
2228
2229 if (getLexer().getKind() == AsmToken::LParen) {
2230 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002231 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002232 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002233 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002234 const AsmToken &nextTok = Parser.getTok();
2235 if (nextTok.isNot(AsmToken::Identifier))
2236 return true;
2237 Str += "(%";
2238 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002239 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002240 if (getLexer().getKind() != AsmToken::LParen)
2241 return true;
2242 } else
2243 break;
2244 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002245 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002246 return true;
2247
2248 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002249 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002250
2251 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002252 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002253
Jack Carterd0bd6422013-04-18 00:41:53 +00002254 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002255 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002256}
2257
Jack Carterb4dbc172012-09-05 23:34:03 +00002258bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2259 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002260 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002261 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002262 if (ResTy == MatchOperand_Success) {
2263 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002264 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002265 StartLoc = Operand.getStartLoc();
2266 EndLoc = Operand.getEndLoc();
2267
2268 // AFAIK, we only support numeric registers and named GPR's in CFI
2269 // directives.
2270 // Don't worry about eating tokens before failing. Using an unrecognised
2271 // register is a parse error.
2272 if (Operand.isGPRAsmReg()) {
2273 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002274 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002275 }
2276
2277 return (RegNo == (unsigned)-1);
2278 }
2279
2280 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002281 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002282}
2283
Jack Carterb5cf5902013-04-17 00:18:04 +00002284bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002285 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002286 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002287 bool Result = true;
2288
2289 while (getLexer().getKind() == AsmToken::LParen)
2290 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002291
Jack Carterd0bd6422013-04-18 00:41:53 +00002292 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002293 default:
2294 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002295 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002296 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002297 case AsmToken::Integer:
2298 case AsmToken::Minus:
2299 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002300 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002301 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002302 else
2303 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002304 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002305 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002306 break;
Jack Carter873c7242013-01-12 01:03:14 +00002307 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002308 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002309 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002310 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002311}
2312
David Blaikie960ea3f2014-06-08 16:18:35 +00002313MipsAsmParser::OperandMatchResultTy
2314MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002315 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002316 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002317 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002318 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002319 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002320 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002321 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002322 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002323
Jack Carterb5cf5902013-04-17 00:18:04 +00002324 if (getLexer().getKind() == AsmToken::LParen) {
2325 Parser.Lex();
2326 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002327 }
2328
Jack Carterb5cf5902013-04-17 00:18:04 +00002329 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002330 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002331 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002332
Jack Carterd0bd6422013-04-18 00:41:53 +00002333 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002334 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002335 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2336 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002337 SMLoc E =
2338 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002339 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002340 return MatchOperand_Success;
2341 }
2342 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002343 SMLoc E =
2344 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002345
Jack Carterd0bd6422013-04-18 00:41:53 +00002346 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002347 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002348 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002349 S, E, *this);
2350 Operands.push_back(
2351 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002352 return MatchOperand_Success;
2353 }
2354 Error(Parser.getTok().getLoc(), "'(' expected");
2355 return MatchOperand_ParseFail;
2356 }
2357
Jack Carterd0bd6422013-04-18 00:41:53 +00002358 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002359 }
2360
Toma Tabacu13964452014-09-04 13:23:44 +00002361 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002362 if (Res != MatchOperand_Success)
2363 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002364
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002365 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002366 Error(Parser.getTok().getLoc(), "')' expected");
2367 return MatchOperand_ParseFail;
2368 }
2369
Jack Carter873c7242013-01-12 01:03:14 +00002370 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2371
Jack Carterd0bd6422013-04-18 00:41:53 +00002372 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002373
Craig Topper062a2ba2014-04-25 05:30:21 +00002374 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002375 IdVal = MCConstantExpr::Create(0, getContext());
2376
Jack Carterd0bd6422013-04-18 00:41:53 +00002377 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002378 std::unique_ptr<MipsOperand> op(
2379 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002380 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002381 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002382 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002383 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002384 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2385 int64_t Imm;
2386 if (IdVal->EvaluateAsAbsolute(Imm))
2387 IdVal = MCConstantExpr::Create(Imm, getContext());
2388 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2389 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2390 getContext());
2391 }
2392
David Blaikie960ea3f2014-06-08 16:18:35 +00002393 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002394 return MatchOperand_Success;
2395}
2396
David Blaikie960ea3f2014-06-08 16:18:35 +00002397bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002398 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002399 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2400 if (Sym) {
2401 SMLoc S = Parser.getTok().getLoc();
2402 const MCExpr *Expr;
2403 if (Sym->isVariable())
2404 Expr = Sym->getVariableValue();
2405 else
2406 return false;
2407 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002408 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002409 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002410 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002411 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002412 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002413 if (ResTy == MatchOperand_Success) {
2414 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002415 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002416 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002417 llvm_unreachable("Should never ParseFail");
2418 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002419 }
2420 } else if (Expr->getKind() == MCExpr::Constant) {
2421 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002422 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002423 Operands.push_back(
2424 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002425 return true;
2426 }
2427 }
2428 return false;
2429}
Jack Carterd0bd6422013-04-18 00:41:53 +00002430
Jack Carter873c7242013-01-12 01:03:14 +00002431MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002432MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002433 StringRef Identifier,
2434 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002435 int Index = matchCPURegisterName(Identifier);
2436 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002437 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002438 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2439 return MatchOperand_Success;
2440 }
2441
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002442 Index = matchHWRegsRegisterName(Identifier);
2443 if (Index != -1) {
2444 Operands.push_back(MipsOperand::createHWRegsReg(
2445 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2446 return MatchOperand_Success;
2447 }
2448
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002449 Index = matchFPURegisterName(Identifier);
2450 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002451 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002452 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2453 return MatchOperand_Success;
2454 }
2455
2456 Index = matchFCCRegisterName(Identifier);
2457 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002458 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002459 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2460 return MatchOperand_Success;
2461 }
2462
2463 Index = matchACRegisterName(Identifier);
2464 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002465 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002466 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2467 return MatchOperand_Success;
2468 }
2469
2470 Index = matchMSA128RegisterName(Identifier);
2471 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002472 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2474 return MatchOperand_Success;
2475 }
2476
2477 Index = matchMSA128CtrlRegisterName(Identifier);
2478 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002479 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2481 return MatchOperand_Success;
2482 }
2483
2484 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002485}
2486
2487MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002488MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002489 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002490 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002491
2492 if (Token.is(AsmToken::Identifier)) {
2493 DEBUG(dbgs() << ".. identifier\n");
2494 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002495 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002496 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002497 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002498 } else if (Token.is(AsmToken::Integer)) {
2499 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002500 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002501 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2502 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002503 return MatchOperand_Success;
2504 }
2505
2506 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2507
2508 return MatchOperand_NoMatch;
2509}
2510
David Blaikie960ea3f2014-06-08 16:18:35 +00002511MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002512MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002513 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002514 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002515
2516 auto Token = Parser.getTok();
2517
2518 SMLoc S = Token.getLoc();
2519
2520 if (Token.isNot(AsmToken::Dollar)) {
2521 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2522 if (Token.is(AsmToken::Identifier)) {
2523 if (searchSymbolAlias(Operands))
2524 return MatchOperand_Success;
2525 }
2526 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2527 return MatchOperand_NoMatch;
2528 }
2529 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002530
Toma Tabacu13964452014-09-04 13:23:44 +00002531 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002532 if (ResTy == MatchOperand_Success) {
2533 Parser.Lex(); // $
2534 Parser.Lex(); // identifier
2535 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002536 return ResTy;
2537}
2538
2539MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002540MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002541 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002542 switch (getLexer().getKind()) {
2543 default:
2544 return MatchOperand_NoMatch;
2545 case AsmToken::LParen:
2546 case AsmToken::Minus:
2547 case AsmToken::Plus:
2548 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002549 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002550 case AsmToken::String:
2551 break;
2552 }
2553
2554 const MCExpr *IdVal;
2555 SMLoc S = Parser.getTok().getLoc();
2556 if (getParser().parseExpression(IdVal))
2557 return MatchOperand_ParseFail;
2558
2559 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2560 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2561 return MatchOperand_Success;
2562}
2563
David Blaikie960ea3f2014-06-08 16:18:35 +00002564MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002565MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002566 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002567 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002568
2569 SMLoc S = getLexer().getLoc();
2570
2571 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002572 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002573 if (ResTy != MatchOperand_NoMatch)
2574 return ResTy;
2575
Daniel Sanders315386c2014-04-01 10:40:14 +00002576 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002577 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002578 if (ResTy != MatchOperand_NoMatch)
2579 return ResTy;
2580
Daniel Sandersffd84362014-04-01 10:41:48 +00002581 const MCExpr *Expr = nullptr;
2582 if (Parser.parseExpression(Expr)) {
2583 // We have no way of knowing if a symbol was consumed so we must ParseFail
2584 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002585 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002586 Operands.push_back(
2587 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002588 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002589}
2590
Vladimir Medic2b953d02013-10-01 09:48:56 +00002591MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002592MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002593 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002594 const MCExpr *IdVal;
2595 // If the first token is '$' we may have register operand.
2596 if (Parser.getTok().is(AsmToken::Dollar))
2597 return MatchOperand_NoMatch;
2598 SMLoc S = Parser.getTok().getLoc();
2599 if (getParser().parseExpression(IdVal))
2600 return MatchOperand_ParseFail;
2601 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002602 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002603 int64_t Val = MCE->getValue();
2604 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2605 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002606 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002607 return MatchOperand_Success;
2608}
2609
Matheus Almeida779c5932013-11-18 12:32:49 +00002610MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002611MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002612 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002613 switch (getLexer().getKind()) {
2614 default:
2615 return MatchOperand_NoMatch;
2616 case AsmToken::LParen:
2617 case AsmToken::Plus:
2618 case AsmToken::Minus:
2619 case AsmToken::Integer:
2620 break;
2621 }
2622
2623 const MCExpr *Expr;
2624 SMLoc S = Parser.getTok().getLoc();
2625
2626 if (getParser().parseExpression(Expr))
2627 return MatchOperand_ParseFail;
2628
2629 int64_t Val;
2630 if (!Expr->EvaluateAsAbsolute(Val)) {
2631 Error(S, "expected immediate value");
2632 return MatchOperand_ParseFail;
2633 }
2634
2635 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2636 // and because the CPU always adds one to the immediate field, the allowed
2637 // range becomes 1..4. We'll only check the range here and will deal
2638 // with the addition/subtraction when actually decoding/encoding
2639 // the instruction.
2640 if (Val < 1 || Val > 4) {
2641 Error(S, "immediate not in range (1..4)");
2642 return MatchOperand_ParseFail;
2643 }
2644
Jack Carter3b2c96e2014-01-22 23:31:38 +00002645 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002646 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002647 return MatchOperand_Success;
2648}
2649
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002650MipsAsmParser::OperandMatchResultTy
2651MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2652 MCAsmParser &Parser = getParser();
2653 SmallVector<unsigned, 10> Regs;
2654 unsigned RegNo;
2655 unsigned PrevReg = Mips::NoRegister;
2656 bool RegRange = false;
2657 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2658
2659 if (Parser.getTok().isNot(AsmToken::Dollar))
2660 return MatchOperand_ParseFail;
2661
2662 SMLoc S = Parser.getTok().getLoc();
2663 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2664 SMLoc E = getLexer().getLoc();
2665 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2666 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2667 if (RegRange) {
2668 // Remove last register operand because registers from register range
2669 // should be inserted first.
2670 if (RegNo == Mips::RA) {
2671 Regs.push_back(RegNo);
2672 } else {
2673 unsigned TmpReg = PrevReg + 1;
2674 while (TmpReg <= RegNo) {
2675 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2676 Error(E, "invalid register operand");
2677 return MatchOperand_ParseFail;
2678 }
2679
2680 PrevReg = TmpReg;
2681 Regs.push_back(TmpReg++);
2682 }
2683 }
2684
2685 RegRange = false;
2686 } else {
2687 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2688 (RegNo != Mips::RA)) {
2689 Error(E, "$16 or $31 expected");
2690 return MatchOperand_ParseFail;
2691 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2692 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2693 Error(E, "invalid register operand");
2694 return MatchOperand_ParseFail;
2695 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2696 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2697 Error(E, "consecutive register numbers expected");
2698 return MatchOperand_ParseFail;
2699 }
2700
2701 Regs.push_back(RegNo);
2702 }
2703
2704 if (Parser.getTok().is(AsmToken::Minus))
2705 RegRange = true;
2706
2707 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2708 !Parser.getTok().isNot(AsmToken::Comma)) {
2709 Error(E, "',' or '-' expected");
2710 return MatchOperand_ParseFail;
2711 }
2712
2713 Lex(); // Consume comma or minus
2714 if (Parser.getTok().isNot(AsmToken::Dollar))
2715 break;
2716
2717 PrevReg = RegNo;
2718 }
2719
2720 SMLoc E = Parser.getTok().getLoc();
2721 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2722 parseMemOperand(Operands);
2723 return MatchOperand_Success;
2724}
2725
Jack Carterdc1e35d2012-09-06 20:00:02 +00002726MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2727
Vladimir Medic4c299852013-11-06 11:27:05 +00002728 MCSymbolRefExpr::VariantKind VK =
2729 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2730 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2731 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2732 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2733 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2734 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2735 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2736 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2737 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2738 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2739 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2740 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2741 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2742 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2743 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2744 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2745 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2746 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002747 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2748 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2749 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2750 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2751 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2752 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002753 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2754 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002755 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002756
Matheus Almeida2852af82014-04-22 10:15:54 +00002757 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002758
Jack Carterdc1e35d2012-09-06 20:00:02 +00002759 return VK;
2760}
Jack Cartera63b16a2012-09-07 00:23:42 +00002761
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002762/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2763/// either this.
2764/// ::= '(', register, ')'
2765/// handle it before we iterate so we don't get tripped up by the lack of
2766/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002767bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002768 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002769 if (getLexer().is(AsmToken::LParen)) {
2770 Operands.push_back(
2771 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2772 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002773 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002774 SMLoc Loc = getLexer().getLoc();
2775 Parser.eatToEndOfStatement();
2776 return Error(Loc, "unexpected token in argument list");
2777 }
2778 if (Parser.getTok().isNot(AsmToken::RParen)) {
2779 SMLoc Loc = getLexer().getLoc();
2780 Parser.eatToEndOfStatement();
2781 return Error(Loc, "unexpected token, expected ')'");
2782 }
2783 Operands.push_back(
2784 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2785 Parser.Lex();
2786 }
2787 return false;
2788}
2789
2790/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2791/// either one of these.
2792/// ::= '[', register, ']'
2793/// ::= '[', integer, ']'
2794/// handle it before we iterate so we don't get tripped up by the lack of
2795/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002796bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002797 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002798 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002799 if (getLexer().is(AsmToken::LBrac)) {
2800 Operands.push_back(
2801 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2802 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002803 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002804 SMLoc Loc = getLexer().getLoc();
2805 Parser.eatToEndOfStatement();
2806 return Error(Loc, "unexpected token in argument list");
2807 }
2808 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2809 SMLoc Loc = getLexer().getLoc();
2810 Parser.eatToEndOfStatement();
2811 return Error(Loc, "unexpected token, expected ']'");
2812 }
2813 Operands.push_back(
2814 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2815 Parser.Lex();
2816 }
2817 return false;
2818}
2819
David Blaikie960ea3f2014-06-08 16:18:35 +00002820bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2821 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002822 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002823 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002824
2825 // We have reached first instruction, module directive are now forbidden.
2826 getTargetStreamer().forbidModuleDirective();
2827
Vladimir Medic74593e62013-07-17 15:00:42 +00002828 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002829 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002830 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002831 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002832 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002833 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002835
2836 // Read the remaining operands.
2837 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2838 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002839 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002840 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002841 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002842 return Error(Loc, "unexpected token in argument list");
2843 }
Toma Tabacu13964452014-09-04 13:23:44 +00002844 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845 return true;
2846 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002847
Jack Carterd0bd6422013-04-18 00:41:53 +00002848 while (getLexer().is(AsmToken::Comma)) {
2849 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002850 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002851 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002852 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002853 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002854 return Error(Loc, "unexpected token in argument list");
2855 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002856 // Parse bracket and parenthesis suffixes before we iterate
2857 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002858 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002859 return true;
2860 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002861 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002862 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002863 }
2864 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002865 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2866 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002867 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002868 return Error(Loc, "unexpected token in argument list");
2869 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002870 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002871 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002872}
2873
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002874bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002875 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002876 SMLoc Loc = getLexer().getLoc();
2877 Parser.eatToEndOfStatement();
2878 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002879}
2880
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002881bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002882 return Error(Loc, ErrorMsg);
2883}
2884
Jack Carter0b744b32012-10-04 02:29:46 +00002885bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002886 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002887 // Line should look like: ".set noat".
2888 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002889 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002890 // eat noat
2891 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002892 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002893 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002894 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002895 return false;
2896 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002897 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002898 return false;
2899}
Jack Carterd0bd6422013-04-18 00:41:53 +00002900
Jack Carter0b744b32012-10-04 02:29:46 +00002901bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002902 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002903 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002904 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002905 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002906 getParser().Lex();
2907 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002908 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002909 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002910 return false;
2911 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002912 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002913 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002914 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002915 return false;
2916 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002917 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002918 const AsmToken &Reg = Parser.getTok();
2919 if (Reg.is(AsmToken::Identifier)) {
2920 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2921 } else if (Reg.is(AsmToken::Integer)) {
2922 AtRegNo = Reg.getIntVal();
2923 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002924 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002925 return false;
2926 }
Jack Carter1ac53222013-02-20 23:11:17 +00002927
Daniel Sanders71a89d922014-03-25 13:01:06 +00002928 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002929 reportParseError("unexpected token in statement");
2930 return false;
2931 }
2932
Toma Tabacu9db22db2014-09-09 10:15:38 +00002933 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002934 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002935 return false;
2936 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002937 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002938
2939 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002940 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002941 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002942 }
2943 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002944 return false;
2945 } else {
2946 reportParseError("unexpected token in statement");
2947 return false;
2948 }
2949}
2950
2951bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002952 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002953 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002954 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002955 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002956 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002957 return false;
2958 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002959 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002960 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002961 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002962 return false;
2963}
2964
2965bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002966 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002967 Parser.Lex();
2968 // If this is not the end of the statement, report an error.
2969 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002970 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002971 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002972 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002973 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002974 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002975 Parser.Lex(); // Consume the EndOfStatement.
2976 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002977}
2978
2979bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002980 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002981 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002982 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002983 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002984 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002985 return false;
2986 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002987 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002988 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002989 return false;
2990}
2991
2992bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002993 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002994 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002995 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002996 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002997 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002998 return false;
2999 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003000 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003001 reportParseError("`noreorder' must be set before `nomacro'");
3002 return false;
3003 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003004 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003005 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003006 return false;
3007}
Jack Carterd76b2372013-03-21 21:44:16 +00003008
Daniel Sanders44934432014-08-07 12:03:36 +00003009bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003010 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003011 Parser.Lex();
3012
3013 // If this is not the end of the statement, report an error.
3014 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003015 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003016
3017 setFeatureBits(Mips::FeatureMSA, "msa");
3018 getTargetStreamer().emitDirectiveSetMsa();
3019 return false;
3020}
3021
3022bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003023 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003024 Parser.Lex();
3025
3026 // If this is not the end of the statement, report an error.
3027 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003028 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003029
3030 clearFeatureBits(Mips::FeatureMSA, "msa");
3031 getTargetStreamer().emitDirectiveSetNoMsa();
3032 return false;
3033}
3034
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003035bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003036 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003037 Parser.Lex(); // Eat "nodsp".
3038
3039 // If this is not the end of the statement, report an error.
3040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3041 reportParseError("unexpected token, expected end of statement");
3042 return false;
3043 }
3044
3045 clearFeatureBits(Mips::FeatureDSP, "dsp");
3046 getTargetStreamer().emitDirectiveSetNoDsp();
3047 return false;
3048}
3049
Toma Tabacucc2502d2014-11-04 17:18:07 +00003050bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003051 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003052 Parser.Lex(); // Eat "mips16".
3053
Jack Carter39536722014-01-22 23:08:42 +00003054 // If this is not the end of the statement, report an error.
3055 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003056 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003057 return false;
3058 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003059
3060 setFeatureBits(Mips::FeatureMips16, "mips16");
3061 getTargetStreamer().emitDirectiveSetMips16();
3062 Parser.Lex(); // Consume the EndOfStatement.
3063 return false;
3064}
3065
3066bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003067 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003068 Parser.Lex(); // Eat "nomips16".
3069
3070 // If this is not the end of the statement, report an error.
3071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3072 reportParseError("unexpected token, expected end of statement");
3073 return false;
3074 }
3075
3076 clearFeatureBits(Mips::FeatureMips16, "mips16");
3077 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003078 Parser.Lex(); // Consume the EndOfStatement.
3079 return false;
3080}
3081
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003082bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003083 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003084 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003085 // Line can be: .set fp=32
3086 // .set fp=xx
3087 // .set fp=64
3088 Parser.Lex(); // Eat fp token
3089 AsmToken Tok = Parser.getTok();
3090 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003091 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003092 return false;
3093 }
3094 Parser.Lex(); // Eat '=' token.
3095 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003096
3097 if (!parseFpABIValue(FpAbiVal, ".set"))
3098 return false;
3099
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003100 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003101 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003102 return false;
3103 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003104 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003105 Parser.Lex(); // Consume the EndOfStatement.
3106 return false;
3107}
3108
Toma Tabacu9db22db2014-09-09 10:15:38 +00003109bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003110 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003111 SMLoc Loc = getLexer().getLoc();
3112
3113 Parser.Lex();
3114 if (getLexer().isNot(AsmToken::EndOfStatement))
3115 return reportParseError("unexpected token, expected end of statement");
3116
3117 // Always keep an element on the options "stack" to prevent the user
3118 // from changing the initial options. This is how we remember them.
3119 if (AssemblerOptions.size() == 2)
3120 return reportParseError(Loc, ".set pop with no .set push");
3121
3122 AssemblerOptions.pop_back();
3123 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3124
3125 getTargetStreamer().emitDirectiveSetPop();
3126 return false;
3127}
3128
3129bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003130 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003131 Parser.Lex();
3132 if (getLexer().isNot(AsmToken::EndOfStatement))
3133 return reportParseError("unexpected token, expected end of statement");
3134
3135 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003136 AssemblerOptions.push_back(
3137 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003138
3139 getTargetStreamer().emitDirectiveSetPush();
3140 return false;
3141}
3142
Jack Carterd76b2372013-03-21 21:44:16 +00003143bool MipsAsmParser::parseSetAssignment() {
3144 StringRef Name;
3145 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003146 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003147
3148 if (Parser.parseIdentifier(Name))
3149 reportParseError("expected identifier after .set");
3150
3151 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003152 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003153 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003154
Jack Carter3b2c96e2014-01-22 23:31:38 +00003155 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003156 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003157
Jack Carterd0bd6422013-04-18 00:41:53 +00003158 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003159 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003160 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003161 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003162 Sym = getContext().GetOrCreateSymbol(Name);
3163 Sym->setVariableValue(Value);
3164
3165 return false;
3166}
Jack Carterd0bd6422013-04-18 00:41:53 +00003167
Toma Tabacu26647792014-09-09 12:52:14 +00003168bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003169 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003170 Parser.Lex();
3171 if (getLexer().isNot(AsmToken::EndOfStatement))
3172 return reportParseError("unexpected token, expected end of statement");
3173
3174 // Reset assembler options to their initial values.
3175 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3176 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3177
3178 getTargetStreamer().emitDirectiveSetMips0();
3179 return false;
3180}
3181
Toma Tabacu85618b32014-08-19 14:22:52 +00003182bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003183 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003184 Parser.Lex();
3185 if (getLexer().isNot(AsmToken::Equal))
3186 return reportParseError("unexpected token, expected equals sign");
3187
3188 Parser.Lex();
3189 StringRef Arch;
3190 if (Parser.parseIdentifier(Arch))
3191 return reportParseError("expected arch identifier");
3192
3193 StringRef ArchFeatureName =
3194 StringSwitch<StringRef>(Arch)
3195 .Case("mips1", "mips1")
3196 .Case("mips2", "mips2")
3197 .Case("mips3", "mips3")
3198 .Case("mips4", "mips4")
3199 .Case("mips5", "mips5")
3200 .Case("mips32", "mips32")
3201 .Case("mips32r2", "mips32r2")
3202 .Case("mips32r6", "mips32r6")
3203 .Case("mips64", "mips64")
3204 .Case("mips64r2", "mips64r2")
3205 .Case("mips64r6", "mips64r6")
3206 .Case("cnmips", "cnmips")
3207 .Case("r4000", "mips3") // This is an implementation of Mips3.
3208 .Default("");
3209
3210 if (ArchFeatureName.empty())
3211 return reportParseError("unsupported architecture");
3212
3213 selectArch(ArchFeatureName);
3214 getTargetStreamer().emitDirectiveSetArch(Arch);
3215 return false;
3216}
3217
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003218bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003219 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003220 Parser.Lex();
3221 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003222 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003223
Matheus Almeida2852af82014-04-22 10:15:54 +00003224 switch (Feature) {
3225 default:
3226 llvm_unreachable("Unimplemented feature");
3227 case Mips::FeatureDSP:
3228 setFeatureBits(Mips::FeatureDSP, "dsp");
3229 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003230 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003231 case Mips::FeatureMicroMips:
3232 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003233 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003234 case Mips::FeatureMips1:
3235 selectArch("mips1");
3236 getTargetStreamer().emitDirectiveSetMips1();
3237 break;
3238 case Mips::FeatureMips2:
3239 selectArch("mips2");
3240 getTargetStreamer().emitDirectiveSetMips2();
3241 break;
3242 case Mips::FeatureMips3:
3243 selectArch("mips3");
3244 getTargetStreamer().emitDirectiveSetMips3();
3245 break;
3246 case Mips::FeatureMips4:
3247 selectArch("mips4");
3248 getTargetStreamer().emitDirectiveSetMips4();
3249 break;
3250 case Mips::FeatureMips5:
3251 selectArch("mips5");
3252 getTargetStreamer().emitDirectiveSetMips5();
3253 break;
3254 case Mips::FeatureMips32:
3255 selectArch("mips32");
3256 getTargetStreamer().emitDirectiveSetMips32();
3257 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003258 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003259 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003260 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003261 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003262 case Mips::FeatureMips32r6:
3263 selectArch("mips32r6");
3264 getTargetStreamer().emitDirectiveSetMips32R6();
3265 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003266 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003267 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003268 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003269 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003270 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003271 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003272 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003273 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003274 case Mips::FeatureMips64r6:
3275 selectArch("mips64r6");
3276 getTargetStreamer().emitDirectiveSetMips64R6();
3277 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003278 }
3279 return false;
3280}
3281
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003282bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003283 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003284 if (getLexer().isNot(AsmToken::Comma)) {
3285 SMLoc Loc = getLexer().getLoc();
3286 Parser.eatToEndOfStatement();
3287 return Error(Loc, ErrorStr);
3288 }
3289
Matheus Almeida2852af82014-04-22 10:15:54 +00003290 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003291 return true;
3292}
3293
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003294bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003295 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003296 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003297
Toma Tabacudde4c462014-11-06 10:02:45 +00003298 if (inMips16Mode()) {
3299 reportParseError(".cpload is not supported in Mips16 mode");
3300 return false;
3301 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003302
David Blaikie960ea3f2014-06-08 16:18:35 +00003303 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003304 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003305 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3306 reportParseError("expected register containing function address");
3307 return false;
3308 }
3309
David Blaikie960ea3f2014-06-08 16:18:35 +00003310 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3311 if (!RegOpnd.isGPRAsmReg()) {
3312 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003313 return false;
3314 }
3315
Toma Tabacudde4c462014-11-06 10:02:45 +00003316 // If this is not the end of the statement, report an error.
3317 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3318 reportParseError("unexpected token, expected end of statement");
3319 return false;
3320 }
3321
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003322 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003323 return false;
3324}
3325
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003326bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003327 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003328 unsigned FuncReg;
3329 unsigned Save;
3330 bool SaveIsReg = true;
3331
Matheus Almeida7e815762014-06-18 13:08:59 +00003332 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003333 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003334 if (ResTy == MatchOperand_NoMatch) {
3335 reportParseError("expected register containing function address");
3336 Parser.eatToEndOfStatement();
3337 return false;
3338 }
3339
3340 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3341 if (!FuncRegOpnd.isGPRAsmReg()) {
3342 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3343 Parser.eatToEndOfStatement();
3344 return false;
3345 }
3346
3347 FuncReg = FuncRegOpnd.getGPR32Reg();
3348 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003349
Toma Tabacu65f10572014-09-16 15:00:52 +00003350 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003351 return true;
3352
Toma Tabacu13964452014-09-04 13:23:44 +00003353 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003354 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003355 const AsmToken &Tok = Parser.getTok();
3356 if (Tok.is(AsmToken::Integer)) {
3357 Save = Tok.getIntVal();
3358 SaveIsReg = false;
3359 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003360 } else {
3361 reportParseError("expected save register or stack offset");
3362 Parser.eatToEndOfStatement();
3363 return false;
3364 }
3365 } else {
3366 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3367 if (!SaveOpnd.isGPRAsmReg()) {
3368 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3369 Parser.eatToEndOfStatement();
3370 return false;
3371 }
3372 Save = SaveOpnd.getGPR32Reg();
3373 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003374
Toma Tabacu65f10572014-09-16 15:00:52 +00003375 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003376 return true;
3377
3378 StringRef Name;
3379 if (Parser.parseIdentifier(Name))
3380 reportParseError("expected identifier");
3381 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003382
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003383 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003384 return false;
3385}
3386
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003387bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003388 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003389 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3390 const AsmToken &Tok = Parser.getTok();
3391
3392 if (Tok.getString() == "2008") {
3393 Parser.Lex();
3394 getTargetStreamer().emitDirectiveNaN2008();
3395 return false;
3396 } else if (Tok.getString() == "legacy") {
3397 Parser.Lex();
3398 getTargetStreamer().emitDirectiveNaNLegacy();
3399 return false;
3400 }
3401 }
3402 // If we don't recognize the option passed to the .nan
3403 // directive (e.g. no option or unknown option), emit an error.
3404 reportParseError("invalid option in .nan directive");
3405 return false;
3406}
3407
Jack Carter0b744b32012-10-04 02:29:46 +00003408bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003409 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003410 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003411 const AsmToken &Tok = Parser.getTok();
3412
3413 if (Tok.getString() == "noat") {
3414 return parseSetNoAtDirective();
3415 } else if (Tok.getString() == "at") {
3416 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003417 } else if (Tok.getString() == "arch") {
3418 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003419 } else if (Tok.getString() == "fp") {
3420 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003421 } else if (Tok.getString() == "pop") {
3422 return parseSetPopDirective();
3423 } else if (Tok.getString() == "push") {
3424 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003425 } else if (Tok.getString() == "reorder") {
3426 return parseSetReorderDirective();
3427 } else if (Tok.getString() == "noreorder") {
3428 return parseSetNoReorderDirective();
3429 } else if (Tok.getString() == "macro") {
3430 return parseSetMacroDirective();
3431 } else if (Tok.getString() == "nomacro") {
3432 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003433 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003434 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003435 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003436 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003437 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003438 getTargetStreamer().emitDirectiveSetNoMicroMips();
3439 Parser.eatToEndOfStatement();
3440 return false;
3441 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003442 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003443 } else if (Tok.getString() == "mips0") {
3444 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003445 } else if (Tok.getString() == "mips1") {
3446 return parseSetFeature(Mips::FeatureMips1);
3447 } else if (Tok.getString() == "mips2") {
3448 return parseSetFeature(Mips::FeatureMips2);
3449 } else if (Tok.getString() == "mips3") {
3450 return parseSetFeature(Mips::FeatureMips3);
3451 } else if (Tok.getString() == "mips4") {
3452 return parseSetFeature(Mips::FeatureMips4);
3453 } else if (Tok.getString() == "mips5") {
3454 return parseSetFeature(Mips::FeatureMips5);
3455 } else if (Tok.getString() == "mips32") {
3456 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003457 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003458 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003459 } else if (Tok.getString() == "mips32r6") {
3460 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003461 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003462 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003463 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003464 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003465 } else if (Tok.getString() == "mips64r6") {
3466 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003467 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003468 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003469 } else if (Tok.getString() == "nodsp") {
3470 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003471 } else if (Tok.getString() == "msa") {
3472 return parseSetMsaDirective();
3473 } else if (Tok.getString() == "nomsa") {
3474 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003475 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003476 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003477 parseSetAssignment();
3478 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003479 }
Jack Carter07c818d2013-01-25 01:31:34 +00003480
Jack Carter0b744b32012-10-04 02:29:46 +00003481 return true;
3482}
3483
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003484/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003485/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003486bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003487 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003488 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3489 for (;;) {
3490 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003491 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003492 return true;
3493
3494 getParser().getStreamer().EmitValue(Value, Size);
3495
3496 if (getLexer().is(AsmToken::EndOfStatement))
3497 break;
3498
Jack Carter07c818d2013-01-25 01:31:34 +00003499 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003500 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003501 Parser.Lex();
3502 }
3503 }
3504
3505 Parser.Lex();
3506 return false;
3507}
3508
Vladimir Medic4c299852013-11-06 11:27:05 +00003509/// parseDirectiveGpWord
3510/// ::= .gpword local_sym
3511bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003512 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003513 const MCExpr *Value;
3514 // EmitGPRel32Value requires an expression, so we are using base class
3515 // method to evaluate the expression.
3516 if (getParser().parseExpression(Value))
3517 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003518 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003519
Vladimir Medice10c1122013-11-13 13:18:04 +00003520 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003521 return Error(getLexer().getLoc(),
3522 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003523 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003524 return false;
3525}
3526
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003527/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003528/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003529bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003530 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003531 const MCExpr *Value;
3532 // EmitGPRel64Value requires an expression, so we are using base class
3533 // method to evaluate the expression.
3534 if (getParser().parseExpression(Value))
3535 return true;
3536 getParser().getStreamer().EmitGPRel64Value(Value);
3537
3538 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003539 return Error(getLexer().getLoc(),
3540 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003541 Parser.Lex(); // Eat EndOfStatement token.
3542 return false;
3543}
3544
Jack Carter0cd3c192014-01-06 23:27:31 +00003545bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003546 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003547 // Get the option token.
3548 AsmToken Tok = Parser.getTok();
3549 // At the moment only identifiers are supported.
3550 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003551 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003552 Parser.eatToEndOfStatement();
3553 return false;
3554 }
3555
3556 StringRef Option = Tok.getIdentifier();
3557
3558 if (Option == "pic0") {
3559 getTargetStreamer().emitDirectiveOptionPic0();
3560 Parser.Lex();
3561 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3562 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003563 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003564 Parser.eatToEndOfStatement();
3565 }
3566 return false;
3567 }
3568
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003569 if (Option == "pic2") {
3570 getTargetStreamer().emitDirectiveOptionPic2();
3571 Parser.Lex();
3572 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3573 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003574 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003575 Parser.eatToEndOfStatement();
3576 }
3577 return false;
3578 }
3579
Jack Carter0cd3c192014-01-06 23:27:31 +00003580 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003581 Warning(Parser.getTok().getLoc(),
3582 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003583 Parser.eatToEndOfStatement();
3584 return false;
3585}
3586
Daniel Sanders7e527422014-07-10 13:38:23 +00003587/// parseDirectiveModule
3588/// ::= .module oddspreg
3589/// ::= .module nooddspreg
3590/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003591bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003592 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003593 MCAsmLexer &Lexer = getLexer();
3594 SMLoc L = Lexer.getLoc();
3595
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003596 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003597 // TODO : get a better message.
3598 reportParseError(".module directive must appear before any code");
3599 return false;
3600 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003601
3602 if (Lexer.is(AsmToken::Identifier)) {
3603 StringRef Option = Parser.getTok().getString();
3604 Parser.Lex();
3605
3606 if (Option == "oddspreg") {
3607 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3608 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3609
3610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003611 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003612 return false;
3613 }
3614
3615 return false;
3616 } else if (Option == "nooddspreg") {
3617 if (!isABI_O32()) {
3618 Error(L, "'.module nooddspreg' requires the O32 ABI");
3619 return false;
3620 }
3621
3622 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3623 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3624
3625 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003626 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003627 return false;
3628 }
3629
3630 return false;
3631 } else if (Option == "fp") {
3632 return parseDirectiveModuleFP();
3633 }
3634
3635 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003636 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003637
3638 return false;
3639}
3640
3641/// parseDirectiveModuleFP
3642/// ::= =32
3643/// ::= =xx
3644/// ::= =64
3645bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003646 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003647 MCAsmLexer &Lexer = getLexer();
3648
3649 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003650 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003651 return false;
3652 }
3653 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003654
Daniel Sanders7e527422014-07-10 13:38:23 +00003655 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003656 if (!parseFpABIValue(FpABI, ".module"))
3657 return false;
3658
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003660 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003661 return false;
3662 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003663
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003664 // Emit appropriate flags.
3665 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003666 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003667 return false;
3668}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003669
Daniel Sanders7e527422014-07-10 13:38:23 +00003670bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003671 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003672 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003673 MCAsmLexer &Lexer = getLexer();
3674
3675 if (Lexer.is(AsmToken::Identifier)) {
3676 StringRef Value = Parser.getTok().getString();
3677 Parser.Lex();
3678
3679 if (Value != "xx") {
3680 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3681 return false;
3682 }
3683
3684 if (!isABI_O32()) {
3685 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3686 return false;
3687 }
3688
Daniel Sanders7e527422014-07-10 13:38:23 +00003689 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003690 return true;
3691 }
3692
3693 if (Lexer.is(AsmToken::Integer)) {
3694 unsigned Value = Parser.getTok().getIntVal();
3695 Parser.Lex();
3696
3697 if (Value != 32 && Value != 64) {
3698 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3699 return false;
3700 }
3701
3702 if (Value == 32) {
3703 if (!isABI_O32()) {
3704 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3705 return false;
3706 }
3707
Daniel Sanders7e527422014-07-10 13:38:23 +00003708 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3709 } else
3710 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003711
Daniel Sanders7e527422014-07-10 13:38:23 +00003712 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003713 }
3714
3715 return false;
3716}
3717
Jack Carter0b744b32012-10-04 02:29:46 +00003718bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003719 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003720 StringRef IDVal = DirectiveID.getString();
3721
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003722 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003723 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003724 if (IDVal == ".dword") {
3725 parseDataDirective(8, DirectiveID.getLoc());
3726 return false;
3727 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003728 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003729 StringRef SymbolName;
3730
3731 if (Parser.parseIdentifier(SymbolName)) {
3732 reportParseError("expected identifier after .ent");
3733 return false;
3734 }
3735
3736 // There's an undocumented extension that allows an integer to
3737 // follow the name of the procedure which AFAICS is ignored by GAS.
3738 // Example: .ent foo,2
3739 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3740 if (getLexer().isNot(AsmToken::Comma)) {
3741 // Even though we accept this undocumented extension for compatibility
3742 // reasons, the additional integer argument does not actually change
3743 // the behaviour of the '.ent' directive, so we would like to discourage
3744 // its use. We do this by not referring to the extended version in
3745 // error messages which are not directly related to its use.
3746 reportParseError("unexpected token, expected end of statement");
3747 return false;
3748 }
3749 Parser.Lex(); // Eat the comma.
3750 const MCExpr *DummyNumber;
3751 int64_t DummyNumberVal;
3752 // If the user was explicitly trying to use the extended version,
3753 // we still give helpful extension-related error messages.
3754 if (Parser.parseExpression(DummyNumber)) {
3755 reportParseError("expected number after comma");
3756 return false;
3757 }
3758 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3759 reportParseError("expected an absolute expression after comma");
3760 return false;
3761 }
3762 }
3763
3764 // If this is not the end of the statement, report an error.
3765 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3766 reportParseError("unexpected token, expected end of statement");
3767 return false;
3768 }
3769
3770 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3771
3772 getTargetStreamer().emitDirectiveEnt(*Sym);
3773 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003774 return false;
3775 }
3776
Jack Carter07c818d2013-01-25 01:31:34 +00003777 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003778 StringRef SymbolName;
3779
3780 if (Parser.parseIdentifier(SymbolName)) {
3781 reportParseError("expected identifier after .end");
3782 return false;
3783 }
3784
3785 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3786 reportParseError("unexpected token, expected end of statement");
3787 return false;
3788 }
3789
3790 if (CurrentFn == nullptr) {
3791 reportParseError(".end used without .ent");
3792 return false;
3793 }
3794
3795 if ((SymbolName != CurrentFn->getName())) {
3796 reportParseError(".end symbol does not match .ent symbol");
3797 return false;
3798 }
3799
3800 getTargetStreamer().emitDirectiveEnd(SymbolName);
3801 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003802 return false;
3803 }
3804
Jack Carter07c818d2013-01-25 01:31:34 +00003805 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003806 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3807 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003808 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003809 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3810 reportParseError("expected stack register");
3811 return false;
3812 }
3813
3814 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3815 if (!StackRegOpnd.isGPRAsmReg()) {
3816 reportParseError(StackRegOpnd.getStartLoc(),
3817 "expected general purpose register");
3818 return false;
3819 }
3820 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3821
3822 if (Parser.getTok().is(AsmToken::Comma))
3823 Parser.Lex();
3824 else {
3825 reportParseError("unexpected token, expected comma");
3826 return false;
3827 }
3828
3829 // Parse the frame size.
3830 const MCExpr *FrameSize;
3831 int64_t FrameSizeVal;
3832
3833 if (Parser.parseExpression(FrameSize)) {
3834 reportParseError("expected frame size value");
3835 return false;
3836 }
3837
3838 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3839 reportParseError("frame size not an absolute expression");
3840 return false;
3841 }
3842
3843 if (Parser.getTok().is(AsmToken::Comma))
3844 Parser.Lex();
3845 else {
3846 reportParseError("unexpected token, expected comma");
3847 return false;
3848 }
3849
3850 // Parse the return register.
3851 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003852 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003853 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3854 reportParseError("expected return register");
3855 return false;
3856 }
3857
3858 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3859 if (!ReturnRegOpnd.isGPRAsmReg()) {
3860 reportParseError(ReturnRegOpnd.getStartLoc(),
3861 "expected general purpose register");
3862 return false;
3863 }
3864
3865 // If this is not the end of the statement, report an error.
3866 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3867 reportParseError("unexpected token, expected end of statement");
3868 return false;
3869 }
3870
3871 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3872 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003873 return false;
3874 }
3875
Jack Carter07c818d2013-01-25 01:31:34 +00003876 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003877 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003878 }
3879
Daniel Sandersd97a6342014-08-13 10:07:34 +00003880 if (IDVal == ".mask" || IDVal == ".fmask") {
3881 // .mask bitmask, frame_offset
3882 // bitmask: One bit for each register used.
3883 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3884 // first register is expected to be saved.
3885 // Examples:
3886 // .mask 0x80000000, -4
3887 // .fmask 0x80000000, -4
3888 //
Jack Carterbe332172012-09-07 00:48:02 +00003889
Daniel Sandersd97a6342014-08-13 10:07:34 +00003890 // Parse the bitmask
3891 const MCExpr *BitMask;
3892 int64_t BitMaskVal;
3893
3894 if (Parser.parseExpression(BitMask)) {
3895 reportParseError("expected bitmask value");
3896 return false;
3897 }
3898
3899 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3900 reportParseError("bitmask not an absolute expression");
3901 return false;
3902 }
3903
3904 if (Parser.getTok().is(AsmToken::Comma))
3905 Parser.Lex();
3906 else {
3907 reportParseError("unexpected token, expected comma");
3908 return false;
3909 }
3910
3911 // Parse the frame_offset
3912 const MCExpr *FrameOffset;
3913 int64_t FrameOffsetVal;
3914
3915 if (Parser.parseExpression(FrameOffset)) {
3916 reportParseError("expected frame offset value");
3917 return false;
3918 }
3919
3920 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3921 reportParseError("frame offset not an absolute expression");
3922 return false;
3923 }
3924
3925 // If this is not the end of the statement, report an error.
3926 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3927 reportParseError("unexpected token, expected end of statement");
3928 return false;
3929 }
3930
3931 if (IDVal == ".mask")
3932 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3933 else
3934 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003935 return false;
3936 }
3937
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003938 if (IDVal == ".nan")
3939 return parseDirectiveNaN();
3940
Jack Carter07c818d2013-01-25 01:31:34 +00003941 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003942 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003943 return false;
3944 }
3945
Rafael Espindolab59fb732014-03-28 18:50:26 +00003946 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003947 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003948 return false;
3949 }
3950
Jack Carter07c818d2013-01-25 01:31:34 +00003951 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003952 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003953 return false;
3954 }
3955
Jack Carter0cd3c192014-01-06 23:27:31 +00003956 if (IDVal == ".option")
3957 return parseDirectiveOption();
3958
3959 if (IDVal == ".abicalls") {
3960 getTargetStreamer().emitDirectiveAbiCalls();
3961 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003962 Error(Parser.getTok().getLoc(),
3963 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003964 // Clear line
3965 Parser.eatToEndOfStatement();
3966 }
3967 return false;
3968 }
3969
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003970 if (IDVal == ".cpsetup")
3971 return parseDirectiveCPSetup();
3972
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003973 if (IDVal == ".module")
3974 return parseDirectiveModule();
3975
Rafael Espindola870c4e92012-01-11 03:56:41 +00003976 return true;
3977}
3978
Rafael Espindola870c4e92012-01-11 03:56:41 +00003979extern "C" void LLVMInitializeMipsAsmParser() {
3980 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3981 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3982 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3983 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3984}
Jack Carterb4dbc172012-09-05 23:34:03 +00003985
3986#define GET_REGISTER_MATCHER
3987#define GET_MATCHER_IMPLEMENTATION
3988#include "MipsGenAsmMatcher.inc"