blob: efb987e281b9bb1fdc855cabbb74df2a55325bd2 [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"
Toma Tabacu9db22db2014-09-09 10:15:38 +000015#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000016#include "llvm/ADT/StringSwitch.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"
Daniel Sandersef638fe2014-10-03 15:37:37 +000029#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000030#include "llvm/Support/TargetRegistry.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
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000150 parseRegisterPair (OperandVector &Operands);
151
152 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000153 parseRegisterList (OperandVector &Operands);
154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 bool searchSymbolAlias(OperandVector &Operands);
156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000158
Jack Carter30a59822012-10-04 04:03:53 +0000159 bool needsExpansion(MCInst &Inst);
160
Matheus Almeida3813d572014-06-19 14:39:14 +0000161 // Expands assembly pseudo instructions.
162 // Returns false on success, true otherwise.
163 bool expandInstruction(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 expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000167 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000168
169 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
172 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000173 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000174
Toma Tabacu0d64b202014-08-14 10:29:17 +0000175 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
176 SmallVectorImpl<MCInst> &Instructions);
177
Jack Carter9e65aa32013-03-22 00:05:30 +0000178 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000179 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
180 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000181 bool reportParseError(Twine ErrorMsg);
182 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000183
Jack Carterb5cf5902013-04-17 00:18:04 +0000184 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000185 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000186
Vladimir Medic4c299852013-11-06 11:27:05 +0000187 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000188
189 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000190 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000191 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000192 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000193 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000194 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000195 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000196 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000197 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000198
199 bool parseSetAtDirective();
200 bool parseSetNoAtDirective();
201 bool parseSetMacroDirective();
202 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000203 bool parseSetMsaDirective();
204 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000205 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000206 bool parseSetReorderDirective();
207 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000208 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000209 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000210 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000211 bool parseSetPopDirective();
212 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000213
Jack Carterd76b2372013-03-21 21:44:16 +0000214 bool parseSetAssignment();
215
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000216 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000217 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000218 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000219 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000220 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000221 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
222 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000223
Jack Carterdc1e35d2012-09-06 20:00:02 +0000224 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000225
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000226 bool eatComma(StringRef ErrorStr);
227
Jack Carter1ac53222013-02-20 23:11:17 +0000228 int matchCPURegisterName(StringRef Symbol);
229
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000230 int matchHWRegsRegisterName(StringRef Symbol);
231
Jack Carter873c7242013-01-12 01:03:14 +0000232 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000233
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000234 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000235
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000236 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000237
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000238 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000239
Jack Carter5dc8ac92013-09-25 23:50:44 +0000240 int matchMSA128RegisterName(StringRef Name);
241
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000242 int matchMSA128CtrlRegisterName(StringRef Name);
243
Jack Carterd0bd6422013-04-18 00:41:53 +0000244 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000245
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000246 unsigned getGPR(int RegNo);
247
Matheus Almeida7de68e72014-06-18 14:46:05 +0000248 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000249
250 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000252
253 // Helper function that checks if the value of a vector index is within the
254 // boundaries of accepted values for each RegisterKind
255 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
256 bool validateMSAIndex(int Val, int RegKind);
257
Daniel Sandersf0df2212014-08-04 12:20:00 +0000258 // Selects a new architecture by updating the FeatureBits with the necessary
259 // info including implied dependencies.
260 // Internally, it clears all the feature bits related to *any* architecture
261 // and selects the new one using the ToggleFeature functionality of the
262 // MCSubtargetInfo object that handles implied dependencies. The reason we
263 // clear all the arch related bits manually is because ToggleFeature only
264 // clears the features that imply the feature being cleared and not the
265 // features implied by the feature being cleared. This is easier to see
266 // with an example:
267 // --------------------------------------------------
268 // | Feature | Implies |
269 // | -------------------------------------------------|
270 // | FeatureMips1 | None |
271 // | FeatureMips2 | FeatureMips1 |
272 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
273 // | FeatureMips4 | FeatureMips3 |
274 // | ... | |
275 // --------------------------------------------------
276 //
277 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
278 // FeatureMipsGP64 | FeatureMips1)
279 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
280 void selectArch(StringRef ArchFeature) {
281 uint64_t FeatureBits = STI.getFeatureBits();
282 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
283 STI.setFeatureBits(FeatureBits);
284 setAvailableFeatures(
285 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000286 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000287 }
288
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000289 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000291 setAvailableFeatures(
292 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000293 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000294 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
296
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000297 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000298 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000299 setAvailableFeatures(
300 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000301 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000302 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000303 }
304
Rafael Espindola870c4e92012-01-11 03:56:41 +0000305public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000306 enum MipsMatchResultTy {
307 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
308#define GET_OPERAND_DIAGNOSTIC_TYPES
309#include "MipsGenAsmMatcher.inc"
310#undef GET_OPERAND_DIAGNOSTIC_TYPES
311
312 };
313
Joey Gouly0e76fa72013-09-12 10:28:05 +0000314 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000315 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000316 : MCTargetAsmParser(), STI(sti) {
317 MCAsmParserExtension::Initialize(parser);
318
Jack Carterb4dbc172012-09-05 23:34:03 +0000319 // Initialize the set of available features.
320 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000321
322 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000323 AssemblerOptions.push_back(
324 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325
326 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000327 AssemblerOptions.push_back(
328 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000329
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000330 getTargetStreamer().updateABIInfo(*this);
331
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000332 // Assert exactly one ABI was chosen.
333 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
334 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
335 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
336 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000337
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000338 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000339 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000340
341 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000342 }
343
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000344 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
345 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
348 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
349 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
350 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
351 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000352 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000353
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000354 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000355 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
356 }
357
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000358 bool inMicroMipsMode() const {
359 return STI.getFeatureBits() & Mips::FeatureMicroMips;
360 }
361 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
362 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
363 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
364 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
365 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
366 bool hasMips32() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips32);
368 }
369 bool hasMips64() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips64);
371 }
372 bool hasMips32r2() const {
373 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
374 }
375 bool hasMips64r2() const {
376 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
377 }
378 bool hasMips32r6() const {
379 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
380 }
381 bool hasMips64r6() const {
382 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
383 }
384 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
385 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
386 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
387
388 bool inMips16Mode() const {
389 return STI.getFeatureBits() & Mips::FeatureMips16;
390 }
391 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000392 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000393
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000394 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000395 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000396};
397}
398
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000399namespace {
400
401/// MipsOperand - Instances of this class represent a parsed Mips machine
402/// instruction.
403class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000404public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000405 /// Broad categories of register classes
406 /// The exact class is finalized by the render method.
407 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000408 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000409 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000411 RegKind_FCC = 4, /// FCC
412 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
413 RegKind_MSACtrl = 16, /// MSA control registers
414 RegKind_COP2 = 32, /// COP2
415 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
416 /// context).
417 RegKind_CCR = 128, /// CCR
418 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000419 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000420
421 /// Potentially any (e.g. $1)
422 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
423 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000424 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000425 };
426
427private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000428 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000429 k_Immediate, /// An immediate (possibly involving symbol references)
430 k_Memory, /// Base + Offset Memory Address
431 k_PhysRegister, /// A physical register from the Mips namespace
432 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000433 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000434 k_RegList, /// A physical register list
435 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000436 } Kind;
437
David Blaikie960ea3f2014-06-08 16:18:35 +0000438public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000439 MipsOperand(KindTy K, MipsAsmParser &Parser)
440 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
441
David Blaikie960ea3f2014-06-08 16:18:35 +0000442private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 /// For diagnostics, and checking the assembler temporary
444 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000445
Eric Christopher8996c5d2013-03-15 00:42:55 +0000446 struct Token {
447 const char *Data;
448 unsigned Length;
449 };
450
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000451 struct PhysRegOp {
452 unsigned Num; /// Register Number
453 };
454
455 struct RegIdxOp {
456 unsigned Index; /// Index into the register class
457 RegKind Kind; /// Bitfield of the kinds it could possibly be
458 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000459 };
460
461 struct ImmOp {
462 const MCExpr *Val;
463 };
464
465 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000467 const MCExpr *Off;
468 };
469
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000470 struct RegListOp {
471 SmallVector<unsigned, 10> *List;
472 };
473
Jack Carterb4dbc172012-09-05 23:34:03 +0000474 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000475 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000476 struct PhysRegOp PhysReg;
477 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000478 struct ImmOp Imm;
479 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000480 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000481 };
482
483 SMLoc StartLoc, EndLoc;
484
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000485 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000486 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
487 const MCRegisterInfo *RegInfo,
488 SMLoc S, SMLoc E,
489 MipsAsmParser &Parser) {
490 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 Op->RegIdx.Index = Index;
492 Op->RegIdx.RegInfo = RegInfo;
493 Op->RegIdx.Kind = RegKind;
494 Op->StartLoc = S;
495 Op->EndLoc = E;
496 return Op;
497 }
498
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000499public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000500 /// Coerce the register to GPR32 and return the real register for the current
501 /// target.
502 unsigned getGPR32Reg() const {
503 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000504 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 unsigned ClassID = Mips::GPR32RegClassID;
506 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000507 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000508
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000509 /// Coerce the register to GPR32 and return the real register for the current
510 /// target.
511 unsigned getGPRMM16Reg() const {
512 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
513 unsigned ClassID = Mips::GPR32RegClassID;
514 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
515 }
516
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 /// Coerce the register to GPR64 and return the real register for the current
518 /// target.
519 unsigned getGPR64Reg() const {
520 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
521 unsigned ClassID = Mips::GPR64RegClassID;
522 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000523 }
524
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000525private:
526 /// Coerce the register to AFGR64 and return the real register for the current
527 /// target.
528 unsigned getAFGR64Reg() const {
529 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
530 if (RegIdx.Index % 2 != 0)
531 AsmParser.Warning(StartLoc, "Float register should be even.");
532 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
533 .getRegister(RegIdx.Index / 2);
534 }
535
536 /// Coerce the register to FGR64 and return the real register for the current
537 /// target.
538 unsigned getFGR64Reg() const {
539 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
540 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
541 .getRegister(RegIdx.Index);
542 }
543
544 /// Coerce the register to FGR32 and return the real register for the current
545 /// target.
546 unsigned getFGR32Reg() const {
547 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
548 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
549 .getRegister(RegIdx.Index);
550 }
551
552 /// Coerce the register to FGRH32 and return the real register for the current
553 /// target.
554 unsigned getFGRH32Reg() const {
555 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
556 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
557 .getRegister(RegIdx.Index);
558 }
559
560 /// Coerce the register to FCC and return the real register for the current
561 /// target.
562 unsigned getFCCReg() const {
563 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
564 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
565 .getRegister(RegIdx.Index);
566 }
567
568 /// Coerce the register to MSA128 and return the real register for the current
569 /// target.
570 unsigned getMSA128Reg() const {
571 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
572 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
573 // identical
574 unsigned ClassID = Mips::MSA128BRegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
576 }
577
578 /// Coerce the register to MSACtrl and return the real register for the
579 /// current target.
580 unsigned getMSACtrlReg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
582 unsigned ClassID = Mips::MSACtrlRegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584 }
585
586 /// Coerce the register to COP2 and return the real register for the
587 /// current target.
588 unsigned getCOP2Reg() const {
589 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
590 unsigned ClassID = Mips::COP2RegClassID;
591 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
592 }
593
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000594 /// Coerce the register to COP3 and return the real register for the
595 /// current target.
596 unsigned getCOP3Reg() const {
597 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
598 unsigned ClassID = Mips::COP3RegClassID;
599 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
600 }
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// Coerce the register to ACC64DSP and return the real register for the
603 /// current target.
604 unsigned getACC64DSPReg() const {
605 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
606 unsigned ClassID = Mips::ACC64DSPRegClassID;
607 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
608 }
609
610 /// Coerce the register to HI32DSP and return the real register for the
611 /// current target.
612 unsigned getHI32DSPReg() const {
613 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
614 unsigned ClassID = Mips::HI32DSPRegClassID;
615 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
616 }
617
618 /// Coerce the register to LO32DSP and return the real register for the
619 /// current target.
620 unsigned getLO32DSPReg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
622 unsigned ClassID = Mips::LO32DSPRegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
624 }
625
626 /// Coerce the register to CCR and return the real register for the
627 /// current target.
628 unsigned getCCRReg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
630 unsigned ClassID = Mips::CCRRegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
634 /// Coerce the register to HWRegs and return the real register for the
635 /// current target.
636 unsigned getHWRegsReg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
638 unsigned ClassID = Mips::HWRegsRegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
640 }
641
642public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000643 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000644 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000645 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 Inst.addOperand(MCOperand::CreateImm(0));
647 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
648 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
649 else
650 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000651 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000652
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 void addRegOperands(MCInst &Inst, unsigned N) const {
654 llvm_unreachable("Use a custom parser instead");
655 }
656
Daniel Sanders21bce302014-04-01 12:35:23 +0000657 /// Render the operand to an MCInst as a GPR32
658 /// Asserts if the wrong number of operands are requested, or the operand
659 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000660 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
661 assert(N == 1 && "Invalid number of operands!");
662 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
663 }
664
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000665 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
666 assert(N == 1 && "Invalid number of operands!");
667 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
668 }
669
Jozef Kolek1904fa22014-11-24 14:25:53 +0000670 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
673 }
674
Daniel Sanders21bce302014-04-01 12:35:23 +0000675 /// Render the operand to an MCInst as a GPR64
676 /// Asserts if the wrong number of operands are requested, or the operand
677 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
679 assert(N == 1 && "Invalid number of operands!");
680 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
681 }
682
683 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
684 assert(N == 1 && "Invalid number of operands!");
685 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
686 }
687
688 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
689 assert(N == 1 && "Invalid number of operands!");
690 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
691 }
692
693 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
694 assert(N == 1 && "Invalid number of operands!");
695 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000696 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000697 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000698 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
699 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 }
701
702 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
703 assert(N == 1 && "Invalid number of operands!");
704 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
705 }
706
707 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
708 assert(N == 1 && "Invalid number of operands!");
709 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
710 }
711
712 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
713 assert(N == 1 && "Invalid number of operands!");
714 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
715 }
716
717 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
718 assert(N == 1 && "Invalid number of operands!");
719 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
720 }
721
722 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
724 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
725 }
726
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000727 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
728 assert(N == 1 && "Invalid number of operands!");
729 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
730 }
731
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
733 assert(N == 1 && "Invalid number of operands!");
734 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
735 }
736
737 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
738 assert(N == 1 && "Invalid number of operands!");
739 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
740 }
741
742 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
743 assert(N == 1 && "Invalid number of operands!");
744 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
745 }
746
747 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
748 assert(N == 1 && "Invalid number of operands!");
749 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
750 }
751
752 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
754 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
755 }
756
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000758 assert(N == 1 && "Invalid number of operands!");
759 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000760 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000761 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000762
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000763 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000764 assert(N == 2 && "Invalid number of operands!");
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000767
768 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000769 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000770 }
771
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000772 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 2 && "Invalid number of operands!");
774
775 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
776
777 const MCExpr *Expr = getMemOff();
778 addExpr(Inst, Expr);
779 }
780
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000781 void addRegListOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
783
784 for (auto RegNo : getRegList())
785 Inst.addOperand(MCOperand::CreateReg(RegNo));
786 }
787
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000788 void addRegPairOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 2 && "Invalid number of operands!");
790 unsigned RegNo = getRegPair();
791 Inst.addOperand(MCOperand::CreateReg(RegNo++));
792 Inst.addOperand(MCOperand::CreateReg(RegNo));
793 }
794
Craig Topper56c590a2014-04-29 07:58:02 +0000795 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 // As a special case until we sort out the definition of div/divu, pretend
797 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
798 if (isGPRAsmReg() && RegIdx.Index == 0)
799 return true;
800
801 return Kind == k_PhysRegister;
802 }
803 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000804 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 bool isConstantImm() const {
806 return isImm() && dyn_cast<MCConstantExpr>(getImm());
807 }
Craig Topper56c590a2014-04-29 07:58:02 +0000808 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 // Note: It's not possible to pretend that other operand kinds are tokens.
810 // The matcher emitter checks tokens first.
811 return Kind == k_Token;
812 }
Craig Topper56c590a2014-04-29 07:58:02 +0000813 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000814 bool isConstantMemOff() const {
815 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
816 }
817 template <unsigned Bits> bool isMemWithSimmOffset() const {
818 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
819 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000820 bool isMemWithGRPMM16Base() const {
821 return isMem() && getMemBase()->isMM16AsmReg();
822 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000823 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
824 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
825 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
826 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000827 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
828 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
829 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
830 && (getMemBase()->getGPR32Reg() == Mips::SP);
831 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000832 bool isRegList16() const {
833 if (!isRegList())
834 return false;
835
836 int Size = RegList.List->size();
837 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
838 RegList.List->back() != Mips::RA)
839 return false;
840
841 int PrevReg = *RegList.List->begin();
842 for (int i = 1; i < Size - 1; i++) {
843 int Reg = (*(RegList.List))[i];
844 if ( Reg != PrevReg + 1)
845 return false;
846 PrevReg = Reg;
847 }
848
849 return true;
850 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000851 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000852 bool isLSAImm() const {
853 if (!isConstantImm())
854 return false;
855 int64_t Val = getConstantImm();
856 return 1 <= Val && Val <= 4;
857 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000858 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000859
860 StringRef getToken() const {
861 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000862 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000863 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000864 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000865
Craig Topper56c590a2014-04-29 07:58:02 +0000866 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 // As a special case until we sort out the definition of div/divu, pretend
868 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
869 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
870 RegIdx.Kind & RegKind_GPR)
871 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000872
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 assert(Kind == k_PhysRegister && "Invalid access!");
874 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000875 }
876
Jack Carterb4dbc172012-09-05 23:34:03 +0000877 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000879 return Imm.Val;
880 }
881
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 int64_t getConstantImm() const {
883 const MCExpr *Val = getImm();
884 return static_cast<const MCConstantExpr *>(Val)->getValue();
885 }
886
887 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000888 assert((Kind == k_Memory) && "Invalid access!");
889 return Mem.Base;
890 }
891
892 const MCExpr *getMemOff() const {
893 assert((Kind == k_Memory) && "Invalid access!");
894 return Mem.Off;
895 }
896
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000897 int64_t getConstantMemOff() const {
898 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
899 }
900
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 const SmallVectorImpl<unsigned> &getRegList() const {
902 assert((Kind == k_RegList) && "Invalid access!");
903 return *(RegList.List);
904 }
905
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000906 unsigned getRegPair() const {
907 assert((Kind == k_RegPair) && "Invalid access!");
908 return RegIdx.Index;
909 }
910
David Blaikie960ea3f2014-06-08 16:18:35 +0000911 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
912 MipsAsmParser &Parser) {
913 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000914 Op->Tok.Data = Str.data();
915 Op->Tok.Length = Str.size();
916 Op->StartLoc = S;
917 Op->EndLoc = S;
918 return Op;
919 }
920
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 /// Create a numeric register (e.g. $1). The exact register remains
922 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000923 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000924 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000925 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000926 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000928 }
929
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 /// Create a register that is definitely a GPR.
931 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000932 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000933 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000934 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000936 }
937
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 /// Create a register that is definitely a FGR.
939 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000940 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000941 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000942 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000943 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
944 }
945
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000946 /// Create a register that is definitely a HWReg.
947 /// This is typically only used for named registers such as $hwr_cpunum.
948 static std::unique_ptr<MipsOperand>
949 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
950 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
951 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
952 }
953
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000954 /// Create a register that is definitely an FCC.
955 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000956 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000957 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000958 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
960 }
961
962 /// Create a register that is definitely an ACC.
963 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000964 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000965 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000966 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000967 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
968 }
969
970 /// Create a register that is definitely an MSA128.
971 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000972 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000973 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000974 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
976 }
977
978 /// Create a register that is definitely an MSACtrl.
979 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000980 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000981 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000982 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000983 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
984 }
985
David Blaikie960ea3f2014-06-08 16:18:35 +0000986 static std::unique_ptr<MipsOperand>
987 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
988 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000989 Op->Imm.Val = Val;
990 Op->StartLoc = S;
991 Op->EndLoc = E;
992 return Op;
993 }
994
David Blaikie960ea3f2014-06-08 16:18:35 +0000995 static std::unique_ptr<MipsOperand>
996 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
997 SMLoc E, MipsAsmParser &Parser) {
998 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
999 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001000 Op->Mem.Off = Off;
1001 Op->StartLoc = S;
1002 Op->EndLoc = E;
1003 return Op;
1004 }
1005
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001006 static std::unique_ptr<MipsOperand>
1007 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1008 MipsAsmParser &Parser) {
1009 assert (Regs.size() > 0 && "Empty list not allowed");
1010
1011 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1012 Op->RegList.List = new SmallVector<unsigned, 10>();
1013 for (auto Reg : Regs)
1014 Op->RegList.List->push_back(Reg);
1015 Op->StartLoc = StartLoc;
1016 Op->EndLoc = EndLoc;
1017 return Op;
1018 }
1019
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001020 static std::unique_ptr<MipsOperand>
1021 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1022 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1023 Op->RegIdx.Index = RegNo;
1024 Op->StartLoc = S;
1025 Op->EndLoc = E;
1026 return Op;
1027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 bool isGPRAsmReg() const {
1030 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001031 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001032 bool isMM16AsmReg() const {
1033 if (!(isRegIdx() && RegIdx.Kind))
1034 return false;
1035 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1036 || RegIdx.Index == 16 || RegIdx.Index == 17);
1037 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001038 bool isMM16AsmRegZero() const {
1039 if (!(isRegIdx() && RegIdx.Kind))
1040 return false;
1041 return (RegIdx.Index == 0 ||
1042 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1043 RegIdx.Index == 17);
1044 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 bool isFGRAsmReg() const {
1046 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1047 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001048 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 bool isHWRegsAsmReg() const {
1050 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001051 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 bool isCCRAsmReg() const {
1053 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001054 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001056 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1057 return false;
1058 if (!AsmParser.hasEightFccRegisters())
1059 return RegIdx.Index == 0;
1060 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001061 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 bool isACCAsmReg() const {
1063 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001064 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 bool isCOP2AsmReg() const {
1066 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001067 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001068 bool isCOP3AsmReg() const {
1069 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1070 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 bool isMSA128AsmReg() const {
1072 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001073 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 bool isMSACtrlAsmReg() const {
1075 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001076 }
1077
Jack Carterb4dbc172012-09-05 23:34:03 +00001078 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001079 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001080 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001081 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001082
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001083 virtual ~MipsOperand() {
1084 switch (Kind) {
1085 case k_Immediate:
1086 break;
1087 case k_Memory:
1088 delete Mem.Base;
1089 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001090 case k_RegList:
1091 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001092 case k_PhysRegister:
1093 case k_RegisterIndex:
1094 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001095 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001096 break;
1097 }
1098 }
1099
Craig Topper56c590a2014-04-29 07:58:02 +00001100 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 switch (Kind) {
1102 case k_Immediate:
1103 OS << "Imm<";
1104 Imm.Val->print(OS);
1105 OS << ">";
1106 break;
1107 case k_Memory:
1108 OS << "Mem<";
1109 Mem.Base->print(OS);
1110 OS << ", ";
1111 Mem.Off->print(OS);
1112 OS << ">";
1113 break;
1114 case k_PhysRegister:
1115 OS << "PhysReg<" << PhysReg.Num << ">";
1116 break;
1117 case k_RegisterIndex:
1118 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1119 break;
1120 case k_Token:
1121 OS << Tok.Data;
1122 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001123 case k_RegList:
1124 OS << "RegList< ";
1125 for (auto Reg : (*RegList.List))
1126 OS << Reg << " ";
1127 OS << ">";
1128 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001129 case k_RegPair:
1130 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1131 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001133 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001134}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001135} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001136
Jack Carter9e65aa32013-03-22 00:05:30 +00001137namespace llvm {
1138extern const MCInstrDesc MipsInsts[];
1139}
1140static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1141 return MipsInsts[Opcode];
1142}
1143
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001144static bool hasShortDelaySlot(unsigned Opcode) {
1145 switch (Opcode) {
1146 case Mips::JALS_MM:
1147 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001148 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001149 case Mips::BGEZALS_MM:
1150 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001151 return true;
1152 default:
1153 return false;
1154 }
1155}
1156
Jack Carter9e65aa32013-03-22 00:05:30 +00001157bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001158 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001159 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001160
Jack Carter9e65aa32013-03-22 00:05:30 +00001161 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001162
1163 if (MCID.isBranch() || MCID.isCall()) {
1164 const unsigned Opcode = Inst.getOpcode();
1165 MCOperand Offset;
1166
1167 switch (Opcode) {
1168 default:
1169 break;
1170 case Mips::BEQ:
1171 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001172 case Mips::BEQ_MM:
1173 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001174 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001175 Offset = Inst.getOperand(2);
1176 if (!Offset.isImm())
1177 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001178 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001179 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001180 if (OffsetToAlignment(Offset.getImm(),
1181 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001182 return Error(IDLoc, "branch to misaligned address");
1183 break;
1184 case Mips::BGEZ:
1185 case Mips::BGTZ:
1186 case Mips::BLEZ:
1187 case Mips::BLTZ:
1188 case Mips::BGEZAL:
1189 case Mips::BLTZAL:
1190 case Mips::BC1F:
1191 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 case Mips::BGEZ_MM:
1193 case Mips::BGTZ_MM:
1194 case Mips::BLEZ_MM:
1195 case Mips::BLTZ_MM:
1196 case Mips::BGEZAL_MM:
1197 case Mips::BLTZAL_MM:
1198 case Mips::BC1F_MM:
1199 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001200 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001201 Offset = Inst.getOperand(1);
1202 if (!Offset.isImm())
1203 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001204 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001205 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001206 if (OffsetToAlignment(Offset.getImm(),
1207 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001208 return Error(IDLoc, "branch to misaligned address");
1209 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001210 case Mips::BEQZ16_MM:
1211 case Mips::BNEZ16_MM:
1212 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1213 Offset = Inst.getOperand(1);
1214 if (!Offset.isImm())
1215 break; // We'll deal with this situation later on when applying fixups.
1216 if (!isIntN(8, Offset.getImm()))
1217 return Error(IDLoc, "branch target out of range");
1218 if (OffsetToAlignment(Offset.getImm(), 2LL))
1219 return Error(IDLoc, "branch to misaligned address");
1220 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001221 }
1222 }
1223
Daniel Sandersa84989a2014-06-16 13:25:35 +00001224 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1225 // We still accept it but it is a normal nop.
1226 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1227 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1228 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1229 "nop instruction");
1230 }
1231
Toma Tabacu9db22db2014-09-09 10:15:38 +00001232 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001233 // If this instruction has a delay slot and .set reorder is active,
1234 // emit a NOP after it.
1235 Instructions.push_back(Inst);
1236 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001237 if (hasShortDelaySlot(Inst.getOpcode())) {
1238 NopInst.setOpcode(Mips::MOVE16_MM);
1239 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1240 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1241 } else {
1242 NopInst.setOpcode(Mips::SLL);
1243 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1244 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1245 NopInst.addOperand(MCOperand::CreateImm(0));
1246 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001247 Instructions.push_back(NopInst);
1248 return false;
1249 }
1250
Jack Carter9e65aa32013-03-22 00:05:30 +00001251 if (MCID.mayLoad() || MCID.mayStore()) {
1252 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001253 // reference or immediate we may have to expand instructions.
1254 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001255 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001256 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1257 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001258 MCOperand &Op = Inst.getOperand(i);
1259 if (Op.isImm()) {
1260 int MemOffset = Op.getImm();
1261 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001262 // Offset can't exceed 16bit value.
1263 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001264 return false;
1265 }
1266 } else if (Op.isExpr()) {
1267 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001268 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001269 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001270 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001271 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001272 // Expand symbol.
1273 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001274 return false;
1275 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001276 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001277 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001278 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001279 }
1280 }
1281 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001282 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001283 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001284
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001285 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1286 if (inMicroMipsMode()) {
1287 MCOperand Opnd;
1288 int Imm;
1289
1290 switch (Inst.getOpcode()) {
1291 default:
1292 break;
1293 case Mips::ADDIUS5_MM:
1294 Opnd = Inst.getOperand(2);
1295 if (!Opnd.isImm())
1296 return Error(IDLoc, "expected immediate operand kind");
1297 Imm = Opnd.getImm();
1298 if (Imm < -8 || Imm > 7)
1299 return Error(IDLoc, "immediate operand value out of range");
1300 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001301 case Mips::ADDIUSP_MM:
1302 Opnd = Inst.getOperand(0);
1303 if (!Opnd.isImm())
1304 return Error(IDLoc, "expected immediate operand kind");
1305 Imm = Opnd.getImm();
1306 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1307 Imm % 4 != 0)
1308 return Error(IDLoc, "immediate operand value out of range");
1309 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001310 case Mips::SLL16_MM:
1311 case Mips::SRL16_MM:
1312 Opnd = Inst.getOperand(2);
1313 if (!Opnd.isImm())
1314 return Error(IDLoc, "expected immediate operand kind");
1315 Imm = Opnd.getImm();
1316 if (Imm < 1 || Imm > 8)
1317 return Error(IDLoc, "immediate operand value out of range");
1318 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001319 case Mips::LI16_MM:
1320 Opnd = Inst.getOperand(1);
1321 if (!Opnd.isImm())
1322 return Error(IDLoc, "expected immediate operand kind");
1323 Imm = Opnd.getImm();
1324 if (Imm < -1 || Imm > 126)
1325 return Error(IDLoc, "immediate operand value out of range");
1326 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001327 case Mips::ADDIUR2_MM:
1328 Opnd = Inst.getOperand(2);
1329 if (!Opnd.isImm())
1330 return Error(IDLoc, "expected immediate operand kind");
1331 Imm = Opnd.getImm();
1332 if (!(Imm == 1 || Imm == -1 ||
1333 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1334 return Error(IDLoc, "immediate operand value out of range");
1335 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001336 case Mips::ADDIUR1SP_MM:
1337 Opnd = Inst.getOperand(1);
1338 if (!Opnd.isImm())
1339 return Error(IDLoc, "expected immediate operand kind");
1340 Imm = Opnd.getImm();
1341 if (OffsetToAlignment(Imm, 4LL))
1342 return Error(IDLoc, "misaligned immediate operand value");
1343 if (Imm < 0 || Imm > 255)
1344 return Error(IDLoc, "immediate operand value out of range");
1345 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001346 case Mips::ANDI16_MM:
1347 Opnd = Inst.getOperand(2);
1348 if (!Opnd.isImm())
1349 return Error(IDLoc, "expected immediate operand kind");
1350 Imm = Opnd.getImm();
1351 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1352 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1353 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1354 return Error(IDLoc, "immediate operand value out of range");
1355 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001356 case Mips::LBU16_MM:
1357 Opnd = Inst.getOperand(2);
1358 if (!Opnd.isImm())
1359 return Error(IDLoc, "expected immediate operand kind");
1360 Imm = Opnd.getImm();
1361 if (Imm < -1 || Imm > 14)
1362 return Error(IDLoc, "immediate operand value out of range");
1363 break;
1364 case Mips::SB16_MM:
1365 Opnd = Inst.getOperand(2);
1366 if (!Opnd.isImm())
1367 return Error(IDLoc, "expected immediate operand kind");
1368 Imm = Opnd.getImm();
1369 if (Imm < 0 || Imm > 15)
1370 return Error(IDLoc, "immediate operand value out of range");
1371 break;
1372 case Mips::LHU16_MM:
1373 case Mips::SH16_MM:
1374 Opnd = Inst.getOperand(2);
1375 if (!Opnd.isImm())
1376 return Error(IDLoc, "expected immediate operand kind");
1377 Imm = Opnd.getImm();
1378 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1379 return Error(IDLoc, "immediate operand value out of range");
1380 break;
1381 case Mips::LW16_MM:
1382 case Mips::SW16_MM:
1383 Opnd = Inst.getOperand(2);
1384 if (!Opnd.isImm())
1385 return Error(IDLoc, "expected immediate operand kind");
1386 Imm = Opnd.getImm();
1387 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1388 return Error(IDLoc, "immediate operand value out of range");
1389 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001390 case Mips::CACHE:
1391 case Mips::PREF:
1392 Opnd = Inst.getOperand(2);
1393 if (!Opnd.isImm())
1394 return Error(IDLoc, "expected immediate operand kind");
1395 Imm = Opnd.getImm();
1396 if (!isUInt<5>(Imm))
1397 return Error(IDLoc, "immediate operand value out of range");
1398 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001399 case Mips::ADDIUPC_MM:
1400 MCOperand Opnd = Inst.getOperand(1);
1401 if (!Opnd.isImm())
1402 return Error(IDLoc, "expected immediate operand kind");
1403 int Imm = Opnd.getImm();
1404 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1405 return Error(IDLoc, "immediate operand value out of range");
1406 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001407 }
1408 }
1409
Jack Carter9e65aa32013-03-22 00:05:30 +00001410 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001411 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001412 else
1413 Instructions.push_back(Inst);
1414
1415 return false;
1416}
1417
Jack Carter30a59822012-10-04 04:03:53 +00001418bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1419
Jack Carterd0bd6422013-04-18 00:41:53 +00001420 switch (Inst.getOpcode()) {
1421 case Mips::LoadImm32Reg:
1422 case Mips::LoadAddr32Imm:
1423 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001424 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001425 return true;
1426 default:
1427 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001428 }
1429}
Jack Carter92995f12012-10-06 00:53:28 +00001430
Matheus Almeida3813d572014-06-19 14:39:14 +00001431bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001432 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001433 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001434 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001435 case Mips::LoadImm32Reg:
1436 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001437 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001438 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001439 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001440 return true;
1441 }
1442 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001443 case Mips::LoadAddr32Imm:
1444 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1445 case Mips::LoadAddr32Reg:
1446 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1447 }
Jack Carter30a59822012-10-04 04:03:53 +00001448}
Jack Carter92995f12012-10-06 00:53:28 +00001449
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001450namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001451template <bool PerformShift>
1452void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001453 SmallVectorImpl<MCInst> &Instructions) {
1454 MCInst tmpInst;
1455 if (PerformShift) {
1456 tmpInst.setOpcode(Mips::DSLL);
1457 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1458 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1459 tmpInst.addOperand(MCOperand::CreateImm(16));
1460 tmpInst.setLoc(IDLoc);
1461 Instructions.push_back(tmpInst);
1462 tmpInst.clear();
1463 }
1464 tmpInst.setOpcode(Mips::ORi);
1465 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1466 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001467 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001468 tmpInst.setLoc(IDLoc);
1469 Instructions.push_back(tmpInst);
1470}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001471
1472template <int Shift, bool PerformShift>
1473void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1474 SmallVectorImpl<MCInst> &Instructions) {
1475 createShiftOr<PerformShift>(
1476 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1477 IDLoc, Instructions);
1478}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001479}
1480
Matheus Almeida3813d572014-06-19 14:39:14 +00001481bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001482 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001483 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001484 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001485 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001486 const MCOperand &RegOp = Inst.getOperand(0);
1487 assert(RegOp.isReg() && "expected register operand kind");
1488
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001489 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001490 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001491 // FIXME: gas has a special case for values that are 000...1111, which
1492 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 if (0 <= ImmValue && ImmValue <= 65535) {
1494 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001495 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001496 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001497 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001499 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001500 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001501 } else if (ImmValue < 0 && ImmValue >= -32768) {
1502 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001503 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001504 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001505 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001506 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001507 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001508 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001509 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1510 // For any value of j that is representable as a 32-bit integer, create
1511 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001512 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001513 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001514 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001515 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1516 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001517 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001518 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1519 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001520 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001521 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001522 return true;
1523 }
1524
1525 // <------- lo32 ------>
1526 // <------- hi32 ------>
1527 // <- hi16 -> <- lo16 ->
1528 // _________________________________
1529 // | | | |
1530 // | 16-bytes | 16-bytes | 16-bytes |
1531 // |__________|__________|__________|
1532 //
1533 // For any value of j that is representable as a 48-bit integer, create
1534 // a sequence of:
1535 // li d,j => lui d,hi16(j)
1536 // ori d,d,hi16(lo32(j))
1537 // dsll d,d,16
1538 // ori d,d,lo16(lo32(j))
1539 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001540 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001541 tmpInst.addOperand(
1542 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001543 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001544 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1545 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1546 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001547 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001548 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001549 return true;
1550 }
1551
1552 // <------- hi32 ------> <------- lo32 ------>
1553 // <- hi16 -> <- lo16 ->
1554 // ___________________________________________
1555 // | | | | |
1556 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1557 // |__________|__________|__________|__________|
1558 //
1559 // For any value of j that isn't representable as a 48-bit integer.
1560 // li d,j => lui d,hi16(j)
1561 // ori d,d,lo16(hi32(j))
1562 // dsll d,d,16
1563 // ori d,d,hi16(lo32(j))
1564 // dsll d,d,16
1565 // ori d,d,lo16(lo32(j))
1566 tmpInst.setOpcode(Mips::LUi);
1567 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1568 tmpInst.addOperand(
1569 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1570 Instructions.push_back(tmpInst);
1571 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1572 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1573 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001574 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001575 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001576}
Jack Carter92995f12012-10-06 00:53:28 +00001577
Matheus Almeida3813d572014-06-19 14:39:14 +00001578bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001579MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1580 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001581 MCInst tmpInst;
1582 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001583 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1584 "expected immediate operand kind");
1585 if (!ImmOp.isImm()) {
1586 expandLoadAddressSym(Inst, IDLoc, Instructions);
1587 return false;
1588 }
Jack Carter543fdf82012-10-09 23:29:45 +00001589 const MCOperand &SrcRegOp = Inst.getOperand(1);
1590 assert(SrcRegOp.isReg() && "expected register operand kind");
1591 const MCOperand &DstRegOp = Inst.getOperand(0);
1592 assert(DstRegOp.isReg() && "expected register operand kind");
1593 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001594 if (-32768 <= ImmValue && ImmValue <= 65535) {
1595 // For -32768 <= j <= 65535.
1596 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001597 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001598 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1599 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1600 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1601 Instructions.push_back(tmpInst);
1602 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 // For any other value of j that is representable as a 32-bit integer.
1604 // la d,j(s) => lui d,hi16(j)
1605 // ori d,d,lo16(j)
1606 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001607 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001608 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1609 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1610 Instructions.push_back(tmpInst);
1611 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001612 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001613 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1614 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1615 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1616 Instructions.push_back(tmpInst);
1617 tmpInst.clear();
1618 tmpInst.setOpcode(Mips::ADDu);
1619 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1620 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1621 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1622 Instructions.push_back(tmpInst);
1623 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001624 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001625}
1626
Matheus Almeida3813d572014-06-19 14:39:14 +00001627bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001628MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1629 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001630 MCInst tmpInst;
1631 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001632 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1633 "expected immediate operand kind");
1634 if (!ImmOp.isImm()) {
1635 expandLoadAddressSym(Inst, IDLoc, Instructions);
1636 return false;
1637 }
Jack Carter543fdf82012-10-09 23:29:45 +00001638 const MCOperand &RegOp = Inst.getOperand(0);
1639 assert(RegOp.isReg() && "expected register operand kind");
1640 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001641 if (-32768 <= ImmValue && ImmValue <= 65535) {
1642 // For -32768 <= j <= 65535.
1643 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001644 tmpInst.setOpcode(Mips::ADDiu);
1645 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001647 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1648 Instructions.push_back(tmpInst);
1649 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001650 // For any other value of j that is representable as a 32-bit integer.
1651 // la d,j => lui d,hi16(j)
1652 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001653 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001654 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1655 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1656 Instructions.push_back(tmpInst);
1657 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001658 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001659 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1660 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1661 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1662 Instructions.push_back(tmpInst);
1663 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001664 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001665}
1666
Toma Tabacu0d64b202014-08-14 10:29:17 +00001667void
1668MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1669 SmallVectorImpl<MCInst> &Instructions) {
1670 // FIXME: If we do have a valid at register to use, we should generate a
1671 // slightly shorter sequence here.
1672 MCInst tmpInst;
1673 int ExprOperandNo = 1;
1674 // Sometimes the assembly parser will get the immediate expression as
1675 // a $zero + an immediate.
1676 if (Inst.getNumOperands() == 3) {
1677 assert(Inst.getOperand(1).getReg() ==
1678 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1679 ExprOperandNo = 2;
1680 }
1681 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1682 assert(SymOp.isExpr() && "expected symbol operand kind");
1683 const MCOperand &RegOp = Inst.getOperand(0);
1684 unsigned RegNo = RegOp.getReg();
1685 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1686 const MCSymbolRefExpr *HiExpr =
1687 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1688 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1689 const MCSymbolRefExpr *LoExpr =
1690 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1691 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1692 if (isGP64bit()) {
1693 // If it's a 64-bit architecture, expand to:
1694 // la d,sym => lui d,highest(sym)
1695 // ori d,d,higher(sym)
1696 // dsll d,d,16
1697 // ori d,d,hi16(sym)
1698 // dsll d,d,16
1699 // ori d,d,lo16(sym)
1700 const MCSymbolRefExpr *HighestExpr =
1701 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1702 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1703 const MCSymbolRefExpr *HigherExpr =
1704 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1705 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1706
1707 tmpInst.setOpcode(Mips::LUi);
1708 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1709 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1710 Instructions.push_back(tmpInst);
1711
1712 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1713 Instructions);
1714 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1715 Instructions);
1716 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1717 Instructions);
1718 } else {
1719 // Otherwise, expand to:
1720 // la d,sym => lui d,hi16(sym)
1721 // ori d,d,lo16(sym)
1722 tmpInst.setOpcode(Mips::LUi);
1723 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1724 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1725 Instructions.push_back(tmpInst);
1726
1727 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1728 Instructions);
1729 }
1730}
1731
Jack Carter9e65aa32013-03-22 00:05:30 +00001732void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001733 SmallVectorImpl<MCInst> &Instructions,
1734 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001735 const MCSymbolRefExpr *SR;
1736 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001737 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001738 const MCExpr *ExprOffset;
1739 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001741 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1742 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001743 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1745 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001747 if (isImmOpnd) {
1748 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1749 ImmOffset = Inst.getOperand(2).getImm();
1750 LoOffset = ImmOffset & 0x0000ffff;
1751 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001752 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001753 if (LoOffset & 0x8000)
1754 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001755 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001756 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001757 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001758 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001759 // These are some of the types of expansions we perform here:
1760 // 1) lw $8, sym => lui $8, %hi(sym)
1761 // lw $8, %lo(sym)($8)
1762 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1763 // add $8, $8, $9
1764 // lw $8, %lo(offset)($9)
1765 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1766 // add $at, $at, $8
1767 // lw $8, %lo(offset)($at)
1768 // 4) sw $8, sym => lui $at, %hi(sym)
1769 // sw $8, %lo(sym)($at)
1770 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1771 // add $at, $at, $8
1772 // sw $8, %lo(offset)($at)
1773 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1774 // ldc1 $f0, %lo(sym)($at)
1775 //
1776 // For load instructions we can use the destination register as a temporary
1777 // if base and dst are different (examples 1 and 2) and if the base register
1778 // is general purpose otherwise we must use $at (example 6) and error if it's
1779 // not available. For stores we must use $at (examples 4 and 5) because we
1780 // must not clobber the source register setting up the offset.
1781 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1782 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1783 unsigned RegClassIDOp0 =
1784 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1785 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1786 (RegClassIDOp0 == Mips::GPR64RegClassID);
1787 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001788 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001789 else {
1790 int AT = getATReg(IDLoc);
1791 // At this point we need AT to perform the expansions and we exit if it is
1792 // not available.
1793 if (!AT)
1794 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001795 TmpRegNum = getReg(
1796 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001797 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001798
Jack Carter9e65aa32013-03-22 00:05:30 +00001799 TempInst.setOpcode(Mips::LUi);
1800 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1801 if (isImmOpnd)
1802 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1803 else {
1804 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001805 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001806 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1807 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1808 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001809 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001810 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001811 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001812 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001813 }
1814 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001815 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001816 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001817 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001818 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001819 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001820 TempInst.setOpcode(Mips::ADDu);
1821 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1822 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1823 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1824 Instructions.push_back(TempInst);
1825 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001826 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001827 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001828 TempInst.setOpcode(Inst.getOpcode());
1829 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1830 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1831 if (isImmOpnd)
1832 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1833 else {
1834 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001835 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1836 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1837 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001838 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001839 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001840 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001841 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001842 }
1843 }
1844 Instructions.push_back(TempInst);
1845 TempInst.clear();
1846}
1847
Matheus Almeida595fcab2014-06-11 15:05:56 +00001848unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1849 // As described by the Mips32r2 spec, the registers Rd and Rs for
1850 // jalr.hb must be different.
1851 unsigned Opcode = Inst.getOpcode();
1852
1853 if (Opcode == Mips::JALR_HB &&
1854 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1855 return Match_RequiresDifferentSrcAndDst;
1856
1857 return Match_Success;
1858}
1859
David Blaikie960ea3f2014-06-08 16:18:35 +00001860bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1861 OperandVector &Operands,
1862 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001863 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001864 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001865
Jack Carterb4dbc172012-09-05 23:34:03 +00001866 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001867 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001868 unsigned MatchResult =
1869 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001870
1871 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001872 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001873 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001874 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001876 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001877 return false;
1878 }
1879 case Match_MissingFeature:
1880 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1881 return true;
1882 case Match_InvalidOperand: {
1883 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001884 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001885 if (ErrorInfo >= Operands.size())
1886 return Error(IDLoc, "too few operands for instruction");
1887
David Blaikie960ea3f2014-06-08 16:18:35 +00001888 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001889 if (ErrorLoc == SMLoc())
1890 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001891 }
1892
1893 return Error(ErrorLoc, "invalid operand for instruction");
1894 }
1895 case Match_MnemonicFail:
1896 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001897 case Match_RequiresDifferentSrcAndDst:
1898 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001899 }
Craig Topper589ceee2015-01-03 08:16:34 +00001900
1901 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00001902}
1903
Toma Tabacu13964452014-09-04 13:23:44 +00001904void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001905 if ((RegIndex != 0) &&
1906 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001907 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001908 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001909 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001910 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001911 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001912 }
1913}
1914
Daniel Sandersef638fe2014-10-03 15:37:37 +00001915void
1916MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1917 SMRange Range, bool ShowColors) {
1918 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001919 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001920 ShowColors);
1921}
1922
Jack Carter1ac53222013-02-20 23:11:17 +00001923int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001924 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001925
Vladimir Medic4c299852013-11-06 11:27:05 +00001926 CC = StringSwitch<unsigned>(Name)
1927 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001928 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001929 .Case("a0", 4)
1930 .Case("a1", 5)
1931 .Case("a2", 6)
1932 .Case("a3", 7)
1933 .Case("v0", 2)
1934 .Case("v1", 3)
1935 .Case("s0", 16)
1936 .Case("s1", 17)
1937 .Case("s2", 18)
1938 .Case("s3", 19)
1939 .Case("s4", 20)
1940 .Case("s5", 21)
1941 .Case("s6", 22)
1942 .Case("s7", 23)
1943 .Case("k0", 26)
1944 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001945 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001946 .Case("sp", 29)
1947 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001948 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001949 .Case("ra", 31)
1950 .Case("t0", 8)
1951 .Case("t1", 9)
1952 .Case("t2", 10)
1953 .Case("t3", 11)
1954 .Case("t4", 12)
1955 .Case("t5", 13)
1956 .Case("t6", 14)
1957 .Case("t7", 15)
1958 .Case("t8", 24)
1959 .Case("t9", 25)
1960 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001961
Toma Tabacufda445c2014-09-15 15:33:01 +00001962 if (!(isABI_N32() || isABI_N64()))
1963 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001964
Daniel Sandersef638fe2014-10-03 15:37:37 +00001965 if (12 <= CC && CC <= 15) {
1966 // Name is one of t4-t7
1967 AsmToken RegTok = getLexer().peekTok();
1968 SMRange RegRange = RegTok.getLocRange();
1969
1970 StringRef FixedName = StringSwitch<StringRef>(Name)
1971 .Case("t4", "t0")
1972 .Case("t5", "t1")
1973 .Case("t6", "t2")
1974 .Case("t7", "t3")
1975 .Default("");
1976 assert(FixedName != "" && "Register name is not one of t4-t7.");
1977
1978 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1979 "Did you mean $" + FixedName + "?", RegRange);
1980 }
1981
Toma Tabacufda445c2014-09-15 15:33:01 +00001982 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1983 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1984 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1985 if (8 <= CC && CC <= 11)
1986 CC += 4;
1987
1988 if (CC == -1)
1989 CC = StringSwitch<unsigned>(Name)
1990 .Case("a4", 8)
1991 .Case("a5", 9)
1992 .Case("a6", 10)
1993 .Case("a7", 11)
1994 .Case("kt0", 26)
1995 .Case("kt1", 27)
1996 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001997
1998 return CC;
1999}
Jack Carterd0bd6422013-04-18 00:41:53 +00002000
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002001int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2002 int CC;
2003
2004 CC = StringSwitch<unsigned>(Name)
2005 .Case("hwr_cpunum", 0)
2006 .Case("hwr_synci_step", 1)
2007 .Case("hwr_cc", 2)
2008 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002009 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002010 .Default(-1);
2011
2012 return CC;
2013}
2014
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002015int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002016
Jack Cartera63b16a2012-09-07 00:23:42 +00002017 if (Name[0] == 'f') {
2018 StringRef NumString = Name.substr(1);
2019 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002020 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002021 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002022 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002023 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002024 return IntVal;
2025 }
2026 return -1;
2027}
Jack Cartera63b16a2012-09-07 00:23:42 +00002028
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002029int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2030
2031 if (Name.startswith("fcc")) {
2032 StringRef NumString = Name.substr(3);
2033 unsigned IntVal;
2034 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002035 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002036 if (IntVal > 7) // There are only 8 fcc registers.
2037 return -1;
2038 return IntVal;
2039 }
2040 return -1;
2041}
2042
2043int MipsAsmParser::matchACRegisterName(StringRef Name) {
2044
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002045 if (Name.startswith("ac")) {
2046 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002047 unsigned IntVal;
2048 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002049 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002050 if (IntVal > 3) // There are only 3 acc registers.
2051 return -1;
2052 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002053 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002054 return -1;
2055}
Jack Carterd0bd6422013-04-18 00:41:53 +00002056
Jack Carter5dc8ac92013-09-25 23:50:44 +00002057int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2058 unsigned IntVal;
2059
2060 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2061 return -1;
2062
2063 if (IntVal > 31)
2064 return -1;
2065
2066 return IntVal;
2067}
2068
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002069int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2070 int CC;
2071
2072 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002073 .Case("msair", 0)
2074 .Case("msacsr", 1)
2075 .Case("msaaccess", 2)
2076 .Case("msasave", 3)
2077 .Case("msamodify", 4)
2078 .Case("msarequest", 5)
2079 .Case("msamap", 6)
2080 .Case("msaunmap", 7)
2081 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002082
2083 return CC;
2084}
2085
Jack Carter0b744b32012-10-04 02:29:46 +00002086bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2087 if (Reg > 31)
2088 return false;
2089
Toma Tabacu3c24b042014-09-05 15:43:21 +00002090 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002091 return true;
2092}
2093
Matheus Almeida7de68e72014-06-18 14:46:05 +00002094int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002095 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002096 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002097 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002098 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002099 return AT;
2100}
Jack Carter0b744b32012-10-04 02:29:46 +00002101
Jack Carterd0bd6422013-04-18 00:41:53 +00002102unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002103 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002104}
2105
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002106unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002107 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002108 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002109}
2110
Jack Carter873c7242013-01-12 01:03:14 +00002111int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002112 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002113 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002114 return -1;
2115
Jack Carter873c7242013-01-12 01:03:14 +00002116 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002117}
2118
Toma Tabacu13964452014-09-04 13:23:44 +00002119bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002120 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002121 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002122
Jack Carter30a59822012-10-04 04:03:53 +00002123 // Check if the current operand has a custom associated parser, if so, try to
2124 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002125 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2126 if (ResTy == MatchOperand_Success)
2127 return false;
2128 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2129 // there was a match, but an error occurred, in which case, just return that
2130 // the operand parsing failed.
2131 if (ResTy == MatchOperand_ParseFail)
2132 return true;
2133
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002134 DEBUG(dbgs() << ".. Generic Parser\n");
2135
Jack Carterb4dbc172012-09-05 23:34:03 +00002136 switch (getLexer().getKind()) {
2137 default:
2138 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2139 return true;
2140 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002142 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002143
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002144 // Almost all registers have been parsed by custom parsers. There is only
2145 // one exception to this. $zero (and it's alias $0) will reach this point
2146 // for div, divu, and similar instructions because it is not an operand
2147 // to the instruction definition but an explicit register. Special case
2148 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002149 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002150 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002151
Jack Carterd0bd6422013-04-18 00:41:53 +00002152 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002153 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002154 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002155 return true;
2156
Jack Carter873c7242013-01-12 01:03:14 +00002157 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002158 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002159 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002160 const MCExpr *Res =
2161 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002162
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002163 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002164 return false;
2165 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002166 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002167 case AsmToken::LParen:
2168 case AsmToken::Minus:
2169 case AsmToken::Plus:
2170 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002171 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002172 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002173 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002174 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002175 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002176 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002177 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002179 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002181 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002182 return true;
2183
Jack Carter873c7242013-01-12 01:03:14 +00002184 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2185
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002186 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002187 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002188 } // case AsmToken::Percent
2189 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002190 return true;
2191}
2192
Vladimir Medic4c299852013-11-06 11:27:05 +00002193const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002194 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002195 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002196 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002197 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002198 // It's a constant, evaluate reloc value.
2199 int16_t Val;
2200 switch (getVariantKind(RelocStr)) {
2201 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2202 // Get the 1st 16-bits.
2203 Val = MCE->getValue() & 0xffff;
2204 break;
2205 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2206 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2207 // 16 bits being negative.
2208 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2209 break;
2210 case MCSymbolRefExpr::VK_Mips_HIGHER:
2211 // Get the 3rd 16-bits.
2212 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2213 break;
2214 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2215 // Get the 4th 16-bits.
2216 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2217 break;
2218 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002219 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002220 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002221 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002222 }
2223
Jack Carterb5cf5902013-04-17 00:18:04 +00002224 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002226 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002227 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002228 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002229 return Res;
2230 }
2231
2232 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002233 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2234
Sasa Stankovic06c47802014-04-03 10:37:45 +00002235 // Try to create target expression.
2236 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2237 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002238
Jack Carterd0bd6422013-04-18 00:41:53 +00002239 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2240 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002241 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2242 return Res;
2243 }
2244
2245 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002246 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2247 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2248 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002249 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002250 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002251 return Expr;
2252}
2253
2254bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2255
2256 switch (Expr->getKind()) {
2257 case MCExpr::Constant:
2258 return true;
2259 case MCExpr::SymbolRef:
2260 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2261 case MCExpr::Binary:
2262 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2263 if (!isEvaluated(BE->getLHS()))
2264 return false;
2265 return isEvaluated(BE->getRHS());
2266 }
2267 case MCExpr::Unary:
2268 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002269 case MCExpr::Target:
2270 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002271 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002272 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002273}
Jack Carterd0bd6422013-04-18 00:41:53 +00002274
Jack Carterb5cf5902013-04-17 00:18:04 +00002275bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002276 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002277 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002278 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002279 if (Tok.isNot(AsmToken::Identifier))
2280 return true;
2281
2282 std::string Str = Tok.getIdentifier().str();
2283
Jack Carterd0bd6422013-04-18 00:41:53 +00002284 Parser.Lex(); // Eat the identifier.
2285 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002286 const MCExpr *IdVal;
2287 SMLoc EndLoc;
2288
2289 if (getLexer().getKind() == AsmToken::LParen) {
2290 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002291 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002292 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002293 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002294 const AsmToken &nextTok = Parser.getTok();
2295 if (nextTok.isNot(AsmToken::Identifier))
2296 return true;
2297 Str += "(%";
2298 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002299 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002300 if (getLexer().getKind() != AsmToken::LParen)
2301 return true;
2302 } else
2303 break;
2304 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002305 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002306 return true;
2307
2308 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002309 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002310
2311 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002312 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002313
Jack Carterd0bd6422013-04-18 00:41:53 +00002314 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002315 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002316}
2317
Jack Carterb4dbc172012-09-05 23:34:03 +00002318bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2319 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002320 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002321 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002322 if (ResTy == MatchOperand_Success) {
2323 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002324 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002325 StartLoc = Operand.getStartLoc();
2326 EndLoc = Operand.getEndLoc();
2327
2328 // AFAIK, we only support numeric registers and named GPR's in CFI
2329 // directives.
2330 // Don't worry about eating tokens before failing. Using an unrecognised
2331 // register is a parse error.
2332 if (Operand.isGPRAsmReg()) {
2333 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002334 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002335 }
2336
2337 return (RegNo == (unsigned)-1);
2338 }
2339
2340 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002341 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002342}
2343
Jack Carterb5cf5902013-04-17 00:18:04 +00002344bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002345 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002346 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002347 bool Result = true;
2348
2349 while (getLexer().getKind() == AsmToken::LParen)
2350 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002351
Jack Carterd0bd6422013-04-18 00:41:53 +00002352 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002353 default:
2354 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002355 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002356 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002357 case AsmToken::Integer:
2358 case AsmToken::Minus:
2359 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002360 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002361 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002362 else
2363 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002364 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002365 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002366 break;
Jack Carter873c7242013-01-12 01:03:14 +00002367 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002368 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002369 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002370 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002371}
2372
David Blaikie960ea3f2014-06-08 16:18:35 +00002373MipsAsmParser::OperandMatchResultTy
2374MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002375 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002376 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002377 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002378 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002379 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002380 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002381 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002382 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002383
Jack Carterb5cf5902013-04-17 00:18:04 +00002384 if (getLexer().getKind() == AsmToken::LParen) {
2385 Parser.Lex();
2386 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002387 }
2388
Jack Carterb5cf5902013-04-17 00:18:04 +00002389 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002390 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002391 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002392
Jack Carterd0bd6422013-04-18 00:41:53 +00002393 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002394 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002395 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2396 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002397 SMLoc E =
2398 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002399 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002400 return MatchOperand_Success;
2401 }
2402 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002403 SMLoc E =
2404 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002405
Jack Carterd0bd6422013-04-18 00:41:53 +00002406 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002407 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002408 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002409 S, E, *this);
2410 Operands.push_back(
2411 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002412 return MatchOperand_Success;
2413 }
2414 Error(Parser.getTok().getLoc(), "'(' expected");
2415 return MatchOperand_ParseFail;
2416 }
2417
Jack Carterd0bd6422013-04-18 00:41:53 +00002418 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002419 }
2420
Toma Tabacu13964452014-09-04 13:23:44 +00002421 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002422 if (Res != MatchOperand_Success)
2423 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002424
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002425 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002426 Error(Parser.getTok().getLoc(), "')' expected");
2427 return MatchOperand_ParseFail;
2428 }
2429
Jack Carter873c7242013-01-12 01:03:14 +00002430 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2431
Jack Carterd0bd6422013-04-18 00:41:53 +00002432 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002433
Craig Topper062a2ba2014-04-25 05:30:21 +00002434 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002435 IdVal = MCConstantExpr::Create(0, getContext());
2436
Jack Carterd0bd6422013-04-18 00:41:53 +00002437 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002438 std::unique_ptr<MipsOperand> op(
2439 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002440 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002441 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002442 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002443 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002444 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2445 int64_t Imm;
2446 if (IdVal->EvaluateAsAbsolute(Imm))
2447 IdVal = MCConstantExpr::Create(Imm, getContext());
2448 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2449 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2450 getContext());
2451 }
2452
David Blaikie960ea3f2014-06-08 16:18:35 +00002453 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 return MatchOperand_Success;
2455}
2456
David Blaikie960ea3f2014-06-08 16:18:35 +00002457bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002458 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002459 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2460 if (Sym) {
2461 SMLoc S = Parser.getTok().getLoc();
2462 const MCExpr *Expr;
2463 if (Sym->isVariable())
2464 Expr = Sym->getVariableValue();
2465 else
2466 return false;
2467 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002468 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002469 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002470 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002471 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002472 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002473 if (ResTy == MatchOperand_Success) {
2474 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002475 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002476 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002477 llvm_unreachable("Should never ParseFail");
2478 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002479 }
2480 } else if (Expr->getKind() == MCExpr::Constant) {
2481 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002482 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002483 Operands.push_back(
2484 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002485 return true;
2486 }
2487 }
2488 return false;
2489}
Jack Carterd0bd6422013-04-18 00:41:53 +00002490
Jack Carter873c7242013-01-12 01:03:14 +00002491MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002492MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002493 StringRef Identifier,
2494 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002495 int Index = matchCPURegisterName(Identifier);
2496 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002497 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002498 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2499 return MatchOperand_Success;
2500 }
2501
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002502 Index = matchHWRegsRegisterName(Identifier);
2503 if (Index != -1) {
2504 Operands.push_back(MipsOperand::createHWRegsReg(
2505 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2506 return MatchOperand_Success;
2507 }
2508
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002509 Index = matchFPURegisterName(Identifier);
2510 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002511 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002512 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2513 return MatchOperand_Success;
2514 }
2515
2516 Index = matchFCCRegisterName(Identifier);
2517 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002518 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002519 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2520 return MatchOperand_Success;
2521 }
2522
2523 Index = matchACRegisterName(Identifier);
2524 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002525 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002526 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2527 return MatchOperand_Success;
2528 }
2529
2530 Index = matchMSA128RegisterName(Identifier);
2531 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002532 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002533 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2534 return MatchOperand_Success;
2535 }
2536
2537 Index = matchMSA128CtrlRegisterName(Identifier);
2538 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002539 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002540 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2541 return MatchOperand_Success;
2542 }
2543
2544 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002545}
2546
2547MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002548MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002549 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002550 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002551
2552 if (Token.is(AsmToken::Identifier)) {
2553 DEBUG(dbgs() << ".. identifier\n");
2554 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002555 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002556 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002557 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002558 } else if (Token.is(AsmToken::Integer)) {
2559 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002560 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002561 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2562 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002563 return MatchOperand_Success;
2564 }
2565
2566 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2567
2568 return MatchOperand_NoMatch;
2569}
2570
David Blaikie960ea3f2014-06-08 16:18:35 +00002571MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002572MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002573 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002574 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002575
2576 auto Token = Parser.getTok();
2577
2578 SMLoc S = Token.getLoc();
2579
2580 if (Token.isNot(AsmToken::Dollar)) {
2581 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2582 if (Token.is(AsmToken::Identifier)) {
2583 if (searchSymbolAlias(Operands))
2584 return MatchOperand_Success;
2585 }
2586 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2587 return MatchOperand_NoMatch;
2588 }
2589 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002590
Toma Tabacu13964452014-09-04 13:23:44 +00002591 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002592 if (ResTy == MatchOperand_Success) {
2593 Parser.Lex(); // $
2594 Parser.Lex(); // identifier
2595 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002596 return ResTy;
2597}
2598
2599MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002600MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002601 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002602 switch (getLexer().getKind()) {
2603 default:
2604 return MatchOperand_NoMatch;
2605 case AsmToken::LParen:
2606 case AsmToken::Minus:
2607 case AsmToken::Plus:
2608 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002609 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002610 case AsmToken::String:
2611 break;
2612 }
2613
2614 const MCExpr *IdVal;
2615 SMLoc S = Parser.getTok().getLoc();
2616 if (getParser().parseExpression(IdVal))
2617 return MatchOperand_ParseFail;
2618
2619 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2620 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2621 return MatchOperand_Success;
2622}
2623
David Blaikie960ea3f2014-06-08 16:18:35 +00002624MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002625MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002626 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002627 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002628
2629 SMLoc S = getLexer().getLoc();
2630
2631 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002632 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002633 if (ResTy != MatchOperand_NoMatch)
2634 return ResTy;
2635
Daniel Sanders315386c2014-04-01 10:40:14 +00002636 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002637 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002638 if (ResTy != MatchOperand_NoMatch)
2639 return ResTy;
2640
Daniel Sandersffd84362014-04-01 10:41:48 +00002641 const MCExpr *Expr = nullptr;
2642 if (Parser.parseExpression(Expr)) {
2643 // We have no way of knowing if a symbol was consumed so we must ParseFail
2644 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002645 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002646 Operands.push_back(
2647 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002648 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002649}
2650
Vladimir Medic2b953d02013-10-01 09:48:56 +00002651MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002652MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002653 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002654 const MCExpr *IdVal;
2655 // If the first token is '$' we may have register operand.
2656 if (Parser.getTok().is(AsmToken::Dollar))
2657 return MatchOperand_NoMatch;
2658 SMLoc S = Parser.getTok().getLoc();
2659 if (getParser().parseExpression(IdVal))
2660 return MatchOperand_ParseFail;
2661 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002662 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002663 int64_t Val = MCE->getValue();
2664 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2665 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002666 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002667 return MatchOperand_Success;
2668}
2669
Matheus Almeida779c5932013-11-18 12:32:49 +00002670MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002671MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002672 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002673 switch (getLexer().getKind()) {
2674 default:
2675 return MatchOperand_NoMatch;
2676 case AsmToken::LParen:
2677 case AsmToken::Plus:
2678 case AsmToken::Minus:
2679 case AsmToken::Integer:
2680 break;
2681 }
2682
2683 const MCExpr *Expr;
2684 SMLoc S = Parser.getTok().getLoc();
2685
2686 if (getParser().parseExpression(Expr))
2687 return MatchOperand_ParseFail;
2688
2689 int64_t Val;
2690 if (!Expr->EvaluateAsAbsolute(Val)) {
2691 Error(S, "expected immediate value");
2692 return MatchOperand_ParseFail;
2693 }
2694
2695 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2696 // and because the CPU always adds one to the immediate field, the allowed
2697 // range becomes 1..4. We'll only check the range here and will deal
2698 // with the addition/subtraction when actually decoding/encoding
2699 // the instruction.
2700 if (Val < 1 || Val > 4) {
2701 Error(S, "immediate not in range (1..4)");
2702 return MatchOperand_ParseFail;
2703 }
2704
Jack Carter3b2c96e2014-01-22 23:31:38 +00002705 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002706 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002707 return MatchOperand_Success;
2708}
2709
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002710MipsAsmParser::OperandMatchResultTy
2711MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2712 MCAsmParser &Parser = getParser();
2713 SmallVector<unsigned, 10> Regs;
2714 unsigned RegNo;
2715 unsigned PrevReg = Mips::NoRegister;
2716 bool RegRange = false;
2717 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2718
2719 if (Parser.getTok().isNot(AsmToken::Dollar))
2720 return MatchOperand_ParseFail;
2721
2722 SMLoc S = Parser.getTok().getLoc();
2723 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2724 SMLoc E = getLexer().getLoc();
2725 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2726 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2727 if (RegRange) {
2728 // Remove last register operand because registers from register range
2729 // should be inserted first.
2730 if (RegNo == Mips::RA) {
2731 Regs.push_back(RegNo);
2732 } else {
2733 unsigned TmpReg = PrevReg + 1;
2734 while (TmpReg <= RegNo) {
2735 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2736 Error(E, "invalid register operand");
2737 return MatchOperand_ParseFail;
2738 }
2739
2740 PrevReg = TmpReg;
2741 Regs.push_back(TmpReg++);
2742 }
2743 }
2744
2745 RegRange = false;
2746 } else {
2747 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2748 (RegNo != Mips::RA)) {
2749 Error(E, "$16 or $31 expected");
2750 return MatchOperand_ParseFail;
2751 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2752 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2753 Error(E, "invalid register operand");
2754 return MatchOperand_ParseFail;
2755 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2756 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2757 Error(E, "consecutive register numbers expected");
2758 return MatchOperand_ParseFail;
2759 }
2760
2761 Regs.push_back(RegNo);
2762 }
2763
2764 if (Parser.getTok().is(AsmToken::Minus))
2765 RegRange = true;
2766
2767 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2768 !Parser.getTok().isNot(AsmToken::Comma)) {
2769 Error(E, "',' or '-' expected");
2770 return MatchOperand_ParseFail;
2771 }
2772
2773 Lex(); // Consume comma or minus
2774 if (Parser.getTok().isNot(AsmToken::Dollar))
2775 break;
2776
2777 PrevReg = RegNo;
2778 }
2779
2780 SMLoc E = Parser.getTok().getLoc();
2781 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2782 parseMemOperand(Operands);
2783 return MatchOperand_Success;
2784}
2785
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002786MipsAsmParser::OperandMatchResultTy
2787MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2788 MCAsmParser &Parser = getParser();
2789
2790 SMLoc S = Parser.getTok().getLoc();
2791 if (parseAnyRegister(Operands) != MatchOperand_Success)
2792 return MatchOperand_ParseFail;
2793
2794 SMLoc E = Parser.getTok().getLoc();
2795 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2796 unsigned Reg = Op.getGPR32Reg();
2797 Operands.pop_back();
2798 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2799 return MatchOperand_Success;
2800}
2801
Jack Carterdc1e35d2012-09-06 20:00:02 +00002802MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2803
Vladimir Medic4c299852013-11-06 11:27:05 +00002804 MCSymbolRefExpr::VariantKind VK =
2805 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2806 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2807 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2808 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2809 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2810 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2811 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2812 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2813 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2814 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2815 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2816 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2817 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2818 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2819 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2820 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2821 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2822 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002823 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2824 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2825 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2826 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2827 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2828 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002829 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2830 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002831 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002832
Matheus Almeida2852af82014-04-22 10:15:54 +00002833 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002834
Jack Carterdc1e35d2012-09-06 20:00:02 +00002835 return VK;
2836}
Jack Cartera63b16a2012-09-07 00:23:42 +00002837
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002838/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2839/// either this.
2840/// ::= '(', register, ')'
2841/// handle it before we iterate so we don't get tripped up by the lack of
2842/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002843bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002844 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845 if (getLexer().is(AsmToken::LParen)) {
2846 Operands.push_back(
2847 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2848 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002849 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 SMLoc Loc = getLexer().getLoc();
2851 Parser.eatToEndOfStatement();
2852 return Error(Loc, "unexpected token in argument list");
2853 }
2854 if (Parser.getTok().isNot(AsmToken::RParen)) {
2855 SMLoc Loc = getLexer().getLoc();
2856 Parser.eatToEndOfStatement();
2857 return Error(Loc, "unexpected token, expected ')'");
2858 }
2859 Operands.push_back(
2860 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2861 Parser.Lex();
2862 }
2863 return false;
2864}
2865
2866/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2867/// either one of these.
2868/// ::= '[', register, ']'
2869/// ::= '[', integer, ']'
2870/// handle it before we iterate so we don't get tripped up by the lack of
2871/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002872bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002873 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002874 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002875 if (getLexer().is(AsmToken::LBrac)) {
2876 Operands.push_back(
2877 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2878 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002879 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880 SMLoc Loc = getLexer().getLoc();
2881 Parser.eatToEndOfStatement();
2882 return Error(Loc, "unexpected token in argument list");
2883 }
2884 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2885 SMLoc Loc = getLexer().getLoc();
2886 Parser.eatToEndOfStatement();
2887 return Error(Loc, "unexpected token, expected ']'");
2888 }
2889 Operands.push_back(
2890 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2891 Parser.Lex();
2892 }
2893 return false;
2894}
2895
David Blaikie960ea3f2014-06-08 16:18:35 +00002896bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2897 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002898 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002899 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002900
2901 // We have reached first instruction, module directive are now forbidden.
2902 getTargetStreamer().forbidModuleDirective();
2903
Vladimir Medic74593e62013-07-17 15:00:42 +00002904 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002905 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002906 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002907 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002908 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002909 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002910 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002911
2912 // Read the remaining operands.
2913 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2914 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002915 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002916 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002917 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002918 return Error(Loc, "unexpected token in argument list");
2919 }
Toma Tabacu13964452014-09-04 13:23:44 +00002920 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002921 return true;
2922 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002923
Jack Carterd0bd6422013-04-18 00:41:53 +00002924 while (getLexer().is(AsmToken::Comma)) {
2925 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002926 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002927 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002928 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002929 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002930 return Error(Loc, "unexpected token in argument list");
2931 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002932 // Parse bracket and parenthesis suffixes before we iterate
2933 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002934 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002935 return true;
2936 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002937 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002938 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002939 }
2940 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002941 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2942 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002943 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002944 return Error(Loc, "unexpected token in argument list");
2945 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002946 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002947 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002948}
2949
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002950bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002951 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002952 SMLoc Loc = getLexer().getLoc();
2953 Parser.eatToEndOfStatement();
2954 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002955}
2956
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002957bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002958 return Error(Loc, ErrorMsg);
2959}
2960
Jack Carter0b744b32012-10-04 02:29:46 +00002961bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002962 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002963 // Line should look like: ".set noat".
2964 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002965 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002966 // eat noat
2967 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002968 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002969 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002970 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002971 return false;
2972 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002973 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002974 return false;
2975}
Jack Carterd0bd6422013-04-18 00:41:53 +00002976
Jack Carter0b744b32012-10-04 02:29:46 +00002977bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002978 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002979 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002980 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002981 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002982 getParser().Lex();
2983 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002984 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002985 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002986 return false;
2987 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002988 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002989 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002990 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002991 return false;
2992 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002993 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002994 const AsmToken &Reg = Parser.getTok();
2995 if (Reg.is(AsmToken::Identifier)) {
2996 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2997 } else if (Reg.is(AsmToken::Integer)) {
2998 AtRegNo = Reg.getIntVal();
2999 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003000 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003001 return false;
3002 }
Jack Carter1ac53222013-02-20 23:11:17 +00003003
Daniel Sanders71a89d922014-03-25 13:01:06 +00003004 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00003005 reportParseError("unexpected token in statement");
3006 return false;
3007 }
3008
Toma Tabacu9db22db2014-09-09 10:15:38 +00003009 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003010 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00003011 return false;
3012 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003013 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00003014
3015 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003016 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003017 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003018 }
3019 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003020 return false;
3021 } else {
3022 reportParseError("unexpected token in statement");
3023 return false;
3024 }
3025}
3026
3027bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003028 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003029 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003030 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003031 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003032 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003033 return false;
3034 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003035 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003036 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003037 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003038 return false;
3039}
3040
3041bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003042 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003043 Parser.Lex();
3044 // If this is not the end of the statement, report an error.
3045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003046 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003047 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003048 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003049 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003050 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003051 Parser.Lex(); // Consume the EndOfStatement.
3052 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003053}
3054
3055bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003056 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003057 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003058 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003059 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003060 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003061 return false;
3062 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003063 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003064 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003065 return false;
3066}
3067
3068bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003069 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003070 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003071 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003073 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003074 return false;
3075 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003076 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003077 reportParseError("`noreorder' must be set before `nomacro'");
3078 return false;
3079 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003080 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003081 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003082 return false;
3083}
Jack Carterd76b2372013-03-21 21:44:16 +00003084
Daniel Sanders44934432014-08-07 12:03:36 +00003085bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003086 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003087 Parser.Lex();
3088
3089 // If this is not the end of the statement, report an error.
3090 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003091 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003092
3093 setFeatureBits(Mips::FeatureMSA, "msa");
3094 getTargetStreamer().emitDirectiveSetMsa();
3095 return false;
3096}
3097
3098bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003099 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003100 Parser.Lex();
3101
3102 // If this is not the end of the statement, report an error.
3103 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003104 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003105
3106 clearFeatureBits(Mips::FeatureMSA, "msa");
3107 getTargetStreamer().emitDirectiveSetNoMsa();
3108 return false;
3109}
3110
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003111bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003112 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003113 Parser.Lex(); // Eat "nodsp".
3114
3115 // If this is not the end of the statement, report an error.
3116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3117 reportParseError("unexpected token, expected end of statement");
3118 return false;
3119 }
3120
3121 clearFeatureBits(Mips::FeatureDSP, "dsp");
3122 getTargetStreamer().emitDirectiveSetNoDsp();
3123 return false;
3124}
3125
Toma Tabacucc2502d2014-11-04 17:18:07 +00003126bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003127 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003128 Parser.Lex(); // Eat "mips16".
3129
Jack Carter39536722014-01-22 23:08:42 +00003130 // If this is not the end of the statement, report an error.
3131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003132 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003133 return false;
3134 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003135
3136 setFeatureBits(Mips::FeatureMips16, "mips16");
3137 getTargetStreamer().emitDirectiveSetMips16();
3138 Parser.Lex(); // Consume the EndOfStatement.
3139 return false;
3140}
3141
3142bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003143 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003144 Parser.Lex(); // Eat "nomips16".
3145
3146 // If this is not the end of the statement, report an error.
3147 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3148 reportParseError("unexpected token, expected end of statement");
3149 return false;
3150 }
3151
3152 clearFeatureBits(Mips::FeatureMips16, "mips16");
3153 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003154 Parser.Lex(); // Consume the EndOfStatement.
3155 return false;
3156}
3157
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003158bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003159 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003160 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003161 // Line can be: .set fp=32
3162 // .set fp=xx
3163 // .set fp=64
3164 Parser.Lex(); // Eat fp token
3165 AsmToken Tok = Parser.getTok();
3166 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003167 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003168 return false;
3169 }
3170 Parser.Lex(); // Eat '=' token.
3171 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003172
3173 if (!parseFpABIValue(FpAbiVal, ".set"))
3174 return false;
3175
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003176 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003177 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003178 return false;
3179 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003180 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003181 Parser.Lex(); // Consume the EndOfStatement.
3182 return false;
3183}
3184
Toma Tabacu9db22db2014-09-09 10:15:38 +00003185bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003186 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003187 SMLoc Loc = getLexer().getLoc();
3188
3189 Parser.Lex();
3190 if (getLexer().isNot(AsmToken::EndOfStatement))
3191 return reportParseError("unexpected token, expected end of statement");
3192
3193 // Always keep an element on the options "stack" to prevent the user
3194 // from changing the initial options. This is how we remember them.
3195 if (AssemblerOptions.size() == 2)
3196 return reportParseError(Loc, ".set pop with no .set push");
3197
3198 AssemblerOptions.pop_back();
3199 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3200
3201 getTargetStreamer().emitDirectiveSetPop();
3202 return false;
3203}
3204
3205bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003206 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003207 Parser.Lex();
3208 if (getLexer().isNot(AsmToken::EndOfStatement))
3209 return reportParseError("unexpected token, expected end of statement");
3210
3211 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003212 AssemblerOptions.push_back(
3213 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003214
3215 getTargetStreamer().emitDirectiveSetPush();
3216 return false;
3217}
3218
Jack Carterd76b2372013-03-21 21:44:16 +00003219bool MipsAsmParser::parseSetAssignment() {
3220 StringRef Name;
3221 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003222 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003223
3224 if (Parser.parseIdentifier(Name))
3225 reportParseError("expected identifier after .set");
3226
3227 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003228 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003229 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003230
Jack Carter3b2c96e2014-01-22 23:31:38 +00003231 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003232 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003233
Jack Carterd0bd6422013-04-18 00:41:53 +00003234 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003235 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003236 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003237 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003238 Sym = getContext().GetOrCreateSymbol(Name);
3239 Sym->setVariableValue(Value);
3240
3241 return false;
3242}
Jack Carterd0bd6422013-04-18 00:41:53 +00003243
Toma Tabacu26647792014-09-09 12:52:14 +00003244bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003245 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003246 Parser.Lex();
3247 if (getLexer().isNot(AsmToken::EndOfStatement))
3248 return reportParseError("unexpected token, expected end of statement");
3249
3250 // Reset assembler options to their initial values.
3251 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3252 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3253
3254 getTargetStreamer().emitDirectiveSetMips0();
3255 return false;
3256}
3257
Toma Tabacu85618b32014-08-19 14:22:52 +00003258bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003259 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003260 Parser.Lex();
3261 if (getLexer().isNot(AsmToken::Equal))
3262 return reportParseError("unexpected token, expected equals sign");
3263
3264 Parser.Lex();
3265 StringRef Arch;
3266 if (Parser.parseIdentifier(Arch))
3267 return reportParseError("expected arch identifier");
3268
3269 StringRef ArchFeatureName =
3270 StringSwitch<StringRef>(Arch)
3271 .Case("mips1", "mips1")
3272 .Case("mips2", "mips2")
3273 .Case("mips3", "mips3")
3274 .Case("mips4", "mips4")
3275 .Case("mips5", "mips5")
3276 .Case("mips32", "mips32")
3277 .Case("mips32r2", "mips32r2")
3278 .Case("mips32r6", "mips32r6")
3279 .Case("mips64", "mips64")
3280 .Case("mips64r2", "mips64r2")
3281 .Case("mips64r6", "mips64r6")
3282 .Case("cnmips", "cnmips")
3283 .Case("r4000", "mips3") // This is an implementation of Mips3.
3284 .Default("");
3285
3286 if (ArchFeatureName.empty())
3287 return reportParseError("unsupported architecture");
3288
3289 selectArch(ArchFeatureName);
3290 getTargetStreamer().emitDirectiveSetArch(Arch);
3291 return false;
3292}
3293
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003294bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003295 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003296 Parser.Lex();
3297 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003298 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003299
Matheus Almeida2852af82014-04-22 10:15:54 +00003300 switch (Feature) {
3301 default:
3302 llvm_unreachable("Unimplemented feature");
3303 case Mips::FeatureDSP:
3304 setFeatureBits(Mips::FeatureDSP, "dsp");
3305 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003306 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003307 case Mips::FeatureMicroMips:
3308 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003309 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003310 case Mips::FeatureMips1:
3311 selectArch("mips1");
3312 getTargetStreamer().emitDirectiveSetMips1();
3313 break;
3314 case Mips::FeatureMips2:
3315 selectArch("mips2");
3316 getTargetStreamer().emitDirectiveSetMips2();
3317 break;
3318 case Mips::FeatureMips3:
3319 selectArch("mips3");
3320 getTargetStreamer().emitDirectiveSetMips3();
3321 break;
3322 case Mips::FeatureMips4:
3323 selectArch("mips4");
3324 getTargetStreamer().emitDirectiveSetMips4();
3325 break;
3326 case Mips::FeatureMips5:
3327 selectArch("mips5");
3328 getTargetStreamer().emitDirectiveSetMips5();
3329 break;
3330 case Mips::FeatureMips32:
3331 selectArch("mips32");
3332 getTargetStreamer().emitDirectiveSetMips32();
3333 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003334 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003335 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003336 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003337 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003338 case Mips::FeatureMips32r6:
3339 selectArch("mips32r6");
3340 getTargetStreamer().emitDirectiveSetMips32R6();
3341 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003342 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003343 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003344 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003345 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003346 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003347 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003348 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003349 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003350 case Mips::FeatureMips64r6:
3351 selectArch("mips64r6");
3352 getTargetStreamer().emitDirectiveSetMips64R6();
3353 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003354 }
3355 return false;
3356}
3357
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003358bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003359 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003360 if (getLexer().isNot(AsmToken::Comma)) {
3361 SMLoc Loc = getLexer().getLoc();
3362 Parser.eatToEndOfStatement();
3363 return Error(Loc, ErrorStr);
3364 }
3365
Matheus Almeida2852af82014-04-22 10:15:54 +00003366 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003367 return true;
3368}
3369
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003370bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003371 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003372 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003373
Toma Tabacudde4c462014-11-06 10:02:45 +00003374 if (inMips16Mode()) {
3375 reportParseError(".cpload is not supported in Mips16 mode");
3376 return false;
3377 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003378
David Blaikie960ea3f2014-06-08 16:18:35 +00003379 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003380 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003381 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3382 reportParseError("expected register containing function address");
3383 return false;
3384 }
3385
David Blaikie960ea3f2014-06-08 16:18:35 +00003386 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3387 if (!RegOpnd.isGPRAsmReg()) {
3388 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003389 return false;
3390 }
3391
Toma Tabacudde4c462014-11-06 10:02:45 +00003392 // If this is not the end of the statement, report an error.
3393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3394 reportParseError("unexpected token, expected end of statement");
3395 return false;
3396 }
3397
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003398 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003399 return false;
3400}
3401
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003402bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003403 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003404 unsigned FuncReg;
3405 unsigned Save;
3406 bool SaveIsReg = true;
3407
Matheus Almeida7e815762014-06-18 13:08:59 +00003408 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003409 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003410 if (ResTy == MatchOperand_NoMatch) {
3411 reportParseError("expected register containing function address");
3412 Parser.eatToEndOfStatement();
3413 return false;
3414 }
3415
3416 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3417 if (!FuncRegOpnd.isGPRAsmReg()) {
3418 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3419 Parser.eatToEndOfStatement();
3420 return false;
3421 }
3422
3423 FuncReg = FuncRegOpnd.getGPR32Reg();
3424 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003425
Toma Tabacu65f10572014-09-16 15:00:52 +00003426 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003427 return true;
3428
Toma Tabacu13964452014-09-04 13:23:44 +00003429 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003430 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003431 const AsmToken &Tok = Parser.getTok();
3432 if (Tok.is(AsmToken::Integer)) {
3433 Save = Tok.getIntVal();
3434 SaveIsReg = false;
3435 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003436 } else {
3437 reportParseError("expected save register or stack offset");
3438 Parser.eatToEndOfStatement();
3439 return false;
3440 }
3441 } else {
3442 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3443 if (!SaveOpnd.isGPRAsmReg()) {
3444 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3445 Parser.eatToEndOfStatement();
3446 return false;
3447 }
3448 Save = SaveOpnd.getGPR32Reg();
3449 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003450
Toma Tabacu65f10572014-09-16 15:00:52 +00003451 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003452 return true;
3453
3454 StringRef Name;
3455 if (Parser.parseIdentifier(Name))
3456 reportParseError("expected identifier");
3457 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003458
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003459 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003460 return false;
3461}
3462
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003463bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003464 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3466 const AsmToken &Tok = Parser.getTok();
3467
3468 if (Tok.getString() == "2008") {
3469 Parser.Lex();
3470 getTargetStreamer().emitDirectiveNaN2008();
3471 return false;
3472 } else if (Tok.getString() == "legacy") {
3473 Parser.Lex();
3474 getTargetStreamer().emitDirectiveNaNLegacy();
3475 return false;
3476 }
3477 }
3478 // If we don't recognize the option passed to the .nan
3479 // directive (e.g. no option or unknown option), emit an error.
3480 reportParseError("invalid option in .nan directive");
3481 return false;
3482}
3483
Jack Carter0b744b32012-10-04 02:29:46 +00003484bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003485 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003486 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003487 const AsmToken &Tok = Parser.getTok();
3488
3489 if (Tok.getString() == "noat") {
3490 return parseSetNoAtDirective();
3491 } else if (Tok.getString() == "at") {
3492 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003493 } else if (Tok.getString() == "arch") {
3494 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003495 } else if (Tok.getString() == "fp") {
3496 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003497 } else if (Tok.getString() == "pop") {
3498 return parseSetPopDirective();
3499 } else if (Tok.getString() == "push") {
3500 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003501 } else if (Tok.getString() == "reorder") {
3502 return parseSetReorderDirective();
3503 } else if (Tok.getString() == "noreorder") {
3504 return parseSetNoReorderDirective();
3505 } else if (Tok.getString() == "macro") {
3506 return parseSetMacroDirective();
3507 } else if (Tok.getString() == "nomacro") {
3508 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003509 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003510 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003511 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003512 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003513 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003514 getTargetStreamer().emitDirectiveSetNoMicroMips();
3515 Parser.eatToEndOfStatement();
3516 return false;
3517 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003518 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003519 } else if (Tok.getString() == "mips0") {
3520 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003521 } else if (Tok.getString() == "mips1") {
3522 return parseSetFeature(Mips::FeatureMips1);
3523 } else if (Tok.getString() == "mips2") {
3524 return parseSetFeature(Mips::FeatureMips2);
3525 } else if (Tok.getString() == "mips3") {
3526 return parseSetFeature(Mips::FeatureMips3);
3527 } else if (Tok.getString() == "mips4") {
3528 return parseSetFeature(Mips::FeatureMips4);
3529 } else if (Tok.getString() == "mips5") {
3530 return parseSetFeature(Mips::FeatureMips5);
3531 } else if (Tok.getString() == "mips32") {
3532 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003533 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003534 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003535 } else if (Tok.getString() == "mips32r6") {
3536 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003537 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003538 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003539 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003540 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003541 } else if (Tok.getString() == "mips64r6") {
3542 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003543 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003544 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003545 } else if (Tok.getString() == "nodsp") {
3546 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003547 } else if (Tok.getString() == "msa") {
3548 return parseSetMsaDirective();
3549 } else if (Tok.getString() == "nomsa") {
3550 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003551 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003552 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003553 parseSetAssignment();
3554 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003555 }
Jack Carter07c818d2013-01-25 01:31:34 +00003556
Jack Carter0b744b32012-10-04 02:29:46 +00003557 return true;
3558}
3559
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003560/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003561/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003562bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003563 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3565 for (;;) {
3566 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003567 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003568 return true;
3569
3570 getParser().getStreamer().EmitValue(Value, Size);
3571
3572 if (getLexer().is(AsmToken::EndOfStatement))
3573 break;
3574
Jack Carter07c818d2013-01-25 01:31:34 +00003575 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003576 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003577 Parser.Lex();
3578 }
3579 }
3580
3581 Parser.Lex();
3582 return false;
3583}
3584
Vladimir Medic4c299852013-11-06 11:27:05 +00003585/// parseDirectiveGpWord
3586/// ::= .gpword local_sym
3587bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003588 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003589 const MCExpr *Value;
3590 // EmitGPRel32Value requires an expression, so we are using base class
3591 // method to evaluate the expression.
3592 if (getParser().parseExpression(Value))
3593 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003594 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003595
Vladimir Medice10c1122013-11-13 13:18:04 +00003596 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003597 return Error(getLexer().getLoc(),
3598 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003599 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003600 return false;
3601}
3602
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003603/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003604/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003605bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003606 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003607 const MCExpr *Value;
3608 // EmitGPRel64Value requires an expression, so we are using base class
3609 // method to evaluate the expression.
3610 if (getParser().parseExpression(Value))
3611 return true;
3612 getParser().getStreamer().EmitGPRel64Value(Value);
3613
3614 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003615 return Error(getLexer().getLoc(),
3616 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003617 Parser.Lex(); // Eat EndOfStatement token.
3618 return false;
3619}
3620
Jack Carter0cd3c192014-01-06 23:27:31 +00003621bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003622 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003623 // Get the option token.
3624 AsmToken Tok = Parser.getTok();
3625 // At the moment only identifiers are supported.
3626 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003627 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003628 Parser.eatToEndOfStatement();
3629 return false;
3630 }
3631
3632 StringRef Option = Tok.getIdentifier();
3633
3634 if (Option == "pic0") {
3635 getTargetStreamer().emitDirectiveOptionPic0();
3636 Parser.Lex();
3637 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3638 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003639 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003640 Parser.eatToEndOfStatement();
3641 }
3642 return false;
3643 }
3644
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003645 if (Option == "pic2") {
3646 getTargetStreamer().emitDirectiveOptionPic2();
3647 Parser.Lex();
3648 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3649 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003650 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003651 Parser.eatToEndOfStatement();
3652 }
3653 return false;
3654 }
3655
Jack Carter0cd3c192014-01-06 23:27:31 +00003656 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003657 Warning(Parser.getTok().getLoc(),
3658 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003659 Parser.eatToEndOfStatement();
3660 return false;
3661}
3662
Daniel Sanders7e527422014-07-10 13:38:23 +00003663/// parseDirectiveModule
3664/// ::= .module oddspreg
3665/// ::= .module nooddspreg
3666/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003667bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003668 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003669 MCAsmLexer &Lexer = getLexer();
3670 SMLoc L = Lexer.getLoc();
3671
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003672 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003673 // TODO : get a better message.
3674 reportParseError(".module directive must appear before any code");
3675 return false;
3676 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003677
3678 if (Lexer.is(AsmToken::Identifier)) {
3679 StringRef Option = Parser.getTok().getString();
3680 Parser.Lex();
3681
3682 if (Option == "oddspreg") {
3683 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3684 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3685
3686 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003687 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003688 return false;
3689 }
3690
3691 return false;
3692 } else if (Option == "nooddspreg") {
3693 if (!isABI_O32()) {
3694 Error(L, "'.module nooddspreg' requires the O32 ABI");
3695 return false;
3696 }
3697
3698 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3699 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3700
3701 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003702 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003703 return false;
3704 }
3705
3706 return false;
3707 } else if (Option == "fp") {
3708 return parseDirectiveModuleFP();
3709 }
3710
3711 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003712 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003713
3714 return false;
3715}
3716
3717/// parseDirectiveModuleFP
3718/// ::= =32
3719/// ::= =xx
3720/// ::= =64
3721bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003722 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003723 MCAsmLexer &Lexer = getLexer();
3724
3725 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003726 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003727 return false;
3728 }
3729 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003730
Daniel Sanders7e527422014-07-10 13:38:23 +00003731 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003732 if (!parseFpABIValue(FpABI, ".module"))
3733 return false;
3734
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003735 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003736 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003737 return false;
3738 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003739
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003740 // Emit appropriate flags.
3741 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003742 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003743 return false;
3744}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003745
Daniel Sanders7e527422014-07-10 13:38:23 +00003746bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003747 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003748 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003749 MCAsmLexer &Lexer = getLexer();
3750
3751 if (Lexer.is(AsmToken::Identifier)) {
3752 StringRef Value = Parser.getTok().getString();
3753 Parser.Lex();
3754
3755 if (Value != "xx") {
3756 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3757 return false;
3758 }
3759
3760 if (!isABI_O32()) {
3761 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3762 return false;
3763 }
3764
Daniel Sanders7e527422014-07-10 13:38:23 +00003765 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003766 return true;
3767 }
3768
3769 if (Lexer.is(AsmToken::Integer)) {
3770 unsigned Value = Parser.getTok().getIntVal();
3771 Parser.Lex();
3772
3773 if (Value != 32 && Value != 64) {
3774 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3775 return false;
3776 }
3777
3778 if (Value == 32) {
3779 if (!isABI_O32()) {
3780 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3781 return false;
3782 }
3783
Daniel Sanders7e527422014-07-10 13:38:23 +00003784 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3785 } else
3786 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003787
Daniel Sanders7e527422014-07-10 13:38:23 +00003788 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003789 }
3790
3791 return false;
3792}
3793
Jack Carter0b744b32012-10-04 02:29:46 +00003794bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003795 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003796 StringRef IDVal = DirectiveID.getString();
3797
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003798 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003799 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003800 if (IDVal == ".dword") {
3801 parseDataDirective(8, DirectiveID.getLoc());
3802 return false;
3803 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003804 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003805 StringRef SymbolName;
3806
3807 if (Parser.parseIdentifier(SymbolName)) {
3808 reportParseError("expected identifier after .ent");
3809 return false;
3810 }
3811
3812 // There's an undocumented extension that allows an integer to
3813 // follow the name of the procedure which AFAICS is ignored by GAS.
3814 // Example: .ent foo,2
3815 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3816 if (getLexer().isNot(AsmToken::Comma)) {
3817 // Even though we accept this undocumented extension for compatibility
3818 // reasons, the additional integer argument does not actually change
3819 // the behaviour of the '.ent' directive, so we would like to discourage
3820 // its use. We do this by not referring to the extended version in
3821 // error messages which are not directly related to its use.
3822 reportParseError("unexpected token, expected end of statement");
3823 return false;
3824 }
3825 Parser.Lex(); // Eat the comma.
3826 const MCExpr *DummyNumber;
3827 int64_t DummyNumberVal;
3828 // If the user was explicitly trying to use the extended version,
3829 // we still give helpful extension-related error messages.
3830 if (Parser.parseExpression(DummyNumber)) {
3831 reportParseError("expected number after comma");
3832 return false;
3833 }
3834 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3835 reportParseError("expected an absolute expression after comma");
3836 return false;
3837 }
3838 }
3839
3840 // If this is not the end of the statement, report an error.
3841 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3842 reportParseError("unexpected token, expected end of statement");
3843 return false;
3844 }
3845
3846 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3847
3848 getTargetStreamer().emitDirectiveEnt(*Sym);
3849 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003850 return false;
3851 }
3852
Jack Carter07c818d2013-01-25 01:31:34 +00003853 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003854 StringRef SymbolName;
3855
3856 if (Parser.parseIdentifier(SymbolName)) {
3857 reportParseError("expected identifier after .end");
3858 return false;
3859 }
3860
3861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3862 reportParseError("unexpected token, expected end of statement");
3863 return false;
3864 }
3865
3866 if (CurrentFn == nullptr) {
3867 reportParseError(".end used without .ent");
3868 return false;
3869 }
3870
3871 if ((SymbolName != CurrentFn->getName())) {
3872 reportParseError(".end symbol does not match .ent symbol");
3873 return false;
3874 }
3875
3876 getTargetStreamer().emitDirectiveEnd(SymbolName);
3877 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003878 return false;
3879 }
3880
Jack Carter07c818d2013-01-25 01:31:34 +00003881 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003882 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3883 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003884 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003885 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3886 reportParseError("expected stack register");
3887 return false;
3888 }
3889
3890 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3891 if (!StackRegOpnd.isGPRAsmReg()) {
3892 reportParseError(StackRegOpnd.getStartLoc(),
3893 "expected general purpose register");
3894 return false;
3895 }
3896 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3897
3898 if (Parser.getTok().is(AsmToken::Comma))
3899 Parser.Lex();
3900 else {
3901 reportParseError("unexpected token, expected comma");
3902 return false;
3903 }
3904
3905 // Parse the frame size.
3906 const MCExpr *FrameSize;
3907 int64_t FrameSizeVal;
3908
3909 if (Parser.parseExpression(FrameSize)) {
3910 reportParseError("expected frame size value");
3911 return false;
3912 }
3913
3914 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3915 reportParseError("frame size not an absolute expression");
3916 return false;
3917 }
3918
3919 if (Parser.getTok().is(AsmToken::Comma))
3920 Parser.Lex();
3921 else {
3922 reportParseError("unexpected token, expected comma");
3923 return false;
3924 }
3925
3926 // Parse the return register.
3927 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003928 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003929 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3930 reportParseError("expected return register");
3931 return false;
3932 }
3933
3934 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3935 if (!ReturnRegOpnd.isGPRAsmReg()) {
3936 reportParseError(ReturnRegOpnd.getStartLoc(),
3937 "expected general purpose register");
3938 return false;
3939 }
3940
3941 // If this is not the end of the statement, report an error.
3942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3943 reportParseError("unexpected token, expected end of statement");
3944 return false;
3945 }
3946
3947 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3948 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003949 return false;
3950 }
3951
Jack Carter07c818d2013-01-25 01:31:34 +00003952 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003953 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003954 }
3955
Daniel Sandersd97a6342014-08-13 10:07:34 +00003956 if (IDVal == ".mask" || IDVal == ".fmask") {
3957 // .mask bitmask, frame_offset
3958 // bitmask: One bit for each register used.
3959 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3960 // first register is expected to be saved.
3961 // Examples:
3962 // .mask 0x80000000, -4
3963 // .fmask 0x80000000, -4
3964 //
Jack Carterbe332172012-09-07 00:48:02 +00003965
Daniel Sandersd97a6342014-08-13 10:07:34 +00003966 // Parse the bitmask
3967 const MCExpr *BitMask;
3968 int64_t BitMaskVal;
3969
3970 if (Parser.parseExpression(BitMask)) {
3971 reportParseError("expected bitmask value");
3972 return false;
3973 }
3974
3975 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3976 reportParseError("bitmask not an absolute expression");
3977 return false;
3978 }
3979
3980 if (Parser.getTok().is(AsmToken::Comma))
3981 Parser.Lex();
3982 else {
3983 reportParseError("unexpected token, expected comma");
3984 return false;
3985 }
3986
3987 // Parse the frame_offset
3988 const MCExpr *FrameOffset;
3989 int64_t FrameOffsetVal;
3990
3991 if (Parser.parseExpression(FrameOffset)) {
3992 reportParseError("expected frame offset value");
3993 return false;
3994 }
3995
3996 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3997 reportParseError("frame offset not an absolute expression");
3998 return false;
3999 }
4000
4001 // If this is not the end of the statement, report an error.
4002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4003 reportParseError("unexpected token, expected end of statement");
4004 return false;
4005 }
4006
4007 if (IDVal == ".mask")
4008 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4009 else
4010 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004011 return false;
4012 }
4013
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004014 if (IDVal == ".nan")
4015 return parseDirectiveNaN();
4016
Jack Carter07c818d2013-01-25 01:31:34 +00004017 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004018 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004019 return false;
4020 }
4021
Rafael Espindolab59fb732014-03-28 18:50:26 +00004022 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004023 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004024 return false;
4025 }
4026
Jack Carter07c818d2013-01-25 01:31:34 +00004027 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004028 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004029 return false;
4030 }
4031
Jack Carter0cd3c192014-01-06 23:27:31 +00004032 if (IDVal == ".option")
4033 return parseDirectiveOption();
4034
4035 if (IDVal == ".abicalls") {
4036 getTargetStreamer().emitDirectiveAbiCalls();
4037 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004038 Error(Parser.getTok().getLoc(),
4039 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004040 // Clear line
4041 Parser.eatToEndOfStatement();
4042 }
4043 return false;
4044 }
4045
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004046 if (IDVal == ".cpsetup")
4047 return parseDirectiveCPSetup();
4048
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004049 if (IDVal == ".module")
4050 return parseDirectiveModule();
4051
Rafael Espindola870c4e92012-01-11 03:56:41 +00004052 return true;
4053}
4054
Rafael Espindola870c4e92012-01-11 03:56:41 +00004055extern "C" void LLVMInitializeMipsAsmParser() {
4056 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4057 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4058 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4059 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4060}
Jack Carterb4dbc172012-09-05 23:34:03 +00004061
4062#define GET_REGISTER_MATCHER
4063#define GET_MATCHER_IMPLEMENTATION
4064#include "MipsGenAsmMatcher.inc"