blob: fb380ed4a09fa469fd263e56d8f169b30dbca18c [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000017#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000020#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCParser/MCAsmLexer.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000026#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000027#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000028#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000029#include "llvm/Support/TargetRegistry.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000031#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000032
33using namespace llvm;
34
Chandler Carruthe96dd892014-04-21 22:55:11 +000035#define DEBUG_TYPE "mips-asm-parser"
36
Joey Gouly0e76fa72013-09-12 10:28:05 +000037namespace llvm {
38class MCInstrInfo;
39}
40
Rafael Espindola870c4e92012-01-11 03:56:41 +000041namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000042class MipsAssemblerOptions {
43public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000044 MipsAssemblerOptions(uint64_t Features_) :
45 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000046
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48 ATReg = Opts->getATRegNum();
49 Reorder = Opts->isReorder();
50 Macro = Opts->isMacro();
51 Features = Opts->getFeatures();
52 }
53
54 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000055 bool setATReg(unsigned Reg);
56
Toma Tabacu9db22db2014-09-09 10:15:38 +000057 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000058 void setReorder() { Reorder = true; }
59 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000060
Toma Tabacu9db22db2014-09-09 10:15:38 +000061 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000062 void setMacro() { Macro = true; }
63 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 uint64_t getFeatures() const { return Features; }
66 void setFeatures(uint64_t Features_) { Features = Features_; }
67
Daniel Sandersf0df2212014-08-04 12:20:00 +000068 // Set of features that are either architecture features or referenced
69 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71 // The reason we need this mask is explained in the selectArch function.
72 // FIXME: Ideally we would like TableGen to generate this information.
73 static const uint64_t AllArchRelatedMask =
74 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81
Jack Carter0b744b32012-10-04 02:29:46 +000082private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000083 unsigned ATReg;
84 bool Reorder;
85 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000086 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000087};
88}
89
90namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000091class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000092 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000093 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 return static_cast<MipsTargetStreamer &>(TS);
95 }
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 MCSubtargetInfo &STI;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Daniel Sandersef638fe2014-10-03 15:37:37 +0000104 // Print a warning along with its fix-it message at the given range.
105 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
106 SMRange Range, bool ShowColors = true);
107
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000108#define GET_ASSEMBLER_HEADER
109#include "MipsGenAsmMatcher.inc"
110
Matheus Almeida595fcab2014-06-11 15:05:56 +0000111 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
112
Chad Rosier49963552012-10-13 00:26:04 +0000113 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000114 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000115 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000116 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000117
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Toma Tabacu13964452014-09-04 13:23:44 +0000121 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
David Blaikie960ea3f2014-06-08 16:18:35 +0000125 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
126 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Craig Topper56c590a2014-04-29 07:58:02 +0000128 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000135
Jack Carter873c7242013-01-12 01:03:14 +0000136 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000137 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000149 MipsAsmParser::OperandMatchResultTy
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;
1210 }
1211 }
1212
Daniel Sandersa84989a2014-06-16 13:25:35 +00001213 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1214 // We still accept it but it is a normal nop.
1215 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1216 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1217 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1218 "nop instruction");
1219 }
1220
Toma Tabacu9db22db2014-09-09 10:15:38 +00001221 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001222 // If this instruction has a delay slot and .set reorder is active,
1223 // emit a NOP after it.
1224 Instructions.push_back(Inst);
1225 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001226 if (hasShortDelaySlot(Inst.getOpcode())) {
1227 NopInst.setOpcode(Mips::MOVE16_MM);
1228 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1229 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1230 } else {
1231 NopInst.setOpcode(Mips::SLL);
1232 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1233 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1234 NopInst.addOperand(MCOperand::CreateImm(0));
1235 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001236 Instructions.push_back(NopInst);
1237 return false;
1238 }
1239
Jack Carter9e65aa32013-03-22 00:05:30 +00001240 if (MCID.mayLoad() || MCID.mayStore()) {
1241 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001242 // reference or immediate we may have to expand instructions.
1243 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001244 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001245 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1246 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001247 MCOperand &Op = Inst.getOperand(i);
1248 if (Op.isImm()) {
1249 int MemOffset = Op.getImm();
1250 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001251 // Offset can't exceed 16bit value.
1252 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001253 return false;
1254 }
1255 } else if (Op.isExpr()) {
1256 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001257 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001258 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001259 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001260 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 // Expand symbol.
1262 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001263 return false;
1264 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001265 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001266 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001267 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001268 }
1269 }
1270 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001271 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001272 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001273
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001274 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1275 if (inMicroMipsMode()) {
1276 MCOperand Opnd;
1277 int Imm;
1278
1279 switch (Inst.getOpcode()) {
1280 default:
1281 break;
1282 case Mips::ADDIUS5_MM:
1283 Opnd = Inst.getOperand(2);
1284 if (!Opnd.isImm())
1285 return Error(IDLoc, "expected immediate operand kind");
1286 Imm = Opnd.getImm();
1287 if (Imm < -8 || Imm > 7)
1288 return Error(IDLoc, "immediate operand value out of range");
1289 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001290 case Mips::ADDIUSP_MM:
1291 Opnd = Inst.getOperand(0);
1292 if (!Opnd.isImm())
1293 return Error(IDLoc, "expected immediate operand kind");
1294 Imm = Opnd.getImm();
1295 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1296 Imm % 4 != 0)
1297 return Error(IDLoc, "immediate operand value out of range");
1298 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001299 case Mips::SLL16_MM:
1300 case Mips::SRL16_MM:
1301 Opnd = Inst.getOperand(2);
1302 if (!Opnd.isImm())
1303 return Error(IDLoc, "expected immediate operand kind");
1304 Imm = Opnd.getImm();
1305 if (Imm < 1 || Imm > 8)
1306 return Error(IDLoc, "immediate operand value out of range");
1307 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001308 case Mips::LI16_MM:
1309 Opnd = Inst.getOperand(1);
1310 if (!Opnd.isImm())
1311 return Error(IDLoc, "expected immediate operand kind");
1312 Imm = Opnd.getImm();
1313 if (Imm < -1 || Imm > 126)
1314 return Error(IDLoc, "immediate operand value out of range");
1315 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001316 case Mips::ADDIUR2_MM:
1317 Opnd = Inst.getOperand(2);
1318 if (!Opnd.isImm())
1319 return Error(IDLoc, "expected immediate operand kind");
1320 Imm = Opnd.getImm();
1321 if (!(Imm == 1 || Imm == -1 ||
1322 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1323 return Error(IDLoc, "immediate operand value out of range");
1324 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001325 case Mips::ADDIUR1SP_MM:
1326 Opnd = Inst.getOperand(1);
1327 if (!Opnd.isImm())
1328 return Error(IDLoc, "expected immediate operand kind");
1329 Imm = Opnd.getImm();
1330 if (OffsetToAlignment(Imm, 4LL))
1331 return Error(IDLoc, "misaligned immediate operand value");
1332 if (Imm < 0 || Imm > 255)
1333 return Error(IDLoc, "immediate operand value out of range");
1334 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001335 case Mips::ANDI16_MM:
1336 Opnd = Inst.getOperand(2);
1337 if (!Opnd.isImm())
1338 return Error(IDLoc, "expected immediate operand kind");
1339 Imm = Opnd.getImm();
1340 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1341 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1342 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1343 return Error(IDLoc, "immediate operand value out of range");
1344 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001345 case Mips::LBU16_MM:
1346 Opnd = Inst.getOperand(2);
1347 if (!Opnd.isImm())
1348 return Error(IDLoc, "expected immediate operand kind");
1349 Imm = Opnd.getImm();
1350 if (Imm < -1 || Imm > 14)
1351 return Error(IDLoc, "immediate operand value out of range");
1352 break;
1353 case Mips::SB16_MM:
1354 Opnd = Inst.getOperand(2);
1355 if (!Opnd.isImm())
1356 return Error(IDLoc, "expected immediate operand kind");
1357 Imm = Opnd.getImm();
1358 if (Imm < 0 || Imm > 15)
1359 return Error(IDLoc, "immediate operand value out of range");
1360 break;
1361 case Mips::LHU16_MM:
1362 case Mips::SH16_MM:
1363 Opnd = Inst.getOperand(2);
1364 if (!Opnd.isImm())
1365 return Error(IDLoc, "expected immediate operand kind");
1366 Imm = Opnd.getImm();
1367 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1368 return Error(IDLoc, "immediate operand value out of range");
1369 break;
1370 case Mips::LW16_MM:
1371 case Mips::SW16_MM:
1372 Opnd = Inst.getOperand(2);
1373 if (!Opnd.isImm())
1374 return Error(IDLoc, "expected immediate operand kind");
1375 Imm = Opnd.getImm();
1376 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1377 return Error(IDLoc, "immediate operand value out of range");
1378 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001379 case Mips::CACHE:
1380 case Mips::PREF:
1381 Opnd = Inst.getOperand(2);
1382 if (!Opnd.isImm())
1383 return Error(IDLoc, "expected immediate operand kind");
1384 Imm = Opnd.getImm();
1385 if (!isUInt<5>(Imm))
1386 return Error(IDLoc, "immediate operand value out of range");
1387 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001388 }
1389 }
1390
Jack Carter9e65aa32013-03-22 00:05:30 +00001391 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001392 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001393 else
1394 Instructions.push_back(Inst);
1395
1396 return false;
1397}
1398
Jack Carter30a59822012-10-04 04:03:53 +00001399bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1400
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 switch (Inst.getOpcode()) {
1402 case Mips::LoadImm32Reg:
1403 case Mips::LoadAddr32Imm:
1404 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001405 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001406 return true;
1407 default:
1408 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001409 }
1410}
Jack Carter92995f12012-10-06 00:53:28 +00001411
Matheus Almeida3813d572014-06-19 14:39:14 +00001412bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001413 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001415 default:
1416 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001417 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001418 case Mips::LoadImm32Reg:
1419 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001420 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001421 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001422 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001423 return true;
1424 }
1425 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001426 case Mips::LoadAddr32Imm:
1427 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1428 case Mips::LoadAddr32Reg:
1429 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1430 }
Jack Carter30a59822012-10-04 04:03:53 +00001431}
Jack Carter92995f12012-10-06 00:53:28 +00001432
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001433namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001434template <bool PerformShift>
1435void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001436 SmallVectorImpl<MCInst> &Instructions) {
1437 MCInst tmpInst;
1438 if (PerformShift) {
1439 tmpInst.setOpcode(Mips::DSLL);
1440 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1441 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1442 tmpInst.addOperand(MCOperand::CreateImm(16));
1443 tmpInst.setLoc(IDLoc);
1444 Instructions.push_back(tmpInst);
1445 tmpInst.clear();
1446 }
1447 tmpInst.setOpcode(Mips::ORi);
1448 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1449 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001450 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001451 tmpInst.setLoc(IDLoc);
1452 Instructions.push_back(tmpInst);
1453}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001454
1455template <int Shift, bool PerformShift>
1456void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1457 SmallVectorImpl<MCInst> &Instructions) {
1458 createShiftOr<PerformShift>(
1459 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1460 IDLoc, Instructions);
1461}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001462}
1463
Matheus Almeida3813d572014-06-19 14:39:14 +00001464bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001465 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001466 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001467 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001468 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001469 const MCOperand &RegOp = Inst.getOperand(0);
1470 assert(RegOp.isReg() && "expected register operand kind");
1471
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001472 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001473 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001474 // FIXME: gas has a special case for values that are 000...1111, which
1475 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001476 if (0 <= ImmValue && ImmValue <= 65535) {
1477 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001478 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001479 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001480 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001481 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001482 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001483 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001484 } else if (ImmValue < 0 && ImmValue >= -32768) {
1485 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001486 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001487 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001488 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001489 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001490 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001491 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001492 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1493 // For any value of j that is representable as a 32-bit integer, create
1494 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001495 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001496 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001497 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001498 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1499 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001500 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001501 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1502 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001503 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001504 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001505 return true;
1506 }
1507
1508 // <------- lo32 ------>
1509 // <------- hi32 ------>
1510 // <- hi16 -> <- lo16 ->
1511 // _________________________________
1512 // | | | |
1513 // | 16-bytes | 16-bytes | 16-bytes |
1514 // |__________|__________|__________|
1515 //
1516 // For any value of j that is representable as a 48-bit integer, create
1517 // a sequence of:
1518 // li d,j => lui d,hi16(j)
1519 // ori d,d,hi16(lo32(j))
1520 // dsll d,d,16
1521 // ori d,d,lo16(lo32(j))
1522 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001523 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001524 tmpInst.addOperand(
1525 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001526 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001527 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1528 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1529 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001530 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001531 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001532 return true;
1533 }
1534
1535 // <------- hi32 ------> <------- lo32 ------>
1536 // <- hi16 -> <- lo16 ->
1537 // ___________________________________________
1538 // | | | | |
1539 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1540 // |__________|__________|__________|__________|
1541 //
1542 // For any value of j that isn't representable as a 48-bit integer.
1543 // li d,j => lui d,hi16(j)
1544 // ori d,d,lo16(hi32(j))
1545 // dsll d,d,16
1546 // ori d,d,hi16(lo32(j))
1547 // dsll d,d,16
1548 // ori d,d,lo16(lo32(j))
1549 tmpInst.setOpcode(Mips::LUi);
1550 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1551 tmpInst.addOperand(
1552 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1553 Instructions.push_back(tmpInst);
1554 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1555 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1556 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001557 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001558 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001559}
Jack Carter92995f12012-10-06 00:53:28 +00001560
Matheus Almeida3813d572014-06-19 14:39:14 +00001561bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001562MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1563 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001564 MCInst tmpInst;
1565 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001566 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1567 "expected immediate operand kind");
1568 if (!ImmOp.isImm()) {
1569 expandLoadAddressSym(Inst, IDLoc, Instructions);
1570 return false;
1571 }
Jack Carter543fdf82012-10-09 23:29:45 +00001572 const MCOperand &SrcRegOp = Inst.getOperand(1);
1573 assert(SrcRegOp.isReg() && "expected register operand kind");
1574 const MCOperand &DstRegOp = Inst.getOperand(0);
1575 assert(DstRegOp.isReg() && "expected register operand kind");
1576 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001577 if (-32768 <= ImmValue && ImmValue <= 65535) {
1578 // For -32768 <= j <= 65535.
1579 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001580 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001581 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1582 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1583 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1584 Instructions.push_back(tmpInst);
1585 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001586 // For any other value of j that is representable as a 32-bit integer.
1587 // la d,j(s) => lui d,hi16(j)
1588 // ori d,d,lo16(j)
1589 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001590 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001591 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1592 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1593 Instructions.push_back(tmpInst);
1594 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001595 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001596 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1597 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1598 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1599 Instructions.push_back(tmpInst);
1600 tmpInst.clear();
1601 tmpInst.setOpcode(Mips::ADDu);
1602 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1603 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1604 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1605 Instructions.push_back(tmpInst);
1606 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001607 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001608}
1609
Matheus Almeida3813d572014-06-19 14:39:14 +00001610bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001611MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1612 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001613 MCInst tmpInst;
1614 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001615 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1616 "expected immediate operand kind");
1617 if (!ImmOp.isImm()) {
1618 expandLoadAddressSym(Inst, IDLoc, Instructions);
1619 return false;
1620 }
Jack Carter543fdf82012-10-09 23:29:45 +00001621 const MCOperand &RegOp = Inst.getOperand(0);
1622 assert(RegOp.isReg() && "expected register operand kind");
1623 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 if (-32768 <= ImmValue && ImmValue <= 65535) {
1625 // For -32768 <= j <= 65535.
1626 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001627 tmpInst.setOpcode(Mips::ADDiu);
1628 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001630 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1631 Instructions.push_back(tmpInst);
1632 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 // For any other value of j that is representable as a 32-bit integer.
1634 // la d,j => lui d,hi16(j)
1635 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001636 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001637 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1638 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1639 Instructions.push_back(tmpInst);
1640 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001641 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001642 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1643 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1644 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1645 Instructions.push_back(tmpInst);
1646 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001647 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001648}
1649
Toma Tabacu0d64b202014-08-14 10:29:17 +00001650void
1651MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1652 SmallVectorImpl<MCInst> &Instructions) {
1653 // FIXME: If we do have a valid at register to use, we should generate a
1654 // slightly shorter sequence here.
1655 MCInst tmpInst;
1656 int ExprOperandNo = 1;
1657 // Sometimes the assembly parser will get the immediate expression as
1658 // a $zero + an immediate.
1659 if (Inst.getNumOperands() == 3) {
1660 assert(Inst.getOperand(1).getReg() ==
1661 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1662 ExprOperandNo = 2;
1663 }
1664 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1665 assert(SymOp.isExpr() && "expected symbol operand kind");
1666 const MCOperand &RegOp = Inst.getOperand(0);
1667 unsigned RegNo = RegOp.getReg();
1668 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1669 const MCSymbolRefExpr *HiExpr =
1670 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1671 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1672 const MCSymbolRefExpr *LoExpr =
1673 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1674 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1675 if (isGP64bit()) {
1676 // If it's a 64-bit architecture, expand to:
1677 // la d,sym => lui d,highest(sym)
1678 // ori d,d,higher(sym)
1679 // dsll d,d,16
1680 // ori d,d,hi16(sym)
1681 // dsll d,d,16
1682 // ori d,d,lo16(sym)
1683 const MCSymbolRefExpr *HighestExpr =
1684 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1685 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1686 const MCSymbolRefExpr *HigherExpr =
1687 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1688 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1689
1690 tmpInst.setOpcode(Mips::LUi);
1691 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1692 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1693 Instructions.push_back(tmpInst);
1694
1695 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1696 Instructions);
1697 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1698 Instructions);
1699 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1700 Instructions);
1701 } else {
1702 // Otherwise, expand to:
1703 // la d,sym => lui d,hi16(sym)
1704 // ori d,d,lo16(sym)
1705 tmpInst.setOpcode(Mips::LUi);
1706 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1707 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1708 Instructions.push_back(tmpInst);
1709
1710 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1711 Instructions);
1712 }
1713}
1714
Jack Carter9e65aa32013-03-22 00:05:30 +00001715void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001716 SmallVectorImpl<MCInst> &Instructions,
1717 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001718 const MCSymbolRefExpr *SR;
1719 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001720 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001721 const MCExpr *ExprOffset;
1722 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001723 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001724 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1725 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1728 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001730 if (isImmOpnd) {
1731 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1732 ImmOffset = Inst.getOperand(2).getImm();
1733 LoOffset = ImmOffset & 0x0000ffff;
1734 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001735 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001736 if (LoOffset & 0x8000)
1737 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001739 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001741 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001742 // These are some of the types of expansions we perform here:
1743 // 1) lw $8, sym => lui $8, %hi(sym)
1744 // lw $8, %lo(sym)($8)
1745 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1746 // add $8, $8, $9
1747 // lw $8, %lo(offset)($9)
1748 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1749 // add $at, $at, $8
1750 // lw $8, %lo(offset)($at)
1751 // 4) sw $8, sym => lui $at, %hi(sym)
1752 // sw $8, %lo(sym)($at)
1753 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1754 // add $at, $at, $8
1755 // sw $8, %lo(offset)($at)
1756 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1757 // ldc1 $f0, %lo(sym)($at)
1758 //
1759 // For load instructions we can use the destination register as a temporary
1760 // if base and dst are different (examples 1 and 2) and if the base register
1761 // is general purpose otherwise we must use $at (example 6) and error if it's
1762 // not available. For stores we must use $at (examples 4 and 5) because we
1763 // must not clobber the source register setting up the offset.
1764 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1765 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1766 unsigned RegClassIDOp0 =
1767 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1768 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1769 (RegClassIDOp0 == Mips::GPR64RegClassID);
1770 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001771 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001772 else {
1773 int AT = getATReg(IDLoc);
1774 // At this point we need AT to perform the expansions and we exit if it is
1775 // not available.
1776 if (!AT)
1777 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001778 TmpRegNum = getReg(
1779 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001780 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001781
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 TempInst.setOpcode(Mips::LUi);
1783 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1784 if (isImmOpnd)
1785 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1786 else {
1787 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001788 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001789 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1790 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1791 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001792 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001793 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001794 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001795 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001796 }
1797 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001798 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001799 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001800 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001801 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001802 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001803 TempInst.setOpcode(Mips::ADDu);
1804 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1805 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1806 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1807 Instructions.push_back(TempInst);
1808 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001809 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001810 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001811 TempInst.setOpcode(Inst.getOpcode());
1812 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1813 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1814 if (isImmOpnd)
1815 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1816 else {
1817 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001818 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1819 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1820 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001821 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001822 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001823 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001824 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001825 }
1826 }
1827 Instructions.push_back(TempInst);
1828 TempInst.clear();
1829}
1830
Matheus Almeida595fcab2014-06-11 15:05:56 +00001831unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1832 // As described by the Mips32r2 spec, the registers Rd and Rs for
1833 // jalr.hb must be different.
1834 unsigned Opcode = Inst.getOpcode();
1835
1836 if (Opcode == Mips::JALR_HB &&
1837 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1838 return Match_RequiresDifferentSrcAndDst;
1839
1840 return Match_Success;
1841}
1842
David Blaikie960ea3f2014-06-08 16:18:35 +00001843bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1844 OperandVector &Operands,
1845 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001846 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001847 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001848
Jack Carterb4dbc172012-09-05 23:34:03 +00001849 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001850 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001851 unsigned MatchResult =
1852 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001853
1854 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001855 default:
1856 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001857 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001859 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001860 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001861 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001862 return false;
1863 }
1864 case Match_MissingFeature:
1865 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1866 return true;
1867 case Match_InvalidOperand: {
1868 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001869 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001870 if (ErrorInfo >= Operands.size())
1871 return Error(IDLoc, "too few operands for instruction");
1872
David Blaikie960ea3f2014-06-08 16:18:35 +00001873 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001874 if (ErrorLoc == SMLoc())
1875 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001876 }
1877
1878 return Error(ErrorLoc, "invalid operand for instruction");
1879 }
1880 case Match_MnemonicFail:
1881 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001882 case Match_RequiresDifferentSrcAndDst:
1883 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001884 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001885 return true;
1886}
1887
Toma Tabacu13964452014-09-04 13:23:44 +00001888void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001889 if ((RegIndex != 0) &&
1890 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001891 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001892 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001893 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001894 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001895 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001896 }
1897}
1898
Daniel Sandersef638fe2014-10-03 15:37:37 +00001899void
1900MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1901 SMRange Range, bool ShowColors) {
1902 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001903 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001904 ShowColors);
1905}
1906
Jack Carter1ac53222013-02-20 23:11:17 +00001907int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001908 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001909
Vladimir Medic4c299852013-11-06 11:27:05 +00001910 CC = StringSwitch<unsigned>(Name)
1911 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001912 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001913 .Case("a0", 4)
1914 .Case("a1", 5)
1915 .Case("a2", 6)
1916 .Case("a3", 7)
1917 .Case("v0", 2)
1918 .Case("v1", 3)
1919 .Case("s0", 16)
1920 .Case("s1", 17)
1921 .Case("s2", 18)
1922 .Case("s3", 19)
1923 .Case("s4", 20)
1924 .Case("s5", 21)
1925 .Case("s6", 22)
1926 .Case("s7", 23)
1927 .Case("k0", 26)
1928 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001929 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001930 .Case("sp", 29)
1931 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001932 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001933 .Case("ra", 31)
1934 .Case("t0", 8)
1935 .Case("t1", 9)
1936 .Case("t2", 10)
1937 .Case("t3", 11)
1938 .Case("t4", 12)
1939 .Case("t5", 13)
1940 .Case("t6", 14)
1941 .Case("t7", 15)
1942 .Case("t8", 24)
1943 .Case("t9", 25)
1944 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001945
Toma Tabacufda445c2014-09-15 15:33:01 +00001946 if (!(isABI_N32() || isABI_N64()))
1947 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001948
Daniel Sandersef638fe2014-10-03 15:37:37 +00001949 if (12 <= CC && CC <= 15) {
1950 // Name is one of t4-t7
1951 AsmToken RegTok = getLexer().peekTok();
1952 SMRange RegRange = RegTok.getLocRange();
1953
1954 StringRef FixedName = StringSwitch<StringRef>(Name)
1955 .Case("t4", "t0")
1956 .Case("t5", "t1")
1957 .Case("t6", "t2")
1958 .Case("t7", "t3")
1959 .Default("");
1960 assert(FixedName != "" && "Register name is not one of t4-t7.");
1961
1962 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1963 "Did you mean $" + FixedName + "?", RegRange);
1964 }
1965
Toma Tabacufda445c2014-09-15 15:33:01 +00001966 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1967 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1968 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1969 if (8 <= CC && CC <= 11)
1970 CC += 4;
1971
1972 if (CC == -1)
1973 CC = StringSwitch<unsigned>(Name)
1974 .Case("a4", 8)
1975 .Case("a5", 9)
1976 .Case("a6", 10)
1977 .Case("a7", 11)
1978 .Case("kt0", 26)
1979 .Case("kt1", 27)
1980 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001981
1982 return CC;
1983}
Jack Carterd0bd6422013-04-18 00:41:53 +00001984
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001985int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1986 int CC;
1987
1988 CC = StringSwitch<unsigned>(Name)
1989 .Case("hwr_cpunum", 0)
1990 .Case("hwr_synci_step", 1)
1991 .Case("hwr_cc", 2)
1992 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001993 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001994 .Default(-1);
1995
1996 return CC;
1997}
1998
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001999int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002000
Jack Cartera63b16a2012-09-07 00:23:42 +00002001 if (Name[0] == 'f') {
2002 StringRef NumString = Name.substr(1);
2003 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002004 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002005 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002006 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002007 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002008 return IntVal;
2009 }
2010 return -1;
2011}
Jack Cartera63b16a2012-09-07 00:23:42 +00002012
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002013int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2014
2015 if (Name.startswith("fcc")) {
2016 StringRef NumString = Name.substr(3);
2017 unsigned IntVal;
2018 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002019 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002020 if (IntVal > 7) // There are only 8 fcc registers.
2021 return -1;
2022 return IntVal;
2023 }
2024 return -1;
2025}
2026
2027int MipsAsmParser::matchACRegisterName(StringRef Name) {
2028
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002029 if (Name.startswith("ac")) {
2030 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002031 unsigned IntVal;
2032 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002033 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002034 if (IntVal > 3) // There are only 3 acc registers.
2035 return -1;
2036 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002037 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002038 return -1;
2039}
Jack Carterd0bd6422013-04-18 00:41:53 +00002040
Jack Carter5dc8ac92013-09-25 23:50:44 +00002041int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2042 unsigned IntVal;
2043
2044 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2045 return -1;
2046
2047 if (IntVal > 31)
2048 return -1;
2049
2050 return IntVal;
2051}
2052
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002053int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2054 int CC;
2055
2056 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002057 .Case("msair", 0)
2058 .Case("msacsr", 1)
2059 .Case("msaaccess", 2)
2060 .Case("msasave", 3)
2061 .Case("msamodify", 4)
2062 .Case("msarequest", 5)
2063 .Case("msamap", 6)
2064 .Case("msaunmap", 7)
2065 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002066
2067 return CC;
2068}
2069
Jack Carter0b744b32012-10-04 02:29:46 +00002070bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2071 if (Reg > 31)
2072 return false;
2073
Toma Tabacu3c24b042014-09-05 15:43:21 +00002074 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002075 return true;
2076}
2077
Matheus Almeida7de68e72014-06-18 14:46:05 +00002078int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002079 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002080 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002081 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002082 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002083 return AT;
2084}
Jack Carter0b744b32012-10-04 02:29:46 +00002085
Jack Carterd0bd6422013-04-18 00:41:53 +00002086unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002087 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002088}
2089
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002090unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002091 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002092 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002093}
2094
Jack Carter873c7242013-01-12 01:03:14 +00002095int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002096 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002097 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002098 return -1;
2099
Jack Carter873c7242013-01-12 01:03:14 +00002100 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002101}
2102
Toma Tabacu13964452014-09-04 13:23:44 +00002103bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002104 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002105 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002106
Jack Carter30a59822012-10-04 04:03:53 +00002107 // Check if the current operand has a custom associated parser, if so, try to
2108 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002109 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2110 if (ResTy == MatchOperand_Success)
2111 return false;
2112 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2113 // there was a match, but an error occurred, in which case, just return that
2114 // the operand parsing failed.
2115 if (ResTy == MatchOperand_ParseFail)
2116 return true;
2117
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002118 DEBUG(dbgs() << ".. Generic Parser\n");
2119
Jack Carterb4dbc172012-09-05 23:34:03 +00002120 switch (getLexer().getKind()) {
2121 default:
2122 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2123 return true;
2124 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002125 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002126 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002127
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002128 // Almost all registers have been parsed by custom parsers. There is only
2129 // one exception to this. $zero (and it's alias $0) will reach this point
2130 // for div, divu, and similar instructions because it is not an operand
2131 // to the instruction definition but an explicit register. Special case
2132 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002133 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002134 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002135
Jack Carterd0bd6422013-04-18 00:41:53 +00002136 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002137 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002138 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002139 return true;
2140
Jack Carter873c7242013-01-12 01:03:14 +00002141 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002142 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002143 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002144 const MCExpr *Res =
2145 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002146
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002147 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002148 return false;
2149 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002150 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002151 case AsmToken::LParen:
2152 case AsmToken::Minus:
2153 case AsmToken::Plus:
2154 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002155 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002156 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002157 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002158 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002159 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002160 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002161 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002163 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002164 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002165 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002166 return true;
2167
Jack Carter873c7242013-01-12 01:03:14 +00002168 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2169
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002170 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002171 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002172 } // case AsmToken::Percent
2173 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002174 return true;
2175}
2176
Vladimir Medic4c299852013-11-06 11:27:05 +00002177const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002178 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002179 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002181 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002182 // It's a constant, evaluate reloc value.
2183 int16_t Val;
2184 switch (getVariantKind(RelocStr)) {
2185 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2186 // Get the 1st 16-bits.
2187 Val = MCE->getValue() & 0xffff;
2188 break;
2189 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2190 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2191 // 16 bits being negative.
2192 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2193 break;
2194 case MCSymbolRefExpr::VK_Mips_HIGHER:
2195 // Get the 3rd 16-bits.
2196 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2197 break;
2198 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2199 // Get the 4th 16-bits.
2200 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2201 break;
2202 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002203 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002204 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002205 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002206 }
2207
Jack Carterb5cf5902013-04-17 00:18:04 +00002208 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002209 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002210 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002211 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002212 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002213 return Res;
2214 }
2215
2216 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002217 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2218
Sasa Stankovic06c47802014-04-03 10:37:45 +00002219 // Try to create target expression.
2220 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2221 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002222
Jack Carterd0bd6422013-04-18 00:41:53 +00002223 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2224 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002225 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2226 return Res;
2227 }
2228
2229 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002230 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2231 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2232 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002233 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002234 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002235 return Expr;
2236}
2237
2238bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2239
2240 switch (Expr->getKind()) {
2241 case MCExpr::Constant:
2242 return true;
2243 case MCExpr::SymbolRef:
2244 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2245 case MCExpr::Binary:
2246 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2247 if (!isEvaluated(BE->getLHS()))
2248 return false;
2249 return isEvaluated(BE->getRHS());
2250 }
2251 case MCExpr::Unary:
2252 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002253 case MCExpr::Target:
2254 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002255 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002256 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002257}
Jack Carterd0bd6422013-04-18 00:41:53 +00002258
Jack Carterb5cf5902013-04-17 00:18:04 +00002259bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002260 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002261 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002262 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002263 if (Tok.isNot(AsmToken::Identifier))
2264 return true;
2265
2266 std::string Str = Tok.getIdentifier().str();
2267
Jack Carterd0bd6422013-04-18 00:41:53 +00002268 Parser.Lex(); // Eat the identifier.
2269 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002270 const MCExpr *IdVal;
2271 SMLoc EndLoc;
2272
2273 if (getLexer().getKind() == AsmToken::LParen) {
2274 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002275 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002276 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002278 const AsmToken &nextTok = Parser.getTok();
2279 if (nextTok.isNot(AsmToken::Identifier))
2280 return true;
2281 Str += "(%";
2282 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002283 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002284 if (getLexer().getKind() != AsmToken::LParen)
2285 return true;
2286 } else
2287 break;
2288 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002289 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002290 return true;
2291
2292 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002293 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002294
2295 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002296 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002297
Jack Carterd0bd6422013-04-18 00:41:53 +00002298 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002299 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002300}
2301
Jack Carterb4dbc172012-09-05 23:34:03 +00002302bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2303 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002304 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002305 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002306 if (ResTy == MatchOperand_Success) {
2307 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002308 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002309 StartLoc = Operand.getStartLoc();
2310 EndLoc = Operand.getEndLoc();
2311
2312 // AFAIK, we only support numeric registers and named GPR's in CFI
2313 // directives.
2314 // Don't worry about eating tokens before failing. Using an unrecognised
2315 // register is a parse error.
2316 if (Operand.isGPRAsmReg()) {
2317 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002318 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002319 }
2320
2321 return (RegNo == (unsigned)-1);
2322 }
2323
2324 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002325 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002326}
2327
Jack Carterb5cf5902013-04-17 00:18:04 +00002328bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002329 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002330 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002331 bool Result = true;
2332
2333 while (getLexer().getKind() == AsmToken::LParen)
2334 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002335
Jack Carterd0bd6422013-04-18 00:41:53 +00002336 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002337 default:
2338 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002339 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002340 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002341 case AsmToken::Integer:
2342 case AsmToken::Minus:
2343 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002344 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002345 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002346 else
2347 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002348 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002349 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002350 break;
Jack Carter873c7242013-01-12 01:03:14 +00002351 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002352 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002353 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002354 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002355}
2356
David Blaikie960ea3f2014-06-08 16:18:35 +00002357MipsAsmParser::OperandMatchResultTy
2358MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002359 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002360 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002361 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002362 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002363 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002364 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002365 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002366 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002367
Jack Carterb5cf5902013-04-17 00:18:04 +00002368 if (getLexer().getKind() == AsmToken::LParen) {
2369 Parser.Lex();
2370 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002371 }
2372
Jack Carterb5cf5902013-04-17 00:18:04 +00002373 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002374 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002375 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002376
Jack Carterd0bd6422013-04-18 00:41:53 +00002377 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002378 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002379 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2380 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002381 SMLoc E =
2382 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002383 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002384 return MatchOperand_Success;
2385 }
2386 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002387 SMLoc E =
2388 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002389
Jack Carterd0bd6422013-04-18 00:41:53 +00002390 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002391 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002392 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002393 S, E, *this);
2394 Operands.push_back(
2395 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002396 return MatchOperand_Success;
2397 }
2398 Error(Parser.getTok().getLoc(), "'(' expected");
2399 return MatchOperand_ParseFail;
2400 }
2401
Jack Carterd0bd6422013-04-18 00:41:53 +00002402 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002403 }
2404
Toma Tabacu13964452014-09-04 13:23:44 +00002405 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002406 if (Res != MatchOperand_Success)
2407 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002408
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002409 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002410 Error(Parser.getTok().getLoc(), "')' expected");
2411 return MatchOperand_ParseFail;
2412 }
2413
Jack Carter873c7242013-01-12 01:03:14 +00002414 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2415
Jack Carterd0bd6422013-04-18 00:41:53 +00002416 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002417
Craig Topper062a2ba2014-04-25 05:30:21 +00002418 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002419 IdVal = MCConstantExpr::Create(0, getContext());
2420
Jack Carterd0bd6422013-04-18 00:41:53 +00002421 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002422 std::unique_ptr<MipsOperand> op(
2423 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002424 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002425 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002426 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002427 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002428 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2429 int64_t Imm;
2430 if (IdVal->EvaluateAsAbsolute(Imm))
2431 IdVal = MCConstantExpr::Create(Imm, getContext());
2432 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2433 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2434 getContext());
2435 }
2436
David Blaikie960ea3f2014-06-08 16:18:35 +00002437 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002438 return MatchOperand_Success;
2439}
2440
David Blaikie960ea3f2014-06-08 16:18:35 +00002441bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002442 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002443 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2444 if (Sym) {
2445 SMLoc S = Parser.getTok().getLoc();
2446 const MCExpr *Expr;
2447 if (Sym->isVariable())
2448 Expr = Sym->getVariableValue();
2449 else
2450 return false;
2451 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002452 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002453 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002454 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002455 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002456 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002457 if (ResTy == MatchOperand_Success) {
2458 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002459 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002460 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002461 llvm_unreachable("Should never ParseFail");
2462 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002463 }
2464 } else if (Expr->getKind() == MCExpr::Constant) {
2465 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002466 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002467 Operands.push_back(
2468 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002469 return true;
2470 }
2471 }
2472 return false;
2473}
Jack Carterd0bd6422013-04-18 00:41:53 +00002474
Jack Carter873c7242013-01-12 01:03:14 +00002475MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002476MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002477 StringRef Identifier,
2478 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002479 int Index = matchCPURegisterName(Identifier);
2480 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002481 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002482 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2483 return MatchOperand_Success;
2484 }
2485
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002486 Index = matchHWRegsRegisterName(Identifier);
2487 if (Index != -1) {
2488 Operands.push_back(MipsOperand::createHWRegsReg(
2489 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2490 return MatchOperand_Success;
2491 }
2492
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002493 Index = matchFPURegisterName(Identifier);
2494 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002495 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002496 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2497 return MatchOperand_Success;
2498 }
2499
2500 Index = matchFCCRegisterName(Identifier);
2501 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002502 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002503 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2504 return MatchOperand_Success;
2505 }
2506
2507 Index = matchACRegisterName(Identifier);
2508 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002509 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002510 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2511 return MatchOperand_Success;
2512 }
2513
2514 Index = matchMSA128RegisterName(Identifier);
2515 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002516 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002517 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2518 return MatchOperand_Success;
2519 }
2520
2521 Index = matchMSA128CtrlRegisterName(Identifier);
2522 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002523 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002524 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2525 return MatchOperand_Success;
2526 }
2527
2528 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002529}
2530
2531MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002532MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002533 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002534 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002535
2536 if (Token.is(AsmToken::Identifier)) {
2537 DEBUG(dbgs() << ".. identifier\n");
2538 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002539 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002540 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002541 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002542 } else if (Token.is(AsmToken::Integer)) {
2543 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002544 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002545 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2546 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002547 return MatchOperand_Success;
2548 }
2549
2550 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2551
2552 return MatchOperand_NoMatch;
2553}
2554
David Blaikie960ea3f2014-06-08 16:18:35 +00002555MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002556MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002557 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002558 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002559
2560 auto Token = Parser.getTok();
2561
2562 SMLoc S = Token.getLoc();
2563
2564 if (Token.isNot(AsmToken::Dollar)) {
2565 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2566 if (Token.is(AsmToken::Identifier)) {
2567 if (searchSymbolAlias(Operands))
2568 return MatchOperand_Success;
2569 }
2570 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2571 return MatchOperand_NoMatch;
2572 }
2573 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002574
Toma Tabacu13964452014-09-04 13:23:44 +00002575 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002576 if (ResTy == MatchOperand_Success) {
2577 Parser.Lex(); // $
2578 Parser.Lex(); // identifier
2579 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002580 return ResTy;
2581}
2582
2583MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002584MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002585 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002586 switch (getLexer().getKind()) {
2587 default:
2588 return MatchOperand_NoMatch;
2589 case AsmToken::LParen:
2590 case AsmToken::Minus:
2591 case AsmToken::Plus:
2592 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002593 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002594 case AsmToken::String:
2595 break;
2596 }
2597
2598 const MCExpr *IdVal;
2599 SMLoc S = Parser.getTok().getLoc();
2600 if (getParser().parseExpression(IdVal))
2601 return MatchOperand_ParseFail;
2602
2603 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2604 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2605 return MatchOperand_Success;
2606}
2607
David Blaikie960ea3f2014-06-08 16:18:35 +00002608MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002609MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002610 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002611 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002612
2613 SMLoc S = getLexer().getLoc();
2614
2615 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002616 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002617 if (ResTy != MatchOperand_NoMatch)
2618 return ResTy;
2619
Daniel Sanders315386c2014-04-01 10:40:14 +00002620 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002621 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002622 if (ResTy != MatchOperand_NoMatch)
2623 return ResTy;
2624
Daniel Sandersffd84362014-04-01 10:41:48 +00002625 const MCExpr *Expr = nullptr;
2626 if (Parser.parseExpression(Expr)) {
2627 // We have no way of knowing if a symbol was consumed so we must ParseFail
2628 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002629 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002630 Operands.push_back(
2631 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002632 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002633}
2634
Vladimir Medic2b953d02013-10-01 09:48:56 +00002635MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002636MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002637 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002638 const MCExpr *IdVal;
2639 // If the first token is '$' we may have register operand.
2640 if (Parser.getTok().is(AsmToken::Dollar))
2641 return MatchOperand_NoMatch;
2642 SMLoc S = Parser.getTok().getLoc();
2643 if (getParser().parseExpression(IdVal))
2644 return MatchOperand_ParseFail;
2645 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002646 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002647 int64_t Val = MCE->getValue();
2648 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2649 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002650 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002651 return MatchOperand_Success;
2652}
2653
Matheus Almeida779c5932013-11-18 12:32:49 +00002654MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002655MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002656 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002657 switch (getLexer().getKind()) {
2658 default:
2659 return MatchOperand_NoMatch;
2660 case AsmToken::LParen:
2661 case AsmToken::Plus:
2662 case AsmToken::Minus:
2663 case AsmToken::Integer:
2664 break;
2665 }
2666
2667 const MCExpr *Expr;
2668 SMLoc S = Parser.getTok().getLoc();
2669
2670 if (getParser().parseExpression(Expr))
2671 return MatchOperand_ParseFail;
2672
2673 int64_t Val;
2674 if (!Expr->EvaluateAsAbsolute(Val)) {
2675 Error(S, "expected immediate value");
2676 return MatchOperand_ParseFail;
2677 }
2678
2679 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2680 // and because the CPU always adds one to the immediate field, the allowed
2681 // range becomes 1..4. We'll only check the range here and will deal
2682 // with the addition/subtraction when actually decoding/encoding
2683 // the instruction.
2684 if (Val < 1 || Val > 4) {
2685 Error(S, "immediate not in range (1..4)");
2686 return MatchOperand_ParseFail;
2687 }
2688
Jack Carter3b2c96e2014-01-22 23:31:38 +00002689 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002690 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002691 return MatchOperand_Success;
2692}
2693
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002694MipsAsmParser::OperandMatchResultTy
2695MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2696 MCAsmParser &Parser = getParser();
2697 SmallVector<unsigned, 10> Regs;
2698 unsigned RegNo;
2699 unsigned PrevReg = Mips::NoRegister;
2700 bool RegRange = false;
2701 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2702
2703 if (Parser.getTok().isNot(AsmToken::Dollar))
2704 return MatchOperand_ParseFail;
2705
2706 SMLoc S = Parser.getTok().getLoc();
2707 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2708 SMLoc E = getLexer().getLoc();
2709 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2710 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2711 if (RegRange) {
2712 // Remove last register operand because registers from register range
2713 // should be inserted first.
2714 if (RegNo == Mips::RA) {
2715 Regs.push_back(RegNo);
2716 } else {
2717 unsigned TmpReg = PrevReg + 1;
2718 while (TmpReg <= RegNo) {
2719 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2720 Error(E, "invalid register operand");
2721 return MatchOperand_ParseFail;
2722 }
2723
2724 PrevReg = TmpReg;
2725 Regs.push_back(TmpReg++);
2726 }
2727 }
2728
2729 RegRange = false;
2730 } else {
2731 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2732 (RegNo != Mips::RA)) {
2733 Error(E, "$16 or $31 expected");
2734 return MatchOperand_ParseFail;
2735 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2736 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2737 Error(E, "invalid register operand");
2738 return MatchOperand_ParseFail;
2739 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2740 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2741 Error(E, "consecutive register numbers expected");
2742 return MatchOperand_ParseFail;
2743 }
2744
2745 Regs.push_back(RegNo);
2746 }
2747
2748 if (Parser.getTok().is(AsmToken::Minus))
2749 RegRange = true;
2750
2751 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2752 !Parser.getTok().isNot(AsmToken::Comma)) {
2753 Error(E, "',' or '-' expected");
2754 return MatchOperand_ParseFail;
2755 }
2756
2757 Lex(); // Consume comma or minus
2758 if (Parser.getTok().isNot(AsmToken::Dollar))
2759 break;
2760
2761 PrevReg = RegNo;
2762 }
2763
2764 SMLoc E = Parser.getTok().getLoc();
2765 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2766 parseMemOperand(Operands);
2767 return MatchOperand_Success;
2768}
2769
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002770MipsAsmParser::OperandMatchResultTy
2771MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2772 MCAsmParser &Parser = getParser();
2773
2774 SMLoc S = Parser.getTok().getLoc();
2775 if (parseAnyRegister(Operands) != MatchOperand_Success)
2776 return MatchOperand_ParseFail;
2777
2778 SMLoc E = Parser.getTok().getLoc();
2779 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2780 unsigned Reg = Op.getGPR32Reg();
2781 Operands.pop_back();
2782 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2783 return MatchOperand_Success;
2784}
2785
Jack Carterdc1e35d2012-09-06 20:00:02 +00002786MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2787
Vladimir Medic4c299852013-11-06 11:27:05 +00002788 MCSymbolRefExpr::VariantKind VK =
2789 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2790 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2791 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2792 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2793 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2794 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2795 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2796 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2797 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2798 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2799 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2800 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2801 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2802 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2803 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2804 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2805 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2806 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002807 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2808 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2809 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2810 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2811 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2812 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002813 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2814 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002815 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002816
Matheus Almeida2852af82014-04-22 10:15:54 +00002817 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002818
Jack Carterdc1e35d2012-09-06 20:00:02 +00002819 return VK;
2820}
Jack Cartera63b16a2012-09-07 00:23:42 +00002821
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002822/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2823/// either this.
2824/// ::= '(', register, ')'
2825/// handle it before we iterate so we don't get tripped up by the lack of
2826/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002827bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002828 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002829 if (getLexer().is(AsmToken::LParen)) {
2830 Operands.push_back(
2831 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2832 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002833 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 SMLoc Loc = getLexer().getLoc();
2835 Parser.eatToEndOfStatement();
2836 return Error(Loc, "unexpected token in argument list");
2837 }
2838 if (Parser.getTok().isNot(AsmToken::RParen)) {
2839 SMLoc Loc = getLexer().getLoc();
2840 Parser.eatToEndOfStatement();
2841 return Error(Loc, "unexpected token, expected ')'");
2842 }
2843 Operands.push_back(
2844 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2845 Parser.Lex();
2846 }
2847 return false;
2848}
2849
2850/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2851/// either one of these.
2852/// ::= '[', register, ']'
2853/// ::= '[', integer, ']'
2854/// handle it before we iterate so we don't get tripped up by the lack of
2855/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002856bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002857 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002858 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002859 if (getLexer().is(AsmToken::LBrac)) {
2860 Operands.push_back(
2861 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2862 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002863 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002864 SMLoc Loc = getLexer().getLoc();
2865 Parser.eatToEndOfStatement();
2866 return Error(Loc, "unexpected token in argument list");
2867 }
2868 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2869 SMLoc Loc = getLexer().getLoc();
2870 Parser.eatToEndOfStatement();
2871 return Error(Loc, "unexpected token, expected ']'");
2872 }
2873 Operands.push_back(
2874 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2875 Parser.Lex();
2876 }
2877 return false;
2878}
2879
David Blaikie960ea3f2014-06-08 16:18:35 +00002880bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2881 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002882 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002884
2885 // We have reached first instruction, module directive are now forbidden.
2886 getTargetStreamer().forbidModuleDirective();
2887
Vladimir Medic74593e62013-07-17 15:00:42 +00002888 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002889 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002890 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002891 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002892 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002893 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002894 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002895
2896 // Read the remaining operands.
2897 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2898 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002899 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002900 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002901 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002902 return Error(Loc, "unexpected token in argument list");
2903 }
Toma Tabacu13964452014-09-04 13:23:44 +00002904 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002905 return true;
2906 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002907
Jack Carterd0bd6422013-04-18 00:41:53 +00002908 while (getLexer().is(AsmToken::Comma)) {
2909 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002910 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002911 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002912 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002913 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002914 return Error(Loc, "unexpected token in argument list");
2915 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002916 // Parse bracket and parenthesis suffixes before we iterate
2917 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002918 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002919 return true;
2920 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002921 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002923 }
2924 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002925 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2926 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002927 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002928 return Error(Loc, "unexpected token in argument list");
2929 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002930 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002931 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002932}
2933
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002934bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002935 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002936 SMLoc Loc = getLexer().getLoc();
2937 Parser.eatToEndOfStatement();
2938 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002939}
2940
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002941bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002942 return Error(Loc, ErrorMsg);
2943}
2944
Jack Carter0b744b32012-10-04 02:29:46 +00002945bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002946 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002947 // Line should look like: ".set noat".
2948 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002949 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002950 // eat noat
2951 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002952 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002953 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002954 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002955 return false;
2956 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002957 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002958 return false;
2959}
Jack Carterd0bd6422013-04-18 00:41:53 +00002960
Jack Carter0b744b32012-10-04 02:29:46 +00002961bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002962 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002963 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002964 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002965 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002966 getParser().Lex();
2967 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002968 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002969 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002970 return false;
2971 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002972 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002973 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002974 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002975 return false;
2976 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002977 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002978 const AsmToken &Reg = Parser.getTok();
2979 if (Reg.is(AsmToken::Identifier)) {
2980 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2981 } else if (Reg.is(AsmToken::Integer)) {
2982 AtRegNo = Reg.getIntVal();
2983 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002984 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002985 return false;
2986 }
Jack Carter1ac53222013-02-20 23:11:17 +00002987
Daniel Sanders71a89d922014-03-25 13:01:06 +00002988 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002989 reportParseError("unexpected token in statement");
2990 return false;
2991 }
2992
Toma Tabacu9db22db2014-09-09 10:15:38 +00002993 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002994 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002995 return false;
2996 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002997 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002998
2999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003000 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003001 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003002 }
3003 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003004 return false;
3005 } else {
3006 reportParseError("unexpected token in statement");
3007 return false;
3008 }
3009}
3010
3011bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003012 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003013 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003014 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003015 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;
3018 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003019 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003020 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003021 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003022 return false;
3023}
3024
3025bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003026 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003027 Parser.Lex();
3028 // If this is not the end of the statement, report an error.
3029 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003030 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003031 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003032 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003033 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003034 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003035 Parser.Lex(); // Consume the EndOfStatement.
3036 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003037}
3038
3039bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003040 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003041 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003042 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003043 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003044 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003045 return false;
3046 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003047 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003048 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003049 return false;
3050}
3051
3052bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003053 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003054 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003055 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003056 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003057 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003058 return false;
3059 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003060 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003061 reportParseError("`noreorder' must be set before `nomacro'");
3062 return false;
3063 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003064 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003065 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003066 return false;
3067}
Jack Carterd76b2372013-03-21 21:44:16 +00003068
Daniel Sanders44934432014-08-07 12:03:36 +00003069bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003070 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003071 Parser.Lex();
3072
3073 // If this is not the end of the statement, report an error.
3074 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003075 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003076
3077 setFeatureBits(Mips::FeatureMSA, "msa");
3078 getTargetStreamer().emitDirectiveSetMsa();
3079 return false;
3080}
3081
3082bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003083 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003084 Parser.Lex();
3085
3086 // If this is not the end of the statement, report an error.
3087 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003088 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003089
3090 clearFeatureBits(Mips::FeatureMSA, "msa");
3091 getTargetStreamer().emitDirectiveSetNoMsa();
3092 return false;
3093}
3094
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003095bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003096 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003097 Parser.Lex(); // Eat "nodsp".
3098
3099 // If this is not the end of the statement, report an error.
3100 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3101 reportParseError("unexpected token, expected end of statement");
3102 return false;
3103 }
3104
3105 clearFeatureBits(Mips::FeatureDSP, "dsp");
3106 getTargetStreamer().emitDirectiveSetNoDsp();
3107 return false;
3108}
3109
Toma Tabacucc2502d2014-11-04 17:18:07 +00003110bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003111 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003112 Parser.Lex(); // Eat "mips16".
3113
Jack Carter39536722014-01-22 23:08:42 +00003114 // If this is not the end of the statement, report an error.
3115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003116 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003117 return false;
3118 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003119
3120 setFeatureBits(Mips::FeatureMips16, "mips16");
3121 getTargetStreamer().emitDirectiveSetMips16();
3122 Parser.Lex(); // Consume the EndOfStatement.
3123 return false;
3124}
3125
3126bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003127 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003128 Parser.Lex(); // Eat "nomips16".
3129
3130 // If this is not the end of the statement, report an error.
3131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3132 reportParseError("unexpected token, expected end of statement");
3133 return false;
3134 }
3135
3136 clearFeatureBits(Mips::FeatureMips16, "mips16");
3137 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003138 Parser.Lex(); // Consume the EndOfStatement.
3139 return false;
3140}
3141
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003142bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003143 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003144 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003145 // Line can be: .set fp=32
3146 // .set fp=xx
3147 // .set fp=64
3148 Parser.Lex(); // Eat fp token
3149 AsmToken Tok = Parser.getTok();
3150 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003151 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003152 return false;
3153 }
3154 Parser.Lex(); // Eat '=' token.
3155 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003156
3157 if (!parseFpABIValue(FpAbiVal, ".set"))
3158 return false;
3159
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003160 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003161 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003162 return false;
3163 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003164 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003165 Parser.Lex(); // Consume the EndOfStatement.
3166 return false;
3167}
3168
Toma Tabacu9db22db2014-09-09 10:15:38 +00003169bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003170 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003171 SMLoc Loc = getLexer().getLoc();
3172
3173 Parser.Lex();
3174 if (getLexer().isNot(AsmToken::EndOfStatement))
3175 return reportParseError("unexpected token, expected end of statement");
3176
3177 // Always keep an element on the options "stack" to prevent the user
3178 // from changing the initial options. This is how we remember them.
3179 if (AssemblerOptions.size() == 2)
3180 return reportParseError(Loc, ".set pop with no .set push");
3181
3182 AssemblerOptions.pop_back();
3183 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3184
3185 getTargetStreamer().emitDirectiveSetPop();
3186 return false;
3187}
3188
3189bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003190 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003191 Parser.Lex();
3192 if (getLexer().isNot(AsmToken::EndOfStatement))
3193 return reportParseError("unexpected token, expected end of statement");
3194
3195 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003196 AssemblerOptions.push_back(
3197 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003198
3199 getTargetStreamer().emitDirectiveSetPush();
3200 return false;
3201}
3202
Jack Carterd76b2372013-03-21 21:44:16 +00003203bool MipsAsmParser::parseSetAssignment() {
3204 StringRef Name;
3205 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003206 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003207
3208 if (Parser.parseIdentifier(Name))
3209 reportParseError("expected identifier after .set");
3210
3211 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003212 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003213 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003214
Jack Carter3b2c96e2014-01-22 23:31:38 +00003215 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003216 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003217
Jack Carterd0bd6422013-04-18 00:41:53 +00003218 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003219 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003220 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003221 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003222 Sym = getContext().GetOrCreateSymbol(Name);
3223 Sym->setVariableValue(Value);
3224
3225 return false;
3226}
Jack Carterd0bd6422013-04-18 00:41:53 +00003227
Toma Tabacu26647792014-09-09 12:52:14 +00003228bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003229 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003230 Parser.Lex();
3231 if (getLexer().isNot(AsmToken::EndOfStatement))
3232 return reportParseError("unexpected token, expected end of statement");
3233
3234 // Reset assembler options to their initial values.
3235 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3236 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3237
3238 getTargetStreamer().emitDirectiveSetMips0();
3239 return false;
3240}
3241
Toma Tabacu85618b32014-08-19 14:22:52 +00003242bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003243 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003244 Parser.Lex();
3245 if (getLexer().isNot(AsmToken::Equal))
3246 return reportParseError("unexpected token, expected equals sign");
3247
3248 Parser.Lex();
3249 StringRef Arch;
3250 if (Parser.parseIdentifier(Arch))
3251 return reportParseError("expected arch identifier");
3252
3253 StringRef ArchFeatureName =
3254 StringSwitch<StringRef>(Arch)
3255 .Case("mips1", "mips1")
3256 .Case("mips2", "mips2")
3257 .Case("mips3", "mips3")
3258 .Case("mips4", "mips4")
3259 .Case("mips5", "mips5")
3260 .Case("mips32", "mips32")
3261 .Case("mips32r2", "mips32r2")
3262 .Case("mips32r6", "mips32r6")
3263 .Case("mips64", "mips64")
3264 .Case("mips64r2", "mips64r2")
3265 .Case("mips64r6", "mips64r6")
3266 .Case("cnmips", "cnmips")
3267 .Case("r4000", "mips3") // This is an implementation of Mips3.
3268 .Default("");
3269
3270 if (ArchFeatureName.empty())
3271 return reportParseError("unsupported architecture");
3272
3273 selectArch(ArchFeatureName);
3274 getTargetStreamer().emitDirectiveSetArch(Arch);
3275 return false;
3276}
3277
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003278bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003279 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003280 Parser.Lex();
3281 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003282 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003283
Matheus Almeida2852af82014-04-22 10:15:54 +00003284 switch (Feature) {
3285 default:
3286 llvm_unreachable("Unimplemented feature");
3287 case Mips::FeatureDSP:
3288 setFeatureBits(Mips::FeatureDSP, "dsp");
3289 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003290 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003291 case Mips::FeatureMicroMips:
3292 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003293 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003294 case Mips::FeatureMips1:
3295 selectArch("mips1");
3296 getTargetStreamer().emitDirectiveSetMips1();
3297 break;
3298 case Mips::FeatureMips2:
3299 selectArch("mips2");
3300 getTargetStreamer().emitDirectiveSetMips2();
3301 break;
3302 case Mips::FeatureMips3:
3303 selectArch("mips3");
3304 getTargetStreamer().emitDirectiveSetMips3();
3305 break;
3306 case Mips::FeatureMips4:
3307 selectArch("mips4");
3308 getTargetStreamer().emitDirectiveSetMips4();
3309 break;
3310 case Mips::FeatureMips5:
3311 selectArch("mips5");
3312 getTargetStreamer().emitDirectiveSetMips5();
3313 break;
3314 case Mips::FeatureMips32:
3315 selectArch("mips32");
3316 getTargetStreamer().emitDirectiveSetMips32();
3317 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003318 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003319 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003320 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003321 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003322 case Mips::FeatureMips32r6:
3323 selectArch("mips32r6");
3324 getTargetStreamer().emitDirectiveSetMips32R6();
3325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003326 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003327 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003328 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003329 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003330 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003331 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003332 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003333 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003334 case Mips::FeatureMips64r6:
3335 selectArch("mips64r6");
3336 getTargetStreamer().emitDirectiveSetMips64R6();
3337 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003338 }
3339 return false;
3340}
3341
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003342bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003343 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003344 if (getLexer().isNot(AsmToken::Comma)) {
3345 SMLoc Loc = getLexer().getLoc();
3346 Parser.eatToEndOfStatement();
3347 return Error(Loc, ErrorStr);
3348 }
3349
Matheus Almeida2852af82014-04-22 10:15:54 +00003350 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003351 return true;
3352}
3353
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003354bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003355 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003356 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003357
Toma Tabacudde4c462014-11-06 10:02:45 +00003358 if (inMips16Mode()) {
3359 reportParseError(".cpload is not supported in Mips16 mode");
3360 return false;
3361 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003362
David Blaikie960ea3f2014-06-08 16:18:35 +00003363 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003364 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003365 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3366 reportParseError("expected register containing function address");
3367 return false;
3368 }
3369
David Blaikie960ea3f2014-06-08 16:18:35 +00003370 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3371 if (!RegOpnd.isGPRAsmReg()) {
3372 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003373 return false;
3374 }
3375
Toma Tabacudde4c462014-11-06 10:02:45 +00003376 // If this is not the end of the statement, report an error.
3377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3378 reportParseError("unexpected token, expected end of statement");
3379 return false;
3380 }
3381
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003382 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003383 return false;
3384}
3385
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003386bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003387 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003388 unsigned FuncReg;
3389 unsigned Save;
3390 bool SaveIsReg = true;
3391
Matheus Almeida7e815762014-06-18 13:08:59 +00003392 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003393 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003394 if (ResTy == MatchOperand_NoMatch) {
3395 reportParseError("expected register containing function address");
3396 Parser.eatToEndOfStatement();
3397 return false;
3398 }
3399
3400 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3401 if (!FuncRegOpnd.isGPRAsmReg()) {
3402 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3403 Parser.eatToEndOfStatement();
3404 return false;
3405 }
3406
3407 FuncReg = FuncRegOpnd.getGPR32Reg();
3408 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003409
Toma Tabacu65f10572014-09-16 15:00:52 +00003410 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003411 return true;
3412
Toma Tabacu13964452014-09-04 13:23:44 +00003413 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003414 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003415 const AsmToken &Tok = Parser.getTok();
3416 if (Tok.is(AsmToken::Integer)) {
3417 Save = Tok.getIntVal();
3418 SaveIsReg = false;
3419 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003420 } else {
3421 reportParseError("expected save register or stack offset");
3422 Parser.eatToEndOfStatement();
3423 return false;
3424 }
3425 } else {
3426 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3427 if (!SaveOpnd.isGPRAsmReg()) {
3428 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3429 Parser.eatToEndOfStatement();
3430 return false;
3431 }
3432 Save = SaveOpnd.getGPR32Reg();
3433 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003434
Toma Tabacu65f10572014-09-16 15:00:52 +00003435 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003436 return true;
3437
3438 StringRef Name;
3439 if (Parser.parseIdentifier(Name))
3440 reportParseError("expected identifier");
3441 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003442
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003443 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003444 return false;
3445}
3446
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003447bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003448 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003449 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3450 const AsmToken &Tok = Parser.getTok();
3451
3452 if (Tok.getString() == "2008") {
3453 Parser.Lex();
3454 getTargetStreamer().emitDirectiveNaN2008();
3455 return false;
3456 } else if (Tok.getString() == "legacy") {
3457 Parser.Lex();
3458 getTargetStreamer().emitDirectiveNaNLegacy();
3459 return false;
3460 }
3461 }
3462 // If we don't recognize the option passed to the .nan
3463 // directive (e.g. no option or unknown option), emit an error.
3464 reportParseError("invalid option in .nan directive");
3465 return false;
3466}
3467
Jack Carter0b744b32012-10-04 02:29:46 +00003468bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003469 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003470 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003471 const AsmToken &Tok = Parser.getTok();
3472
3473 if (Tok.getString() == "noat") {
3474 return parseSetNoAtDirective();
3475 } else if (Tok.getString() == "at") {
3476 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003477 } else if (Tok.getString() == "arch") {
3478 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003479 } else if (Tok.getString() == "fp") {
3480 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003481 } else if (Tok.getString() == "pop") {
3482 return parseSetPopDirective();
3483 } else if (Tok.getString() == "push") {
3484 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003485 } else if (Tok.getString() == "reorder") {
3486 return parseSetReorderDirective();
3487 } else if (Tok.getString() == "noreorder") {
3488 return parseSetNoReorderDirective();
3489 } else if (Tok.getString() == "macro") {
3490 return parseSetMacroDirective();
3491 } else if (Tok.getString() == "nomacro") {
3492 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003493 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003494 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003495 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003496 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003497 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003498 getTargetStreamer().emitDirectiveSetNoMicroMips();
3499 Parser.eatToEndOfStatement();
3500 return false;
3501 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003502 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003503 } else if (Tok.getString() == "mips0") {
3504 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003505 } else if (Tok.getString() == "mips1") {
3506 return parseSetFeature(Mips::FeatureMips1);
3507 } else if (Tok.getString() == "mips2") {
3508 return parseSetFeature(Mips::FeatureMips2);
3509 } else if (Tok.getString() == "mips3") {
3510 return parseSetFeature(Mips::FeatureMips3);
3511 } else if (Tok.getString() == "mips4") {
3512 return parseSetFeature(Mips::FeatureMips4);
3513 } else if (Tok.getString() == "mips5") {
3514 return parseSetFeature(Mips::FeatureMips5);
3515 } else if (Tok.getString() == "mips32") {
3516 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003517 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003518 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003519 } else if (Tok.getString() == "mips32r6") {
3520 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003521 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003522 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003523 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003524 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003525 } else if (Tok.getString() == "mips64r6") {
3526 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003527 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003528 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003529 } else if (Tok.getString() == "nodsp") {
3530 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003531 } else if (Tok.getString() == "msa") {
3532 return parseSetMsaDirective();
3533 } else if (Tok.getString() == "nomsa") {
3534 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003535 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003536 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003537 parseSetAssignment();
3538 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003539 }
Jack Carter07c818d2013-01-25 01:31:34 +00003540
Jack Carter0b744b32012-10-04 02:29:46 +00003541 return true;
3542}
3543
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003544/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003545/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003546bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003547 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3549 for (;;) {
3550 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003551 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003552 return true;
3553
3554 getParser().getStreamer().EmitValue(Value, Size);
3555
3556 if (getLexer().is(AsmToken::EndOfStatement))
3557 break;
3558
Jack Carter07c818d2013-01-25 01:31:34 +00003559 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003560 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003561 Parser.Lex();
3562 }
3563 }
3564
3565 Parser.Lex();
3566 return false;
3567}
3568
Vladimir Medic4c299852013-11-06 11:27:05 +00003569/// parseDirectiveGpWord
3570/// ::= .gpword local_sym
3571bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003572 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003573 const MCExpr *Value;
3574 // EmitGPRel32Value requires an expression, so we are using base class
3575 // method to evaluate the expression.
3576 if (getParser().parseExpression(Value))
3577 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003578 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003579
Vladimir Medice10c1122013-11-13 13:18:04 +00003580 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003581 return Error(getLexer().getLoc(),
3582 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003583 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003584 return false;
3585}
3586
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003587/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003588/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003589bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003590 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003591 const MCExpr *Value;
3592 // EmitGPRel64Value requires an expression, so we are using base class
3593 // method to evaluate the expression.
3594 if (getParser().parseExpression(Value))
3595 return true;
3596 getParser().getStreamer().EmitGPRel64Value(Value);
3597
3598 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003599 return Error(getLexer().getLoc(),
3600 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003601 Parser.Lex(); // Eat EndOfStatement token.
3602 return false;
3603}
3604
Jack Carter0cd3c192014-01-06 23:27:31 +00003605bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003606 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003607 // Get the option token.
3608 AsmToken Tok = Parser.getTok();
3609 // At the moment only identifiers are supported.
3610 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003611 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003612 Parser.eatToEndOfStatement();
3613 return false;
3614 }
3615
3616 StringRef Option = Tok.getIdentifier();
3617
3618 if (Option == "pic0") {
3619 getTargetStreamer().emitDirectiveOptionPic0();
3620 Parser.Lex();
3621 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3622 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003623 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003624 Parser.eatToEndOfStatement();
3625 }
3626 return false;
3627 }
3628
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003629 if (Option == "pic2") {
3630 getTargetStreamer().emitDirectiveOptionPic2();
3631 Parser.Lex();
3632 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3633 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003634 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003635 Parser.eatToEndOfStatement();
3636 }
3637 return false;
3638 }
3639
Jack Carter0cd3c192014-01-06 23:27:31 +00003640 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003641 Warning(Parser.getTok().getLoc(),
3642 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003643 Parser.eatToEndOfStatement();
3644 return false;
3645}
3646
Daniel Sanders7e527422014-07-10 13:38:23 +00003647/// parseDirectiveModule
3648/// ::= .module oddspreg
3649/// ::= .module nooddspreg
3650/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003651bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003652 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003653 MCAsmLexer &Lexer = getLexer();
3654 SMLoc L = Lexer.getLoc();
3655
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003656 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003657 // TODO : get a better message.
3658 reportParseError(".module directive must appear before any code");
3659 return false;
3660 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003661
3662 if (Lexer.is(AsmToken::Identifier)) {
3663 StringRef Option = Parser.getTok().getString();
3664 Parser.Lex();
3665
3666 if (Option == "oddspreg") {
3667 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3668 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3669
3670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003671 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003672 return false;
3673 }
3674
3675 return false;
3676 } else if (Option == "nooddspreg") {
3677 if (!isABI_O32()) {
3678 Error(L, "'.module nooddspreg' requires the O32 ABI");
3679 return false;
3680 }
3681
3682 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3683 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3684
3685 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003686 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003687 return false;
3688 }
3689
3690 return false;
3691 } else if (Option == "fp") {
3692 return parseDirectiveModuleFP();
3693 }
3694
3695 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003696 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003697
3698 return false;
3699}
3700
3701/// parseDirectiveModuleFP
3702/// ::= =32
3703/// ::= =xx
3704/// ::= =64
3705bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003706 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003707 MCAsmLexer &Lexer = getLexer();
3708
3709 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003710 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003711 return false;
3712 }
3713 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003714
Daniel Sanders7e527422014-07-10 13:38:23 +00003715 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003716 if (!parseFpABIValue(FpABI, ".module"))
3717 return false;
3718
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003720 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003721 return false;
3722 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003723
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003724 // Emit appropriate flags.
3725 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003726 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003727 return false;
3728}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003729
Daniel Sanders7e527422014-07-10 13:38:23 +00003730bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003731 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003732 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003733 MCAsmLexer &Lexer = getLexer();
3734
3735 if (Lexer.is(AsmToken::Identifier)) {
3736 StringRef Value = Parser.getTok().getString();
3737 Parser.Lex();
3738
3739 if (Value != "xx") {
3740 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3741 return false;
3742 }
3743
3744 if (!isABI_O32()) {
3745 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3746 return false;
3747 }
3748
Daniel Sanders7e527422014-07-10 13:38:23 +00003749 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003750 return true;
3751 }
3752
3753 if (Lexer.is(AsmToken::Integer)) {
3754 unsigned Value = Parser.getTok().getIntVal();
3755 Parser.Lex();
3756
3757 if (Value != 32 && Value != 64) {
3758 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3759 return false;
3760 }
3761
3762 if (Value == 32) {
3763 if (!isABI_O32()) {
3764 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3765 return false;
3766 }
3767
Daniel Sanders7e527422014-07-10 13:38:23 +00003768 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3769 } else
3770 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003771
Daniel Sanders7e527422014-07-10 13:38:23 +00003772 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003773 }
3774
3775 return false;
3776}
3777
Jack Carter0b744b32012-10-04 02:29:46 +00003778bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003779 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003780 StringRef IDVal = DirectiveID.getString();
3781
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003782 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003783 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003784 if (IDVal == ".dword") {
3785 parseDataDirective(8, DirectiveID.getLoc());
3786 return false;
3787 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003788 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003789 StringRef SymbolName;
3790
3791 if (Parser.parseIdentifier(SymbolName)) {
3792 reportParseError("expected identifier after .ent");
3793 return false;
3794 }
3795
3796 // There's an undocumented extension that allows an integer to
3797 // follow the name of the procedure which AFAICS is ignored by GAS.
3798 // Example: .ent foo,2
3799 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3800 if (getLexer().isNot(AsmToken::Comma)) {
3801 // Even though we accept this undocumented extension for compatibility
3802 // reasons, the additional integer argument does not actually change
3803 // the behaviour of the '.ent' directive, so we would like to discourage
3804 // its use. We do this by not referring to the extended version in
3805 // error messages which are not directly related to its use.
3806 reportParseError("unexpected token, expected end of statement");
3807 return false;
3808 }
3809 Parser.Lex(); // Eat the comma.
3810 const MCExpr *DummyNumber;
3811 int64_t DummyNumberVal;
3812 // If the user was explicitly trying to use the extended version,
3813 // we still give helpful extension-related error messages.
3814 if (Parser.parseExpression(DummyNumber)) {
3815 reportParseError("expected number after comma");
3816 return false;
3817 }
3818 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3819 reportParseError("expected an absolute expression after comma");
3820 return false;
3821 }
3822 }
3823
3824 // If this is not the end of the statement, report an error.
3825 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3826 reportParseError("unexpected token, expected end of statement");
3827 return false;
3828 }
3829
3830 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3831
3832 getTargetStreamer().emitDirectiveEnt(*Sym);
3833 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003834 return false;
3835 }
3836
Jack Carter07c818d2013-01-25 01:31:34 +00003837 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003838 StringRef SymbolName;
3839
3840 if (Parser.parseIdentifier(SymbolName)) {
3841 reportParseError("expected identifier after .end");
3842 return false;
3843 }
3844
3845 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3846 reportParseError("unexpected token, expected end of statement");
3847 return false;
3848 }
3849
3850 if (CurrentFn == nullptr) {
3851 reportParseError(".end used without .ent");
3852 return false;
3853 }
3854
3855 if ((SymbolName != CurrentFn->getName())) {
3856 reportParseError(".end symbol does not match .ent symbol");
3857 return false;
3858 }
3859
3860 getTargetStreamer().emitDirectiveEnd(SymbolName);
3861 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003862 return false;
3863 }
3864
Jack Carter07c818d2013-01-25 01:31:34 +00003865 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003866 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3867 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003868 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003869 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3870 reportParseError("expected stack register");
3871 return false;
3872 }
3873
3874 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3875 if (!StackRegOpnd.isGPRAsmReg()) {
3876 reportParseError(StackRegOpnd.getStartLoc(),
3877 "expected general purpose register");
3878 return false;
3879 }
3880 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3881
3882 if (Parser.getTok().is(AsmToken::Comma))
3883 Parser.Lex();
3884 else {
3885 reportParseError("unexpected token, expected comma");
3886 return false;
3887 }
3888
3889 // Parse the frame size.
3890 const MCExpr *FrameSize;
3891 int64_t FrameSizeVal;
3892
3893 if (Parser.parseExpression(FrameSize)) {
3894 reportParseError("expected frame size value");
3895 return false;
3896 }
3897
3898 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3899 reportParseError("frame size not an absolute expression");
3900 return false;
3901 }
3902
3903 if (Parser.getTok().is(AsmToken::Comma))
3904 Parser.Lex();
3905 else {
3906 reportParseError("unexpected token, expected comma");
3907 return false;
3908 }
3909
3910 // Parse the return register.
3911 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003912 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003913 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3914 reportParseError("expected return register");
3915 return false;
3916 }
3917
3918 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3919 if (!ReturnRegOpnd.isGPRAsmReg()) {
3920 reportParseError(ReturnRegOpnd.getStartLoc(),
3921 "expected general purpose register");
3922 return false;
3923 }
3924
3925 // If this is not the end of the statement, report an error.
3926 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3927 reportParseError("unexpected token, expected end of statement");
3928 return false;
3929 }
3930
3931 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3932 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003933 return false;
3934 }
3935
Jack Carter07c818d2013-01-25 01:31:34 +00003936 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003937 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003938 }
3939
Daniel Sandersd97a6342014-08-13 10:07:34 +00003940 if (IDVal == ".mask" || IDVal == ".fmask") {
3941 // .mask bitmask, frame_offset
3942 // bitmask: One bit for each register used.
3943 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3944 // first register is expected to be saved.
3945 // Examples:
3946 // .mask 0x80000000, -4
3947 // .fmask 0x80000000, -4
3948 //
Jack Carterbe332172012-09-07 00:48:02 +00003949
Daniel Sandersd97a6342014-08-13 10:07:34 +00003950 // Parse the bitmask
3951 const MCExpr *BitMask;
3952 int64_t BitMaskVal;
3953
3954 if (Parser.parseExpression(BitMask)) {
3955 reportParseError("expected bitmask value");
3956 return false;
3957 }
3958
3959 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3960 reportParseError("bitmask not an absolute expression");
3961 return false;
3962 }
3963
3964 if (Parser.getTok().is(AsmToken::Comma))
3965 Parser.Lex();
3966 else {
3967 reportParseError("unexpected token, expected comma");
3968 return false;
3969 }
3970
3971 // Parse the frame_offset
3972 const MCExpr *FrameOffset;
3973 int64_t FrameOffsetVal;
3974
3975 if (Parser.parseExpression(FrameOffset)) {
3976 reportParseError("expected frame offset value");
3977 return false;
3978 }
3979
3980 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3981 reportParseError("frame offset not an absolute expression");
3982 return false;
3983 }
3984
3985 // If this is not the end of the statement, report an error.
3986 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3987 reportParseError("unexpected token, expected end of statement");
3988 return false;
3989 }
3990
3991 if (IDVal == ".mask")
3992 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3993 else
3994 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003995 return false;
3996 }
3997
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003998 if (IDVal == ".nan")
3999 return parseDirectiveNaN();
4000
Jack Carter07c818d2013-01-25 01:31:34 +00004001 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004002 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004003 return false;
4004 }
4005
Rafael Espindolab59fb732014-03-28 18:50:26 +00004006 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004007 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004008 return false;
4009 }
4010
Jack Carter07c818d2013-01-25 01:31:34 +00004011 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004012 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004013 return false;
4014 }
4015
Jack Carter0cd3c192014-01-06 23:27:31 +00004016 if (IDVal == ".option")
4017 return parseDirectiveOption();
4018
4019 if (IDVal == ".abicalls") {
4020 getTargetStreamer().emitDirectiveAbiCalls();
4021 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004022 Error(Parser.getTok().getLoc(),
4023 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004024 // Clear line
4025 Parser.eatToEndOfStatement();
4026 }
4027 return false;
4028 }
4029
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004030 if (IDVal == ".cpsetup")
4031 return parseDirectiveCPSetup();
4032
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004033 if (IDVal == ".module")
4034 return parseDirectiveModule();
4035
Rafael Espindola870c4e92012-01-11 03:56:41 +00004036 return true;
4037}
4038
Rafael Espindola870c4e92012-01-11 03:56:41 +00004039extern "C" void LLVMInitializeMipsAsmParser() {
4040 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4041 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4042 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4043 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4044}
Jack Carterb4dbc172012-09-05 23:34:03 +00004045
4046#define GET_REGISTER_MATCHER
4047#define GET_MATCHER_IMPLEMENTATION
4048#include "MipsGenAsmMatcher.inc"