blob: f458b5bf520fe363ef5eb81f0a4e4763e60293b0 [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 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000812 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 bool isLSAImm() const {
814 if (!isConstantImm())
815 return false;
816 int64_t Val = getConstantImm();
817 return 1 <= Val && Val <= 4;
818 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000819 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000820
821 StringRef getToken() const {
822 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000823 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824 }
825
Craig Topper56c590a2014-04-29 07:58:02 +0000826 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 // As a special case until we sort out the definition of div/divu, pretend
828 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
829 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
830 RegIdx.Kind & RegKind_GPR)
831 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000832
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 assert(Kind == k_PhysRegister && "Invalid access!");
834 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000835 }
836
Jack Carterb4dbc172012-09-05 23:34:03 +0000837 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000838 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000839 return Imm.Val;
840 }
841
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 int64_t getConstantImm() const {
843 const MCExpr *Val = getImm();
844 return static_cast<const MCConstantExpr *>(Val)->getValue();
845 }
846
847 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000848 assert((Kind == k_Memory) && "Invalid access!");
849 return Mem.Base;
850 }
851
852 const MCExpr *getMemOff() const {
853 assert((Kind == k_Memory) && "Invalid access!");
854 return Mem.Off;
855 }
856
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000857 int64_t getConstantMemOff() const {
858 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
859 }
860
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000861 const SmallVectorImpl<unsigned> &getRegList() const {
862 assert((Kind == k_RegList) && "Invalid access!");
863 return *(RegList.List);
864 }
865
David Blaikie960ea3f2014-06-08 16:18:35 +0000866 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
867 MipsAsmParser &Parser) {
868 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000869 Op->Tok.Data = Str.data();
870 Op->Tok.Length = Str.size();
871 Op->StartLoc = S;
872 Op->EndLoc = S;
873 return Op;
874 }
875
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 /// Create a numeric register (e.g. $1). The exact register remains
877 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000878 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000879 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000880 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000881 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000883 }
884
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 /// Create a register that is definitely a GPR.
886 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000887 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000888 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000889 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000891 }
892
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000893 /// Create a register that is definitely a FGR.
894 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000895 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000896 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000897 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
899 }
900
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000901 /// Create a register that is definitely a HWReg.
902 /// This is typically only used for named registers such as $hwr_cpunum.
903 static std::unique_ptr<MipsOperand>
904 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
905 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
906 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
907 }
908
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000909 /// Create a register that is definitely an FCC.
910 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000911 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000912 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000913 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
915 }
916
917 /// Create a register that is definitely an ACC.
918 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000919 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000920 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000921 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
923 }
924
925 /// Create a register that is definitely an MSA128.
926 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000927 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000928 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000929 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
931 }
932
933 /// Create a register that is definitely an MSACtrl.
934 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000935 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000936 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000937 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
939 }
940
David Blaikie960ea3f2014-06-08 16:18:35 +0000941 static std::unique_ptr<MipsOperand>
942 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
943 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000944 Op->Imm.Val = Val;
945 Op->StartLoc = S;
946 Op->EndLoc = E;
947 return Op;
948 }
949
David Blaikie960ea3f2014-06-08 16:18:35 +0000950 static std::unique_ptr<MipsOperand>
951 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
952 SMLoc E, MipsAsmParser &Parser) {
953 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
954 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000955 Op->Mem.Off = Off;
956 Op->StartLoc = S;
957 Op->EndLoc = E;
958 return Op;
959 }
960
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000961 static std::unique_ptr<MipsOperand>
962 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
963 MipsAsmParser &Parser) {
964 assert (Regs.size() > 0 && "Empty list not allowed");
965
966 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
967 Op->RegList.List = new SmallVector<unsigned, 10>();
968 for (auto Reg : Regs)
969 Op->RegList.List->push_back(Reg);
970 Op->StartLoc = StartLoc;
971 Op->EndLoc = EndLoc;
972 return Op;
973 }
974
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 bool isGPRAsmReg() const {
976 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000977 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000978 bool isMM16AsmReg() const {
979 if (!(isRegIdx() && RegIdx.Kind))
980 return false;
981 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
982 || RegIdx.Index == 16 || RegIdx.Index == 17);
983 }
Jozef Kolek1904fa22014-11-24 14:25:53 +0000984 bool isMM16AsmRegZero() const {
985 if (!(isRegIdx() && RegIdx.Kind))
986 return false;
987 return (RegIdx.Index == 0 ||
988 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
989 RegIdx.Index == 17);
990 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 bool isFGRAsmReg() const {
992 // AFGR64 is $0-$15 but we handle this in getAFGR64()
993 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000994 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000995 bool isHWRegsAsmReg() const {
996 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000997 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000998 bool isCCRAsmReg() const {
999 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001000 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001001 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001002 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1003 return false;
1004 if (!AsmParser.hasEightFccRegisters())
1005 return RegIdx.Index == 0;
1006 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001007 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001008 bool isACCAsmReg() const {
1009 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001010 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 bool isCOP2AsmReg() const {
1012 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001013 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001014 bool isCOP3AsmReg() const {
1015 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1016 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 bool isMSA128AsmReg() const {
1018 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001019 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 bool isMSACtrlAsmReg() const {
1021 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001022 }
1023
Jack Carterb4dbc172012-09-05 23:34:03 +00001024 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001025 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001026 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001027 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001028
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001029 virtual ~MipsOperand() {
1030 switch (Kind) {
1031 case k_Immediate:
1032 break;
1033 case k_Memory:
1034 delete Mem.Base;
1035 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001036 case k_RegList:
1037 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001038 case k_PhysRegister:
1039 case k_RegisterIndex:
1040 case k_Token:
1041 break;
1042 }
1043 }
1044
Craig Topper56c590a2014-04-29 07:58:02 +00001045 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 switch (Kind) {
1047 case k_Immediate:
1048 OS << "Imm<";
1049 Imm.Val->print(OS);
1050 OS << ">";
1051 break;
1052 case k_Memory:
1053 OS << "Mem<";
1054 Mem.Base->print(OS);
1055 OS << ", ";
1056 Mem.Off->print(OS);
1057 OS << ">";
1058 break;
1059 case k_PhysRegister:
1060 OS << "PhysReg<" << PhysReg.Num << ">";
1061 break;
1062 case k_RegisterIndex:
1063 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1064 break;
1065 case k_Token:
1066 OS << Tok.Data;
1067 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001068 case k_RegList:
1069 OS << "RegList< ";
1070 for (auto Reg : (*RegList.List))
1071 OS << Reg << " ";
1072 OS << ">";
1073 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001075 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001076}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001077} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001078
Jack Carter9e65aa32013-03-22 00:05:30 +00001079namespace llvm {
1080extern const MCInstrDesc MipsInsts[];
1081}
1082static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1083 return MipsInsts[Opcode];
1084}
1085
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001086static bool hasShortDelaySlot(unsigned Opcode) {
1087 switch (Opcode) {
1088 case Mips::JALS_MM:
1089 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001090 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001091 case Mips::BGEZALS_MM:
1092 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001093 return true;
1094 default:
1095 return false;
1096 }
1097}
1098
Jack Carter9e65aa32013-03-22 00:05:30 +00001099bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001100 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001101 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001102
Jack Carter9e65aa32013-03-22 00:05:30 +00001103 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001104
1105 if (MCID.isBranch() || MCID.isCall()) {
1106 const unsigned Opcode = Inst.getOpcode();
1107 MCOperand Offset;
1108
1109 switch (Opcode) {
1110 default:
1111 break;
1112 case Mips::BEQ:
1113 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 case Mips::BEQ_MM:
1115 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001116 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001117 Offset = Inst.getOperand(2);
1118 if (!Offset.isImm())
1119 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001120 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001121 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001122 if (OffsetToAlignment(Offset.getImm(),
1123 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001124 return Error(IDLoc, "branch to misaligned address");
1125 break;
1126 case Mips::BGEZ:
1127 case Mips::BGTZ:
1128 case Mips::BLEZ:
1129 case Mips::BLTZ:
1130 case Mips::BGEZAL:
1131 case Mips::BLTZAL:
1132 case Mips::BC1F:
1133 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 case Mips::BGEZ_MM:
1135 case Mips::BGTZ_MM:
1136 case Mips::BLEZ_MM:
1137 case Mips::BLTZ_MM:
1138 case Mips::BGEZAL_MM:
1139 case Mips::BLTZAL_MM:
1140 case Mips::BC1F_MM:
1141 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001142 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001143 Offset = Inst.getOperand(1);
1144 if (!Offset.isImm())
1145 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001146 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001147 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001148 if (OffsetToAlignment(Offset.getImm(),
1149 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001150 return Error(IDLoc, "branch to misaligned address");
1151 break;
1152 }
1153 }
1154
Daniel Sandersa84989a2014-06-16 13:25:35 +00001155 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1156 // We still accept it but it is a normal nop.
1157 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1158 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1159 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1160 "nop instruction");
1161 }
1162
Toma Tabacu9db22db2014-09-09 10:15:38 +00001163 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001164 // If this instruction has a delay slot and .set reorder is active,
1165 // emit a NOP after it.
1166 Instructions.push_back(Inst);
1167 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001168 if (hasShortDelaySlot(Inst.getOpcode())) {
1169 NopInst.setOpcode(Mips::MOVE16_MM);
1170 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1171 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1172 } else {
1173 NopInst.setOpcode(Mips::SLL);
1174 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1175 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1176 NopInst.addOperand(MCOperand::CreateImm(0));
1177 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001178 Instructions.push_back(NopInst);
1179 return false;
1180 }
1181
Jack Carter9e65aa32013-03-22 00:05:30 +00001182 if (MCID.mayLoad() || MCID.mayStore()) {
1183 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001184 // reference or immediate we may have to expand instructions.
1185 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001186 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001187 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1188 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001189 MCOperand &Op = Inst.getOperand(i);
1190 if (Op.isImm()) {
1191 int MemOffset = Op.getImm();
1192 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001193 // Offset can't exceed 16bit value.
1194 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001195 return false;
1196 }
1197 } else if (Op.isExpr()) {
1198 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001199 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001200 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001201 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001202 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001203 // Expand symbol.
1204 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001205 return false;
1206 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001207 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001208 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001209 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001210 }
1211 }
1212 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001213 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001214 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001215
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001216 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1217 if (inMicroMipsMode()) {
1218 MCOperand Opnd;
1219 int Imm;
1220
1221 switch (Inst.getOpcode()) {
1222 default:
1223 break;
1224 case Mips::ADDIUS5_MM:
1225 Opnd = Inst.getOperand(2);
1226 if (!Opnd.isImm())
1227 return Error(IDLoc, "expected immediate operand kind");
1228 Imm = Opnd.getImm();
1229 if (Imm < -8 || Imm > 7)
1230 return Error(IDLoc, "immediate operand value out of range");
1231 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001232 case Mips::ADDIUSP_MM:
1233 Opnd = Inst.getOperand(0);
1234 if (!Opnd.isImm())
1235 return Error(IDLoc, "expected immediate operand kind");
1236 Imm = Opnd.getImm();
1237 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1238 Imm % 4 != 0)
1239 return Error(IDLoc, "immediate operand value out of range");
1240 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001241 case Mips::SLL16_MM:
1242 case Mips::SRL16_MM:
1243 Opnd = Inst.getOperand(2);
1244 if (!Opnd.isImm())
1245 return Error(IDLoc, "expected immediate operand kind");
1246 Imm = Opnd.getImm();
1247 if (Imm < 1 || Imm > 8)
1248 return Error(IDLoc, "immediate operand value out of range");
1249 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001250 case Mips::LI16_MM:
1251 Opnd = Inst.getOperand(1);
1252 if (!Opnd.isImm())
1253 return Error(IDLoc, "expected immediate operand kind");
1254 Imm = Opnd.getImm();
1255 if (Imm < -1 || Imm > 126)
1256 return Error(IDLoc, "immediate operand value out of range");
1257 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001258 case Mips::ADDIUR2_MM:
1259 Opnd = Inst.getOperand(2);
1260 if (!Opnd.isImm())
1261 return Error(IDLoc, "expected immediate operand kind");
1262 Imm = Opnd.getImm();
1263 if (!(Imm == 1 || Imm == -1 ||
1264 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1265 return Error(IDLoc, "immediate operand value out of range");
1266 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001267 case Mips::ADDIUR1SP_MM:
1268 Opnd = Inst.getOperand(1);
1269 if (!Opnd.isImm())
1270 return Error(IDLoc, "expected immediate operand kind");
1271 Imm = Opnd.getImm();
1272 if (OffsetToAlignment(Imm, 4LL))
1273 return Error(IDLoc, "misaligned immediate operand value");
1274 if (Imm < 0 || Imm > 255)
1275 return Error(IDLoc, "immediate operand value out of range");
1276 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001277 case Mips::ANDI16_MM:
1278 Opnd = Inst.getOperand(2);
1279 if (!Opnd.isImm())
1280 return Error(IDLoc, "expected immediate operand kind");
1281 Imm = Opnd.getImm();
1282 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1283 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1284 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1285 return Error(IDLoc, "immediate operand value out of range");
1286 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001287 case Mips::LBU16_MM:
1288 Opnd = Inst.getOperand(2);
1289 if (!Opnd.isImm())
1290 return Error(IDLoc, "expected immediate operand kind");
1291 Imm = Opnd.getImm();
1292 if (Imm < -1 || Imm > 14)
1293 return Error(IDLoc, "immediate operand value out of range");
1294 break;
1295 case Mips::SB16_MM:
1296 Opnd = Inst.getOperand(2);
1297 if (!Opnd.isImm())
1298 return Error(IDLoc, "expected immediate operand kind");
1299 Imm = Opnd.getImm();
1300 if (Imm < 0 || Imm > 15)
1301 return Error(IDLoc, "immediate operand value out of range");
1302 break;
1303 case Mips::LHU16_MM:
1304 case Mips::SH16_MM:
1305 Opnd = Inst.getOperand(2);
1306 if (!Opnd.isImm())
1307 return Error(IDLoc, "expected immediate operand kind");
1308 Imm = Opnd.getImm();
1309 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1310 return Error(IDLoc, "immediate operand value out of range");
1311 break;
1312 case Mips::LW16_MM:
1313 case Mips::SW16_MM:
1314 Opnd = Inst.getOperand(2);
1315 if (!Opnd.isImm())
1316 return Error(IDLoc, "expected immediate operand kind");
1317 Imm = Opnd.getImm();
1318 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1319 return Error(IDLoc, "immediate operand value out of range");
1320 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001321 }
1322 }
1323
Jack Carter9e65aa32013-03-22 00:05:30 +00001324 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001325 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001326 else
1327 Instructions.push_back(Inst);
1328
1329 return false;
1330}
1331
Jack Carter30a59822012-10-04 04:03:53 +00001332bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1333
Jack Carterd0bd6422013-04-18 00:41:53 +00001334 switch (Inst.getOpcode()) {
1335 case Mips::LoadImm32Reg:
1336 case Mips::LoadAddr32Imm:
1337 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001338 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001339 return true;
1340 default:
1341 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001342 }
1343}
Jack Carter92995f12012-10-06 00:53:28 +00001344
Matheus Almeida3813d572014-06-19 14:39:14 +00001345bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001346 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001347 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001348 default:
1349 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001350 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001351 case Mips::LoadImm32Reg:
1352 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001353 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001354 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001355 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001356 return true;
1357 }
1358 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001359 case Mips::LoadAddr32Imm:
1360 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1361 case Mips::LoadAddr32Reg:
1362 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1363 }
Jack Carter30a59822012-10-04 04:03:53 +00001364}
Jack Carter92995f12012-10-06 00:53:28 +00001365
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001366namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001367template <bool PerformShift>
1368void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001369 SmallVectorImpl<MCInst> &Instructions) {
1370 MCInst tmpInst;
1371 if (PerformShift) {
1372 tmpInst.setOpcode(Mips::DSLL);
1373 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1374 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1375 tmpInst.addOperand(MCOperand::CreateImm(16));
1376 tmpInst.setLoc(IDLoc);
1377 Instructions.push_back(tmpInst);
1378 tmpInst.clear();
1379 }
1380 tmpInst.setOpcode(Mips::ORi);
1381 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1382 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001383 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001384 tmpInst.setLoc(IDLoc);
1385 Instructions.push_back(tmpInst);
1386}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001387
1388template <int Shift, bool PerformShift>
1389void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1390 SmallVectorImpl<MCInst> &Instructions) {
1391 createShiftOr<PerformShift>(
1392 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1393 IDLoc, Instructions);
1394}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001395}
1396
Matheus Almeida3813d572014-06-19 14:39:14 +00001397bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001399 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001400 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001401 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001402 const MCOperand &RegOp = Inst.getOperand(0);
1403 assert(RegOp.isReg() && "expected register operand kind");
1404
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001405 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001406 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001407 // FIXME: gas has a special case for values that are 000...1111, which
1408 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 if (0 <= ImmValue && ImmValue <= 65535) {
1410 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001411 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001412 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001413 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001415 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001416 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 } else if (ImmValue < 0 && ImmValue >= -32768) {
1418 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001419 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001420 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001421 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001422 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001423 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001424 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001425 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1426 // For any value of j that is representable as a 32-bit integer, create
1427 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001428 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001429 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001430 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001431 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1432 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001433 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001434 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1435 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001436 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001437 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001438 return true;
1439 }
1440
1441 // <------- lo32 ------>
1442 // <------- hi32 ------>
1443 // <- hi16 -> <- lo16 ->
1444 // _________________________________
1445 // | | | |
1446 // | 16-bytes | 16-bytes | 16-bytes |
1447 // |__________|__________|__________|
1448 //
1449 // For any value of j that is representable as a 48-bit integer, create
1450 // a sequence of:
1451 // li d,j => lui d,hi16(j)
1452 // ori d,d,hi16(lo32(j))
1453 // dsll d,d,16
1454 // ori d,d,lo16(lo32(j))
1455 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001456 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001457 tmpInst.addOperand(
1458 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001459 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001460 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1461 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1462 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001463 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001464 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001465 return true;
1466 }
1467
1468 // <------- hi32 ------> <------- lo32 ------>
1469 // <- hi16 -> <- lo16 ->
1470 // ___________________________________________
1471 // | | | | |
1472 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1473 // |__________|__________|__________|__________|
1474 //
1475 // For any value of j that isn't representable as a 48-bit integer.
1476 // li d,j => lui d,hi16(j)
1477 // ori d,d,lo16(hi32(j))
1478 // dsll d,d,16
1479 // ori d,d,hi16(lo32(j))
1480 // dsll d,d,16
1481 // ori d,d,lo16(lo32(j))
1482 tmpInst.setOpcode(Mips::LUi);
1483 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1484 tmpInst.addOperand(
1485 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1486 Instructions.push_back(tmpInst);
1487 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1488 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1489 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001490 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001491 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001492}
Jack Carter92995f12012-10-06 00:53:28 +00001493
Matheus Almeida3813d572014-06-19 14:39:14 +00001494bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001495MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1496 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001497 MCInst tmpInst;
1498 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001499 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1500 "expected immediate operand kind");
1501 if (!ImmOp.isImm()) {
1502 expandLoadAddressSym(Inst, IDLoc, Instructions);
1503 return false;
1504 }
Jack Carter543fdf82012-10-09 23:29:45 +00001505 const MCOperand &SrcRegOp = Inst.getOperand(1);
1506 assert(SrcRegOp.isReg() && "expected register operand kind");
1507 const MCOperand &DstRegOp = Inst.getOperand(0);
1508 assert(DstRegOp.isReg() && "expected register operand kind");
1509 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001510 if (-32768 <= ImmValue && ImmValue <= 65535) {
1511 // For -32768 <= j <= 65535.
1512 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001513 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001514 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1515 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1516 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1517 Instructions.push_back(tmpInst);
1518 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001519 // For any other value of j that is representable as a 32-bit integer.
1520 // la d,j(s) => lui d,hi16(j)
1521 // ori d,d,lo16(j)
1522 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001523 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001524 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1525 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1526 Instructions.push_back(tmpInst);
1527 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001528 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001529 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1530 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1531 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1532 Instructions.push_back(tmpInst);
1533 tmpInst.clear();
1534 tmpInst.setOpcode(Mips::ADDu);
1535 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1536 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1537 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1538 Instructions.push_back(tmpInst);
1539 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001540 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001541}
1542
Matheus Almeida3813d572014-06-19 14:39:14 +00001543bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001544MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1545 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001546 MCInst tmpInst;
1547 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001548 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1549 "expected immediate operand kind");
1550 if (!ImmOp.isImm()) {
1551 expandLoadAddressSym(Inst, IDLoc, Instructions);
1552 return false;
1553 }
Jack Carter543fdf82012-10-09 23:29:45 +00001554 const MCOperand &RegOp = Inst.getOperand(0);
1555 assert(RegOp.isReg() && "expected register operand kind");
1556 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 if (-32768 <= ImmValue && ImmValue <= 65535) {
1558 // For -32768 <= j <= 65535.
1559 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001560 tmpInst.setOpcode(Mips::ADDiu);
1561 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001562 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001563 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1564 Instructions.push_back(tmpInst);
1565 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001566 // For any other value of j that is representable as a 32-bit integer.
1567 // la d,j => lui d,hi16(j)
1568 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001569 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001570 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1571 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1572 Instructions.push_back(tmpInst);
1573 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001574 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001575 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1576 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1577 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1578 Instructions.push_back(tmpInst);
1579 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001580 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001581}
1582
Toma Tabacu0d64b202014-08-14 10:29:17 +00001583void
1584MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1585 SmallVectorImpl<MCInst> &Instructions) {
1586 // FIXME: If we do have a valid at register to use, we should generate a
1587 // slightly shorter sequence here.
1588 MCInst tmpInst;
1589 int ExprOperandNo = 1;
1590 // Sometimes the assembly parser will get the immediate expression as
1591 // a $zero + an immediate.
1592 if (Inst.getNumOperands() == 3) {
1593 assert(Inst.getOperand(1).getReg() ==
1594 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1595 ExprOperandNo = 2;
1596 }
1597 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1598 assert(SymOp.isExpr() && "expected symbol operand kind");
1599 const MCOperand &RegOp = Inst.getOperand(0);
1600 unsigned RegNo = RegOp.getReg();
1601 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1602 const MCSymbolRefExpr *HiExpr =
1603 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1604 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1605 const MCSymbolRefExpr *LoExpr =
1606 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1607 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1608 if (isGP64bit()) {
1609 // If it's a 64-bit architecture, expand to:
1610 // la d,sym => lui d,highest(sym)
1611 // ori d,d,higher(sym)
1612 // dsll d,d,16
1613 // ori d,d,hi16(sym)
1614 // dsll d,d,16
1615 // ori d,d,lo16(sym)
1616 const MCSymbolRefExpr *HighestExpr =
1617 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1618 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1619 const MCSymbolRefExpr *HigherExpr =
1620 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1621 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1622
1623 tmpInst.setOpcode(Mips::LUi);
1624 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1625 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1626 Instructions.push_back(tmpInst);
1627
1628 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1629 Instructions);
1630 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1631 Instructions);
1632 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1633 Instructions);
1634 } else {
1635 // Otherwise, expand to:
1636 // la d,sym => lui d,hi16(sym)
1637 // ori d,d,lo16(sym)
1638 tmpInst.setOpcode(Mips::LUi);
1639 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1640 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1641 Instructions.push_back(tmpInst);
1642
1643 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1644 Instructions);
1645 }
1646}
1647
Jack Carter9e65aa32013-03-22 00:05:30 +00001648void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001649 SmallVectorImpl<MCInst> &Instructions,
1650 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001651 const MCSymbolRefExpr *SR;
1652 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001653 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001654 const MCExpr *ExprOffset;
1655 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001656 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001657 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1658 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001659 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001660 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1661 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001662 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001663 if (isImmOpnd) {
1664 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1665 ImmOffset = Inst.getOperand(2).getImm();
1666 LoOffset = ImmOffset & 0x0000ffff;
1667 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001668 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001669 if (LoOffset & 0x8000)
1670 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001671 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001672 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001673 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001674 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001675 // These are some of the types of expansions we perform here:
1676 // 1) lw $8, sym => lui $8, %hi(sym)
1677 // lw $8, %lo(sym)($8)
1678 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1679 // add $8, $8, $9
1680 // lw $8, %lo(offset)($9)
1681 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1682 // add $at, $at, $8
1683 // lw $8, %lo(offset)($at)
1684 // 4) sw $8, sym => lui $at, %hi(sym)
1685 // sw $8, %lo(sym)($at)
1686 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1687 // add $at, $at, $8
1688 // sw $8, %lo(offset)($at)
1689 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1690 // ldc1 $f0, %lo(sym)($at)
1691 //
1692 // For load instructions we can use the destination register as a temporary
1693 // if base and dst are different (examples 1 and 2) and if the base register
1694 // is general purpose otherwise we must use $at (example 6) and error if it's
1695 // not available. For stores we must use $at (examples 4 and 5) because we
1696 // must not clobber the source register setting up the offset.
1697 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1698 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1699 unsigned RegClassIDOp0 =
1700 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1701 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1702 (RegClassIDOp0 == Mips::GPR64RegClassID);
1703 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001704 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001705 else {
1706 int AT = getATReg(IDLoc);
1707 // At this point we need AT to perform the expansions and we exit if it is
1708 // not available.
1709 if (!AT)
1710 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001711 TmpRegNum = getReg(
1712 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001713 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001714
Jack Carter9e65aa32013-03-22 00:05:30 +00001715 TempInst.setOpcode(Mips::LUi);
1716 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1717 if (isImmOpnd)
1718 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1719 else {
1720 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001721 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001722 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1723 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1724 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001725 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001726 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001727 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001728 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001729 }
1730 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001731 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001733 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001734 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001735 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001736 TempInst.setOpcode(Mips::ADDu);
1737 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1738 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1739 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1740 Instructions.push_back(TempInst);
1741 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001742 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001743 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 TempInst.setOpcode(Inst.getOpcode());
1745 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1746 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1747 if (isImmOpnd)
1748 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1749 else {
1750 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1752 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1753 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001754 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001755 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001756 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001757 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001758 }
1759 }
1760 Instructions.push_back(TempInst);
1761 TempInst.clear();
1762}
1763
Matheus Almeida595fcab2014-06-11 15:05:56 +00001764unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1765 // As described by the Mips32r2 spec, the registers Rd and Rs for
1766 // jalr.hb must be different.
1767 unsigned Opcode = Inst.getOpcode();
1768
1769 if (Opcode == Mips::JALR_HB &&
1770 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1771 return Match_RequiresDifferentSrcAndDst;
1772
1773 return Match_Success;
1774}
1775
David Blaikie960ea3f2014-06-08 16:18:35 +00001776bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1777 OperandVector &Operands,
1778 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001779 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001780 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001781
Jack Carterb4dbc172012-09-05 23:34:03 +00001782 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001783 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001784 unsigned MatchResult =
1785 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001786
1787 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001788 default:
1789 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001790 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001791 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001792 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001793 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001794 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001795 return false;
1796 }
1797 case Match_MissingFeature:
1798 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1799 return true;
1800 case Match_InvalidOperand: {
1801 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001802 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001803 if (ErrorInfo >= Operands.size())
1804 return Error(IDLoc, "too few operands for instruction");
1805
David Blaikie960ea3f2014-06-08 16:18:35 +00001806 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001807 if (ErrorLoc == SMLoc())
1808 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001809 }
1810
1811 return Error(ErrorLoc, "invalid operand for instruction");
1812 }
1813 case Match_MnemonicFail:
1814 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001815 case Match_RequiresDifferentSrcAndDst:
1816 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001817 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001818 return true;
1819}
1820
Toma Tabacu13964452014-09-04 13:23:44 +00001821void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001822 if ((RegIndex != 0) &&
1823 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001824 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001825 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001826 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001827 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001828 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001829 }
1830}
1831
Daniel Sandersef638fe2014-10-03 15:37:37 +00001832void
1833MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1834 SMRange Range, bool ShowColors) {
1835 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001836 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001837 ShowColors);
1838}
1839
Jack Carter1ac53222013-02-20 23:11:17 +00001840int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001841 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001842
Vladimir Medic4c299852013-11-06 11:27:05 +00001843 CC = StringSwitch<unsigned>(Name)
1844 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001845 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001846 .Case("a0", 4)
1847 .Case("a1", 5)
1848 .Case("a2", 6)
1849 .Case("a3", 7)
1850 .Case("v0", 2)
1851 .Case("v1", 3)
1852 .Case("s0", 16)
1853 .Case("s1", 17)
1854 .Case("s2", 18)
1855 .Case("s3", 19)
1856 .Case("s4", 20)
1857 .Case("s5", 21)
1858 .Case("s6", 22)
1859 .Case("s7", 23)
1860 .Case("k0", 26)
1861 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001862 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001863 .Case("sp", 29)
1864 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001865 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001866 .Case("ra", 31)
1867 .Case("t0", 8)
1868 .Case("t1", 9)
1869 .Case("t2", 10)
1870 .Case("t3", 11)
1871 .Case("t4", 12)
1872 .Case("t5", 13)
1873 .Case("t6", 14)
1874 .Case("t7", 15)
1875 .Case("t8", 24)
1876 .Case("t9", 25)
1877 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001878
Toma Tabacufda445c2014-09-15 15:33:01 +00001879 if (!(isABI_N32() || isABI_N64()))
1880 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001881
Daniel Sandersef638fe2014-10-03 15:37:37 +00001882 if (12 <= CC && CC <= 15) {
1883 // Name is one of t4-t7
1884 AsmToken RegTok = getLexer().peekTok();
1885 SMRange RegRange = RegTok.getLocRange();
1886
1887 StringRef FixedName = StringSwitch<StringRef>(Name)
1888 .Case("t4", "t0")
1889 .Case("t5", "t1")
1890 .Case("t6", "t2")
1891 .Case("t7", "t3")
1892 .Default("");
1893 assert(FixedName != "" && "Register name is not one of t4-t7.");
1894
1895 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1896 "Did you mean $" + FixedName + "?", RegRange);
1897 }
1898
Toma Tabacufda445c2014-09-15 15:33:01 +00001899 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1900 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1901 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1902 if (8 <= CC && CC <= 11)
1903 CC += 4;
1904
1905 if (CC == -1)
1906 CC = StringSwitch<unsigned>(Name)
1907 .Case("a4", 8)
1908 .Case("a5", 9)
1909 .Case("a6", 10)
1910 .Case("a7", 11)
1911 .Case("kt0", 26)
1912 .Case("kt1", 27)
1913 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001914
1915 return CC;
1916}
Jack Carterd0bd6422013-04-18 00:41:53 +00001917
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001918int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1919 int CC;
1920
1921 CC = StringSwitch<unsigned>(Name)
1922 .Case("hwr_cpunum", 0)
1923 .Case("hwr_synci_step", 1)
1924 .Case("hwr_cc", 2)
1925 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001926 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001927 .Default(-1);
1928
1929 return CC;
1930}
1931
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001932int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001933
Jack Cartera63b16a2012-09-07 00:23:42 +00001934 if (Name[0] == 'f') {
1935 StringRef NumString = Name.substr(1);
1936 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001937 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001938 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001939 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001940 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001941 return IntVal;
1942 }
1943 return -1;
1944}
Jack Cartera63b16a2012-09-07 00:23:42 +00001945
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001946int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1947
1948 if (Name.startswith("fcc")) {
1949 StringRef NumString = Name.substr(3);
1950 unsigned IntVal;
1951 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001952 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001953 if (IntVal > 7) // There are only 8 fcc registers.
1954 return -1;
1955 return IntVal;
1956 }
1957 return -1;
1958}
1959
1960int MipsAsmParser::matchACRegisterName(StringRef Name) {
1961
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001962 if (Name.startswith("ac")) {
1963 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001964 unsigned IntVal;
1965 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001966 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001967 if (IntVal > 3) // There are only 3 acc registers.
1968 return -1;
1969 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001970 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001971 return -1;
1972}
Jack Carterd0bd6422013-04-18 00:41:53 +00001973
Jack Carter5dc8ac92013-09-25 23:50:44 +00001974int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1975 unsigned IntVal;
1976
1977 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1978 return -1;
1979
1980 if (IntVal > 31)
1981 return -1;
1982
1983 return IntVal;
1984}
1985
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001986int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1987 int CC;
1988
1989 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001990 .Case("msair", 0)
1991 .Case("msacsr", 1)
1992 .Case("msaaccess", 2)
1993 .Case("msasave", 3)
1994 .Case("msamodify", 4)
1995 .Case("msarequest", 5)
1996 .Case("msamap", 6)
1997 .Case("msaunmap", 7)
1998 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001999
2000 return CC;
2001}
2002
Jack Carter0b744b32012-10-04 02:29:46 +00002003bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2004 if (Reg > 31)
2005 return false;
2006
Toma Tabacu3c24b042014-09-05 15:43:21 +00002007 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002008 return true;
2009}
2010
Matheus Almeida7de68e72014-06-18 14:46:05 +00002011int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002012 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002013 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002014 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002015 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002016 return AT;
2017}
Jack Carter0b744b32012-10-04 02:29:46 +00002018
Jack Carterd0bd6422013-04-18 00:41:53 +00002019unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002020 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002021}
2022
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002023unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002024 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002025 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002026}
2027
Jack Carter873c7242013-01-12 01:03:14 +00002028int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002029 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002030 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002031 return -1;
2032
Jack Carter873c7242013-01-12 01:03:14 +00002033 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002034}
2035
Toma Tabacu13964452014-09-04 13:23:44 +00002036bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002037 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002038 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002039
Jack Carter30a59822012-10-04 04:03:53 +00002040 // Check if the current operand has a custom associated parser, if so, try to
2041 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002042 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2043 if (ResTy == MatchOperand_Success)
2044 return false;
2045 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2046 // there was a match, but an error occurred, in which case, just return that
2047 // the operand parsing failed.
2048 if (ResTy == MatchOperand_ParseFail)
2049 return true;
2050
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002051 DEBUG(dbgs() << ".. Generic Parser\n");
2052
Jack Carterb4dbc172012-09-05 23:34:03 +00002053 switch (getLexer().getKind()) {
2054 default:
2055 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2056 return true;
2057 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002058 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002059 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002060
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002061 // Almost all registers have been parsed by custom parsers. There is only
2062 // one exception to this. $zero (and it's alias $0) will reach this point
2063 // for div, divu, and similar instructions because it is not an operand
2064 // to the instruction definition but an explicit register. Special case
2065 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002066 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002067 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002068
Jack Carterd0bd6422013-04-18 00:41:53 +00002069 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002070 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002071 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002072 return true;
2073
Jack Carter873c7242013-01-12 01:03:14 +00002074 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002075 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002077 const MCExpr *Res =
2078 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002079
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002080 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002081 return false;
2082 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002083 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002084 case AsmToken::LParen:
2085 case AsmToken::Minus:
2086 case AsmToken::Plus:
2087 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002088 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002089 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002090 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002091 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002092 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002093 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002094 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002095 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002096 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002098 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002099 return true;
2100
Jack Carter873c7242013-01-12 01:03:14 +00002101 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002103 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002104 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002105 } // case AsmToken::Percent
2106 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002107 return true;
2108}
2109
Vladimir Medic4c299852013-11-06 11:27:05 +00002110const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002111 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002112 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002115 // It's a constant, evaluate reloc value.
2116 int16_t Val;
2117 switch (getVariantKind(RelocStr)) {
2118 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2119 // Get the 1st 16-bits.
2120 Val = MCE->getValue() & 0xffff;
2121 break;
2122 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2123 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2124 // 16 bits being negative.
2125 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2126 break;
2127 case MCSymbolRefExpr::VK_Mips_HIGHER:
2128 // Get the 3rd 16-bits.
2129 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2130 break;
2131 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2132 // Get the 4th 16-bits.
2133 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2134 break;
2135 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002136 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002137 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002138 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002139 }
2140
Jack Carterb5cf5902013-04-17 00:18:04 +00002141 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002142 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002143 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002144 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002145 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002146 return Res;
2147 }
2148
2149 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002150 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2151
Sasa Stankovic06c47802014-04-03 10:37:45 +00002152 // Try to create target expression.
2153 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2154 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002155
Jack Carterd0bd6422013-04-18 00:41:53 +00002156 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2157 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002158 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2159 return Res;
2160 }
2161
2162 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2164 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2165 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002166 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002167 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002168 return Expr;
2169}
2170
2171bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2172
2173 switch (Expr->getKind()) {
2174 case MCExpr::Constant:
2175 return true;
2176 case MCExpr::SymbolRef:
2177 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2178 case MCExpr::Binary:
2179 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2180 if (!isEvaluated(BE->getLHS()))
2181 return false;
2182 return isEvaluated(BE->getRHS());
2183 }
2184 case MCExpr::Unary:
2185 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002186 case MCExpr::Target:
2187 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002188 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002189 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002190}
Jack Carterd0bd6422013-04-18 00:41:53 +00002191
Jack Carterb5cf5902013-04-17 00:18:04 +00002192bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002193 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002194 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002196 if (Tok.isNot(AsmToken::Identifier))
2197 return true;
2198
2199 std::string Str = Tok.getIdentifier().str();
2200
Jack Carterd0bd6422013-04-18 00:41:53 +00002201 Parser.Lex(); // Eat the identifier.
2202 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002203 const MCExpr *IdVal;
2204 SMLoc EndLoc;
2205
2206 if (getLexer().getKind() == AsmToken::LParen) {
2207 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002208 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002209 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002211 const AsmToken &nextTok = Parser.getTok();
2212 if (nextTok.isNot(AsmToken::Identifier))
2213 return true;
2214 Str += "(%";
2215 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002217 if (getLexer().getKind() != AsmToken::LParen)
2218 return true;
2219 } else
2220 break;
2221 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002222 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002223 return true;
2224
2225 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002226 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002227
2228 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002229 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002230
Jack Carterd0bd6422013-04-18 00:41:53 +00002231 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002232 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002233}
2234
Jack Carterb4dbc172012-09-05 23:34:03 +00002235bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2236 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002237 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002238 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002239 if (ResTy == MatchOperand_Success) {
2240 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002241 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002242 StartLoc = Operand.getStartLoc();
2243 EndLoc = Operand.getEndLoc();
2244
2245 // AFAIK, we only support numeric registers and named GPR's in CFI
2246 // directives.
2247 // Don't worry about eating tokens before failing. Using an unrecognised
2248 // register is a parse error.
2249 if (Operand.isGPRAsmReg()) {
2250 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002251 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002252 }
2253
2254 return (RegNo == (unsigned)-1);
2255 }
2256
2257 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002258 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002259}
2260
Jack Carterb5cf5902013-04-17 00:18:04 +00002261bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002262 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002263 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002264 bool Result = true;
2265
2266 while (getLexer().getKind() == AsmToken::LParen)
2267 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002268
Jack Carterd0bd6422013-04-18 00:41:53 +00002269 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002270 default:
2271 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002272 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002273 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002274 case AsmToken::Integer:
2275 case AsmToken::Minus:
2276 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002277 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002278 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002279 else
2280 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002281 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002282 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002283 break;
Jack Carter873c7242013-01-12 01:03:14 +00002284 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002285 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002286 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002287 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002288}
2289
David Blaikie960ea3f2014-06-08 16:18:35 +00002290MipsAsmParser::OperandMatchResultTy
2291MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002292 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002293 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002294 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002295 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002296 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002297 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002298 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002299 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002300
Jack Carterb5cf5902013-04-17 00:18:04 +00002301 if (getLexer().getKind() == AsmToken::LParen) {
2302 Parser.Lex();
2303 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002304 }
2305
Jack Carterb5cf5902013-04-17 00:18:04 +00002306 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002307 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002308 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002309
Jack Carterd0bd6422013-04-18 00:41:53 +00002310 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002311 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002312 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2313 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002314 SMLoc E =
2315 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002316 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002317 return MatchOperand_Success;
2318 }
2319 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002320 SMLoc E =
2321 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002322
Jack Carterd0bd6422013-04-18 00:41:53 +00002323 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002324 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002325 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002326 S, E, *this);
2327 Operands.push_back(
2328 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002329 return MatchOperand_Success;
2330 }
2331 Error(Parser.getTok().getLoc(), "'(' expected");
2332 return MatchOperand_ParseFail;
2333 }
2334
Jack Carterd0bd6422013-04-18 00:41:53 +00002335 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002336 }
2337
Toma Tabacu13964452014-09-04 13:23:44 +00002338 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002339 if (Res != MatchOperand_Success)
2340 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002341
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002342 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002343 Error(Parser.getTok().getLoc(), "')' expected");
2344 return MatchOperand_ParseFail;
2345 }
2346
Jack Carter873c7242013-01-12 01:03:14 +00002347 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2348
Jack Carterd0bd6422013-04-18 00:41:53 +00002349 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002350
Craig Topper062a2ba2014-04-25 05:30:21 +00002351 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002352 IdVal = MCConstantExpr::Create(0, getContext());
2353
Jack Carterd0bd6422013-04-18 00:41:53 +00002354 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002355 std::unique_ptr<MipsOperand> op(
2356 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002357 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002358 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002359 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002360 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002361 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2362 int64_t Imm;
2363 if (IdVal->EvaluateAsAbsolute(Imm))
2364 IdVal = MCConstantExpr::Create(Imm, getContext());
2365 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2366 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2367 getContext());
2368 }
2369
David Blaikie960ea3f2014-06-08 16:18:35 +00002370 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002371 return MatchOperand_Success;
2372}
2373
David Blaikie960ea3f2014-06-08 16:18:35 +00002374bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002375 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002376 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2377 if (Sym) {
2378 SMLoc S = Parser.getTok().getLoc();
2379 const MCExpr *Expr;
2380 if (Sym->isVariable())
2381 Expr = Sym->getVariableValue();
2382 else
2383 return false;
2384 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002385 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002386 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002387 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002388 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002389 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002390 if (ResTy == MatchOperand_Success) {
2391 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002392 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002393 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002394 llvm_unreachable("Should never ParseFail");
2395 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002396 }
2397 } else if (Expr->getKind() == MCExpr::Constant) {
2398 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002399 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002400 Operands.push_back(
2401 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002402 return true;
2403 }
2404 }
2405 return false;
2406}
Jack Carterd0bd6422013-04-18 00:41:53 +00002407
Jack Carter873c7242013-01-12 01:03:14 +00002408MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002409MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002410 StringRef Identifier,
2411 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002412 int Index = matchCPURegisterName(Identifier);
2413 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002414 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002415 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2416 return MatchOperand_Success;
2417 }
2418
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002419 Index = matchHWRegsRegisterName(Identifier);
2420 if (Index != -1) {
2421 Operands.push_back(MipsOperand::createHWRegsReg(
2422 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2423 return MatchOperand_Success;
2424 }
2425
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002426 Index = matchFPURegisterName(Identifier);
2427 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002428 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002429 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2430 return MatchOperand_Success;
2431 }
2432
2433 Index = matchFCCRegisterName(Identifier);
2434 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002435 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002436 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2437 return MatchOperand_Success;
2438 }
2439
2440 Index = matchACRegisterName(Identifier);
2441 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002442 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002443 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2444 return MatchOperand_Success;
2445 }
2446
2447 Index = matchMSA128RegisterName(Identifier);
2448 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002449 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002450 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2451 return MatchOperand_Success;
2452 }
2453
2454 Index = matchMSA128CtrlRegisterName(Identifier);
2455 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002456 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002457 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2458 return MatchOperand_Success;
2459 }
2460
2461 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002462}
2463
2464MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002465MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002466 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002467 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468
2469 if (Token.is(AsmToken::Identifier)) {
2470 DEBUG(dbgs() << ".. identifier\n");
2471 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002472 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002473 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002474 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002475 } else if (Token.is(AsmToken::Integer)) {
2476 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002477 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002478 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2479 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480 return MatchOperand_Success;
2481 }
2482
2483 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2484
2485 return MatchOperand_NoMatch;
2486}
2487
David Blaikie960ea3f2014-06-08 16:18:35 +00002488MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002489MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002490 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002491 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002492
2493 auto Token = Parser.getTok();
2494
2495 SMLoc S = Token.getLoc();
2496
2497 if (Token.isNot(AsmToken::Dollar)) {
2498 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2499 if (Token.is(AsmToken::Identifier)) {
2500 if (searchSymbolAlias(Operands))
2501 return MatchOperand_Success;
2502 }
2503 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2504 return MatchOperand_NoMatch;
2505 }
2506 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002507
Toma Tabacu13964452014-09-04 13:23:44 +00002508 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002509 if (ResTy == MatchOperand_Success) {
2510 Parser.Lex(); // $
2511 Parser.Lex(); // identifier
2512 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002513 return ResTy;
2514}
2515
2516MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002517MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002518 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002519 switch (getLexer().getKind()) {
2520 default:
2521 return MatchOperand_NoMatch;
2522 case AsmToken::LParen:
2523 case AsmToken::Minus:
2524 case AsmToken::Plus:
2525 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002526 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002527 case AsmToken::String:
2528 break;
2529 }
2530
2531 const MCExpr *IdVal;
2532 SMLoc S = Parser.getTok().getLoc();
2533 if (getParser().parseExpression(IdVal))
2534 return MatchOperand_ParseFail;
2535
2536 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2537 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2538 return MatchOperand_Success;
2539}
2540
David Blaikie960ea3f2014-06-08 16:18:35 +00002541MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002542MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002543 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002544 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002545
2546 SMLoc S = getLexer().getLoc();
2547
2548 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002549 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002550 if (ResTy != MatchOperand_NoMatch)
2551 return ResTy;
2552
Daniel Sanders315386c2014-04-01 10:40:14 +00002553 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002554 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002555 if (ResTy != MatchOperand_NoMatch)
2556 return ResTy;
2557
Daniel Sandersffd84362014-04-01 10:41:48 +00002558 const MCExpr *Expr = nullptr;
2559 if (Parser.parseExpression(Expr)) {
2560 // We have no way of knowing if a symbol was consumed so we must ParseFail
2561 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002562 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002563 Operands.push_back(
2564 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002565 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002566}
2567
Vladimir Medic2b953d02013-10-01 09:48:56 +00002568MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002569MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002570 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002571 const MCExpr *IdVal;
2572 // If the first token is '$' we may have register operand.
2573 if (Parser.getTok().is(AsmToken::Dollar))
2574 return MatchOperand_NoMatch;
2575 SMLoc S = Parser.getTok().getLoc();
2576 if (getParser().parseExpression(IdVal))
2577 return MatchOperand_ParseFail;
2578 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002579 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002580 int64_t Val = MCE->getValue();
2581 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2582 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002583 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002584 return MatchOperand_Success;
2585}
2586
Matheus Almeida779c5932013-11-18 12:32:49 +00002587MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002588MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002589 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002590 switch (getLexer().getKind()) {
2591 default:
2592 return MatchOperand_NoMatch;
2593 case AsmToken::LParen:
2594 case AsmToken::Plus:
2595 case AsmToken::Minus:
2596 case AsmToken::Integer:
2597 break;
2598 }
2599
2600 const MCExpr *Expr;
2601 SMLoc S = Parser.getTok().getLoc();
2602
2603 if (getParser().parseExpression(Expr))
2604 return MatchOperand_ParseFail;
2605
2606 int64_t Val;
2607 if (!Expr->EvaluateAsAbsolute(Val)) {
2608 Error(S, "expected immediate value");
2609 return MatchOperand_ParseFail;
2610 }
2611
2612 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2613 // and because the CPU always adds one to the immediate field, the allowed
2614 // range becomes 1..4. We'll only check the range here and will deal
2615 // with the addition/subtraction when actually decoding/encoding
2616 // the instruction.
2617 if (Val < 1 || Val > 4) {
2618 Error(S, "immediate not in range (1..4)");
2619 return MatchOperand_ParseFail;
2620 }
2621
Jack Carter3b2c96e2014-01-22 23:31:38 +00002622 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002623 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002624 return MatchOperand_Success;
2625}
2626
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002627MipsAsmParser::OperandMatchResultTy
2628MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2629 MCAsmParser &Parser = getParser();
2630 SmallVector<unsigned, 10> Regs;
2631 unsigned RegNo;
2632 unsigned PrevReg = Mips::NoRegister;
2633 bool RegRange = false;
2634 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2635
2636 if (Parser.getTok().isNot(AsmToken::Dollar))
2637 return MatchOperand_ParseFail;
2638
2639 SMLoc S = Parser.getTok().getLoc();
2640 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2641 SMLoc E = getLexer().getLoc();
2642 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2643 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2644 if (RegRange) {
2645 // Remove last register operand because registers from register range
2646 // should be inserted first.
2647 if (RegNo == Mips::RA) {
2648 Regs.push_back(RegNo);
2649 } else {
2650 unsigned TmpReg = PrevReg + 1;
2651 while (TmpReg <= RegNo) {
2652 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2653 Error(E, "invalid register operand");
2654 return MatchOperand_ParseFail;
2655 }
2656
2657 PrevReg = TmpReg;
2658 Regs.push_back(TmpReg++);
2659 }
2660 }
2661
2662 RegRange = false;
2663 } else {
2664 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2665 (RegNo != Mips::RA)) {
2666 Error(E, "$16 or $31 expected");
2667 return MatchOperand_ParseFail;
2668 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2669 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2670 Error(E, "invalid register operand");
2671 return MatchOperand_ParseFail;
2672 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2673 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2674 Error(E, "consecutive register numbers expected");
2675 return MatchOperand_ParseFail;
2676 }
2677
2678 Regs.push_back(RegNo);
2679 }
2680
2681 if (Parser.getTok().is(AsmToken::Minus))
2682 RegRange = true;
2683
2684 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2685 !Parser.getTok().isNot(AsmToken::Comma)) {
2686 Error(E, "',' or '-' expected");
2687 return MatchOperand_ParseFail;
2688 }
2689
2690 Lex(); // Consume comma or minus
2691 if (Parser.getTok().isNot(AsmToken::Dollar))
2692 break;
2693
2694 PrevReg = RegNo;
2695 }
2696
2697 SMLoc E = Parser.getTok().getLoc();
2698 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2699 parseMemOperand(Operands);
2700 return MatchOperand_Success;
2701}
2702
Jack Carterdc1e35d2012-09-06 20:00:02 +00002703MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2704
Vladimir Medic4c299852013-11-06 11:27:05 +00002705 MCSymbolRefExpr::VariantKind VK =
2706 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2707 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2708 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2709 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2710 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2711 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2712 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2713 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2714 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2715 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2716 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2717 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2718 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2719 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2720 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2721 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2722 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2723 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002724 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2725 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2726 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2727 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2728 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2729 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002730 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2731 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002732 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002733
Matheus Almeida2852af82014-04-22 10:15:54 +00002734 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002735
Jack Carterdc1e35d2012-09-06 20:00:02 +00002736 return VK;
2737}
Jack Cartera63b16a2012-09-07 00:23:42 +00002738
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002739/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2740/// either this.
2741/// ::= '(', register, ')'
2742/// handle it before we iterate so we don't get tripped up by the lack of
2743/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002744bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002745 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002746 if (getLexer().is(AsmToken::LParen)) {
2747 Operands.push_back(
2748 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2749 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002750 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002751 SMLoc Loc = getLexer().getLoc();
2752 Parser.eatToEndOfStatement();
2753 return Error(Loc, "unexpected token in argument list");
2754 }
2755 if (Parser.getTok().isNot(AsmToken::RParen)) {
2756 SMLoc Loc = getLexer().getLoc();
2757 Parser.eatToEndOfStatement();
2758 return Error(Loc, "unexpected token, expected ')'");
2759 }
2760 Operands.push_back(
2761 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2762 Parser.Lex();
2763 }
2764 return false;
2765}
2766
2767/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2768/// either one of these.
2769/// ::= '[', register, ']'
2770/// ::= '[', integer, ']'
2771/// handle it before we iterate so we don't get tripped up by the lack of
2772/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002773bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002774 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002775 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002776 if (getLexer().is(AsmToken::LBrac)) {
2777 Operands.push_back(
2778 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2779 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002780 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002781 SMLoc Loc = getLexer().getLoc();
2782 Parser.eatToEndOfStatement();
2783 return Error(Loc, "unexpected token in argument list");
2784 }
2785 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2786 SMLoc Loc = getLexer().getLoc();
2787 Parser.eatToEndOfStatement();
2788 return Error(Loc, "unexpected token, expected ']'");
2789 }
2790 Operands.push_back(
2791 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2792 Parser.Lex();
2793 }
2794 return false;
2795}
2796
David Blaikie960ea3f2014-06-08 16:18:35 +00002797bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2798 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002799 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002800 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002801
2802 // We have reached first instruction, module directive are now forbidden.
2803 getTargetStreamer().forbidModuleDirective();
2804
Vladimir Medic74593e62013-07-17 15:00:42 +00002805 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002806 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002807 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002808 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002809 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002810 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002811 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002812
2813 // Read the remaining operands.
2814 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2815 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002816 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002817 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002818 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002819 return Error(Loc, "unexpected token in argument list");
2820 }
Toma Tabacu13964452014-09-04 13:23:44 +00002821 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002822 return true;
2823 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002824
Jack Carterd0bd6422013-04-18 00:41:53 +00002825 while (getLexer().is(AsmToken::Comma)) {
2826 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002827 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002828 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002829 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002830 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002831 return Error(Loc, "unexpected token in argument list");
2832 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002833 // Parse bracket and parenthesis suffixes before we iterate
2834 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002835 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002836 return true;
2837 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002838 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002839 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002840 }
2841 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002842 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2843 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002844 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002845 return Error(Loc, "unexpected token in argument list");
2846 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002847 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002848 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002849}
2850
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002851bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002852 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002853 SMLoc Loc = getLexer().getLoc();
2854 Parser.eatToEndOfStatement();
2855 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002856}
2857
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002858bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002859 return Error(Loc, ErrorMsg);
2860}
2861
Jack Carter0b744b32012-10-04 02:29:46 +00002862bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002863 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002864 // Line should look like: ".set noat".
2865 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002866 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002867 // eat noat
2868 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002869 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002871 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002872 return false;
2873 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002874 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002875 return false;
2876}
Jack Carterd0bd6422013-04-18 00:41:53 +00002877
Jack Carter0b744b32012-10-04 02:29:46 +00002878bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002879 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002880 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002881 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002882 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002883 getParser().Lex();
2884 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002885 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002886 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002887 return false;
2888 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002889 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002890 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002891 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002892 return false;
2893 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002894 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002895 const AsmToken &Reg = Parser.getTok();
2896 if (Reg.is(AsmToken::Identifier)) {
2897 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2898 } else if (Reg.is(AsmToken::Integer)) {
2899 AtRegNo = Reg.getIntVal();
2900 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002901 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002902 return false;
2903 }
Jack Carter1ac53222013-02-20 23:11:17 +00002904
Daniel Sanders71a89d922014-03-25 13:01:06 +00002905 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002906 reportParseError("unexpected token in statement");
2907 return false;
2908 }
2909
Toma Tabacu9db22db2014-09-09 10:15:38 +00002910 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002911 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002912 return false;
2913 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002914 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002915
2916 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002917 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002918 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002919 }
2920 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002921 return false;
2922 } else {
2923 reportParseError("unexpected token in statement");
2924 return false;
2925 }
2926}
2927
2928bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002929 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002930 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002931 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002932 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002933 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002934 return false;
2935 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002936 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002937 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002938 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002939 return false;
2940}
2941
2942bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002943 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002944 Parser.Lex();
2945 // If this is not the end of the statement, report an error.
2946 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002947 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002948 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002949 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002950 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002951 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002952 Parser.Lex(); // Consume the EndOfStatement.
2953 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002954}
2955
2956bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002957 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002958 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002959 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002961 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002962 return false;
2963 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002964 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002965 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002966 return false;
2967}
2968
2969bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002970 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002971 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002972 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002973 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002974 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002975 return false;
2976 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002977 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002978 reportParseError("`noreorder' must be set before `nomacro'");
2979 return false;
2980 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002981 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002982 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002983 return false;
2984}
Jack Carterd76b2372013-03-21 21:44:16 +00002985
Daniel Sanders44934432014-08-07 12:03:36 +00002986bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002987 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002988 Parser.Lex();
2989
2990 // If this is not the end of the statement, report an error.
2991 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002992 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002993
2994 setFeatureBits(Mips::FeatureMSA, "msa");
2995 getTargetStreamer().emitDirectiveSetMsa();
2996 return false;
2997}
2998
2999bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003000 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003001 Parser.Lex();
3002
3003 // If this is not the end of the statement, report an error.
3004 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003005 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003006
3007 clearFeatureBits(Mips::FeatureMSA, "msa");
3008 getTargetStreamer().emitDirectiveSetNoMsa();
3009 return false;
3010}
3011
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003012bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003013 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003014 Parser.Lex(); // Eat "nodsp".
3015
3016 // If this is not the end of the statement, report an error.
3017 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3018 reportParseError("unexpected token, expected end of statement");
3019 return false;
3020 }
3021
3022 clearFeatureBits(Mips::FeatureDSP, "dsp");
3023 getTargetStreamer().emitDirectiveSetNoDsp();
3024 return false;
3025}
3026
Toma Tabacucc2502d2014-11-04 17:18:07 +00003027bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003028 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003029 Parser.Lex(); // Eat "mips16".
3030
Jack Carter39536722014-01-22 23:08:42 +00003031 // If this is not the end of the statement, report an error.
3032 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003033 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003034 return false;
3035 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003036
3037 setFeatureBits(Mips::FeatureMips16, "mips16");
3038 getTargetStreamer().emitDirectiveSetMips16();
3039 Parser.Lex(); // Consume the EndOfStatement.
3040 return false;
3041}
3042
3043bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003044 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003045 Parser.Lex(); // Eat "nomips16".
3046
3047 // If this is not the end of the statement, report an error.
3048 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3049 reportParseError("unexpected token, expected end of statement");
3050 return false;
3051 }
3052
3053 clearFeatureBits(Mips::FeatureMips16, "mips16");
3054 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003055 Parser.Lex(); // Consume the EndOfStatement.
3056 return false;
3057}
3058
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003059bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003060 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003061 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003062 // Line can be: .set fp=32
3063 // .set fp=xx
3064 // .set fp=64
3065 Parser.Lex(); // Eat fp token
3066 AsmToken Tok = Parser.getTok();
3067 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003068 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003069 return false;
3070 }
3071 Parser.Lex(); // Eat '=' token.
3072 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003073
3074 if (!parseFpABIValue(FpAbiVal, ".set"))
3075 return false;
3076
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003077 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003078 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003079 return false;
3080 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003081 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003082 Parser.Lex(); // Consume the EndOfStatement.
3083 return false;
3084}
3085
Toma Tabacu9db22db2014-09-09 10:15:38 +00003086bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003087 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003088 SMLoc Loc = getLexer().getLoc();
3089
3090 Parser.Lex();
3091 if (getLexer().isNot(AsmToken::EndOfStatement))
3092 return reportParseError("unexpected token, expected end of statement");
3093
3094 // Always keep an element on the options "stack" to prevent the user
3095 // from changing the initial options. This is how we remember them.
3096 if (AssemblerOptions.size() == 2)
3097 return reportParseError(Loc, ".set pop with no .set push");
3098
3099 AssemblerOptions.pop_back();
3100 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3101
3102 getTargetStreamer().emitDirectiveSetPop();
3103 return false;
3104}
3105
3106bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003107 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003108 Parser.Lex();
3109 if (getLexer().isNot(AsmToken::EndOfStatement))
3110 return reportParseError("unexpected token, expected end of statement");
3111
3112 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003113 AssemblerOptions.push_back(
3114 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003115
3116 getTargetStreamer().emitDirectiveSetPush();
3117 return false;
3118}
3119
Jack Carterd76b2372013-03-21 21:44:16 +00003120bool MipsAsmParser::parseSetAssignment() {
3121 StringRef Name;
3122 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003123 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003124
3125 if (Parser.parseIdentifier(Name))
3126 reportParseError("expected identifier after .set");
3127
3128 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003129 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003130 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003131
Jack Carter3b2c96e2014-01-22 23:31:38 +00003132 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003133 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003134
Jack Carterd0bd6422013-04-18 00:41:53 +00003135 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003136 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003137 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003138 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003139 Sym = getContext().GetOrCreateSymbol(Name);
3140 Sym->setVariableValue(Value);
3141
3142 return false;
3143}
Jack Carterd0bd6422013-04-18 00:41:53 +00003144
Toma Tabacu26647792014-09-09 12:52:14 +00003145bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003146 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003147 Parser.Lex();
3148 if (getLexer().isNot(AsmToken::EndOfStatement))
3149 return reportParseError("unexpected token, expected end of statement");
3150
3151 // Reset assembler options to their initial values.
3152 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3153 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3154
3155 getTargetStreamer().emitDirectiveSetMips0();
3156 return false;
3157}
3158
Toma Tabacu85618b32014-08-19 14:22:52 +00003159bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003160 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003161 Parser.Lex();
3162 if (getLexer().isNot(AsmToken::Equal))
3163 return reportParseError("unexpected token, expected equals sign");
3164
3165 Parser.Lex();
3166 StringRef Arch;
3167 if (Parser.parseIdentifier(Arch))
3168 return reportParseError("expected arch identifier");
3169
3170 StringRef ArchFeatureName =
3171 StringSwitch<StringRef>(Arch)
3172 .Case("mips1", "mips1")
3173 .Case("mips2", "mips2")
3174 .Case("mips3", "mips3")
3175 .Case("mips4", "mips4")
3176 .Case("mips5", "mips5")
3177 .Case("mips32", "mips32")
3178 .Case("mips32r2", "mips32r2")
3179 .Case("mips32r6", "mips32r6")
3180 .Case("mips64", "mips64")
3181 .Case("mips64r2", "mips64r2")
3182 .Case("mips64r6", "mips64r6")
3183 .Case("cnmips", "cnmips")
3184 .Case("r4000", "mips3") // This is an implementation of Mips3.
3185 .Default("");
3186
3187 if (ArchFeatureName.empty())
3188 return reportParseError("unsupported architecture");
3189
3190 selectArch(ArchFeatureName);
3191 getTargetStreamer().emitDirectiveSetArch(Arch);
3192 return false;
3193}
3194
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003195bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003196 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003197 Parser.Lex();
3198 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003199 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003200
Matheus Almeida2852af82014-04-22 10:15:54 +00003201 switch (Feature) {
3202 default:
3203 llvm_unreachable("Unimplemented feature");
3204 case Mips::FeatureDSP:
3205 setFeatureBits(Mips::FeatureDSP, "dsp");
3206 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003207 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003208 case Mips::FeatureMicroMips:
3209 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003210 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003211 case Mips::FeatureMips1:
3212 selectArch("mips1");
3213 getTargetStreamer().emitDirectiveSetMips1();
3214 break;
3215 case Mips::FeatureMips2:
3216 selectArch("mips2");
3217 getTargetStreamer().emitDirectiveSetMips2();
3218 break;
3219 case Mips::FeatureMips3:
3220 selectArch("mips3");
3221 getTargetStreamer().emitDirectiveSetMips3();
3222 break;
3223 case Mips::FeatureMips4:
3224 selectArch("mips4");
3225 getTargetStreamer().emitDirectiveSetMips4();
3226 break;
3227 case Mips::FeatureMips5:
3228 selectArch("mips5");
3229 getTargetStreamer().emitDirectiveSetMips5();
3230 break;
3231 case Mips::FeatureMips32:
3232 selectArch("mips32");
3233 getTargetStreamer().emitDirectiveSetMips32();
3234 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003235 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003236 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003237 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003238 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003239 case Mips::FeatureMips32r6:
3240 selectArch("mips32r6");
3241 getTargetStreamer().emitDirectiveSetMips32R6();
3242 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003243 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003244 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003245 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003246 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003247 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003248 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003249 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003250 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003251 case Mips::FeatureMips64r6:
3252 selectArch("mips64r6");
3253 getTargetStreamer().emitDirectiveSetMips64R6();
3254 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003255 }
3256 return false;
3257}
3258
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003259bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003260 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003261 if (getLexer().isNot(AsmToken::Comma)) {
3262 SMLoc Loc = getLexer().getLoc();
3263 Parser.eatToEndOfStatement();
3264 return Error(Loc, ErrorStr);
3265 }
3266
Matheus Almeida2852af82014-04-22 10:15:54 +00003267 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003268 return true;
3269}
3270
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003271bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003272 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003273 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003274
Toma Tabacudde4c462014-11-06 10:02:45 +00003275 if (inMips16Mode()) {
3276 reportParseError(".cpload is not supported in Mips16 mode");
3277 return false;
3278 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003279
David Blaikie960ea3f2014-06-08 16:18:35 +00003280 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003281 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003282 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3283 reportParseError("expected register containing function address");
3284 return false;
3285 }
3286
David Blaikie960ea3f2014-06-08 16:18:35 +00003287 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3288 if (!RegOpnd.isGPRAsmReg()) {
3289 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003290 return false;
3291 }
3292
Toma Tabacudde4c462014-11-06 10:02:45 +00003293 // If this is not the end of the statement, report an error.
3294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3295 reportParseError("unexpected token, expected end of statement");
3296 return false;
3297 }
3298
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003299 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003300 return false;
3301}
3302
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003303bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003304 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003305 unsigned FuncReg;
3306 unsigned Save;
3307 bool SaveIsReg = true;
3308
Matheus Almeida7e815762014-06-18 13:08:59 +00003309 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003310 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003311 if (ResTy == MatchOperand_NoMatch) {
3312 reportParseError("expected register containing function address");
3313 Parser.eatToEndOfStatement();
3314 return false;
3315 }
3316
3317 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3318 if (!FuncRegOpnd.isGPRAsmReg()) {
3319 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3320 Parser.eatToEndOfStatement();
3321 return false;
3322 }
3323
3324 FuncReg = FuncRegOpnd.getGPR32Reg();
3325 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003326
Toma Tabacu65f10572014-09-16 15:00:52 +00003327 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003328 return true;
3329
Toma Tabacu13964452014-09-04 13:23:44 +00003330 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003331 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003332 const AsmToken &Tok = Parser.getTok();
3333 if (Tok.is(AsmToken::Integer)) {
3334 Save = Tok.getIntVal();
3335 SaveIsReg = false;
3336 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003337 } else {
3338 reportParseError("expected save register or stack offset");
3339 Parser.eatToEndOfStatement();
3340 return false;
3341 }
3342 } else {
3343 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3344 if (!SaveOpnd.isGPRAsmReg()) {
3345 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3346 Parser.eatToEndOfStatement();
3347 return false;
3348 }
3349 Save = SaveOpnd.getGPR32Reg();
3350 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003351
Toma Tabacu65f10572014-09-16 15:00:52 +00003352 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003353 return true;
3354
3355 StringRef Name;
3356 if (Parser.parseIdentifier(Name))
3357 reportParseError("expected identifier");
3358 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003359
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003360 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003361 return false;
3362}
3363
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003364bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003365 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3367 const AsmToken &Tok = Parser.getTok();
3368
3369 if (Tok.getString() == "2008") {
3370 Parser.Lex();
3371 getTargetStreamer().emitDirectiveNaN2008();
3372 return false;
3373 } else if (Tok.getString() == "legacy") {
3374 Parser.Lex();
3375 getTargetStreamer().emitDirectiveNaNLegacy();
3376 return false;
3377 }
3378 }
3379 // If we don't recognize the option passed to the .nan
3380 // directive (e.g. no option or unknown option), emit an error.
3381 reportParseError("invalid option in .nan directive");
3382 return false;
3383}
3384
Jack Carter0b744b32012-10-04 02:29:46 +00003385bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003386 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003387 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003388 const AsmToken &Tok = Parser.getTok();
3389
3390 if (Tok.getString() == "noat") {
3391 return parseSetNoAtDirective();
3392 } else if (Tok.getString() == "at") {
3393 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003394 } else if (Tok.getString() == "arch") {
3395 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003396 } else if (Tok.getString() == "fp") {
3397 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003398 } else if (Tok.getString() == "pop") {
3399 return parseSetPopDirective();
3400 } else if (Tok.getString() == "push") {
3401 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003402 } else if (Tok.getString() == "reorder") {
3403 return parseSetReorderDirective();
3404 } else if (Tok.getString() == "noreorder") {
3405 return parseSetNoReorderDirective();
3406 } else if (Tok.getString() == "macro") {
3407 return parseSetMacroDirective();
3408 } else if (Tok.getString() == "nomacro") {
3409 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003410 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003411 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003412 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003413 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003414 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003415 getTargetStreamer().emitDirectiveSetNoMicroMips();
3416 Parser.eatToEndOfStatement();
3417 return false;
3418 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003419 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003420 } else if (Tok.getString() == "mips0") {
3421 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003422 } else if (Tok.getString() == "mips1") {
3423 return parseSetFeature(Mips::FeatureMips1);
3424 } else if (Tok.getString() == "mips2") {
3425 return parseSetFeature(Mips::FeatureMips2);
3426 } else if (Tok.getString() == "mips3") {
3427 return parseSetFeature(Mips::FeatureMips3);
3428 } else if (Tok.getString() == "mips4") {
3429 return parseSetFeature(Mips::FeatureMips4);
3430 } else if (Tok.getString() == "mips5") {
3431 return parseSetFeature(Mips::FeatureMips5);
3432 } else if (Tok.getString() == "mips32") {
3433 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003434 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003435 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003436 } else if (Tok.getString() == "mips32r6") {
3437 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003438 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003439 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003440 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003441 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003442 } else if (Tok.getString() == "mips64r6") {
3443 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003444 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003445 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003446 } else if (Tok.getString() == "nodsp") {
3447 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003448 } else if (Tok.getString() == "msa") {
3449 return parseSetMsaDirective();
3450 } else if (Tok.getString() == "nomsa") {
3451 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003452 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003453 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003454 parseSetAssignment();
3455 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003456 }
Jack Carter07c818d2013-01-25 01:31:34 +00003457
Jack Carter0b744b32012-10-04 02:29:46 +00003458 return true;
3459}
3460
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003461/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003462/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003463bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003464 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3466 for (;;) {
3467 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003468 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003469 return true;
3470
3471 getParser().getStreamer().EmitValue(Value, Size);
3472
3473 if (getLexer().is(AsmToken::EndOfStatement))
3474 break;
3475
Jack Carter07c818d2013-01-25 01:31:34 +00003476 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003477 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003478 Parser.Lex();
3479 }
3480 }
3481
3482 Parser.Lex();
3483 return false;
3484}
3485
Vladimir Medic4c299852013-11-06 11:27:05 +00003486/// parseDirectiveGpWord
3487/// ::= .gpword local_sym
3488bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003489 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003490 const MCExpr *Value;
3491 // EmitGPRel32Value requires an expression, so we are using base class
3492 // method to evaluate the expression.
3493 if (getParser().parseExpression(Value))
3494 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003495 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003496
Vladimir Medice10c1122013-11-13 13:18:04 +00003497 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003498 return Error(getLexer().getLoc(),
3499 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003500 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003501 return false;
3502}
3503
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003504/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003505/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003506bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003507 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003508 const MCExpr *Value;
3509 // EmitGPRel64Value requires an expression, so we are using base class
3510 // method to evaluate the expression.
3511 if (getParser().parseExpression(Value))
3512 return true;
3513 getParser().getStreamer().EmitGPRel64Value(Value);
3514
3515 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003516 return Error(getLexer().getLoc(),
3517 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003518 Parser.Lex(); // Eat EndOfStatement token.
3519 return false;
3520}
3521
Jack Carter0cd3c192014-01-06 23:27:31 +00003522bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003523 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003524 // Get the option token.
3525 AsmToken Tok = Parser.getTok();
3526 // At the moment only identifiers are supported.
3527 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003528 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003529 Parser.eatToEndOfStatement();
3530 return false;
3531 }
3532
3533 StringRef Option = Tok.getIdentifier();
3534
3535 if (Option == "pic0") {
3536 getTargetStreamer().emitDirectiveOptionPic0();
3537 Parser.Lex();
3538 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3539 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003540 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003541 Parser.eatToEndOfStatement();
3542 }
3543 return false;
3544 }
3545
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003546 if (Option == "pic2") {
3547 getTargetStreamer().emitDirectiveOptionPic2();
3548 Parser.Lex();
3549 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3550 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003551 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003552 Parser.eatToEndOfStatement();
3553 }
3554 return false;
3555 }
3556
Jack Carter0cd3c192014-01-06 23:27:31 +00003557 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003558 Warning(Parser.getTok().getLoc(),
3559 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003560 Parser.eatToEndOfStatement();
3561 return false;
3562}
3563
Daniel Sanders7e527422014-07-10 13:38:23 +00003564/// parseDirectiveModule
3565/// ::= .module oddspreg
3566/// ::= .module nooddspreg
3567/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003568bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003569 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003570 MCAsmLexer &Lexer = getLexer();
3571 SMLoc L = Lexer.getLoc();
3572
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003573 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003574 // TODO : get a better message.
3575 reportParseError(".module directive must appear before any code");
3576 return false;
3577 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003578
3579 if (Lexer.is(AsmToken::Identifier)) {
3580 StringRef Option = Parser.getTok().getString();
3581 Parser.Lex();
3582
3583 if (Option == "oddspreg") {
3584 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3585 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3586
3587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003588 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003589 return false;
3590 }
3591
3592 return false;
3593 } else if (Option == "nooddspreg") {
3594 if (!isABI_O32()) {
3595 Error(L, "'.module nooddspreg' requires the O32 ABI");
3596 return false;
3597 }
3598
3599 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3600 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3601
3602 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003603 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003604 return false;
3605 }
3606
3607 return false;
3608 } else if (Option == "fp") {
3609 return parseDirectiveModuleFP();
3610 }
3611
3612 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003613 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003614
3615 return false;
3616}
3617
3618/// parseDirectiveModuleFP
3619/// ::= =32
3620/// ::= =xx
3621/// ::= =64
3622bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003623 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003624 MCAsmLexer &Lexer = getLexer();
3625
3626 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003627 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003628 return false;
3629 }
3630 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003631
Daniel Sanders7e527422014-07-10 13:38:23 +00003632 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003633 if (!parseFpABIValue(FpABI, ".module"))
3634 return false;
3635
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003636 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003637 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003638 return false;
3639 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003640
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003641 // Emit appropriate flags.
3642 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003643 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003644 return false;
3645}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003646
Daniel Sanders7e527422014-07-10 13:38:23 +00003647bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003648 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003649 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003650 MCAsmLexer &Lexer = getLexer();
3651
3652 if (Lexer.is(AsmToken::Identifier)) {
3653 StringRef Value = Parser.getTok().getString();
3654 Parser.Lex();
3655
3656 if (Value != "xx") {
3657 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3658 return false;
3659 }
3660
3661 if (!isABI_O32()) {
3662 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3663 return false;
3664 }
3665
Daniel Sanders7e527422014-07-10 13:38:23 +00003666 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003667 return true;
3668 }
3669
3670 if (Lexer.is(AsmToken::Integer)) {
3671 unsigned Value = Parser.getTok().getIntVal();
3672 Parser.Lex();
3673
3674 if (Value != 32 && Value != 64) {
3675 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3676 return false;
3677 }
3678
3679 if (Value == 32) {
3680 if (!isABI_O32()) {
3681 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3682 return false;
3683 }
3684
Daniel Sanders7e527422014-07-10 13:38:23 +00003685 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3686 } else
3687 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003688
Daniel Sanders7e527422014-07-10 13:38:23 +00003689 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003690 }
3691
3692 return false;
3693}
3694
Jack Carter0b744b32012-10-04 02:29:46 +00003695bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003696 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003697 StringRef IDVal = DirectiveID.getString();
3698
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003699 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003700 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003701 if (IDVal == ".dword") {
3702 parseDataDirective(8, DirectiveID.getLoc());
3703 return false;
3704 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003705 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003706 StringRef SymbolName;
3707
3708 if (Parser.parseIdentifier(SymbolName)) {
3709 reportParseError("expected identifier after .ent");
3710 return false;
3711 }
3712
3713 // There's an undocumented extension that allows an integer to
3714 // follow the name of the procedure which AFAICS is ignored by GAS.
3715 // Example: .ent foo,2
3716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3717 if (getLexer().isNot(AsmToken::Comma)) {
3718 // Even though we accept this undocumented extension for compatibility
3719 // reasons, the additional integer argument does not actually change
3720 // the behaviour of the '.ent' directive, so we would like to discourage
3721 // its use. We do this by not referring to the extended version in
3722 // error messages which are not directly related to its use.
3723 reportParseError("unexpected token, expected end of statement");
3724 return false;
3725 }
3726 Parser.Lex(); // Eat the comma.
3727 const MCExpr *DummyNumber;
3728 int64_t DummyNumberVal;
3729 // If the user was explicitly trying to use the extended version,
3730 // we still give helpful extension-related error messages.
3731 if (Parser.parseExpression(DummyNumber)) {
3732 reportParseError("expected number after comma");
3733 return false;
3734 }
3735 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3736 reportParseError("expected an absolute expression after comma");
3737 return false;
3738 }
3739 }
3740
3741 // If this is not the end of the statement, report an error.
3742 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3743 reportParseError("unexpected token, expected end of statement");
3744 return false;
3745 }
3746
3747 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3748
3749 getTargetStreamer().emitDirectiveEnt(*Sym);
3750 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003751 return false;
3752 }
3753
Jack Carter07c818d2013-01-25 01:31:34 +00003754 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003755 StringRef SymbolName;
3756
3757 if (Parser.parseIdentifier(SymbolName)) {
3758 reportParseError("expected identifier after .end");
3759 return false;
3760 }
3761
3762 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3763 reportParseError("unexpected token, expected end of statement");
3764 return false;
3765 }
3766
3767 if (CurrentFn == nullptr) {
3768 reportParseError(".end used without .ent");
3769 return false;
3770 }
3771
3772 if ((SymbolName != CurrentFn->getName())) {
3773 reportParseError(".end symbol does not match .ent symbol");
3774 return false;
3775 }
3776
3777 getTargetStreamer().emitDirectiveEnd(SymbolName);
3778 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003779 return false;
3780 }
3781
Jack Carter07c818d2013-01-25 01:31:34 +00003782 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003783 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3784 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003785 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003786 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3787 reportParseError("expected stack register");
3788 return false;
3789 }
3790
3791 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3792 if (!StackRegOpnd.isGPRAsmReg()) {
3793 reportParseError(StackRegOpnd.getStartLoc(),
3794 "expected general purpose register");
3795 return false;
3796 }
3797 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3798
3799 if (Parser.getTok().is(AsmToken::Comma))
3800 Parser.Lex();
3801 else {
3802 reportParseError("unexpected token, expected comma");
3803 return false;
3804 }
3805
3806 // Parse the frame size.
3807 const MCExpr *FrameSize;
3808 int64_t FrameSizeVal;
3809
3810 if (Parser.parseExpression(FrameSize)) {
3811 reportParseError("expected frame size value");
3812 return false;
3813 }
3814
3815 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3816 reportParseError("frame size not an absolute expression");
3817 return false;
3818 }
3819
3820 if (Parser.getTok().is(AsmToken::Comma))
3821 Parser.Lex();
3822 else {
3823 reportParseError("unexpected token, expected comma");
3824 return false;
3825 }
3826
3827 // Parse the return register.
3828 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003829 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003830 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3831 reportParseError("expected return register");
3832 return false;
3833 }
3834
3835 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3836 if (!ReturnRegOpnd.isGPRAsmReg()) {
3837 reportParseError(ReturnRegOpnd.getStartLoc(),
3838 "expected general purpose register");
3839 return false;
3840 }
3841
3842 // If this is not the end of the statement, report an error.
3843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3844 reportParseError("unexpected token, expected end of statement");
3845 return false;
3846 }
3847
3848 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3849 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003850 return false;
3851 }
3852
Jack Carter07c818d2013-01-25 01:31:34 +00003853 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003854 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003855 }
3856
Daniel Sandersd97a6342014-08-13 10:07:34 +00003857 if (IDVal == ".mask" || IDVal == ".fmask") {
3858 // .mask bitmask, frame_offset
3859 // bitmask: One bit for each register used.
3860 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3861 // first register is expected to be saved.
3862 // Examples:
3863 // .mask 0x80000000, -4
3864 // .fmask 0x80000000, -4
3865 //
Jack Carterbe332172012-09-07 00:48:02 +00003866
Daniel Sandersd97a6342014-08-13 10:07:34 +00003867 // Parse the bitmask
3868 const MCExpr *BitMask;
3869 int64_t BitMaskVal;
3870
3871 if (Parser.parseExpression(BitMask)) {
3872 reportParseError("expected bitmask value");
3873 return false;
3874 }
3875
3876 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3877 reportParseError("bitmask not an absolute expression");
3878 return false;
3879 }
3880
3881 if (Parser.getTok().is(AsmToken::Comma))
3882 Parser.Lex();
3883 else {
3884 reportParseError("unexpected token, expected comma");
3885 return false;
3886 }
3887
3888 // Parse the frame_offset
3889 const MCExpr *FrameOffset;
3890 int64_t FrameOffsetVal;
3891
3892 if (Parser.parseExpression(FrameOffset)) {
3893 reportParseError("expected frame offset value");
3894 return false;
3895 }
3896
3897 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3898 reportParseError("frame offset not an absolute expression");
3899 return false;
3900 }
3901
3902 // If this is not the end of the statement, report an error.
3903 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3904 reportParseError("unexpected token, expected end of statement");
3905 return false;
3906 }
3907
3908 if (IDVal == ".mask")
3909 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3910 else
3911 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003912 return false;
3913 }
3914
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003915 if (IDVal == ".nan")
3916 return parseDirectiveNaN();
3917
Jack Carter07c818d2013-01-25 01:31:34 +00003918 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003919 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003920 return false;
3921 }
3922
Rafael Espindolab59fb732014-03-28 18:50:26 +00003923 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003924 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003925 return false;
3926 }
3927
Jack Carter07c818d2013-01-25 01:31:34 +00003928 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003929 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003930 return false;
3931 }
3932
Jack Carter0cd3c192014-01-06 23:27:31 +00003933 if (IDVal == ".option")
3934 return parseDirectiveOption();
3935
3936 if (IDVal == ".abicalls") {
3937 getTargetStreamer().emitDirectiveAbiCalls();
3938 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003939 Error(Parser.getTok().getLoc(),
3940 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003941 // Clear line
3942 Parser.eatToEndOfStatement();
3943 }
3944 return false;
3945 }
3946
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003947 if (IDVal == ".cpsetup")
3948 return parseDirectiveCPSetup();
3949
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003950 if (IDVal == ".module")
3951 return parseDirectiveModule();
3952
Rafael Espindola870c4e92012-01-11 03:56:41 +00003953 return true;
3954}
3955
Rafael Espindola870c4e92012-01-11 03:56:41 +00003956extern "C" void LLVMInitializeMipsAsmParser() {
3957 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3958 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3959 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3960 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3961}
Jack Carterb4dbc172012-09-05 23:34:03 +00003962
3963#define GET_REGISTER_MATCHER
3964#define GET_MATCHER_IMPLEMENTATION
3965#include "MipsGenAsmMatcher.inc"