blob: 969c6e3a8bf43c90187d472b504042df535d0f5c [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
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000032#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000033
34using namespace llvm;
35
Chandler Carruthe96dd892014-04-21 22:55:11 +000036#define DEBUG_TYPE "mips-asm-parser"
37
Joey Gouly0e76fa72013-09-12 10:28:05 +000038namespace llvm {
39class MCInstrInfo;
40}
41
Rafael Espindola870c4e92012-01-11 03:56:41 +000042namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000043class MipsAssemblerOptions {
44public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000045 MipsAssemblerOptions(uint64_t Features_) :
46 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000047
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
49 ATReg = Opts->getATRegNum();
50 Reorder = Opts->isReorder();
51 Macro = Opts->isMacro();
52 Features = Opts->getFeatures();
53 }
54
55 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000056 bool setATReg(unsigned Reg);
57
Toma Tabacu9db22db2014-09-09 10:15:38 +000058 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000059 void setReorder() { Reorder = true; }
60 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000061
Toma Tabacu9db22db2014-09-09 10:15:38 +000062 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000063 void setMacro() { Macro = true; }
64 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 uint64_t getFeatures() const { return Features; }
67 void setFeatures(uint64_t Features_) { Features = Features_; }
68
Daniel Sandersf0df2212014-08-04 12:20:00 +000069 // Set of features that are either architecture features or referenced
70 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
71 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
72 // The reason we need this mask is explained in the selectArch function.
73 // FIXME: Ideally we would like TableGen to generate this information.
74 static const uint64_t AllArchRelatedMask =
75 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
76 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
77 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
78 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
79 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
80 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
81 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
82
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000087 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
91namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000092class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000093 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000094 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000095 return static_cast<MipsTargetStreamer &>(TS);
96 }
97
Jack Carterb4dbc172012-09-05 23:34:03 +000098 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +000099 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000100 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000101 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
102 // nullptr, which indicates that no function is currently
103 // selected. This usually happens after an '.end func'
104 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000105
Daniel Sandersef638fe2014-10-03 15:37:37 +0000106 // Print a warning along with its fix-it message at the given range.
107 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
108 SMRange Range, bool ShowColors = true);
109
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000110#define GET_ASSEMBLER_HEADER
111#include "MipsGenAsmMatcher.inc"
112
Matheus Almeida595fcab2014-06-11 15:05:56 +0000113 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
114
Chad Rosier49963552012-10-13 00:26:04 +0000115 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000116 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000117 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000118 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000119
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000120 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000121 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
Toma Tabacu13964452014-09-04 13:23:44 +0000125 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000126
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
128 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
David Blaikie960ea3f2014-06-08 16:18:35 +0000132 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000133
134 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000135 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000137
Jack Carter873c7242013-01-12 01:03:14 +0000138 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000139 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000150
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000151 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000152 parseRegisterPair (OperandVector &Operands);
153
154 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000155 parseMovePRegPair(OperandVector &Operands);
156
157 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000158 parseRegisterList (OperandVector &Operands);
159
David Blaikie960ea3f2014-06-08 16:18:35 +0000160 bool searchSymbolAlias(OperandVector &Operands);
161
Toma Tabacu13964452014-09-04 13:23:44 +0000162 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000163
Jack Carter30a59822012-10-04 04:03:53 +0000164 bool needsExpansion(MCInst &Inst);
165
Matheus Almeida3813d572014-06-19 14:39:14 +0000166 // Expands assembly pseudo instructions.
167 // Returns false on success, true otherwise.
168 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000169 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000170
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000171 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
172 SmallVectorImpl<MCInst> &Instructions);
173
Matheus Almeida3813d572014-06-19 14:39:14 +0000174 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000175 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000176
177 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000178 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
180 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000181 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000182 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000184
Toma Tabacu0d64b202014-08-14 10:29:17 +0000185 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
187
Jack Carter9e65aa32013-03-22 00:05:30 +0000188 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000189 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
190 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000191
192 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
193 SmallVectorImpl<MCInst> &Instructions);
194
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000195 bool reportParseError(Twine ErrorMsg);
196 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000197
Jack Carterb5cf5902013-04-17 00:18:04 +0000198 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000199 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000200
Vladimir Medic4c299852013-11-06 11:27:05 +0000201 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000202
203 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000204 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000205 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000206 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000207 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000208 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000209 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000210 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000211 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000212
213 bool parseSetAtDirective();
214 bool parseSetNoAtDirective();
215 bool parseSetMacroDirective();
216 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000217 bool parseSetMsaDirective();
218 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000219 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000220 bool parseSetReorderDirective();
221 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000222 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000223 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000224 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000225 bool parseSetPopDirective();
226 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000227
Jack Carterd76b2372013-03-21 21:44:16 +0000228 bool parseSetAssignment();
229
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000230 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000231 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000232 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000233 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000234 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000235 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
236 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000237
Jack Carterdc1e35d2012-09-06 20:00:02 +0000238 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000239
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000240 bool eatComma(StringRef ErrorStr);
241
Jack Carter1ac53222013-02-20 23:11:17 +0000242 int matchCPURegisterName(StringRef Symbol);
243
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000244 int matchHWRegsRegisterName(StringRef Symbol);
245
Jack Carter873c7242013-01-12 01:03:14 +0000246 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000247
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000248 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000249
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000250 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000251
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000252 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000253
Jack Carter5dc8ac92013-09-25 23:50:44 +0000254 int matchMSA128RegisterName(StringRef Name);
255
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000256 int matchMSA128CtrlRegisterName(StringRef Name);
257
Jack Carterd0bd6422013-04-18 00:41:53 +0000258 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000259
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000260 unsigned getGPR(int RegNo);
261
Matheus Almeida7de68e72014-06-18 14:46:05 +0000262 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000263
264 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000265 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000266
267 // Helper function that checks if the value of a vector index is within the
268 // boundaries of accepted values for each RegisterKind
269 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
270 bool validateMSAIndex(int Val, int RegKind);
271
Daniel Sandersf0df2212014-08-04 12:20:00 +0000272 // Selects a new architecture by updating the FeatureBits with the necessary
273 // info including implied dependencies.
274 // Internally, it clears all the feature bits related to *any* architecture
275 // and selects the new one using the ToggleFeature functionality of the
276 // MCSubtargetInfo object that handles implied dependencies. The reason we
277 // clear all the arch related bits manually is because ToggleFeature only
278 // clears the features that imply the feature being cleared and not the
279 // features implied by the feature being cleared. This is easier to see
280 // with an example:
281 // --------------------------------------------------
282 // | Feature | Implies |
283 // | -------------------------------------------------|
284 // | FeatureMips1 | None |
285 // | FeatureMips2 | FeatureMips1 |
286 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
287 // | FeatureMips4 | FeatureMips3 |
288 // | ... | |
289 // --------------------------------------------------
290 //
291 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
292 // FeatureMipsGP64 | FeatureMips1)
293 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
294 void selectArch(StringRef ArchFeature) {
295 uint64_t FeatureBits = STI.getFeatureBits();
296 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
297 STI.setFeatureBits(FeatureBits);
298 setAvailableFeatures(
299 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000300 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000301 }
302
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000303 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000304 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000305 setAvailableFeatures(
306 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000307 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000308 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000309 }
310
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000311 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000312 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000313 setAvailableFeatures(
314 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000315 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000316 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000317 }
318
Rafael Espindola870c4e92012-01-11 03:56:41 +0000319public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000320 enum MipsMatchResultTy {
321 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
322#define GET_OPERAND_DIAGNOSTIC_TYPES
323#include "MipsGenAsmMatcher.inc"
324#undef GET_OPERAND_DIAGNOSTIC_TYPES
325
326 };
327
Joey Gouly0e76fa72013-09-12 10:28:05 +0000328 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000329 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000330 : MCTargetAsmParser(), STI(sti),
331 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
332 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000333 MCAsmParserExtension::Initialize(parser);
334
Jack Carterb4dbc172012-09-05 23:34:03 +0000335 // Initialize the set of available features.
336 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000337
338 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000339 AssemblerOptions.push_back(
340 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000341
342 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000343 AssemblerOptions.push_back(
344 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000345
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000346 getTargetStreamer().updateABIInfo(*this);
347
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000348 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000349 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000350
351 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000352 }
353
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000354 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
355 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
356
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000357 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
358 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000359 const MipsABIInfo &getABI() const { return ABI; }
360 bool isABI_N32() const { return ABI.IsN32(); }
361 bool isABI_N64() const { return ABI.IsN64(); }
362 bool isABI_O32() const { return ABI.IsO32(); }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000363 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000364
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000365 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000366 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
367 }
368
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000369 bool inMicroMipsMode() const {
370 return STI.getFeatureBits() & Mips::FeatureMicroMips;
371 }
372 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
373 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
374 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
375 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
376 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
377 bool hasMips32() const {
378 return (STI.getFeatureBits() & Mips::FeatureMips32);
379 }
380 bool hasMips64() const {
381 return (STI.getFeatureBits() & Mips::FeatureMips64);
382 }
383 bool hasMips32r2() const {
384 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
385 }
386 bool hasMips64r2() const {
387 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
388 }
389 bool hasMips32r6() const {
390 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
391 }
392 bool hasMips64r6() const {
393 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
394 }
Kai Nackee0245392015-01-27 19:11:28 +0000395 bool hasCnMips() const {
396 return (STI.getFeatureBits() & Mips::FeatureCnMips);
397 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
399 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
400 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
401
402 bool inMips16Mode() const {
403 return STI.getFeatureBits() & Mips::FeatureMips16;
404 }
405 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000406 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000408 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000409 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000410};
411}
412
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000413namespace {
414
415/// MipsOperand - Instances of this class represent a parsed Mips machine
416/// instruction.
417class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000418public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000419 /// Broad categories of register classes
420 /// The exact class is finalized by the render method.
421 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000422 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000423 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000424 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000425 RegKind_FCC = 4, /// FCC
426 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
427 RegKind_MSACtrl = 16, /// MSA control registers
428 RegKind_COP2 = 32, /// COP2
429 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
430 /// context).
431 RegKind_CCR = 128, /// CCR
432 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000433 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000434
435 /// Potentially any (e.g. $1)
436 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
437 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000438 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000439 };
440
441private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000442 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000443 k_Immediate, /// An immediate (possibly involving symbol references)
444 k_Memory, /// Base + Offset Memory Address
445 k_PhysRegister, /// A physical register from the Mips namespace
446 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000447 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000448 k_RegList, /// A physical register list
449 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000450 } Kind;
451
David Blaikie960ea3f2014-06-08 16:18:35 +0000452public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000453 MipsOperand(KindTy K, MipsAsmParser &Parser)
454 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
455
David Blaikie960ea3f2014-06-08 16:18:35 +0000456private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000457 /// For diagnostics, and checking the assembler temporary
458 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000459
Eric Christopher8996c5d2013-03-15 00:42:55 +0000460 struct Token {
461 const char *Data;
462 unsigned Length;
463 };
464
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000465 struct PhysRegOp {
466 unsigned Num; /// Register Number
467 };
468
469 struct RegIdxOp {
470 unsigned Index; /// Index into the register class
471 RegKind Kind; /// Bitfield of the kinds it could possibly be
472 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000473 };
474
475 struct ImmOp {
476 const MCExpr *Val;
477 };
478
479 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000480 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000481 const MCExpr *Off;
482 };
483
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000484 struct RegListOp {
485 SmallVector<unsigned, 10> *List;
486 };
487
Jack Carterb4dbc172012-09-05 23:34:03 +0000488 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000489 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 struct PhysRegOp PhysReg;
491 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000492 struct ImmOp Imm;
493 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000494 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000495 };
496
497 SMLoc StartLoc, EndLoc;
498
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000499 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000500 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
501 const MCRegisterInfo *RegInfo,
502 SMLoc S, SMLoc E,
503 MipsAsmParser &Parser) {
504 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 Op->RegIdx.Index = Index;
506 Op->RegIdx.RegInfo = RegInfo;
507 Op->RegIdx.Kind = RegKind;
508 Op->StartLoc = S;
509 Op->EndLoc = E;
510 return Op;
511 }
512
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000513public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000514 /// Coerce the register to GPR32 and return the real register for the current
515 /// target.
516 unsigned getGPR32Reg() const {
517 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000518 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000519 unsigned ClassID = Mips::GPR32RegClassID;
520 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000521 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000522
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000523 /// Coerce the register to GPR32 and return the real register for the current
524 /// target.
525 unsigned getGPRMM16Reg() const {
526 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
527 unsigned ClassID = Mips::GPR32RegClassID;
528 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
529 }
530
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000531 /// Coerce the register to GPR64 and return the real register for the current
532 /// target.
533 unsigned getGPR64Reg() const {
534 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
535 unsigned ClassID = Mips::GPR64RegClassID;
536 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000537 }
538
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539private:
540 /// Coerce the register to AFGR64 and return the real register for the current
541 /// target.
542 unsigned getAFGR64Reg() const {
543 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
544 if (RegIdx.Index % 2 != 0)
545 AsmParser.Warning(StartLoc, "Float register should be even.");
546 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
547 .getRegister(RegIdx.Index / 2);
548 }
549
550 /// Coerce the register to FGR64 and return the real register for the current
551 /// target.
552 unsigned getFGR64Reg() const {
553 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
554 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
555 .getRegister(RegIdx.Index);
556 }
557
558 /// Coerce the register to FGR32 and return the real register for the current
559 /// target.
560 unsigned getFGR32Reg() const {
561 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
562 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
563 .getRegister(RegIdx.Index);
564 }
565
566 /// Coerce the register to FGRH32 and return the real register for the current
567 /// target.
568 unsigned getFGRH32Reg() const {
569 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
570 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
571 .getRegister(RegIdx.Index);
572 }
573
574 /// Coerce the register to FCC and return the real register for the current
575 /// target.
576 unsigned getFCCReg() const {
577 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
578 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
579 .getRegister(RegIdx.Index);
580 }
581
582 /// Coerce the register to MSA128 and return the real register for the current
583 /// target.
584 unsigned getMSA128Reg() const {
585 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
586 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
587 // identical
588 unsigned ClassID = Mips::MSA128BRegClassID;
589 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
590 }
591
592 /// Coerce the register to MSACtrl and return the real register for the
593 /// current target.
594 unsigned getMSACtrlReg() const {
595 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
596 unsigned ClassID = Mips::MSACtrlRegClassID;
597 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
598 }
599
600 /// Coerce the register to COP2 and return the real register for the
601 /// current target.
602 unsigned getCOP2Reg() const {
603 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
604 unsigned ClassID = Mips::COP2RegClassID;
605 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
606 }
607
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000608 /// Coerce the register to COP3 and return the real register for the
609 /// current target.
610 unsigned getCOP3Reg() const {
611 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
612 unsigned ClassID = Mips::COP3RegClassID;
613 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
614 }
615
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000616 /// Coerce the register to ACC64DSP and return the real register for the
617 /// current target.
618 unsigned getACC64DSPReg() const {
619 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
620 unsigned ClassID = Mips::ACC64DSPRegClassID;
621 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
622 }
623
624 /// Coerce the register to HI32DSP and return the real register for the
625 /// current target.
626 unsigned getHI32DSPReg() const {
627 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
628 unsigned ClassID = Mips::HI32DSPRegClassID;
629 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
630 }
631
632 /// Coerce the register to LO32DSP and return the real register for the
633 /// current target.
634 unsigned getLO32DSPReg() const {
635 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
636 unsigned ClassID = Mips::LO32DSPRegClassID;
637 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
638 }
639
640 /// Coerce the register to CCR and return the real register for the
641 /// current target.
642 unsigned getCCRReg() const {
643 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
644 unsigned ClassID = Mips::CCRRegClassID;
645 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
646 }
647
648 /// Coerce the register to HWRegs and return the real register for the
649 /// current target.
650 unsigned getHWRegsReg() const {
651 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
652 unsigned ClassID = Mips::HWRegsRegClassID;
653 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
654 }
655
656public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000657 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000658 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000659 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000660 Inst.addOperand(MCOperand::CreateImm(0));
661 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
662 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
663 else
664 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000665 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000666
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000667 void addRegOperands(MCInst &Inst, unsigned N) const {
668 llvm_unreachable("Use a custom parser instead");
669 }
670
Daniel Sanders21bce302014-04-01 12:35:23 +0000671 /// Render the operand to an MCInst as a GPR32
672 /// Asserts if the wrong number of operands are requested, or the operand
673 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000674 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
675 assert(N == 1 && "Invalid number of operands!");
676 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
677 }
678
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000679 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
680 assert(N == 1 && "Invalid number of operands!");
681 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
682 }
683
Jozef Kolek1904fa22014-11-24 14:25:53 +0000684 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
685 assert(N == 1 && "Invalid number of operands!");
686 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
687 }
688
Zoran Jovanovic41688672015-02-10 16:36:20 +0000689 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
692 }
693
Daniel Sanders21bce302014-04-01 12:35:23 +0000694 /// Render the operand to an MCInst as a GPR64
695 /// Asserts if the wrong number of operands are requested, or the operand
696 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000697 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
698 assert(N == 1 && "Invalid number of operands!");
699 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
700 }
701
702 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
703 assert(N == 1 && "Invalid number of operands!");
704 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
705 }
706
707 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
708 assert(N == 1 && "Invalid number of operands!");
709 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
710 }
711
712 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
713 assert(N == 1 && "Invalid number of operands!");
714 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000715 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000716 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000717 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
718 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000719 }
720
721 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
722 assert(N == 1 && "Invalid number of operands!");
723 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
724 }
725
726 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
727 assert(N == 1 && "Invalid number of operands!");
728 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
729 }
730
731 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
732 assert(N == 1 && "Invalid number of operands!");
733 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
734 }
735
736 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
737 assert(N == 1 && "Invalid number of operands!");
738 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
739 }
740
741 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
742 assert(N == 1 && "Invalid number of operands!");
743 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
744 }
745
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000746 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
747 assert(N == 1 && "Invalid number of operands!");
748 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
749 }
750
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
752 assert(N == 1 && "Invalid number of operands!");
753 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
754 }
755
756 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
757 assert(N == 1 && "Invalid number of operands!");
758 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
759 }
760
761 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
762 assert(N == 1 && "Invalid number of operands!");
763 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
764 }
765
766 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
767 assert(N == 1 && "Invalid number of operands!");
768 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
769 }
770
771 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
772 assert(N == 1 && "Invalid number of operands!");
773 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
774 }
775
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000776 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000777 assert(N == 1 && "Invalid number of operands!");
778 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000779 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000780 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000781
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000782 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000783 assert(N == 2 && "Invalid number of operands!");
784
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000786
787 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000788 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000789 }
790
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000791 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 2 && "Invalid number of operands!");
793
794 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
795
796 const MCExpr *Expr = getMemOff();
797 addExpr(Inst, Expr);
798 }
799
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000800 void addRegListOperands(MCInst &Inst, unsigned N) const {
801 assert(N == 1 && "Invalid number of operands!");
802
803 for (auto RegNo : getRegList())
804 Inst.addOperand(MCOperand::CreateReg(RegNo));
805 }
806
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000807 void addRegPairOperands(MCInst &Inst, unsigned N) const {
808 assert(N == 2 && "Invalid number of operands!");
809 unsigned RegNo = getRegPair();
810 Inst.addOperand(MCOperand::CreateReg(RegNo++));
811 Inst.addOperand(MCOperand::CreateReg(RegNo));
812 }
813
Zoran Jovanovic41688672015-02-10 16:36:20 +0000814 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
815 assert(N == 2 && "Invalid number of operands!");
816 for (auto RegNo : getRegList())
817 Inst.addOperand(MCOperand::CreateReg(RegNo));
818 }
819
Craig Topper56c590a2014-04-29 07:58:02 +0000820 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 // As a special case until we sort out the definition of div/divu, pretend
822 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
823 if (isGPRAsmReg() && RegIdx.Index == 0)
824 return true;
825
826 return Kind == k_PhysRegister;
827 }
828 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000829 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 bool isConstantImm() const {
831 return isImm() && dyn_cast<MCConstantExpr>(getImm());
832 }
Craig Topper56c590a2014-04-29 07:58:02 +0000833 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000834 // Note: It's not possible to pretend that other operand kinds are tokens.
835 // The matcher emitter checks tokens first.
836 return Kind == k_Token;
837 }
Craig Topper56c590a2014-04-29 07:58:02 +0000838 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000839 bool isConstantMemOff() const {
840 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
841 }
842 template <unsigned Bits> bool isMemWithSimmOffset() const {
843 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
844 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000845 bool isMemWithGRPMM16Base() const {
846 return isMem() && getMemBase()->isMM16AsmReg();
847 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000848 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
849 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
850 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
851 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000852 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
853 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
854 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
855 && (getMemBase()->getGPR32Reg() == Mips::SP);
856 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000857 bool isRegList16() const {
858 if (!isRegList())
859 return false;
860
861 int Size = RegList.List->size();
862 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
863 RegList.List->back() != Mips::RA)
864 return false;
865
866 int PrevReg = *RegList.List->begin();
867 for (int i = 1; i < Size - 1; i++) {
868 int Reg = (*(RegList.List))[i];
869 if ( Reg != PrevReg + 1)
870 return false;
871 PrevReg = Reg;
872 }
873
874 return true;
875 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000876 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 bool isLSAImm() const {
878 if (!isConstantImm())
879 return false;
880 int64_t Val = getConstantImm();
881 return 1 <= Val && Val <= 4;
882 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000883 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000884 bool isMovePRegPair() const {
885 if (Kind != k_RegList || RegList.List->size() != 2)
886 return false;
887
888 unsigned R0 = RegList.List->front();
889 unsigned R1 = RegList.List->back();
890
891 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
892 (R0 == Mips::A1 && R1 == Mips::A3) ||
893 (R0 == Mips::A2 && R1 == Mips::A3) ||
894 (R0 == Mips::A0 && R1 == Mips::S5) ||
895 (R0 == Mips::A0 && R1 == Mips::S6) ||
896 (R0 == Mips::A0 && R1 == Mips::A1) ||
897 (R0 == Mips::A0 && R1 == Mips::A2) ||
898 (R0 == Mips::A0 && R1 == Mips::A3))
899 return true;
900
901 return false;
902 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000903
904 StringRef getToken() const {
905 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000906 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000907 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000908 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000909
Craig Topper56c590a2014-04-29 07:58:02 +0000910 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000911 // As a special case until we sort out the definition of div/divu, pretend
912 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
913 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
914 RegIdx.Kind & RegKind_GPR)
915 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000916
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 assert(Kind == k_PhysRegister && "Invalid access!");
918 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000919 }
920
Jack Carterb4dbc172012-09-05 23:34:03 +0000921 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000923 return Imm.Val;
924 }
925
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 int64_t getConstantImm() const {
927 const MCExpr *Val = getImm();
928 return static_cast<const MCConstantExpr *>(Val)->getValue();
929 }
930
931 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000932 assert((Kind == k_Memory) && "Invalid access!");
933 return Mem.Base;
934 }
935
936 const MCExpr *getMemOff() const {
937 assert((Kind == k_Memory) && "Invalid access!");
938 return Mem.Off;
939 }
940
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000941 int64_t getConstantMemOff() const {
942 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
943 }
944
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000945 const SmallVectorImpl<unsigned> &getRegList() const {
946 assert((Kind == k_RegList) && "Invalid access!");
947 return *(RegList.List);
948 }
949
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000950 unsigned getRegPair() const {
951 assert((Kind == k_RegPair) && "Invalid access!");
952 return RegIdx.Index;
953 }
954
David Blaikie960ea3f2014-06-08 16:18:35 +0000955 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
956 MipsAsmParser &Parser) {
957 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000958 Op->Tok.Data = Str.data();
959 Op->Tok.Length = Str.size();
960 Op->StartLoc = S;
961 Op->EndLoc = S;
962 return Op;
963 }
964
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000965 /// Create a numeric register (e.g. $1). The exact register remains
966 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000967 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000968 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000969 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000970 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000971 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000972 }
973
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000974 /// Create a register that is definitely a GPR.
975 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000976 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000977 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000978 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000979 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000980 }
981
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000982 /// Create a register that is definitely a FGR.
983 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000984 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000985 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000986 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
988 }
989
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000990 /// Create a register that is definitely a HWReg.
991 /// This is typically only used for named registers such as $hwr_cpunum.
992 static std::unique_ptr<MipsOperand>
993 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
994 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
995 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
996 }
997
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000998 /// Create a register that is definitely an FCC.
999 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001000 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001001 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001002 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001003 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1004 }
1005
1006 /// Create a register that is definitely an ACC.
1007 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001008 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001009 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001010 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1012 }
1013
1014 /// Create a register that is definitely an MSA128.
1015 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001016 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001017 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001018 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001019 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1020 }
1021
1022 /// Create a register that is definitely an MSACtrl.
1023 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001024 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001025 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001026 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1028 }
1029
David Blaikie960ea3f2014-06-08 16:18:35 +00001030 static std::unique_ptr<MipsOperand>
1031 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1032 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001033 Op->Imm.Val = Val;
1034 Op->StartLoc = S;
1035 Op->EndLoc = E;
1036 return Op;
1037 }
1038
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 static std::unique_ptr<MipsOperand>
1040 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1041 SMLoc E, MipsAsmParser &Parser) {
1042 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1043 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001044 Op->Mem.Off = Off;
1045 Op->StartLoc = S;
1046 Op->EndLoc = E;
1047 return Op;
1048 }
1049
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001050 static std::unique_ptr<MipsOperand>
1051 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1052 MipsAsmParser &Parser) {
1053 assert (Regs.size() > 0 && "Empty list not allowed");
1054
1055 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1056 Op->RegList.List = new SmallVector<unsigned, 10>();
1057 for (auto Reg : Regs)
1058 Op->RegList.List->push_back(Reg);
1059 Op->StartLoc = StartLoc;
1060 Op->EndLoc = EndLoc;
1061 return Op;
1062 }
1063
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001064 static std::unique_ptr<MipsOperand>
1065 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1066 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1067 Op->RegIdx.Index = RegNo;
1068 Op->StartLoc = S;
1069 Op->EndLoc = E;
1070 return Op;
1071 }
1072
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 bool isGPRAsmReg() const {
1074 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001075 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001076 bool isMM16AsmReg() const {
1077 if (!(isRegIdx() && RegIdx.Kind))
1078 return false;
1079 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1080 || RegIdx.Index == 16 || RegIdx.Index == 17);
1081 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001082 bool isMM16AsmRegZero() const {
1083 if (!(isRegIdx() && RegIdx.Kind))
1084 return false;
1085 return (RegIdx.Index == 0 ||
1086 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1087 RegIdx.Index == 17);
1088 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001089 bool isMM16AsmRegMoveP() const {
1090 if (!(isRegIdx() && RegIdx.Kind))
1091 return false;
1092 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1093 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1094 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 bool isFGRAsmReg() const {
1096 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1097 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001098 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 bool isHWRegsAsmReg() const {
1100 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001101 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 bool isCCRAsmReg() const {
1103 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001104 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001106 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1107 return false;
1108 if (!AsmParser.hasEightFccRegisters())
1109 return RegIdx.Index == 0;
1110 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001111 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 bool isACCAsmReg() const {
1113 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001114 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 bool isCOP2AsmReg() const {
1116 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001117 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001118 bool isCOP3AsmReg() const {
1119 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1120 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001121 bool isMSA128AsmReg() const {
1122 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001123 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 bool isMSACtrlAsmReg() const {
1125 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001126 }
1127
Jack Carterb4dbc172012-09-05 23:34:03 +00001128 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001129 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001130 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001131 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001132
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001133 virtual ~MipsOperand() {
1134 switch (Kind) {
1135 case k_Immediate:
1136 break;
1137 case k_Memory:
1138 delete Mem.Base;
1139 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001140 case k_RegList:
1141 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001142 case k_PhysRegister:
1143 case k_RegisterIndex:
1144 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001145 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001146 break;
1147 }
1148 }
1149
Craig Topper56c590a2014-04-29 07:58:02 +00001150 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 switch (Kind) {
1152 case k_Immediate:
1153 OS << "Imm<";
1154 Imm.Val->print(OS);
1155 OS << ">";
1156 break;
1157 case k_Memory:
1158 OS << "Mem<";
1159 Mem.Base->print(OS);
1160 OS << ", ";
1161 Mem.Off->print(OS);
1162 OS << ">";
1163 break;
1164 case k_PhysRegister:
1165 OS << "PhysReg<" << PhysReg.Num << ">";
1166 break;
1167 case k_RegisterIndex:
1168 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1169 break;
1170 case k_Token:
1171 OS << Tok.Data;
1172 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001173 case k_RegList:
1174 OS << "RegList< ";
1175 for (auto Reg : (*RegList.List))
1176 OS << Reg << " ";
1177 OS << ">";
1178 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001179 case k_RegPair:
1180 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1181 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001183 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001184}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001185} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001186
Jack Carter9e65aa32013-03-22 00:05:30 +00001187namespace llvm {
1188extern const MCInstrDesc MipsInsts[];
1189}
1190static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1191 return MipsInsts[Opcode];
1192}
1193
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001194static bool hasShortDelaySlot(unsigned Opcode) {
1195 switch (Opcode) {
1196 case Mips::JALS_MM:
1197 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001198 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001199 case Mips::BGEZALS_MM:
1200 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001201 return true;
1202 default:
1203 return false;
1204 }
1205}
1206
Jack Carter9e65aa32013-03-22 00:05:30 +00001207bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001208 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001209 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001210
Jack Carter9e65aa32013-03-22 00:05:30 +00001211 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001212
1213 if (MCID.isBranch() || MCID.isCall()) {
1214 const unsigned Opcode = Inst.getOpcode();
1215 MCOperand Offset;
1216
1217 switch (Opcode) {
1218 default:
1219 break;
Kai Nackee0245392015-01-27 19:11:28 +00001220 case Mips::BBIT0:
1221 case Mips::BBIT032:
1222 case Mips::BBIT1:
1223 case Mips::BBIT132:
1224 assert(hasCnMips() && "instruction only valid for octeon cpus");
1225 // Fall through
1226
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001227 case Mips::BEQ:
1228 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 case Mips::BEQ_MM:
1230 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001231 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001232 Offset = Inst.getOperand(2);
1233 if (!Offset.isImm())
1234 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001235 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001236 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001237 if (OffsetToAlignment(Offset.getImm(),
1238 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001239 return Error(IDLoc, "branch to misaligned address");
1240 break;
1241 case Mips::BGEZ:
1242 case Mips::BGTZ:
1243 case Mips::BLEZ:
1244 case Mips::BLTZ:
1245 case Mips::BGEZAL:
1246 case Mips::BLTZAL:
1247 case Mips::BC1F:
1248 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001249 case Mips::BGEZ_MM:
1250 case Mips::BGTZ_MM:
1251 case Mips::BLEZ_MM:
1252 case Mips::BLTZ_MM:
1253 case Mips::BGEZAL_MM:
1254 case Mips::BLTZAL_MM:
1255 case Mips::BC1F_MM:
1256 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001257 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001258 Offset = Inst.getOperand(1);
1259 if (!Offset.isImm())
1260 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001261 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001262 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001263 if (OffsetToAlignment(Offset.getImm(),
1264 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001265 return Error(IDLoc, "branch to misaligned address");
1266 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001267 case Mips::BEQZ16_MM:
1268 case Mips::BNEZ16_MM:
1269 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1270 Offset = Inst.getOperand(1);
1271 if (!Offset.isImm())
1272 break; // We'll deal with this situation later on when applying fixups.
1273 if (!isIntN(8, Offset.getImm()))
1274 return Error(IDLoc, "branch target out of range");
1275 if (OffsetToAlignment(Offset.getImm(), 2LL))
1276 return Error(IDLoc, "branch to misaligned address");
1277 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001278 }
1279 }
1280
Daniel Sandersa84989a2014-06-16 13:25:35 +00001281 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1282 // We still accept it but it is a normal nop.
1283 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1284 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1285 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1286 "nop instruction");
1287 }
1288
Kai Nackee0245392015-01-27 19:11:28 +00001289 if (hasCnMips()) {
1290 const unsigned Opcode = Inst.getOpcode();
1291 MCOperand Opnd;
1292 int Imm;
1293
1294 switch (Opcode) {
1295 default:
1296 break;
1297
1298 case Mips::BBIT0:
1299 case Mips::BBIT032:
1300 case Mips::BBIT1:
1301 case Mips::BBIT132:
1302 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1303 // The offset is handled above
1304 Opnd = Inst.getOperand(1);
1305 if (!Opnd.isImm())
1306 return Error(IDLoc, "expected immediate operand kind");
1307 Imm = Opnd.getImm();
1308 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1309 Opcode == Mips::BBIT1 ? 63 : 31))
1310 return Error(IDLoc, "immediate operand value out of range");
1311 if (Imm > 31) {
1312 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1313 : Mips::BBIT132);
1314 Inst.getOperand(1).setImm(Imm - 32);
1315 }
1316 break;
1317
1318 case Mips::CINS:
1319 case Mips::CINS32:
1320 case Mips::EXTS:
1321 case Mips::EXTS32:
1322 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1323 // Check length
1324 Opnd = Inst.getOperand(3);
1325 if (!Opnd.isImm())
1326 return Error(IDLoc, "expected immediate operand kind");
1327 Imm = Opnd.getImm();
1328 if (Imm < 0 || Imm > 31)
1329 return Error(IDLoc, "immediate operand value out of range");
1330 // Check position
1331 Opnd = Inst.getOperand(2);
1332 if (!Opnd.isImm())
1333 return Error(IDLoc, "expected immediate operand kind");
1334 Imm = Opnd.getImm();
1335 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1336 Opcode == Mips::EXTS ? 63 : 31))
1337 return Error(IDLoc, "immediate operand value out of range");
1338 if (Imm > 31) {
1339 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1340 Inst.getOperand(2).setImm(Imm - 32);
1341 }
1342 break;
1343
1344 case Mips::SEQi:
1345 case Mips::SNEi:
1346 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1347 Opnd = Inst.getOperand(2);
1348 if (!Opnd.isImm())
1349 return Error(IDLoc, "expected immediate operand kind");
1350 Imm = Opnd.getImm();
1351 if (!isInt<10>(Imm))
1352 return Error(IDLoc, "immediate operand value out of range");
1353 break;
1354 }
1355 }
1356
Toma Tabacu9db22db2014-09-09 10:15:38 +00001357 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001358 // If this instruction has a delay slot and .set reorder is active,
1359 // emit a NOP after it.
1360 Instructions.push_back(Inst);
1361 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001362 if (hasShortDelaySlot(Inst.getOpcode())) {
1363 NopInst.setOpcode(Mips::MOVE16_MM);
1364 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1365 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1366 } else {
1367 NopInst.setOpcode(Mips::SLL);
1368 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1369 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1370 NopInst.addOperand(MCOperand::CreateImm(0));
1371 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001372 Instructions.push_back(NopInst);
1373 return false;
1374 }
1375
Jack Carter9e65aa32013-03-22 00:05:30 +00001376 if (MCID.mayLoad() || MCID.mayStore()) {
1377 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001378 // reference or immediate we may have to expand instructions.
1379 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001380 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001381 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1382 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001383 MCOperand &Op = Inst.getOperand(i);
1384 if (Op.isImm()) {
1385 int MemOffset = Op.getImm();
1386 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001387 // Offset can't exceed 16bit value.
1388 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001389 return false;
1390 }
1391 } else if (Op.isExpr()) {
1392 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001393 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001394 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001395 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001396 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // Expand symbol.
1398 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 return false;
1400 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001401 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001402 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001403 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001404 }
1405 }
1406 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001408 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001409
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001410 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001411 if (MCID.mayLoad()) {
1412 // Try to create 16-bit GP relative load instruction.
1413 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1414 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1415 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1416 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1417 MCOperand &Op = Inst.getOperand(i);
1418 if (Op.isImm()) {
1419 int MemOffset = Op.getImm();
1420 MCOperand &DstReg = Inst.getOperand(0);
1421 MCOperand &BaseReg = Inst.getOperand(1);
1422 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1423 getContext().getRegisterInfo()->getRegClass(
1424 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1425 BaseReg.getReg() == Mips::GP) {
1426 MCInst TmpInst;
1427 TmpInst.setLoc(IDLoc);
1428 TmpInst.setOpcode(Mips::LWGP_MM);
1429 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1430 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1431 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1432 Instructions.push_back(TmpInst);
1433 return false;
1434 }
1435 }
1436 }
1437 } // for
1438 } // if load
1439
1440 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1441
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001442 MCOperand Opnd;
1443 int Imm;
1444
1445 switch (Inst.getOpcode()) {
1446 default:
1447 break;
1448 case Mips::ADDIUS5_MM:
1449 Opnd = Inst.getOperand(2);
1450 if (!Opnd.isImm())
1451 return Error(IDLoc, "expected immediate operand kind");
1452 Imm = Opnd.getImm();
1453 if (Imm < -8 || Imm > 7)
1454 return Error(IDLoc, "immediate operand value out of range");
1455 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001456 case Mips::ADDIUSP_MM:
1457 Opnd = Inst.getOperand(0);
1458 if (!Opnd.isImm())
1459 return Error(IDLoc, "expected immediate operand kind");
1460 Imm = Opnd.getImm();
1461 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1462 Imm % 4 != 0)
1463 return Error(IDLoc, "immediate operand value out of range");
1464 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001465 case Mips::SLL16_MM:
1466 case Mips::SRL16_MM:
1467 Opnd = Inst.getOperand(2);
1468 if (!Opnd.isImm())
1469 return Error(IDLoc, "expected immediate operand kind");
1470 Imm = Opnd.getImm();
1471 if (Imm < 1 || Imm > 8)
1472 return Error(IDLoc, "immediate operand value out of range");
1473 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001474 case Mips::LI16_MM:
1475 Opnd = Inst.getOperand(1);
1476 if (!Opnd.isImm())
1477 return Error(IDLoc, "expected immediate operand kind");
1478 Imm = Opnd.getImm();
1479 if (Imm < -1 || Imm > 126)
1480 return Error(IDLoc, "immediate operand value out of range");
1481 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001482 case Mips::ADDIUR2_MM:
1483 Opnd = Inst.getOperand(2);
1484 if (!Opnd.isImm())
1485 return Error(IDLoc, "expected immediate operand kind");
1486 Imm = Opnd.getImm();
1487 if (!(Imm == 1 || Imm == -1 ||
1488 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1489 return Error(IDLoc, "immediate operand value out of range");
1490 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001491 case Mips::ADDIUR1SP_MM:
1492 Opnd = Inst.getOperand(1);
1493 if (!Opnd.isImm())
1494 return Error(IDLoc, "expected immediate operand kind");
1495 Imm = Opnd.getImm();
1496 if (OffsetToAlignment(Imm, 4LL))
1497 return Error(IDLoc, "misaligned immediate operand value");
1498 if (Imm < 0 || Imm > 255)
1499 return Error(IDLoc, "immediate operand value out of range");
1500 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001501 case Mips::ANDI16_MM:
1502 Opnd = Inst.getOperand(2);
1503 if (!Opnd.isImm())
1504 return Error(IDLoc, "expected immediate operand kind");
1505 Imm = Opnd.getImm();
1506 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1507 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1508 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001511 case Mips::LBU16_MM:
1512 Opnd = Inst.getOperand(2);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (Imm < -1 || Imm > 14)
1517 return Error(IDLoc, "immediate operand value out of range");
1518 break;
1519 case Mips::SB16_MM:
1520 Opnd = Inst.getOperand(2);
1521 if (!Opnd.isImm())
1522 return Error(IDLoc, "expected immediate operand kind");
1523 Imm = Opnd.getImm();
1524 if (Imm < 0 || Imm > 15)
1525 return Error(IDLoc, "immediate operand value out of range");
1526 break;
1527 case Mips::LHU16_MM:
1528 case Mips::SH16_MM:
1529 Opnd = Inst.getOperand(2);
1530 if (!Opnd.isImm())
1531 return Error(IDLoc, "expected immediate operand kind");
1532 Imm = Opnd.getImm();
1533 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1534 return Error(IDLoc, "immediate operand value out of range");
1535 break;
1536 case Mips::LW16_MM:
1537 case Mips::SW16_MM:
1538 Opnd = Inst.getOperand(2);
1539 if (!Opnd.isImm())
1540 return Error(IDLoc, "expected immediate operand kind");
1541 Imm = Opnd.getImm();
1542 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1543 return Error(IDLoc, "immediate operand value out of range");
1544 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001545 case Mips::CACHE:
1546 case Mips::PREF:
1547 Opnd = Inst.getOperand(2);
1548 if (!Opnd.isImm())
1549 return Error(IDLoc, "expected immediate operand kind");
1550 Imm = Opnd.getImm();
1551 if (!isUInt<5>(Imm))
1552 return Error(IDLoc, "immediate operand value out of range");
1553 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001554 case Mips::ADDIUPC_MM:
1555 MCOperand Opnd = Inst.getOperand(1);
1556 if (!Opnd.isImm())
1557 return Error(IDLoc, "expected immediate operand kind");
1558 int Imm = Opnd.getImm();
1559 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1560 return Error(IDLoc, "immediate operand value out of range");
1561 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001562 }
1563 }
1564
Jack Carter9e65aa32013-03-22 00:05:30 +00001565 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001566 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001567 else
1568 Instructions.push_back(Inst);
1569
1570 return false;
1571}
1572
Jack Carter30a59822012-10-04 04:03:53 +00001573bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1574
Jack Carterd0bd6422013-04-18 00:41:53 +00001575 switch (Inst.getOpcode()) {
1576 case Mips::LoadImm32Reg:
1577 case Mips::LoadAddr32Imm:
1578 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001579 case Mips::LoadImm64Reg:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001580 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001581 case Mips::LWM_MM:
1582 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001583 case Mips::JalOneReg:
1584 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001585 return true;
1586 default:
1587 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001588 }
1589}
Jack Carter92995f12012-10-06 00:53:28 +00001590
Matheus Almeida3813d572014-06-19 14:39:14 +00001591bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001592 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001594 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001595 case Mips::LoadImm32Reg:
1596 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001597 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001598 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001599 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001600 return true;
1601 }
1602 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 case Mips::LoadAddr32Imm:
1604 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1605 case Mips::LoadAddr32Reg:
1606 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001607 case Mips::B_MM_Pseudo:
1608 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001609 case Mips::SWM_MM:
1610 case Mips::LWM_MM:
1611 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001612 case Mips::JalOneReg:
1613 case Mips::JalTwoReg:
1614 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 }
Jack Carter30a59822012-10-04 04:03:53 +00001616}
Jack Carter92995f12012-10-06 00:53:28 +00001617
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001618namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001619template <bool PerformShift>
1620void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001621 SmallVectorImpl<MCInst> &Instructions) {
1622 MCInst tmpInst;
1623 if (PerformShift) {
1624 tmpInst.setOpcode(Mips::DSLL);
1625 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1626 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1627 tmpInst.addOperand(MCOperand::CreateImm(16));
1628 tmpInst.setLoc(IDLoc);
1629 Instructions.push_back(tmpInst);
1630 tmpInst.clear();
1631 }
1632 tmpInst.setOpcode(Mips::ORi);
1633 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1634 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001635 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001636 tmpInst.setLoc(IDLoc);
1637 Instructions.push_back(tmpInst);
1638}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001639
1640template <int Shift, bool PerformShift>
1641void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1642 SmallVectorImpl<MCInst> &Instructions) {
1643 createShiftOr<PerformShift>(
1644 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1645 IDLoc, Instructions);
1646}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001647}
1648
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001649bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1650 SmallVectorImpl<MCInst> &Instructions) {
1651 // Create a JALR instruction which is going to replace the pseudo-JAL.
1652 MCInst JalrInst;
1653 JalrInst.setLoc(IDLoc);
1654 const MCOperand FirstRegOp = Inst.getOperand(0);
1655 const unsigned Opcode = Inst.getOpcode();
1656
1657 if (Opcode == Mips::JalOneReg) {
1658 // jal $rs => jalr $rs
1659 if (inMicroMipsMode()) {
1660 JalrInst.setOpcode(Mips::JALR16_MM);
1661 JalrInst.addOperand(FirstRegOp);
1662 } else {
1663 JalrInst.setOpcode(Mips::JALR);
1664 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1665 JalrInst.addOperand(FirstRegOp);
1666 }
1667 } else if (Opcode == Mips::JalTwoReg) {
1668 // jal $rd, $rs => jalr $rd, $rs
1669 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1670 JalrInst.addOperand(FirstRegOp);
1671 const MCOperand SecondRegOp = Inst.getOperand(1);
1672 JalrInst.addOperand(SecondRegOp);
1673 }
1674 Instructions.push_back(JalrInst);
1675
1676 // If .set reorder is active, emit a NOP after it.
1677 if (AssemblerOptions.back()->isReorder()) {
1678 // This is a 32-bit NOP because these 2 pseudo-instructions
1679 // do not have a short delay slot.
1680 MCInst NopInst;
1681 NopInst.setOpcode(Mips::SLL);
1682 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1683 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1684 NopInst.addOperand(MCOperand::CreateImm(0));
1685 Instructions.push_back(NopInst);
1686 }
1687
1688 return false;
1689}
1690
Matheus Almeida3813d572014-06-19 14:39:14 +00001691bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001692 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001693 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001694 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001695 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001696 const MCOperand &RegOp = Inst.getOperand(0);
1697 assert(RegOp.isReg() && "expected register operand kind");
1698
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001699 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001700 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001701 // FIXME: gas has a special case for values that are 000...1111, which
1702 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001703 if (0 <= ImmValue && ImmValue <= 65535) {
1704 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001705 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001706 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001707 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001709 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001710 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001711 } else if (ImmValue < 0 && ImmValue >= -32768) {
1712 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001713 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001714 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001715 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001717 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001718 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001719 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1720 // For any value of j that is representable as a 32-bit integer, create
1721 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001722 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001723 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001724 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001725 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1726 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001727 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001728 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1729 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001730 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001731 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001732 return true;
1733 }
1734
1735 // <------- lo32 ------>
1736 // <------- hi32 ------>
1737 // <- hi16 -> <- lo16 ->
1738 // _________________________________
1739 // | | | |
1740 // | 16-bytes | 16-bytes | 16-bytes |
1741 // |__________|__________|__________|
1742 //
1743 // For any value of j that is representable as a 48-bit integer, create
1744 // a sequence of:
1745 // li d,j => lui d,hi16(j)
1746 // ori d,d,hi16(lo32(j))
1747 // dsll d,d,16
1748 // ori d,d,lo16(lo32(j))
1749 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001750 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001751 tmpInst.addOperand(
1752 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001753 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001754 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1755 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1756 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001757 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001758 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001759 return true;
1760 }
1761
1762 // <------- hi32 ------> <------- lo32 ------>
1763 // <- hi16 -> <- lo16 ->
1764 // ___________________________________________
1765 // | | | | |
1766 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1767 // |__________|__________|__________|__________|
1768 //
1769 // For any value of j that isn't representable as a 48-bit integer.
1770 // li d,j => lui d,hi16(j)
1771 // ori d,d,lo16(hi32(j))
1772 // dsll d,d,16
1773 // ori d,d,hi16(lo32(j))
1774 // dsll d,d,16
1775 // ori d,d,lo16(lo32(j))
1776 tmpInst.setOpcode(Mips::LUi);
1777 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1778 tmpInst.addOperand(
1779 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1780 Instructions.push_back(tmpInst);
1781 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1782 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1783 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001784 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001785 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001786}
Jack Carter92995f12012-10-06 00:53:28 +00001787
Matheus Almeida3813d572014-06-19 14:39:14 +00001788bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001789MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1790 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001791 MCInst tmpInst;
1792 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001793 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1794 "expected immediate operand kind");
1795 if (!ImmOp.isImm()) {
1796 expandLoadAddressSym(Inst, IDLoc, Instructions);
1797 return false;
1798 }
Jack Carter543fdf82012-10-09 23:29:45 +00001799 const MCOperand &SrcRegOp = Inst.getOperand(1);
1800 assert(SrcRegOp.isReg() && "expected register operand kind");
1801 const MCOperand &DstRegOp = Inst.getOperand(0);
1802 assert(DstRegOp.isReg() && "expected register operand kind");
1803 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 if (-32768 <= ImmValue && ImmValue <= 65535) {
1805 // For -32768 <= j <= 65535.
1806 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001807 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001808 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1809 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1810 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1811 Instructions.push_back(tmpInst);
1812 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001813 // For any other value of j that is representable as a 32-bit integer.
1814 // la d,j(s) => lui d,hi16(j)
1815 // ori d,d,lo16(j)
1816 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001817 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001818 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1819 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1820 Instructions.push_back(tmpInst);
1821 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001822 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001823 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1824 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1825 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1826 Instructions.push_back(tmpInst);
1827 tmpInst.clear();
1828 tmpInst.setOpcode(Mips::ADDu);
1829 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1830 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1831 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1832 Instructions.push_back(tmpInst);
1833 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001834 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001835}
1836
Matheus Almeida3813d572014-06-19 14:39:14 +00001837bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001838MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1839 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001840 MCInst tmpInst;
1841 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001842 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1843 "expected immediate operand kind");
1844 if (!ImmOp.isImm()) {
1845 expandLoadAddressSym(Inst, IDLoc, Instructions);
1846 return false;
1847 }
Jack Carter543fdf82012-10-09 23:29:45 +00001848 const MCOperand &RegOp = Inst.getOperand(0);
1849 assert(RegOp.isReg() && "expected register operand kind");
1850 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001851 if (-32768 <= ImmValue && ImmValue <= 65535) {
1852 // For -32768 <= j <= 65535.
1853 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001854 tmpInst.setOpcode(Mips::ADDiu);
1855 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001857 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1858 Instructions.push_back(tmpInst);
1859 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001860 // For any other value of j that is representable as a 32-bit integer.
1861 // la d,j => lui d,hi16(j)
1862 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001863 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001864 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1865 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1866 Instructions.push_back(tmpInst);
1867 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001868 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001869 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1870 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1871 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1872 Instructions.push_back(tmpInst);
1873 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001874 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001875}
1876
Toma Tabacu0d64b202014-08-14 10:29:17 +00001877void
1878MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1879 SmallVectorImpl<MCInst> &Instructions) {
1880 // FIXME: If we do have a valid at register to use, we should generate a
1881 // slightly shorter sequence here.
1882 MCInst tmpInst;
1883 int ExprOperandNo = 1;
1884 // Sometimes the assembly parser will get the immediate expression as
1885 // a $zero + an immediate.
1886 if (Inst.getNumOperands() == 3) {
1887 assert(Inst.getOperand(1).getReg() ==
1888 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1889 ExprOperandNo = 2;
1890 }
1891 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1892 assert(SymOp.isExpr() && "expected symbol operand kind");
1893 const MCOperand &RegOp = Inst.getOperand(0);
1894 unsigned RegNo = RegOp.getReg();
1895 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1896 const MCSymbolRefExpr *HiExpr =
1897 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1898 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1899 const MCSymbolRefExpr *LoExpr =
1900 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1901 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1902 if (isGP64bit()) {
1903 // If it's a 64-bit architecture, expand to:
1904 // la d,sym => lui d,highest(sym)
1905 // ori d,d,higher(sym)
1906 // dsll d,d,16
1907 // ori d,d,hi16(sym)
1908 // dsll d,d,16
1909 // ori d,d,lo16(sym)
1910 const MCSymbolRefExpr *HighestExpr =
1911 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1912 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1913 const MCSymbolRefExpr *HigherExpr =
1914 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1915 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1916
1917 tmpInst.setOpcode(Mips::LUi);
1918 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1919 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1920 Instructions.push_back(tmpInst);
1921
1922 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1923 Instructions);
1924 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1925 Instructions);
1926 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1927 Instructions);
1928 } else {
1929 // Otherwise, expand to:
1930 // la d,sym => lui d,hi16(sym)
1931 // ori d,d,lo16(sym)
1932 tmpInst.setOpcode(Mips::LUi);
1933 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1934 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1935 Instructions.push_back(tmpInst);
1936
1937 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1938 Instructions);
1939 }
1940}
1941
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001942bool MipsAsmParser::expandUncondBranchMMPseudo(
1943 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001944 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1945 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001946
1947 MCOperand Offset = Inst.getOperand(0);
1948 if (Offset.isExpr()) {
1949 Inst.clear();
1950 Inst.setOpcode(Mips::BEQ_MM);
1951 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1952 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1953 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1954 } else {
1955 assert(Offset.isImm() && "expected immediate operand kind");
1956 if (isIntN(11, Offset.getImm())) {
1957 // If offset fits into 11 bits then this instruction becomes microMIPS
1958 // 16-bit unconditional branch instruction.
1959 Inst.setOpcode(Mips::B16_MM);
1960 } else {
1961 if (!isIntN(17, Offset.getImm()))
1962 Error(IDLoc, "branch target out of range");
1963 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1964 Error(IDLoc, "branch to misaligned address");
1965 Inst.clear();
1966 Inst.setOpcode(Mips::BEQ_MM);
1967 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1968 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1969 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1970 }
1971 }
1972 Instructions.push_back(Inst);
1973
1974 if (AssemblerOptions.back()->isReorder()) {
1975 // If .set reorder is active, emit a NOP after the branch instruction.
1976 MCInst NopInst;
1977 NopInst.setOpcode(Mips::MOVE16_MM);
1978 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1979 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1980 Instructions.push_back(NopInst);
1981 }
1982 return false;
1983}
1984
Jack Carter9e65aa32013-03-22 00:05:30 +00001985void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001986 SmallVectorImpl<MCInst> &Instructions,
1987 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001988 const MCSymbolRefExpr *SR;
1989 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001990 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001991 const MCExpr *ExprOffset;
1992 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001993 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001994 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1995 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001997 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1998 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001999 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002000 if (isImmOpnd) {
2001 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2002 ImmOffset = Inst.getOperand(2).getImm();
2003 LoOffset = ImmOffset & 0x0000ffff;
2004 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002005 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002006 if (LoOffset & 0x8000)
2007 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002008 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002009 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002010 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002011 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002012 // These are some of the types of expansions we perform here:
2013 // 1) lw $8, sym => lui $8, %hi(sym)
2014 // lw $8, %lo(sym)($8)
2015 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2016 // add $8, $8, $9
2017 // lw $8, %lo(offset)($9)
2018 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2019 // add $at, $at, $8
2020 // lw $8, %lo(offset)($at)
2021 // 4) sw $8, sym => lui $at, %hi(sym)
2022 // sw $8, %lo(sym)($at)
2023 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2024 // add $at, $at, $8
2025 // sw $8, %lo(offset)($at)
2026 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2027 // ldc1 $f0, %lo(sym)($at)
2028 //
2029 // For load instructions we can use the destination register as a temporary
2030 // if base and dst are different (examples 1 and 2) and if the base register
2031 // is general purpose otherwise we must use $at (example 6) and error if it's
2032 // not available. For stores we must use $at (examples 4 and 5) because we
2033 // must not clobber the source register setting up the offset.
2034 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2035 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2036 unsigned RegClassIDOp0 =
2037 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2038 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2039 (RegClassIDOp0 == Mips::GPR64RegClassID);
2040 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002041 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002042 else {
2043 int AT = getATReg(IDLoc);
2044 // At this point we need AT to perform the expansions and we exit if it is
2045 // not available.
2046 if (!AT)
2047 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002048 TmpRegNum = getReg(
2049 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002050 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002051
Jack Carter9e65aa32013-03-22 00:05:30 +00002052 TempInst.setOpcode(Mips::LUi);
2053 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2054 if (isImmOpnd)
2055 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2056 else {
2057 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002058 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002059 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2060 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2061 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002062 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002063 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002064 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002065 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002066 }
2067 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002068 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002069 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002070 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002071 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002073 TempInst.setOpcode(Mips::ADDu);
2074 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2075 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2076 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2077 Instructions.push_back(TempInst);
2078 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00002079 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002081 TempInst.setOpcode(Inst.getOpcode());
2082 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2083 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2084 if (isImmOpnd)
2085 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2086 else {
2087 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2089 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2090 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002092 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002094 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002095 }
2096 }
2097 Instructions.push_back(TempInst);
2098 TempInst.clear();
2099}
2100
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002101bool
2102MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2103 SmallVectorImpl<MCInst> &Instructions) {
2104 unsigned OpNum = Inst.getNumOperands();
2105 unsigned Opcode = Inst.getOpcode();
2106 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2107
2108 assert (Inst.getOperand(OpNum - 1).isImm() &&
2109 Inst.getOperand(OpNum - 2).isReg() &&
2110 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2111
2112 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2113 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2114 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2115 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2116 // It can be implemented as SWM16 or LWM16 instruction.
2117 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2118
2119 Inst.setOpcode(NewOpcode);
2120 Instructions.push_back(Inst);
2121 return false;
2122}
2123
Matheus Almeida595fcab2014-06-11 15:05:56 +00002124unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2125 // As described by the Mips32r2 spec, the registers Rd and Rs for
2126 // jalr.hb must be different.
2127 unsigned Opcode = Inst.getOpcode();
2128
2129 if (Opcode == Mips::JALR_HB &&
2130 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2131 return Match_RequiresDifferentSrcAndDst;
2132
2133 return Match_Success;
2134}
2135
David Blaikie960ea3f2014-06-08 16:18:35 +00002136bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2137 OperandVector &Operands,
2138 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002139 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002140 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002141
Jack Carterb4dbc172012-09-05 23:34:03 +00002142 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002143 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002144 unsigned MatchResult =
2145 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002146
2147 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002148 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002149 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002150 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002151 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002152 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002153 return false;
2154 }
2155 case Match_MissingFeature:
2156 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2157 return true;
2158 case Match_InvalidOperand: {
2159 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002160 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002161 if (ErrorInfo >= Operands.size())
2162 return Error(IDLoc, "too few operands for instruction");
2163
David Blaikie960ea3f2014-06-08 16:18:35 +00002164 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002165 if (ErrorLoc == SMLoc())
2166 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002167 }
2168
2169 return Error(ErrorLoc, "invalid operand for instruction");
2170 }
2171 case Match_MnemonicFail:
2172 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002173 case Match_RequiresDifferentSrcAndDst:
2174 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002175 }
Craig Topper589ceee2015-01-03 08:16:34 +00002176
2177 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002178}
2179
Toma Tabacu13964452014-09-04 13:23:44 +00002180void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002181 if ((RegIndex != 0) &&
2182 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002183 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002184 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002185 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002186 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002187 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002188 }
2189}
2190
Daniel Sandersef638fe2014-10-03 15:37:37 +00002191void
2192MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2193 SMRange Range, bool ShowColors) {
2194 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002195 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002196 ShowColors);
2197}
2198
Jack Carter1ac53222013-02-20 23:11:17 +00002199int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002200 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002201
Vladimir Medic4c299852013-11-06 11:27:05 +00002202 CC = StringSwitch<unsigned>(Name)
2203 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002204 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002205 .Case("a0", 4)
2206 .Case("a1", 5)
2207 .Case("a2", 6)
2208 .Case("a3", 7)
2209 .Case("v0", 2)
2210 .Case("v1", 3)
2211 .Case("s0", 16)
2212 .Case("s1", 17)
2213 .Case("s2", 18)
2214 .Case("s3", 19)
2215 .Case("s4", 20)
2216 .Case("s5", 21)
2217 .Case("s6", 22)
2218 .Case("s7", 23)
2219 .Case("k0", 26)
2220 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002221 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002222 .Case("sp", 29)
2223 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002224 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002225 .Case("ra", 31)
2226 .Case("t0", 8)
2227 .Case("t1", 9)
2228 .Case("t2", 10)
2229 .Case("t3", 11)
2230 .Case("t4", 12)
2231 .Case("t5", 13)
2232 .Case("t6", 14)
2233 .Case("t7", 15)
2234 .Case("t8", 24)
2235 .Case("t9", 25)
2236 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002237
Toma Tabacufda445c2014-09-15 15:33:01 +00002238 if (!(isABI_N32() || isABI_N64()))
2239 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002240
Daniel Sandersef638fe2014-10-03 15:37:37 +00002241 if (12 <= CC && CC <= 15) {
2242 // Name is one of t4-t7
2243 AsmToken RegTok = getLexer().peekTok();
2244 SMRange RegRange = RegTok.getLocRange();
2245
2246 StringRef FixedName = StringSwitch<StringRef>(Name)
2247 .Case("t4", "t0")
2248 .Case("t5", "t1")
2249 .Case("t6", "t2")
2250 .Case("t7", "t3")
2251 .Default("");
2252 assert(FixedName != "" && "Register name is not one of t4-t7.");
2253
2254 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2255 "Did you mean $" + FixedName + "?", RegRange);
2256 }
2257
Toma Tabacufda445c2014-09-15 15:33:01 +00002258 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2259 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2260 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2261 if (8 <= CC && CC <= 11)
2262 CC += 4;
2263
2264 if (CC == -1)
2265 CC = StringSwitch<unsigned>(Name)
2266 .Case("a4", 8)
2267 .Case("a5", 9)
2268 .Case("a6", 10)
2269 .Case("a7", 11)
2270 .Case("kt0", 26)
2271 .Case("kt1", 27)
2272 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002273
2274 return CC;
2275}
Jack Carterd0bd6422013-04-18 00:41:53 +00002276
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002277int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2278 int CC;
2279
2280 CC = StringSwitch<unsigned>(Name)
2281 .Case("hwr_cpunum", 0)
2282 .Case("hwr_synci_step", 1)
2283 .Case("hwr_cc", 2)
2284 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002285 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002286 .Default(-1);
2287
2288 return CC;
2289}
2290
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002291int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002292
Jack Cartera63b16a2012-09-07 00:23:42 +00002293 if (Name[0] == 'f') {
2294 StringRef NumString = Name.substr(1);
2295 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002296 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002297 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002298 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002299 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002300 return IntVal;
2301 }
2302 return -1;
2303}
Jack Cartera63b16a2012-09-07 00:23:42 +00002304
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002305int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2306
2307 if (Name.startswith("fcc")) {
2308 StringRef NumString = Name.substr(3);
2309 unsigned IntVal;
2310 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002311 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002312 if (IntVal > 7) // There are only 8 fcc registers.
2313 return -1;
2314 return IntVal;
2315 }
2316 return -1;
2317}
2318
2319int MipsAsmParser::matchACRegisterName(StringRef Name) {
2320
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002321 if (Name.startswith("ac")) {
2322 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002323 unsigned IntVal;
2324 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002325 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002326 if (IntVal > 3) // There are only 3 acc registers.
2327 return -1;
2328 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002329 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002330 return -1;
2331}
Jack Carterd0bd6422013-04-18 00:41:53 +00002332
Jack Carter5dc8ac92013-09-25 23:50:44 +00002333int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2334 unsigned IntVal;
2335
2336 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2337 return -1;
2338
2339 if (IntVal > 31)
2340 return -1;
2341
2342 return IntVal;
2343}
2344
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002345int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2346 int CC;
2347
2348 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002349 .Case("msair", 0)
2350 .Case("msacsr", 1)
2351 .Case("msaaccess", 2)
2352 .Case("msasave", 3)
2353 .Case("msamodify", 4)
2354 .Case("msarequest", 5)
2355 .Case("msamap", 6)
2356 .Case("msaunmap", 7)
2357 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002358
2359 return CC;
2360}
2361
Jack Carter0b744b32012-10-04 02:29:46 +00002362bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2363 if (Reg > 31)
2364 return false;
2365
Toma Tabacu3c24b042014-09-05 15:43:21 +00002366 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002367 return true;
2368}
2369
Matheus Almeida7de68e72014-06-18 14:46:05 +00002370int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002371 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002372 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002373 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002374 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002375 return AT;
2376}
Jack Carter0b744b32012-10-04 02:29:46 +00002377
Jack Carterd0bd6422013-04-18 00:41:53 +00002378unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002379 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002380}
2381
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002382unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002383 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002384 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002385}
2386
Jack Carter873c7242013-01-12 01:03:14 +00002387int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002388 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002389 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002390 return -1;
2391
Jack Carter873c7242013-01-12 01:03:14 +00002392 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002393}
2394
Toma Tabacu13964452014-09-04 13:23:44 +00002395bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002396 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002397 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002398
Jack Carter30a59822012-10-04 04:03:53 +00002399 // Check if the current operand has a custom associated parser, if so, try to
2400 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002401 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2402 if (ResTy == MatchOperand_Success)
2403 return false;
2404 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2405 // there was a match, but an error occurred, in which case, just return that
2406 // the operand parsing failed.
2407 if (ResTy == MatchOperand_ParseFail)
2408 return true;
2409
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002410 DEBUG(dbgs() << ".. Generic Parser\n");
2411
Jack Carterb4dbc172012-09-05 23:34:03 +00002412 switch (getLexer().getKind()) {
2413 default:
2414 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2415 return true;
2416 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002417 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002418 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002419
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002420 // Almost all registers have been parsed by custom parsers. There is only
2421 // one exception to this. $zero (and it's alias $0) will reach this point
2422 // for div, divu, and similar instructions because it is not an operand
2423 // to the instruction definition but an explicit register. Special case
2424 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002425 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002426 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002427
Jack Carterd0bd6422013-04-18 00:41:53 +00002428 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002429 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002430 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002431 return true;
2432
Jack Carter873c7242013-01-12 01:03:14 +00002433 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002434 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002435 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002436 const MCExpr *Res =
2437 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002438
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002439 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002440 return false;
2441 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002442 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002443 case AsmToken::LParen:
2444 case AsmToken::Minus:
2445 case AsmToken::Plus:
2446 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002447 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002448 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002449 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002450 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002451 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002452 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002453 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002454 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002455 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002456 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002457 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002458 return true;
2459
Jack Carter873c7242013-01-12 01:03:14 +00002460 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2461
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002463 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002464 } // case AsmToken::Percent
2465 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002466 return true;
2467}
2468
Vladimir Medic4c299852013-11-06 11:27:05 +00002469const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002470 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002471 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002472 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002473 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002474 // It's a constant, evaluate reloc value.
2475 int16_t Val;
2476 switch (getVariantKind(RelocStr)) {
2477 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2478 // Get the 1st 16-bits.
2479 Val = MCE->getValue() & 0xffff;
2480 break;
2481 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2482 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2483 // 16 bits being negative.
2484 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2485 break;
2486 case MCSymbolRefExpr::VK_Mips_HIGHER:
2487 // Get the 3rd 16-bits.
2488 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2489 break;
2490 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2491 // Get the 4th 16-bits.
2492 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2493 break;
2494 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002495 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002496 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002497 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002498 }
2499
Jack Carterb5cf5902013-04-17 00:18:04 +00002500 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002501 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002502 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002503 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002504 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002505 return Res;
2506 }
2507
2508 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002509 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2510
Sasa Stankovic06c47802014-04-03 10:37:45 +00002511 // Try to create target expression.
2512 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2513 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002514
Jack Carterd0bd6422013-04-18 00:41:53 +00002515 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2516 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002517 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2518 return Res;
2519 }
2520
2521 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002522 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2523 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2524 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002525 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002526 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002527 return Expr;
2528}
2529
2530bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2531
2532 switch (Expr->getKind()) {
2533 case MCExpr::Constant:
2534 return true;
2535 case MCExpr::SymbolRef:
2536 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2537 case MCExpr::Binary:
2538 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2539 if (!isEvaluated(BE->getLHS()))
2540 return false;
2541 return isEvaluated(BE->getRHS());
2542 }
2543 case MCExpr::Unary:
2544 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002545 case MCExpr::Target:
2546 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002547 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002548 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002549}
Jack Carterd0bd6422013-04-18 00:41:53 +00002550
Jack Carterb5cf5902013-04-17 00:18:04 +00002551bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002552 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002553 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002554 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002555 if (Tok.isNot(AsmToken::Identifier))
2556 return true;
2557
2558 std::string Str = Tok.getIdentifier().str();
2559
Jack Carterd0bd6422013-04-18 00:41:53 +00002560 Parser.Lex(); // Eat the identifier.
2561 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002562 const MCExpr *IdVal;
2563 SMLoc EndLoc;
2564
2565 if (getLexer().getKind() == AsmToken::LParen) {
2566 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002568 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002570 const AsmToken &nextTok = Parser.getTok();
2571 if (nextTok.isNot(AsmToken::Identifier))
2572 return true;
2573 Str += "(%";
2574 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002575 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002576 if (getLexer().getKind() != AsmToken::LParen)
2577 return true;
2578 } else
2579 break;
2580 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002581 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002582 return true;
2583
2584 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002585 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002586
2587 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002589
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002591 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002592}
2593
Jack Carterb4dbc172012-09-05 23:34:03 +00002594bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2595 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002596 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002597 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002598 if (ResTy == MatchOperand_Success) {
2599 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002600 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002601 StartLoc = Operand.getStartLoc();
2602 EndLoc = Operand.getEndLoc();
2603
2604 // AFAIK, we only support numeric registers and named GPR's in CFI
2605 // directives.
2606 // Don't worry about eating tokens before failing. Using an unrecognised
2607 // register is a parse error.
2608 if (Operand.isGPRAsmReg()) {
2609 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002610 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002611 }
2612
2613 return (RegNo == (unsigned)-1);
2614 }
2615
2616 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002617 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002618}
2619
Jack Carterb5cf5902013-04-17 00:18:04 +00002620bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002621 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002622 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002623 bool Result = true;
2624
2625 while (getLexer().getKind() == AsmToken::LParen)
2626 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002627
Jack Carterd0bd6422013-04-18 00:41:53 +00002628 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002629 default:
2630 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002631 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002632 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002633 case AsmToken::Integer:
2634 case AsmToken::Minus:
2635 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002636 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002637 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002638 else
2639 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002640 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002641 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002642 break;
Jack Carter873c7242013-01-12 01:03:14 +00002643 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002644 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002645 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002646 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002647}
2648
David Blaikie960ea3f2014-06-08 16:18:35 +00002649MipsAsmParser::OperandMatchResultTy
2650MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002651 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002652 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002653 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002654 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002655 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002656 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002657 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002658 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002659
Jack Carterb5cf5902013-04-17 00:18:04 +00002660 if (getLexer().getKind() == AsmToken::LParen) {
2661 Parser.Lex();
2662 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002663 }
2664
Jack Carterb5cf5902013-04-17 00:18:04 +00002665 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002666 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002667 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002668
Jack Carterd0bd6422013-04-18 00:41:53 +00002669 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002670 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002671 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2672 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002673 SMLoc E =
2674 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002675 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002676 return MatchOperand_Success;
2677 }
2678 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002679 SMLoc E =
2680 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002681
Jack Carterd0bd6422013-04-18 00:41:53 +00002682 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002683 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002684 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002685 S, E, *this);
2686 Operands.push_back(
2687 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002688 return MatchOperand_Success;
2689 }
2690 Error(Parser.getTok().getLoc(), "'(' expected");
2691 return MatchOperand_ParseFail;
2692 }
2693
Jack Carterd0bd6422013-04-18 00:41:53 +00002694 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002695 }
2696
Toma Tabacu13964452014-09-04 13:23:44 +00002697 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002698 if (Res != MatchOperand_Success)
2699 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002700
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002701 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002702 Error(Parser.getTok().getLoc(), "')' expected");
2703 return MatchOperand_ParseFail;
2704 }
2705
Jack Carter873c7242013-01-12 01:03:14 +00002706 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2707
Jack Carterd0bd6422013-04-18 00:41:53 +00002708 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002709
Craig Topper062a2ba2014-04-25 05:30:21 +00002710 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002711 IdVal = MCConstantExpr::Create(0, getContext());
2712
Jack Carterd0bd6422013-04-18 00:41:53 +00002713 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002714 std::unique_ptr<MipsOperand> op(
2715 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002716 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002717 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002718 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002719 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002720 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2721 int64_t Imm;
2722 if (IdVal->EvaluateAsAbsolute(Imm))
2723 IdVal = MCConstantExpr::Create(Imm, getContext());
2724 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2725 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2726 getContext());
2727 }
2728
David Blaikie960ea3f2014-06-08 16:18:35 +00002729 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002730 return MatchOperand_Success;
2731}
2732
David Blaikie960ea3f2014-06-08 16:18:35 +00002733bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002734 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002735 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2736 if (Sym) {
2737 SMLoc S = Parser.getTok().getLoc();
2738 const MCExpr *Expr;
2739 if (Sym->isVariable())
2740 Expr = Sym->getVariableValue();
2741 else
2742 return false;
2743 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002744 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002745 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002746 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002747 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002748 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002749 if (ResTy == MatchOperand_Success) {
2750 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002751 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002752 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002753 llvm_unreachable("Should never ParseFail");
2754 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002755 }
2756 } else if (Expr->getKind() == MCExpr::Constant) {
2757 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002758 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002759 Operands.push_back(
2760 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002761 return true;
2762 }
2763 }
2764 return false;
2765}
Jack Carterd0bd6422013-04-18 00:41:53 +00002766
Jack Carter873c7242013-01-12 01:03:14 +00002767MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002768MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002769 StringRef Identifier,
2770 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002771 int Index = matchCPURegisterName(Identifier);
2772 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002773 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002774 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2775 return MatchOperand_Success;
2776 }
2777
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002778 Index = matchHWRegsRegisterName(Identifier);
2779 if (Index != -1) {
2780 Operands.push_back(MipsOperand::createHWRegsReg(
2781 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2782 return MatchOperand_Success;
2783 }
2784
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002785 Index = matchFPURegisterName(Identifier);
2786 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002787 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002788 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2789 return MatchOperand_Success;
2790 }
2791
2792 Index = matchFCCRegisterName(Identifier);
2793 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002794 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002795 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2796 return MatchOperand_Success;
2797 }
2798
2799 Index = matchACRegisterName(Identifier);
2800 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002801 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002802 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2803 return MatchOperand_Success;
2804 }
2805
2806 Index = matchMSA128RegisterName(Identifier);
2807 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002808 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002809 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2810 return MatchOperand_Success;
2811 }
2812
2813 Index = matchMSA128CtrlRegisterName(Identifier);
2814 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002815 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002816 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2817 return MatchOperand_Success;
2818 }
2819
2820 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002821}
2822
2823MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002824MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002825 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002826 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002827
2828 if (Token.is(AsmToken::Identifier)) {
2829 DEBUG(dbgs() << ".. identifier\n");
2830 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002831 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002832 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002833 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 } else if (Token.is(AsmToken::Integer)) {
2835 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002836 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002837 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2838 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002839 return MatchOperand_Success;
2840 }
2841
2842 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2843
2844 return MatchOperand_NoMatch;
2845}
2846
David Blaikie960ea3f2014-06-08 16:18:35 +00002847MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002848MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002849 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002850 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002851
2852 auto Token = Parser.getTok();
2853
2854 SMLoc S = Token.getLoc();
2855
2856 if (Token.isNot(AsmToken::Dollar)) {
2857 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2858 if (Token.is(AsmToken::Identifier)) {
2859 if (searchSymbolAlias(Operands))
2860 return MatchOperand_Success;
2861 }
2862 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2863 return MatchOperand_NoMatch;
2864 }
2865 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002866
Toma Tabacu13964452014-09-04 13:23:44 +00002867 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002868 if (ResTy == MatchOperand_Success) {
2869 Parser.Lex(); // $
2870 Parser.Lex(); // identifier
2871 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002872 return ResTy;
2873}
2874
2875MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002876MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002877 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002878 switch (getLexer().getKind()) {
2879 default:
2880 return MatchOperand_NoMatch;
2881 case AsmToken::LParen:
2882 case AsmToken::Minus:
2883 case AsmToken::Plus:
2884 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002885 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002886 case AsmToken::String:
2887 break;
2888 }
2889
2890 const MCExpr *IdVal;
2891 SMLoc S = Parser.getTok().getLoc();
2892 if (getParser().parseExpression(IdVal))
2893 return MatchOperand_ParseFail;
2894
2895 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2896 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2897 return MatchOperand_Success;
2898}
2899
David Blaikie960ea3f2014-06-08 16:18:35 +00002900MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002901MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002902 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002903 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002904
2905 SMLoc S = getLexer().getLoc();
2906
2907 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002908 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002909 if (ResTy != MatchOperand_NoMatch)
2910 return ResTy;
2911
Daniel Sanders315386c2014-04-01 10:40:14 +00002912 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002913 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002914 if (ResTy != MatchOperand_NoMatch)
2915 return ResTy;
2916
Daniel Sandersffd84362014-04-01 10:41:48 +00002917 const MCExpr *Expr = nullptr;
2918 if (Parser.parseExpression(Expr)) {
2919 // We have no way of knowing if a symbol was consumed so we must ParseFail
2920 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002921 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002922 Operands.push_back(
2923 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002924 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002925}
2926
Vladimir Medic2b953d02013-10-01 09:48:56 +00002927MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002928MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002929 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002930 const MCExpr *IdVal;
2931 // If the first token is '$' we may have register operand.
2932 if (Parser.getTok().is(AsmToken::Dollar))
2933 return MatchOperand_NoMatch;
2934 SMLoc S = Parser.getTok().getLoc();
2935 if (getParser().parseExpression(IdVal))
2936 return MatchOperand_ParseFail;
2937 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002938 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002939 int64_t Val = MCE->getValue();
2940 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2941 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002942 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002943 return MatchOperand_Success;
2944}
2945
Matheus Almeida779c5932013-11-18 12:32:49 +00002946MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002947MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002948 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002949 switch (getLexer().getKind()) {
2950 default:
2951 return MatchOperand_NoMatch;
2952 case AsmToken::LParen:
2953 case AsmToken::Plus:
2954 case AsmToken::Minus:
2955 case AsmToken::Integer:
2956 break;
2957 }
2958
2959 const MCExpr *Expr;
2960 SMLoc S = Parser.getTok().getLoc();
2961
2962 if (getParser().parseExpression(Expr))
2963 return MatchOperand_ParseFail;
2964
2965 int64_t Val;
2966 if (!Expr->EvaluateAsAbsolute(Val)) {
2967 Error(S, "expected immediate value");
2968 return MatchOperand_ParseFail;
2969 }
2970
2971 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2972 // and because the CPU always adds one to the immediate field, the allowed
2973 // range becomes 1..4. We'll only check the range here and will deal
2974 // with the addition/subtraction when actually decoding/encoding
2975 // the instruction.
2976 if (Val < 1 || Val > 4) {
2977 Error(S, "immediate not in range (1..4)");
2978 return MatchOperand_ParseFail;
2979 }
2980
Jack Carter3b2c96e2014-01-22 23:31:38 +00002981 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002982 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002983 return MatchOperand_Success;
2984}
2985
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002986MipsAsmParser::OperandMatchResultTy
2987MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2988 MCAsmParser &Parser = getParser();
2989 SmallVector<unsigned, 10> Regs;
2990 unsigned RegNo;
2991 unsigned PrevReg = Mips::NoRegister;
2992 bool RegRange = false;
2993 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2994
2995 if (Parser.getTok().isNot(AsmToken::Dollar))
2996 return MatchOperand_ParseFail;
2997
2998 SMLoc S = Parser.getTok().getLoc();
2999 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3000 SMLoc E = getLexer().getLoc();
3001 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3002 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3003 if (RegRange) {
3004 // Remove last register operand because registers from register range
3005 // should be inserted first.
3006 if (RegNo == Mips::RA) {
3007 Regs.push_back(RegNo);
3008 } else {
3009 unsigned TmpReg = PrevReg + 1;
3010 while (TmpReg <= RegNo) {
3011 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3012 Error(E, "invalid register operand");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 PrevReg = TmpReg;
3017 Regs.push_back(TmpReg++);
3018 }
3019 }
3020
3021 RegRange = false;
3022 } else {
3023 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3024 (RegNo != Mips::RA)) {
3025 Error(E, "$16 or $31 expected");
3026 return MatchOperand_ParseFail;
3027 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3028 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3029 Error(E, "invalid register operand");
3030 return MatchOperand_ParseFail;
3031 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3032 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3033 Error(E, "consecutive register numbers expected");
3034 return MatchOperand_ParseFail;
3035 }
3036
3037 Regs.push_back(RegNo);
3038 }
3039
3040 if (Parser.getTok().is(AsmToken::Minus))
3041 RegRange = true;
3042
3043 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3044 !Parser.getTok().isNot(AsmToken::Comma)) {
3045 Error(E, "',' or '-' expected");
3046 return MatchOperand_ParseFail;
3047 }
3048
3049 Lex(); // Consume comma or minus
3050 if (Parser.getTok().isNot(AsmToken::Dollar))
3051 break;
3052
3053 PrevReg = RegNo;
3054 }
3055
3056 SMLoc E = Parser.getTok().getLoc();
3057 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3058 parseMemOperand(Operands);
3059 return MatchOperand_Success;
3060}
3061
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003062MipsAsmParser::OperandMatchResultTy
3063MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3064 MCAsmParser &Parser = getParser();
3065
3066 SMLoc S = Parser.getTok().getLoc();
3067 if (parseAnyRegister(Operands) != MatchOperand_Success)
3068 return MatchOperand_ParseFail;
3069
3070 SMLoc E = Parser.getTok().getLoc();
3071 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3072 unsigned Reg = Op.getGPR32Reg();
3073 Operands.pop_back();
3074 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3075 return MatchOperand_Success;
3076}
3077
Zoran Jovanovic41688672015-02-10 16:36:20 +00003078MipsAsmParser::OperandMatchResultTy
3079MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3080 MCAsmParser &Parser = getParser();
3081 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3082 SmallVector<unsigned, 10> Regs;
3083
3084 if (Parser.getTok().isNot(AsmToken::Dollar))
3085 return MatchOperand_ParseFail;
3086
3087 SMLoc S = Parser.getTok().getLoc();
3088
3089 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3090 return MatchOperand_ParseFail;
3091
3092 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3093 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3094 Regs.push_back(RegNo);
3095
3096 SMLoc E = Parser.getTok().getLoc();
3097 if (Parser.getTok().isNot(AsmToken::Comma)) {
3098 Error(E, "',' expected");
3099 return MatchOperand_ParseFail;
3100 }
3101
3102 // Remove comma.
3103 Parser.Lex();
3104
3105 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3106 return MatchOperand_ParseFail;
3107
3108 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3109 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3110 Regs.push_back(RegNo);
3111
3112 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3113
3114 return MatchOperand_Success;
3115}
3116
Jack Carterdc1e35d2012-09-06 20:00:02 +00003117MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3118
Vladimir Medic4c299852013-11-06 11:27:05 +00003119 MCSymbolRefExpr::VariantKind VK =
3120 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3121 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3122 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3123 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3124 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3125 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3126 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3127 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3128 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3129 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3130 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3131 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3132 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3133 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3134 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3135 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3136 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3137 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003138 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3139 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3140 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3141 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3142 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3143 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003144 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3145 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003146 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003147
Matheus Almeida2852af82014-04-22 10:15:54 +00003148 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003149
Jack Carterdc1e35d2012-09-06 20:00:02 +00003150 return VK;
3151}
Jack Cartera63b16a2012-09-07 00:23:42 +00003152
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003153/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3154/// either this.
3155/// ::= '(', register, ')'
3156/// handle it before we iterate so we don't get tripped up by the lack of
3157/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003158bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003159 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003160 if (getLexer().is(AsmToken::LParen)) {
3161 Operands.push_back(
3162 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3163 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003164 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003165 SMLoc Loc = getLexer().getLoc();
3166 Parser.eatToEndOfStatement();
3167 return Error(Loc, "unexpected token in argument list");
3168 }
3169 if (Parser.getTok().isNot(AsmToken::RParen)) {
3170 SMLoc Loc = getLexer().getLoc();
3171 Parser.eatToEndOfStatement();
3172 return Error(Loc, "unexpected token, expected ')'");
3173 }
3174 Operands.push_back(
3175 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3176 Parser.Lex();
3177 }
3178 return false;
3179}
3180
3181/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3182/// either one of these.
3183/// ::= '[', register, ']'
3184/// ::= '[', integer, ']'
3185/// handle it before we iterate so we don't get tripped up by the lack of
3186/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003187bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003188 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003189 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003190 if (getLexer().is(AsmToken::LBrac)) {
3191 Operands.push_back(
3192 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3193 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003194 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003195 SMLoc Loc = getLexer().getLoc();
3196 Parser.eatToEndOfStatement();
3197 return Error(Loc, "unexpected token in argument list");
3198 }
3199 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3200 SMLoc Loc = getLexer().getLoc();
3201 Parser.eatToEndOfStatement();
3202 return Error(Loc, "unexpected token, expected ']'");
3203 }
3204 Operands.push_back(
3205 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3206 Parser.Lex();
3207 }
3208 return false;
3209}
3210
David Blaikie960ea3f2014-06-08 16:18:35 +00003211bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3212 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003213 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003214 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003215
3216 // We have reached first instruction, module directive are now forbidden.
3217 getTargetStreamer().forbidModuleDirective();
3218
Vladimir Medic74593e62013-07-17 15:00:42 +00003219 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003220 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003221 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003222 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003223 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003224 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003225 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003226
3227 // Read the remaining operands.
3228 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3229 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003230 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003231 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003232 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003233 return Error(Loc, "unexpected token in argument list");
3234 }
Toma Tabacu13964452014-09-04 13:23:44 +00003235 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 return true;
3237 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003238
Jack Carterd0bd6422013-04-18 00:41:53 +00003239 while (getLexer().is(AsmToken::Comma)) {
3240 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003241 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003242 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003243 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003244 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003245 return Error(Loc, "unexpected token in argument list");
3246 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003247 // Parse bracket and parenthesis suffixes before we iterate
3248 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003249 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003250 return true;
3251 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003252 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003253 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003254 }
3255 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003256 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3257 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003258 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003259 return Error(Loc, "unexpected token in argument list");
3260 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003261 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003262 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003263}
3264
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003265bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003266 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003267 SMLoc Loc = getLexer().getLoc();
3268 Parser.eatToEndOfStatement();
3269 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003270}
3271
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003272bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003273 return Error(Loc, ErrorMsg);
3274}
3275
Jack Carter0b744b32012-10-04 02:29:46 +00003276bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003277 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003278 // Line should look like: ".set noat".
3279 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003280 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00003281 // eat noat
3282 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003283 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003284 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003285 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003286 return false;
3287 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003288 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003289 return false;
3290}
Jack Carterd0bd6422013-04-18 00:41:53 +00003291
Jack Carter0b744b32012-10-04 02:29:46 +00003292bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003293 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003294 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00003295 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00003296 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00003297 getParser().Lex();
3298 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003299 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00003300 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003301 return false;
3302 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00003304 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003305 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003306 return false;
3307 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003308 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00003309 const AsmToken &Reg = Parser.getTok();
3310 if (Reg.is(AsmToken::Identifier)) {
3311 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3312 } else if (Reg.is(AsmToken::Integer)) {
3313 AtRegNo = Reg.getIntVal();
3314 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003315 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003316 return false;
3317 }
Jack Carter1ac53222013-02-20 23:11:17 +00003318
Daniel Sanders71a89d922014-03-25 13:01:06 +00003319 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00003320 reportParseError("unexpected token in statement");
3321 return false;
3322 }
3323
Toma Tabacu9db22db2014-09-09 10:15:38 +00003324 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003325 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00003326 return false;
3327 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003328 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00003329
3330 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003331 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003332 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003333 }
3334 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003335 return false;
3336 } else {
3337 reportParseError("unexpected token in statement");
3338 return false;
3339 }
3340}
3341
3342bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003343 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003344 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003345 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003346 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003347 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003348 return false;
3349 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003350 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003351 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003352 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003353 return false;
3354}
3355
3356bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003357 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003358 Parser.Lex();
3359 // If this is not the end of the statement, report an error.
3360 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003361 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003362 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003363 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003364 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003365 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003366 Parser.Lex(); // Consume the EndOfStatement.
3367 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003368}
3369
3370bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003371 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003372 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003373 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003375 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003376 return false;
3377 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003378 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003379 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003380 return false;
3381}
3382
3383bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003384 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003385 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003386 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003387 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003388 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003389 return false;
3390 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003391 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003392 reportParseError("`noreorder' must be set before `nomacro'");
3393 return false;
3394 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003395 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003396 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003397 return false;
3398}
Jack Carterd76b2372013-03-21 21:44:16 +00003399
Daniel Sanders44934432014-08-07 12:03:36 +00003400bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003401 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003402 Parser.Lex();
3403
3404 // If this is not the end of the statement, report an error.
3405 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003406 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003407
3408 setFeatureBits(Mips::FeatureMSA, "msa");
3409 getTargetStreamer().emitDirectiveSetMsa();
3410 return false;
3411}
3412
3413bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003414 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003415 Parser.Lex();
3416
3417 // If this is not the end of the statement, report an error.
3418 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003419 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003420
3421 clearFeatureBits(Mips::FeatureMSA, "msa");
3422 getTargetStreamer().emitDirectiveSetNoMsa();
3423 return false;
3424}
3425
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003426bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003427 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003428 Parser.Lex(); // Eat "nodsp".
3429
3430 // If this is not the end of the statement, report an error.
3431 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3432 reportParseError("unexpected token, expected end of statement");
3433 return false;
3434 }
3435
3436 clearFeatureBits(Mips::FeatureDSP, "dsp");
3437 getTargetStreamer().emitDirectiveSetNoDsp();
3438 return false;
3439}
3440
Toma Tabacucc2502d2014-11-04 17:18:07 +00003441bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003442 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003443 Parser.Lex(); // Eat "mips16".
3444
Jack Carter39536722014-01-22 23:08:42 +00003445 // If this is not the end of the statement, report an error.
3446 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003447 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003448 return false;
3449 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003450
3451 setFeatureBits(Mips::FeatureMips16, "mips16");
3452 getTargetStreamer().emitDirectiveSetMips16();
3453 Parser.Lex(); // Consume the EndOfStatement.
3454 return false;
3455}
3456
3457bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003458 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003459 Parser.Lex(); // Eat "nomips16".
3460
3461 // If this is not the end of the statement, report an error.
3462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3463 reportParseError("unexpected token, expected end of statement");
3464 return false;
3465 }
3466
3467 clearFeatureBits(Mips::FeatureMips16, "mips16");
3468 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003469 Parser.Lex(); // Consume the EndOfStatement.
3470 return false;
3471}
3472
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003473bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003474 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003475 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003476 // Line can be: .set fp=32
3477 // .set fp=xx
3478 // .set fp=64
3479 Parser.Lex(); // Eat fp token
3480 AsmToken Tok = Parser.getTok();
3481 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003482 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003483 return false;
3484 }
3485 Parser.Lex(); // Eat '=' token.
3486 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003487
3488 if (!parseFpABIValue(FpAbiVal, ".set"))
3489 return false;
3490
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003492 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003493 return false;
3494 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003495 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003496 Parser.Lex(); // Consume the EndOfStatement.
3497 return false;
3498}
3499
Toma Tabacu9db22db2014-09-09 10:15:38 +00003500bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003501 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003502 SMLoc Loc = getLexer().getLoc();
3503
3504 Parser.Lex();
3505 if (getLexer().isNot(AsmToken::EndOfStatement))
3506 return reportParseError("unexpected token, expected end of statement");
3507
3508 // Always keep an element on the options "stack" to prevent the user
3509 // from changing the initial options. This is how we remember them.
3510 if (AssemblerOptions.size() == 2)
3511 return reportParseError(Loc, ".set pop with no .set push");
3512
3513 AssemblerOptions.pop_back();
3514 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3515
3516 getTargetStreamer().emitDirectiveSetPop();
3517 return false;
3518}
3519
3520bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003521 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003522 Parser.Lex();
3523 if (getLexer().isNot(AsmToken::EndOfStatement))
3524 return reportParseError("unexpected token, expected end of statement");
3525
3526 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003527 AssemblerOptions.push_back(
3528 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003529
3530 getTargetStreamer().emitDirectiveSetPush();
3531 return false;
3532}
3533
Jack Carterd76b2372013-03-21 21:44:16 +00003534bool MipsAsmParser::parseSetAssignment() {
3535 StringRef Name;
3536 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003537 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003538
3539 if (Parser.parseIdentifier(Name))
3540 reportParseError("expected identifier after .set");
3541
3542 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003543 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003544 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003545
Jack Carter3b2c96e2014-01-22 23:31:38 +00003546 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003547 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003548
Jack Carterd0bd6422013-04-18 00:41:53 +00003549 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003550 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003551 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003552 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003553 Sym = getContext().GetOrCreateSymbol(Name);
3554 Sym->setVariableValue(Value);
3555
3556 return false;
3557}
Jack Carterd0bd6422013-04-18 00:41:53 +00003558
Toma Tabacu26647792014-09-09 12:52:14 +00003559bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003560 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003561 Parser.Lex();
3562 if (getLexer().isNot(AsmToken::EndOfStatement))
3563 return reportParseError("unexpected token, expected end of statement");
3564
3565 // Reset assembler options to their initial values.
3566 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3567 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3568
3569 getTargetStreamer().emitDirectiveSetMips0();
3570 return false;
3571}
3572
Toma Tabacu85618b32014-08-19 14:22:52 +00003573bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003574 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003575 Parser.Lex();
3576 if (getLexer().isNot(AsmToken::Equal))
3577 return reportParseError("unexpected token, expected equals sign");
3578
3579 Parser.Lex();
3580 StringRef Arch;
3581 if (Parser.parseIdentifier(Arch))
3582 return reportParseError("expected arch identifier");
3583
3584 StringRef ArchFeatureName =
3585 StringSwitch<StringRef>(Arch)
3586 .Case("mips1", "mips1")
3587 .Case("mips2", "mips2")
3588 .Case("mips3", "mips3")
3589 .Case("mips4", "mips4")
3590 .Case("mips5", "mips5")
3591 .Case("mips32", "mips32")
3592 .Case("mips32r2", "mips32r2")
3593 .Case("mips32r6", "mips32r6")
3594 .Case("mips64", "mips64")
3595 .Case("mips64r2", "mips64r2")
3596 .Case("mips64r6", "mips64r6")
3597 .Case("cnmips", "cnmips")
3598 .Case("r4000", "mips3") // This is an implementation of Mips3.
3599 .Default("");
3600
3601 if (ArchFeatureName.empty())
3602 return reportParseError("unsupported architecture");
3603
3604 selectArch(ArchFeatureName);
3605 getTargetStreamer().emitDirectiveSetArch(Arch);
3606 return false;
3607}
3608
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003609bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003610 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003611 Parser.Lex();
3612 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003613 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003614
Matheus Almeida2852af82014-04-22 10:15:54 +00003615 switch (Feature) {
3616 default:
3617 llvm_unreachable("Unimplemented feature");
3618 case Mips::FeatureDSP:
3619 setFeatureBits(Mips::FeatureDSP, "dsp");
3620 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003621 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003622 case Mips::FeatureMicroMips:
3623 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003624 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003625 case Mips::FeatureMips1:
3626 selectArch("mips1");
3627 getTargetStreamer().emitDirectiveSetMips1();
3628 break;
3629 case Mips::FeatureMips2:
3630 selectArch("mips2");
3631 getTargetStreamer().emitDirectiveSetMips2();
3632 break;
3633 case Mips::FeatureMips3:
3634 selectArch("mips3");
3635 getTargetStreamer().emitDirectiveSetMips3();
3636 break;
3637 case Mips::FeatureMips4:
3638 selectArch("mips4");
3639 getTargetStreamer().emitDirectiveSetMips4();
3640 break;
3641 case Mips::FeatureMips5:
3642 selectArch("mips5");
3643 getTargetStreamer().emitDirectiveSetMips5();
3644 break;
3645 case Mips::FeatureMips32:
3646 selectArch("mips32");
3647 getTargetStreamer().emitDirectiveSetMips32();
3648 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003649 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003650 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003651 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003652 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003653 case Mips::FeatureMips32r6:
3654 selectArch("mips32r6");
3655 getTargetStreamer().emitDirectiveSetMips32R6();
3656 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003657 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003658 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003659 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003660 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003661 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003662 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003663 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003664 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003665 case Mips::FeatureMips64r6:
3666 selectArch("mips64r6");
3667 getTargetStreamer().emitDirectiveSetMips64R6();
3668 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003669 }
3670 return false;
3671}
3672
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003673bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003674 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003675 if (getLexer().isNot(AsmToken::Comma)) {
3676 SMLoc Loc = getLexer().getLoc();
3677 Parser.eatToEndOfStatement();
3678 return Error(Loc, ErrorStr);
3679 }
3680
Matheus Almeida2852af82014-04-22 10:15:54 +00003681 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003682 return true;
3683}
3684
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003685bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003686 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003687 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003688
Toma Tabacudde4c462014-11-06 10:02:45 +00003689 if (inMips16Mode()) {
3690 reportParseError(".cpload is not supported in Mips16 mode");
3691 return false;
3692 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003693
David Blaikie960ea3f2014-06-08 16:18:35 +00003694 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003695 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003696 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3697 reportParseError("expected register containing function address");
3698 return false;
3699 }
3700
David Blaikie960ea3f2014-06-08 16:18:35 +00003701 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3702 if (!RegOpnd.isGPRAsmReg()) {
3703 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003704 return false;
3705 }
3706
Toma Tabacudde4c462014-11-06 10:02:45 +00003707 // If this is not the end of the statement, report an error.
3708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3709 reportParseError("unexpected token, expected end of statement");
3710 return false;
3711 }
3712
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003713 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003714 return false;
3715}
3716
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003717bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003718 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003719 unsigned FuncReg;
3720 unsigned Save;
3721 bool SaveIsReg = true;
3722
Matheus Almeida7e815762014-06-18 13:08:59 +00003723 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003724 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003725 if (ResTy == MatchOperand_NoMatch) {
3726 reportParseError("expected register containing function address");
3727 Parser.eatToEndOfStatement();
3728 return false;
3729 }
3730
3731 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3732 if (!FuncRegOpnd.isGPRAsmReg()) {
3733 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3734 Parser.eatToEndOfStatement();
3735 return false;
3736 }
3737
3738 FuncReg = FuncRegOpnd.getGPR32Reg();
3739 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003740
Toma Tabacu65f10572014-09-16 15:00:52 +00003741 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003742 return true;
3743
Toma Tabacu13964452014-09-04 13:23:44 +00003744 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003745 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003746 const AsmToken &Tok = Parser.getTok();
3747 if (Tok.is(AsmToken::Integer)) {
3748 Save = Tok.getIntVal();
3749 SaveIsReg = false;
3750 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003751 } else {
3752 reportParseError("expected save register or stack offset");
3753 Parser.eatToEndOfStatement();
3754 return false;
3755 }
3756 } else {
3757 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3758 if (!SaveOpnd.isGPRAsmReg()) {
3759 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3760 Parser.eatToEndOfStatement();
3761 return false;
3762 }
3763 Save = SaveOpnd.getGPR32Reg();
3764 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003765
Toma Tabacu65f10572014-09-16 15:00:52 +00003766 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003767 return true;
3768
3769 StringRef Name;
3770 if (Parser.parseIdentifier(Name))
3771 reportParseError("expected identifier");
3772 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003773
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003774 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003775 return false;
3776}
3777
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003778bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003779 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003780 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3781 const AsmToken &Tok = Parser.getTok();
3782
3783 if (Tok.getString() == "2008") {
3784 Parser.Lex();
3785 getTargetStreamer().emitDirectiveNaN2008();
3786 return false;
3787 } else if (Tok.getString() == "legacy") {
3788 Parser.Lex();
3789 getTargetStreamer().emitDirectiveNaNLegacy();
3790 return false;
3791 }
3792 }
3793 // If we don't recognize the option passed to the .nan
3794 // directive (e.g. no option or unknown option), emit an error.
3795 reportParseError("invalid option in .nan directive");
3796 return false;
3797}
3798
Jack Carter0b744b32012-10-04 02:29:46 +00003799bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003800 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003801 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003802 const AsmToken &Tok = Parser.getTok();
3803
3804 if (Tok.getString() == "noat") {
3805 return parseSetNoAtDirective();
3806 } else if (Tok.getString() == "at") {
3807 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003808 } else if (Tok.getString() == "arch") {
3809 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003810 } else if (Tok.getString() == "fp") {
3811 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003812 } else if (Tok.getString() == "pop") {
3813 return parseSetPopDirective();
3814 } else if (Tok.getString() == "push") {
3815 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003816 } else if (Tok.getString() == "reorder") {
3817 return parseSetReorderDirective();
3818 } else if (Tok.getString() == "noreorder") {
3819 return parseSetNoReorderDirective();
3820 } else if (Tok.getString() == "macro") {
3821 return parseSetMacroDirective();
3822 } else if (Tok.getString() == "nomacro") {
3823 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003824 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003825 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003826 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003827 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003828 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003829 getTargetStreamer().emitDirectiveSetNoMicroMips();
3830 Parser.eatToEndOfStatement();
3831 return false;
3832 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003833 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003834 } else if (Tok.getString() == "mips0") {
3835 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003836 } else if (Tok.getString() == "mips1") {
3837 return parseSetFeature(Mips::FeatureMips1);
3838 } else if (Tok.getString() == "mips2") {
3839 return parseSetFeature(Mips::FeatureMips2);
3840 } else if (Tok.getString() == "mips3") {
3841 return parseSetFeature(Mips::FeatureMips3);
3842 } else if (Tok.getString() == "mips4") {
3843 return parseSetFeature(Mips::FeatureMips4);
3844 } else if (Tok.getString() == "mips5") {
3845 return parseSetFeature(Mips::FeatureMips5);
3846 } else if (Tok.getString() == "mips32") {
3847 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003848 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003849 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003850 } else if (Tok.getString() == "mips32r6") {
3851 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003852 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003853 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003854 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003855 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003856 } else if (Tok.getString() == "mips64r6") {
3857 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003858 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003859 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003860 } else if (Tok.getString() == "nodsp") {
3861 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003862 } else if (Tok.getString() == "msa") {
3863 return parseSetMsaDirective();
3864 } else if (Tok.getString() == "nomsa") {
3865 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003866 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003867 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003868 parseSetAssignment();
3869 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003870 }
Jack Carter07c818d2013-01-25 01:31:34 +00003871
Jack Carter0b744b32012-10-04 02:29:46 +00003872 return true;
3873}
3874
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003875/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003876/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003877bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003878 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003879 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3880 for (;;) {
3881 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003882 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003883 return true;
3884
3885 getParser().getStreamer().EmitValue(Value, Size);
3886
3887 if (getLexer().is(AsmToken::EndOfStatement))
3888 break;
3889
Jack Carter07c818d2013-01-25 01:31:34 +00003890 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003891 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003892 Parser.Lex();
3893 }
3894 }
3895
3896 Parser.Lex();
3897 return false;
3898}
3899
Vladimir Medic4c299852013-11-06 11:27:05 +00003900/// parseDirectiveGpWord
3901/// ::= .gpword local_sym
3902bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003903 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003904 const MCExpr *Value;
3905 // EmitGPRel32Value requires an expression, so we are using base class
3906 // method to evaluate the expression.
3907 if (getParser().parseExpression(Value))
3908 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003909 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003910
Vladimir Medice10c1122013-11-13 13:18:04 +00003911 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003912 return Error(getLexer().getLoc(),
3913 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003914 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003915 return false;
3916}
3917
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003918/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003919/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003920bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003921 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003922 const MCExpr *Value;
3923 // EmitGPRel64Value requires an expression, so we are using base class
3924 // method to evaluate the expression.
3925 if (getParser().parseExpression(Value))
3926 return true;
3927 getParser().getStreamer().EmitGPRel64Value(Value);
3928
3929 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003930 return Error(getLexer().getLoc(),
3931 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003932 Parser.Lex(); // Eat EndOfStatement token.
3933 return false;
3934}
3935
Jack Carter0cd3c192014-01-06 23:27:31 +00003936bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003937 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003938 // Get the option token.
3939 AsmToken Tok = Parser.getTok();
3940 // At the moment only identifiers are supported.
3941 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003942 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003943 Parser.eatToEndOfStatement();
3944 return false;
3945 }
3946
3947 StringRef Option = Tok.getIdentifier();
3948
3949 if (Option == "pic0") {
3950 getTargetStreamer().emitDirectiveOptionPic0();
3951 Parser.Lex();
3952 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3953 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003954 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003955 Parser.eatToEndOfStatement();
3956 }
3957 return false;
3958 }
3959
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003960 if (Option == "pic2") {
3961 getTargetStreamer().emitDirectiveOptionPic2();
3962 Parser.Lex();
3963 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3964 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003965 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003966 Parser.eatToEndOfStatement();
3967 }
3968 return false;
3969 }
3970
Jack Carter0cd3c192014-01-06 23:27:31 +00003971 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003972 Warning(Parser.getTok().getLoc(),
3973 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003974 Parser.eatToEndOfStatement();
3975 return false;
3976}
3977
Daniel Sanders7e527422014-07-10 13:38:23 +00003978/// parseDirectiveModule
3979/// ::= .module oddspreg
3980/// ::= .module nooddspreg
3981/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003982bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003983 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003984 MCAsmLexer &Lexer = getLexer();
3985 SMLoc L = Lexer.getLoc();
3986
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003987 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003988 // TODO : get a better message.
3989 reportParseError(".module directive must appear before any code");
3990 return false;
3991 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003992
Toma Tabacuc405c822015-01-23 10:40:19 +00003993 StringRef Option;
3994 if (Parser.parseIdentifier(Option)) {
3995 reportParseError("expected .module option identifier");
3996 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003997 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003998
Toma Tabacuc405c822015-01-23 10:40:19 +00003999 if (Option == "oddspreg") {
4000 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4001 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4002
4003 // If this is not the end of the statement, report an error.
4004 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4005 reportParseError("unexpected token, expected end of statement");
4006 return false;
4007 }
4008
4009 return false; // parseDirectiveModule has finished successfully.
4010 } else if (Option == "nooddspreg") {
4011 if (!isABI_O32()) {
4012 Error(L, "'.module nooddspreg' requires the O32 ABI");
4013 return false;
4014 }
4015
4016 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4017 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4018
4019 // If this is not the end of the statement, report an error.
4020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4021 reportParseError("unexpected token, expected end of statement");
4022 return false;
4023 }
4024
4025 return false; // parseDirectiveModule has finished successfully.
4026 } else if (Option == "fp") {
4027 return parseDirectiveModuleFP();
4028 } else {
4029 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4030 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004031}
4032
4033/// parseDirectiveModuleFP
4034/// ::= =32
4035/// ::= =xx
4036/// ::= =64
4037bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004038 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004039 MCAsmLexer &Lexer = getLexer();
4040
4041 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004042 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004043 return false;
4044 }
4045 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004046
Daniel Sanders7e527422014-07-10 13:38:23 +00004047 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004048 if (!parseFpABIValue(FpABI, ".module"))
4049 return false;
4050
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004052 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004053 return false;
4054 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004055
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004056 // Emit appropriate flags.
4057 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004058 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004059 return false;
4060}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004061
Daniel Sanders7e527422014-07-10 13:38:23 +00004062bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004063 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004064 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004065 MCAsmLexer &Lexer = getLexer();
4066
4067 if (Lexer.is(AsmToken::Identifier)) {
4068 StringRef Value = Parser.getTok().getString();
4069 Parser.Lex();
4070
4071 if (Value != "xx") {
4072 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4073 return false;
4074 }
4075
4076 if (!isABI_O32()) {
4077 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4078 return false;
4079 }
4080
Daniel Sanders7e527422014-07-10 13:38:23 +00004081 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004082 return true;
4083 }
4084
4085 if (Lexer.is(AsmToken::Integer)) {
4086 unsigned Value = Parser.getTok().getIntVal();
4087 Parser.Lex();
4088
4089 if (Value != 32 && Value != 64) {
4090 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4091 return false;
4092 }
4093
4094 if (Value == 32) {
4095 if (!isABI_O32()) {
4096 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4097 return false;
4098 }
4099
Daniel Sanders7e527422014-07-10 13:38:23 +00004100 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4101 } else
4102 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004103
Daniel Sanders7e527422014-07-10 13:38:23 +00004104 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004105 }
4106
4107 return false;
4108}
4109
Jack Carter0b744b32012-10-04 02:29:46 +00004110bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004111 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004112 StringRef IDVal = DirectiveID.getString();
4113
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004114 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004115 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004116 if (IDVal == ".dword") {
4117 parseDataDirective(8, DirectiveID.getLoc());
4118 return false;
4119 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004120 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004121 StringRef SymbolName;
4122
4123 if (Parser.parseIdentifier(SymbolName)) {
4124 reportParseError("expected identifier after .ent");
4125 return false;
4126 }
4127
4128 // There's an undocumented extension that allows an integer to
4129 // follow the name of the procedure which AFAICS is ignored by GAS.
4130 // Example: .ent foo,2
4131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4132 if (getLexer().isNot(AsmToken::Comma)) {
4133 // Even though we accept this undocumented extension for compatibility
4134 // reasons, the additional integer argument does not actually change
4135 // the behaviour of the '.ent' directive, so we would like to discourage
4136 // its use. We do this by not referring to the extended version in
4137 // error messages which are not directly related to its use.
4138 reportParseError("unexpected token, expected end of statement");
4139 return false;
4140 }
4141 Parser.Lex(); // Eat the comma.
4142 const MCExpr *DummyNumber;
4143 int64_t DummyNumberVal;
4144 // If the user was explicitly trying to use the extended version,
4145 // we still give helpful extension-related error messages.
4146 if (Parser.parseExpression(DummyNumber)) {
4147 reportParseError("expected number after comma");
4148 return false;
4149 }
4150 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4151 reportParseError("expected an absolute expression after comma");
4152 return false;
4153 }
4154 }
4155
4156 // If this is not the end of the statement, report an error.
4157 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4158 reportParseError("unexpected token, expected end of statement");
4159 return false;
4160 }
4161
4162 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4163
4164 getTargetStreamer().emitDirectiveEnt(*Sym);
4165 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004166 return false;
4167 }
4168
Jack Carter07c818d2013-01-25 01:31:34 +00004169 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004170 StringRef SymbolName;
4171
4172 if (Parser.parseIdentifier(SymbolName)) {
4173 reportParseError("expected identifier after .end");
4174 return false;
4175 }
4176
4177 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4178 reportParseError("unexpected token, expected end of statement");
4179 return false;
4180 }
4181
4182 if (CurrentFn == nullptr) {
4183 reportParseError(".end used without .ent");
4184 return false;
4185 }
4186
4187 if ((SymbolName != CurrentFn->getName())) {
4188 reportParseError(".end symbol does not match .ent symbol");
4189 return false;
4190 }
4191
4192 getTargetStreamer().emitDirectiveEnd(SymbolName);
4193 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004194 return false;
4195 }
4196
Jack Carter07c818d2013-01-25 01:31:34 +00004197 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004198 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4199 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004200 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004201 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4202 reportParseError("expected stack register");
4203 return false;
4204 }
4205
4206 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4207 if (!StackRegOpnd.isGPRAsmReg()) {
4208 reportParseError(StackRegOpnd.getStartLoc(),
4209 "expected general purpose register");
4210 return false;
4211 }
4212 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4213
4214 if (Parser.getTok().is(AsmToken::Comma))
4215 Parser.Lex();
4216 else {
4217 reportParseError("unexpected token, expected comma");
4218 return false;
4219 }
4220
4221 // Parse the frame size.
4222 const MCExpr *FrameSize;
4223 int64_t FrameSizeVal;
4224
4225 if (Parser.parseExpression(FrameSize)) {
4226 reportParseError("expected frame size value");
4227 return false;
4228 }
4229
4230 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4231 reportParseError("frame size not an absolute expression");
4232 return false;
4233 }
4234
4235 if (Parser.getTok().is(AsmToken::Comma))
4236 Parser.Lex();
4237 else {
4238 reportParseError("unexpected token, expected comma");
4239 return false;
4240 }
4241
4242 // Parse the return register.
4243 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004244 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004245 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4246 reportParseError("expected return register");
4247 return false;
4248 }
4249
4250 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4251 if (!ReturnRegOpnd.isGPRAsmReg()) {
4252 reportParseError(ReturnRegOpnd.getStartLoc(),
4253 "expected general purpose register");
4254 return false;
4255 }
4256
4257 // If this is not the end of the statement, report an error.
4258 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4259 reportParseError("unexpected token, expected end of statement");
4260 return false;
4261 }
4262
4263 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4264 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004265 return false;
4266 }
4267
Jack Carter07c818d2013-01-25 01:31:34 +00004268 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004269 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004270 }
4271
Daniel Sandersd97a6342014-08-13 10:07:34 +00004272 if (IDVal == ".mask" || IDVal == ".fmask") {
4273 // .mask bitmask, frame_offset
4274 // bitmask: One bit for each register used.
4275 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4276 // first register is expected to be saved.
4277 // Examples:
4278 // .mask 0x80000000, -4
4279 // .fmask 0x80000000, -4
4280 //
Jack Carterbe332172012-09-07 00:48:02 +00004281
Daniel Sandersd97a6342014-08-13 10:07:34 +00004282 // Parse the bitmask
4283 const MCExpr *BitMask;
4284 int64_t BitMaskVal;
4285
4286 if (Parser.parseExpression(BitMask)) {
4287 reportParseError("expected bitmask value");
4288 return false;
4289 }
4290
4291 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4292 reportParseError("bitmask not an absolute expression");
4293 return false;
4294 }
4295
4296 if (Parser.getTok().is(AsmToken::Comma))
4297 Parser.Lex();
4298 else {
4299 reportParseError("unexpected token, expected comma");
4300 return false;
4301 }
4302
4303 // Parse the frame_offset
4304 const MCExpr *FrameOffset;
4305 int64_t FrameOffsetVal;
4306
4307 if (Parser.parseExpression(FrameOffset)) {
4308 reportParseError("expected frame offset value");
4309 return false;
4310 }
4311
4312 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4313 reportParseError("frame offset not an absolute expression");
4314 return false;
4315 }
4316
4317 // If this is not the end of the statement, report an error.
4318 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4319 reportParseError("unexpected token, expected end of statement");
4320 return false;
4321 }
4322
4323 if (IDVal == ".mask")
4324 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4325 else
4326 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004327 return false;
4328 }
4329
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004330 if (IDVal == ".nan")
4331 return parseDirectiveNaN();
4332
Jack Carter07c818d2013-01-25 01:31:34 +00004333 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004334 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004335 return false;
4336 }
4337
Rafael Espindolab59fb732014-03-28 18:50:26 +00004338 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004339 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004340 return false;
4341 }
4342
Jack Carter07c818d2013-01-25 01:31:34 +00004343 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004344 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004345 return false;
4346 }
4347
Jack Carter0cd3c192014-01-06 23:27:31 +00004348 if (IDVal == ".option")
4349 return parseDirectiveOption();
4350
4351 if (IDVal == ".abicalls") {
4352 getTargetStreamer().emitDirectiveAbiCalls();
4353 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004354 Error(Parser.getTok().getLoc(),
4355 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004356 // Clear line
4357 Parser.eatToEndOfStatement();
4358 }
4359 return false;
4360 }
4361
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004362 if (IDVal == ".cpsetup")
4363 return parseDirectiveCPSetup();
4364
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004365 if (IDVal == ".module")
4366 return parseDirectiveModule();
4367
Rafael Espindola870c4e92012-01-11 03:56:41 +00004368 return true;
4369}
4370
Rafael Espindola870c4e92012-01-11 03:56:41 +00004371extern "C" void LLVMInitializeMipsAsmParser() {
4372 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4373 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4374 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4375 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4376}
Jack Carterb4dbc172012-09-05 23:34:03 +00004377
4378#define GET_REGISTER_MATCHER
4379#define GET_MATCHER_IMPLEMENTATION
4380#include "MipsGenAsmMatcher.inc"