blob: 7d02c542de425a0739c7a20176a38fcf7c1a100e [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);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001056 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001057 Op->StartLoc = StartLoc;
1058 Op->EndLoc = EndLoc;
1059 return Op;
1060 }
1061
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001062 static std::unique_ptr<MipsOperand>
1063 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1064 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1065 Op->RegIdx.Index = RegNo;
1066 Op->StartLoc = S;
1067 Op->EndLoc = E;
1068 return Op;
1069 }
1070
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 bool isGPRAsmReg() const {
1072 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001073 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001074 bool isMM16AsmReg() const {
1075 if (!(isRegIdx() && RegIdx.Kind))
1076 return false;
1077 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1078 || RegIdx.Index == 16 || RegIdx.Index == 17);
1079 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001080 bool isMM16AsmRegZero() const {
1081 if (!(isRegIdx() && RegIdx.Kind))
1082 return false;
1083 return (RegIdx.Index == 0 ||
1084 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1085 RegIdx.Index == 17);
1086 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001087 bool isMM16AsmRegMoveP() const {
1088 if (!(isRegIdx() && RegIdx.Kind))
1089 return false;
1090 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1091 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1092 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001093 bool isFGRAsmReg() const {
1094 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1095 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001096 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 bool isHWRegsAsmReg() const {
1098 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001099 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 bool isCCRAsmReg() const {
1101 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001102 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001104 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1105 return false;
1106 if (!AsmParser.hasEightFccRegisters())
1107 return RegIdx.Index == 0;
1108 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001109 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 bool isACCAsmReg() const {
1111 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001112 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 bool isCOP2AsmReg() const {
1114 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001115 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001116 bool isCOP3AsmReg() const {
1117 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1118 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001119 bool isMSA128AsmReg() const {
1120 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001121 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 bool isMSACtrlAsmReg() const {
1123 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001124 }
1125
Jack Carterb4dbc172012-09-05 23:34:03 +00001126 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001127 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001128 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001129 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001130
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001131 virtual ~MipsOperand() {
1132 switch (Kind) {
1133 case k_Immediate:
1134 break;
1135 case k_Memory:
1136 delete Mem.Base;
1137 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001138 case k_RegList:
1139 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001140 case k_PhysRegister:
1141 case k_RegisterIndex:
1142 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001143 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001144 break;
1145 }
1146 }
1147
Craig Topper56c590a2014-04-29 07:58:02 +00001148 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001149 switch (Kind) {
1150 case k_Immediate:
1151 OS << "Imm<";
1152 Imm.Val->print(OS);
1153 OS << ">";
1154 break;
1155 case k_Memory:
1156 OS << "Mem<";
1157 Mem.Base->print(OS);
1158 OS << ", ";
1159 Mem.Off->print(OS);
1160 OS << ">";
1161 break;
1162 case k_PhysRegister:
1163 OS << "PhysReg<" << PhysReg.Num << ">";
1164 break;
1165 case k_RegisterIndex:
1166 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1167 break;
1168 case k_Token:
1169 OS << Tok.Data;
1170 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001171 case k_RegList:
1172 OS << "RegList< ";
1173 for (auto Reg : (*RegList.List))
1174 OS << Reg << " ";
1175 OS << ">";
1176 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001177 case k_RegPair:
1178 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1179 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001181 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001182}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001183} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001184
Jack Carter9e65aa32013-03-22 00:05:30 +00001185namespace llvm {
1186extern const MCInstrDesc MipsInsts[];
1187}
1188static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1189 return MipsInsts[Opcode];
1190}
1191
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001192static bool hasShortDelaySlot(unsigned Opcode) {
1193 switch (Opcode) {
1194 case Mips::JALS_MM:
1195 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001196 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001197 case Mips::BGEZALS_MM:
1198 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001199 return true;
1200 default:
1201 return false;
1202 }
1203}
1204
Jack Carter9e65aa32013-03-22 00:05:30 +00001205bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001206 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001207 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001208
Jack Carter9e65aa32013-03-22 00:05:30 +00001209 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001210
1211 if (MCID.isBranch() || MCID.isCall()) {
1212 const unsigned Opcode = Inst.getOpcode();
1213 MCOperand Offset;
1214
1215 switch (Opcode) {
1216 default:
1217 break;
Kai Nackee0245392015-01-27 19:11:28 +00001218 case Mips::BBIT0:
1219 case Mips::BBIT032:
1220 case Mips::BBIT1:
1221 case Mips::BBIT132:
1222 assert(hasCnMips() && "instruction only valid for octeon cpus");
1223 // Fall through
1224
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001225 case Mips::BEQ:
1226 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 case Mips::BEQ_MM:
1228 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001229 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001230 Offset = Inst.getOperand(2);
1231 if (!Offset.isImm())
1232 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001233 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001234 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001235 if (OffsetToAlignment(Offset.getImm(),
1236 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001237 return Error(IDLoc, "branch to misaligned address");
1238 break;
1239 case Mips::BGEZ:
1240 case Mips::BGTZ:
1241 case Mips::BLEZ:
1242 case Mips::BLTZ:
1243 case Mips::BGEZAL:
1244 case Mips::BLTZAL:
1245 case Mips::BC1F:
1246 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 case Mips::BGEZ_MM:
1248 case Mips::BGTZ_MM:
1249 case Mips::BLEZ_MM:
1250 case Mips::BLTZ_MM:
1251 case Mips::BGEZAL_MM:
1252 case Mips::BLTZAL_MM:
1253 case Mips::BC1F_MM:
1254 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001255 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001256 Offset = Inst.getOperand(1);
1257 if (!Offset.isImm())
1258 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001259 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001260 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001261 if (OffsetToAlignment(Offset.getImm(),
1262 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001263 return Error(IDLoc, "branch to misaligned address");
1264 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001265 case Mips::BEQZ16_MM:
1266 case Mips::BNEZ16_MM:
1267 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1268 Offset = Inst.getOperand(1);
1269 if (!Offset.isImm())
1270 break; // We'll deal with this situation later on when applying fixups.
1271 if (!isIntN(8, Offset.getImm()))
1272 return Error(IDLoc, "branch target out of range");
1273 if (OffsetToAlignment(Offset.getImm(), 2LL))
1274 return Error(IDLoc, "branch to misaligned address");
1275 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001276 }
1277 }
1278
Daniel Sandersa84989a2014-06-16 13:25:35 +00001279 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1280 // We still accept it but it is a normal nop.
1281 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1282 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1283 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1284 "nop instruction");
1285 }
1286
Kai Nackee0245392015-01-27 19:11:28 +00001287 if (hasCnMips()) {
1288 const unsigned Opcode = Inst.getOpcode();
1289 MCOperand Opnd;
1290 int Imm;
1291
1292 switch (Opcode) {
1293 default:
1294 break;
1295
1296 case Mips::BBIT0:
1297 case Mips::BBIT032:
1298 case Mips::BBIT1:
1299 case Mips::BBIT132:
1300 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1301 // The offset is handled above
1302 Opnd = Inst.getOperand(1);
1303 if (!Opnd.isImm())
1304 return Error(IDLoc, "expected immediate operand kind");
1305 Imm = Opnd.getImm();
1306 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1307 Opcode == Mips::BBIT1 ? 63 : 31))
1308 return Error(IDLoc, "immediate operand value out of range");
1309 if (Imm > 31) {
1310 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1311 : Mips::BBIT132);
1312 Inst.getOperand(1).setImm(Imm - 32);
1313 }
1314 break;
1315
1316 case Mips::CINS:
1317 case Mips::CINS32:
1318 case Mips::EXTS:
1319 case Mips::EXTS32:
1320 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1321 // Check length
1322 Opnd = Inst.getOperand(3);
1323 if (!Opnd.isImm())
1324 return Error(IDLoc, "expected immediate operand kind");
1325 Imm = Opnd.getImm();
1326 if (Imm < 0 || Imm > 31)
1327 return Error(IDLoc, "immediate operand value out of range");
1328 // Check position
1329 Opnd = Inst.getOperand(2);
1330 if (!Opnd.isImm())
1331 return Error(IDLoc, "expected immediate operand kind");
1332 Imm = Opnd.getImm();
1333 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1334 Opcode == Mips::EXTS ? 63 : 31))
1335 return Error(IDLoc, "immediate operand value out of range");
1336 if (Imm > 31) {
1337 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1338 Inst.getOperand(2).setImm(Imm - 32);
1339 }
1340 break;
1341
1342 case Mips::SEQi:
1343 case Mips::SNEi:
1344 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1345 Opnd = Inst.getOperand(2);
1346 if (!Opnd.isImm())
1347 return Error(IDLoc, "expected immediate operand kind");
1348 Imm = Opnd.getImm();
1349 if (!isInt<10>(Imm))
1350 return Error(IDLoc, "immediate operand value out of range");
1351 break;
1352 }
1353 }
1354
Toma Tabacu9db22db2014-09-09 10:15:38 +00001355 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001356 // If this instruction has a delay slot and .set reorder is active,
1357 // emit a NOP after it.
1358 Instructions.push_back(Inst);
1359 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001360 if (hasShortDelaySlot(Inst.getOpcode())) {
1361 NopInst.setOpcode(Mips::MOVE16_MM);
1362 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1363 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1364 } else {
1365 NopInst.setOpcode(Mips::SLL);
1366 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1367 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1368 NopInst.addOperand(MCOperand::CreateImm(0));
1369 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001370 Instructions.push_back(NopInst);
1371 return false;
1372 }
1373
Jack Carter9e65aa32013-03-22 00:05:30 +00001374 if (MCID.mayLoad() || MCID.mayStore()) {
1375 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001376 // reference or immediate we may have to expand instructions.
1377 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001378 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001379 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1380 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001381 MCOperand &Op = Inst.getOperand(i);
1382 if (Op.isImm()) {
1383 int MemOffset = Op.getImm();
1384 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001385 // Offset can't exceed 16bit value.
1386 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001387 return false;
1388 }
1389 } else if (Op.isExpr()) {
1390 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001391 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001392 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001393 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001394 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001395 // Expand symbol.
1396 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001397 return false;
1398 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001399 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001401 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001402 }
1403 }
1404 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001406 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001407
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001408 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001409 if (MCID.mayLoad()) {
1410 // Try to create 16-bit GP relative load instruction.
1411 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1412 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1413 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1414 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1415 MCOperand &Op = Inst.getOperand(i);
1416 if (Op.isImm()) {
1417 int MemOffset = Op.getImm();
1418 MCOperand &DstReg = Inst.getOperand(0);
1419 MCOperand &BaseReg = Inst.getOperand(1);
1420 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1421 getContext().getRegisterInfo()->getRegClass(
1422 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1423 BaseReg.getReg() == Mips::GP) {
1424 MCInst TmpInst;
1425 TmpInst.setLoc(IDLoc);
1426 TmpInst.setOpcode(Mips::LWGP_MM);
1427 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1428 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1429 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1430 Instructions.push_back(TmpInst);
1431 return false;
1432 }
1433 }
1434 }
1435 } // for
1436 } // if load
1437
1438 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1439
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001440 MCOperand Opnd;
1441 int Imm;
1442
1443 switch (Inst.getOpcode()) {
1444 default:
1445 break;
1446 case Mips::ADDIUS5_MM:
1447 Opnd = Inst.getOperand(2);
1448 if (!Opnd.isImm())
1449 return Error(IDLoc, "expected immediate operand kind");
1450 Imm = Opnd.getImm();
1451 if (Imm < -8 || Imm > 7)
1452 return Error(IDLoc, "immediate operand value out of range");
1453 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001454 case Mips::ADDIUSP_MM:
1455 Opnd = Inst.getOperand(0);
1456 if (!Opnd.isImm())
1457 return Error(IDLoc, "expected immediate operand kind");
1458 Imm = Opnd.getImm();
1459 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1460 Imm % 4 != 0)
1461 return Error(IDLoc, "immediate operand value out of range");
1462 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001463 case Mips::SLL16_MM:
1464 case Mips::SRL16_MM:
1465 Opnd = Inst.getOperand(2);
1466 if (!Opnd.isImm())
1467 return Error(IDLoc, "expected immediate operand kind");
1468 Imm = Opnd.getImm();
1469 if (Imm < 1 || Imm > 8)
1470 return Error(IDLoc, "immediate operand value out of range");
1471 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001472 case Mips::LI16_MM:
1473 Opnd = Inst.getOperand(1);
1474 if (!Opnd.isImm())
1475 return Error(IDLoc, "expected immediate operand kind");
1476 Imm = Opnd.getImm();
1477 if (Imm < -1 || Imm > 126)
1478 return Error(IDLoc, "immediate operand value out of range");
1479 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001480 case Mips::ADDIUR2_MM:
1481 Opnd = Inst.getOperand(2);
1482 if (!Opnd.isImm())
1483 return Error(IDLoc, "expected immediate operand kind");
1484 Imm = Opnd.getImm();
1485 if (!(Imm == 1 || Imm == -1 ||
1486 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1487 return Error(IDLoc, "immediate operand value out of range");
1488 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001489 case Mips::ADDIUR1SP_MM:
1490 Opnd = Inst.getOperand(1);
1491 if (!Opnd.isImm())
1492 return Error(IDLoc, "expected immediate operand kind");
1493 Imm = Opnd.getImm();
1494 if (OffsetToAlignment(Imm, 4LL))
1495 return Error(IDLoc, "misaligned immediate operand value");
1496 if (Imm < 0 || Imm > 255)
1497 return Error(IDLoc, "immediate operand value out of range");
1498 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001499 case Mips::ANDI16_MM:
1500 Opnd = Inst.getOperand(2);
1501 if (!Opnd.isImm())
1502 return Error(IDLoc, "expected immediate operand kind");
1503 Imm = Opnd.getImm();
1504 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1505 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1506 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1507 return Error(IDLoc, "immediate operand value out of range");
1508 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001509 case Mips::LBU16_MM:
1510 Opnd = Inst.getOperand(2);
1511 if (!Opnd.isImm())
1512 return Error(IDLoc, "expected immediate operand kind");
1513 Imm = Opnd.getImm();
1514 if (Imm < -1 || Imm > 14)
1515 return Error(IDLoc, "immediate operand value out of range");
1516 break;
1517 case Mips::SB16_MM:
1518 Opnd = Inst.getOperand(2);
1519 if (!Opnd.isImm())
1520 return Error(IDLoc, "expected immediate operand kind");
1521 Imm = Opnd.getImm();
1522 if (Imm < 0 || Imm > 15)
1523 return Error(IDLoc, "immediate operand value out of range");
1524 break;
1525 case Mips::LHU16_MM:
1526 case Mips::SH16_MM:
1527 Opnd = Inst.getOperand(2);
1528 if (!Opnd.isImm())
1529 return Error(IDLoc, "expected immediate operand kind");
1530 Imm = Opnd.getImm();
1531 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1532 return Error(IDLoc, "immediate operand value out of range");
1533 break;
1534 case Mips::LW16_MM:
1535 case Mips::SW16_MM:
1536 Opnd = Inst.getOperand(2);
1537 if (!Opnd.isImm())
1538 return Error(IDLoc, "expected immediate operand kind");
1539 Imm = Opnd.getImm();
1540 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1541 return Error(IDLoc, "immediate operand value out of range");
1542 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001543 case Mips::CACHE:
1544 case Mips::PREF:
1545 Opnd = Inst.getOperand(2);
1546 if (!Opnd.isImm())
1547 return Error(IDLoc, "expected immediate operand kind");
1548 Imm = Opnd.getImm();
1549 if (!isUInt<5>(Imm))
1550 return Error(IDLoc, "immediate operand value out of range");
1551 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001552 case Mips::ADDIUPC_MM:
1553 MCOperand Opnd = Inst.getOperand(1);
1554 if (!Opnd.isImm())
1555 return Error(IDLoc, "expected immediate operand kind");
1556 int Imm = Opnd.getImm();
1557 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1558 return Error(IDLoc, "immediate operand value out of range");
1559 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001560 }
1561 }
1562
Jack Carter9e65aa32013-03-22 00:05:30 +00001563 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001564 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001565 else
1566 Instructions.push_back(Inst);
1567
1568 return false;
1569}
1570
Jack Carter30a59822012-10-04 04:03:53 +00001571bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1572
Jack Carterd0bd6422013-04-18 00:41:53 +00001573 switch (Inst.getOpcode()) {
1574 case Mips::LoadImm32Reg:
1575 case Mips::LoadAddr32Imm:
1576 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001577 case Mips::LoadImm64Reg:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001578 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001579 case Mips::LWM_MM:
1580 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001581 case Mips::JalOneReg:
1582 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001583 return true;
1584 default:
1585 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001586 }
1587}
Jack Carter92995f12012-10-06 00:53:28 +00001588
Matheus Almeida3813d572014-06-19 14:39:14 +00001589bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001590 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001591 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001592 default: llvm_unreachable("unimplemented expansion");
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 case Mips::LoadImm32Reg:
1594 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001595 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001596 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001597 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001598 return true;
1599 }
1600 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 case Mips::LoadAddr32Imm:
1602 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1603 case Mips::LoadAddr32Reg:
1604 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001605 case Mips::B_MM_Pseudo:
1606 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001607 case Mips::SWM_MM:
1608 case Mips::LWM_MM:
1609 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001610 case Mips::JalOneReg:
1611 case Mips::JalTwoReg:
1612 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001613 }
Jack Carter30a59822012-10-04 04:03:53 +00001614}
Jack Carter92995f12012-10-06 00:53:28 +00001615
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001616namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001617template <bool PerformShift>
1618void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001619 SmallVectorImpl<MCInst> &Instructions) {
1620 MCInst tmpInst;
1621 if (PerformShift) {
1622 tmpInst.setOpcode(Mips::DSLL);
1623 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1624 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1625 tmpInst.addOperand(MCOperand::CreateImm(16));
1626 tmpInst.setLoc(IDLoc);
1627 Instructions.push_back(tmpInst);
1628 tmpInst.clear();
1629 }
1630 tmpInst.setOpcode(Mips::ORi);
1631 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1632 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001633 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001634 tmpInst.setLoc(IDLoc);
1635 Instructions.push_back(tmpInst);
1636}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001637
1638template <int Shift, bool PerformShift>
1639void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1640 SmallVectorImpl<MCInst> &Instructions) {
1641 createShiftOr<PerformShift>(
1642 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1643 IDLoc, Instructions);
1644}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001645}
1646
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001647bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1648 SmallVectorImpl<MCInst> &Instructions) {
1649 // Create a JALR instruction which is going to replace the pseudo-JAL.
1650 MCInst JalrInst;
1651 JalrInst.setLoc(IDLoc);
1652 const MCOperand FirstRegOp = Inst.getOperand(0);
1653 const unsigned Opcode = Inst.getOpcode();
1654
1655 if (Opcode == Mips::JalOneReg) {
1656 // jal $rs => jalr $rs
1657 if (inMicroMipsMode()) {
1658 JalrInst.setOpcode(Mips::JALR16_MM);
1659 JalrInst.addOperand(FirstRegOp);
1660 } else {
1661 JalrInst.setOpcode(Mips::JALR);
1662 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1663 JalrInst.addOperand(FirstRegOp);
1664 }
1665 } else if (Opcode == Mips::JalTwoReg) {
1666 // jal $rd, $rs => jalr $rd, $rs
1667 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1668 JalrInst.addOperand(FirstRegOp);
1669 const MCOperand SecondRegOp = Inst.getOperand(1);
1670 JalrInst.addOperand(SecondRegOp);
1671 }
1672 Instructions.push_back(JalrInst);
1673
1674 // If .set reorder is active, emit a NOP after it.
1675 if (AssemblerOptions.back()->isReorder()) {
1676 // This is a 32-bit NOP because these 2 pseudo-instructions
1677 // do not have a short delay slot.
1678 MCInst NopInst;
1679 NopInst.setOpcode(Mips::SLL);
1680 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1681 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1682 NopInst.addOperand(MCOperand::CreateImm(0));
1683 Instructions.push_back(NopInst);
1684 }
1685
1686 return false;
1687}
1688
Matheus Almeida3813d572014-06-19 14:39:14 +00001689bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001690 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001691 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001692 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001693 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001694 const MCOperand &RegOp = Inst.getOperand(0);
1695 assert(RegOp.isReg() && "expected register operand kind");
1696
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001697 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001698 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001699 // FIXME: gas has a special case for values that are 000...1111, which
1700 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001701 if (0 <= ImmValue && ImmValue <= 65535) {
1702 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001703 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001704 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001705 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001706 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001707 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001708 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001709 } else if (ImmValue < 0 && ImmValue >= -32768) {
1710 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001711 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001712 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001713 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001715 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001716 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001717 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1718 // For any value of j that is representable as a 32-bit integer, create
1719 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001720 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001721 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001722 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001723 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1724 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001725 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001726 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1727 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001728 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001729 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001730 return true;
1731 }
1732
1733 // <------- lo32 ------>
1734 // <------- hi32 ------>
1735 // <- hi16 -> <- lo16 ->
1736 // _________________________________
1737 // | | | |
1738 // | 16-bytes | 16-bytes | 16-bytes |
1739 // |__________|__________|__________|
1740 //
1741 // For any value of j that is representable as a 48-bit integer, create
1742 // a sequence of:
1743 // li d,j => lui d,hi16(j)
1744 // ori d,d,hi16(lo32(j))
1745 // dsll d,d,16
1746 // ori d,d,lo16(lo32(j))
1747 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001748 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001749 tmpInst.addOperand(
1750 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001751 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001752 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1753 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1754 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001755 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001756 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001757 return true;
1758 }
1759
1760 // <------- hi32 ------> <------- lo32 ------>
1761 // <- hi16 -> <- lo16 ->
1762 // ___________________________________________
1763 // | | | | |
1764 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1765 // |__________|__________|__________|__________|
1766 //
1767 // For any value of j that isn't representable as a 48-bit integer.
1768 // li d,j => lui d,hi16(j)
1769 // ori d,d,lo16(hi32(j))
1770 // dsll d,d,16
1771 // ori d,d,hi16(lo32(j))
1772 // dsll d,d,16
1773 // ori d,d,lo16(lo32(j))
1774 tmpInst.setOpcode(Mips::LUi);
1775 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1776 tmpInst.addOperand(
1777 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1778 Instructions.push_back(tmpInst);
1779 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1780 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1781 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001782 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001783 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001784}
Jack Carter92995f12012-10-06 00:53:28 +00001785
Matheus Almeida3813d572014-06-19 14:39:14 +00001786bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001787MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1788 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001789 MCInst tmpInst;
1790 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001791 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1792 "expected immediate operand kind");
1793 if (!ImmOp.isImm()) {
1794 expandLoadAddressSym(Inst, IDLoc, Instructions);
1795 return false;
1796 }
Jack Carter543fdf82012-10-09 23:29:45 +00001797 const MCOperand &SrcRegOp = Inst.getOperand(1);
1798 assert(SrcRegOp.isReg() && "expected register operand kind");
1799 const MCOperand &DstRegOp = Inst.getOperand(0);
1800 assert(DstRegOp.isReg() && "expected register operand kind");
1801 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001802 if (-32768 <= ImmValue && ImmValue <= 65535) {
1803 // For -32768 <= j <= 65535.
1804 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001805 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001806 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1807 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1808 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1809 Instructions.push_back(tmpInst);
1810 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001811 // For any other value of j that is representable as a 32-bit integer.
1812 // la d,j(s) => lui d,hi16(j)
1813 // ori d,d,lo16(j)
1814 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001815 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001816 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1817 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1818 Instructions.push_back(tmpInst);
1819 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001820 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001821 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1822 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1823 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1824 Instructions.push_back(tmpInst);
1825 tmpInst.clear();
1826 tmpInst.setOpcode(Mips::ADDu);
1827 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1828 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1829 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1830 Instructions.push_back(tmpInst);
1831 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001832 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001833}
1834
Matheus Almeida3813d572014-06-19 14:39:14 +00001835bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001836MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1837 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001838 MCInst tmpInst;
1839 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001840 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1841 "expected immediate operand kind");
1842 if (!ImmOp.isImm()) {
1843 expandLoadAddressSym(Inst, IDLoc, Instructions);
1844 return false;
1845 }
Jack Carter543fdf82012-10-09 23:29:45 +00001846 const MCOperand &RegOp = Inst.getOperand(0);
1847 assert(RegOp.isReg() && "expected register operand kind");
1848 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001849 if (-32768 <= ImmValue && ImmValue <= 65535) {
1850 // For -32768 <= j <= 65535.
1851 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001852 tmpInst.setOpcode(Mips::ADDiu);
1853 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001854 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001855 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1856 Instructions.push_back(tmpInst);
1857 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 // For any other value of j that is representable as a 32-bit integer.
1859 // la d,j => lui d,hi16(j)
1860 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001861 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001862 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1863 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1864 Instructions.push_back(tmpInst);
1865 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001866 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001867 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1868 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1869 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1870 Instructions.push_back(tmpInst);
1871 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001872 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001873}
1874
Toma Tabacu0d64b202014-08-14 10:29:17 +00001875void
1876MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1877 SmallVectorImpl<MCInst> &Instructions) {
1878 // FIXME: If we do have a valid at register to use, we should generate a
1879 // slightly shorter sequence here.
1880 MCInst tmpInst;
1881 int ExprOperandNo = 1;
1882 // Sometimes the assembly parser will get the immediate expression as
1883 // a $zero + an immediate.
1884 if (Inst.getNumOperands() == 3) {
1885 assert(Inst.getOperand(1).getReg() ==
1886 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1887 ExprOperandNo = 2;
1888 }
1889 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1890 assert(SymOp.isExpr() && "expected symbol operand kind");
1891 const MCOperand &RegOp = Inst.getOperand(0);
1892 unsigned RegNo = RegOp.getReg();
1893 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1894 const MCSymbolRefExpr *HiExpr =
1895 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1896 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1897 const MCSymbolRefExpr *LoExpr =
1898 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1899 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1900 if (isGP64bit()) {
1901 // If it's a 64-bit architecture, expand to:
1902 // la d,sym => lui d,highest(sym)
1903 // ori d,d,higher(sym)
1904 // dsll d,d,16
1905 // ori d,d,hi16(sym)
1906 // dsll d,d,16
1907 // ori d,d,lo16(sym)
1908 const MCSymbolRefExpr *HighestExpr =
1909 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1910 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1911 const MCSymbolRefExpr *HigherExpr =
1912 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1913 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1914
1915 tmpInst.setOpcode(Mips::LUi);
1916 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1917 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1918 Instructions.push_back(tmpInst);
1919
1920 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1921 Instructions);
1922 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1923 Instructions);
1924 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1925 Instructions);
1926 } else {
1927 // Otherwise, expand to:
1928 // la d,sym => lui d,hi16(sym)
1929 // ori d,d,lo16(sym)
1930 tmpInst.setOpcode(Mips::LUi);
1931 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1932 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1933 Instructions.push_back(tmpInst);
1934
1935 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1936 Instructions);
1937 }
1938}
1939
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001940bool MipsAsmParser::expandUncondBranchMMPseudo(
1941 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001942 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1943 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001944
1945 MCOperand Offset = Inst.getOperand(0);
1946 if (Offset.isExpr()) {
1947 Inst.clear();
1948 Inst.setOpcode(Mips::BEQ_MM);
1949 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1950 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1951 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1952 } else {
1953 assert(Offset.isImm() && "expected immediate operand kind");
1954 if (isIntN(11, Offset.getImm())) {
1955 // If offset fits into 11 bits then this instruction becomes microMIPS
1956 // 16-bit unconditional branch instruction.
1957 Inst.setOpcode(Mips::B16_MM);
1958 } else {
1959 if (!isIntN(17, Offset.getImm()))
1960 Error(IDLoc, "branch target out of range");
1961 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1962 Error(IDLoc, "branch to misaligned address");
1963 Inst.clear();
1964 Inst.setOpcode(Mips::BEQ_MM);
1965 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1966 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1967 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1968 }
1969 }
1970 Instructions.push_back(Inst);
1971
1972 if (AssemblerOptions.back()->isReorder()) {
1973 // If .set reorder is active, emit a NOP after the branch instruction.
1974 MCInst NopInst;
1975 NopInst.setOpcode(Mips::MOVE16_MM);
1976 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1977 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1978 Instructions.push_back(NopInst);
1979 }
1980 return false;
1981}
1982
Jack Carter9e65aa32013-03-22 00:05:30 +00001983void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001984 SmallVectorImpl<MCInst> &Instructions,
1985 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001986 const MCSymbolRefExpr *SR;
1987 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001988 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001989 const MCExpr *ExprOffset;
1990 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001991 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001992 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1993 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001994 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001995 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1996 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001997 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001998 if (isImmOpnd) {
1999 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2000 ImmOffset = Inst.getOperand(2).getImm();
2001 LoOffset = ImmOffset & 0x0000ffff;
2002 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002003 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002004 if (LoOffset & 0x8000)
2005 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002006 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002007 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002008 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002009 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002010 // These are some of the types of expansions we perform here:
2011 // 1) lw $8, sym => lui $8, %hi(sym)
2012 // lw $8, %lo(sym)($8)
2013 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2014 // add $8, $8, $9
2015 // lw $8, %lo(offset)($9)
2016 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2017 // add $at, $at, $8
2018 // lw $8, %lo(offset)($at)
2019 // 4) sw $8, sym => lui $at, %hi(sym)
2020 // sw $8, %lo(sym)($at)
2021 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2022 // add $at, $at, $8
2023 // sw $8, %lo(offset)($at)
2024 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2025 // ldc1 $f0, %lo(sym)($at)
2026 //
2027 // For load instructions we can use the destination register as a temporary
2028 // if base and dst are different (examples 1 and 2) and if the base register
2029 // is general purpose otherwise we must use $at (example 6) and error if it's
2030 // not available. For stores we must use $at (examples 4 and 5) because we
2031 // must not clobber the source register setting up the offset.
2032 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2033 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2034 unsigned RegClassIDOp0 =
2035 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2036 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2037 (RegClassIDOp0 == Mips::GPR64RegClassID);
2038 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002039 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002040 else {
2041 int AT = getATReg(IDLoc);
2042 // At this point we need AT to perform the expansions and we exit if it is
2043 // not available.
2044 if (!AT)
2045 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002046 TmpRegNum = getReg(
2047 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002048 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002049
Jack Carter9e65aa32013-03-22 00:05:30 +00002050 TempInst.setOpcode(Mips::LUi);
2051 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2052 if (isImmOpnd)
2053 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2054 else {
2055 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002056 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002057 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2058 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2059 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002060 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002061 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002062 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002063 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002064 }
2065 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002066 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002067 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002068 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002069 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002070 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002071 TempInst.setOpcode(Mips::ADDu);
2072 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2073 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2074 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2075 Instructions.push_back(TempInst);
2076 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00002077 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002078 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 TempInst.setOpcode(Inst.getOpcode());
2080 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2081 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2082 if (isImmOpnd)
2083 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2084 else {
2085 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2087 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2088 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002089 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002090 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002092 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002093 }
2094 }
2095 Instructions.push_back(TempInst);
2096 TempInst.clear();
2097}
2098
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002099bool
2100MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2101 SmallVectorImpl<MCInst> &Instructions) {
2102 unsigned OpNum = Inst.getNumOperands();
2103 unsigned Opcode = Inst.getOpcode();
2104 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2105
2106 assert (Inst.getOperand(OpNum - 1).isImm() &&
2107 Inst.getOperand(OpNum - 2).isReg() &&
2108 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2109
2110 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2111 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2112 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2113 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2114 // It can be implemented as SWM16 or LWM16 instruction.
2115 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2116
2117 Inst.setOpcode(NewOpcode);
2118 Instructions.push_back(Inst);
2119 return false;
2120}
2121
Matheus Almeida595fcab2014-06-11 15:05:56 +00002122unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2123 // As described by the Mips32r2 spec, the registers Rd and Rs for
2124 // jalr.hb must be different.
2125 unsigned Opcode = Inst.getOpcode();
2126
2127 if (Opcode == Mips::JALR_HB &&
2128 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2129 return Match_RequiresDifferentSrcAndDst;
2130
2131 return Match_Success;
2132}
2133
David Blaikie960ea3f2014-06-08 16:18:35 +00002134bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2135 OperandVector &Operands,
2136 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002137 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002138 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002139
Jack Carterb4dbc172012-09-05 23:34:03 +00002140 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002141 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002142 unsigned MatchResult =
2143 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002144
2145 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002146 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002147 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002148 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002149 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002150 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002151 return false;
2152 }
2153 case Match_MissingFeature:
2154 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2155 return true;
2156 case Match_InvalidOperand: {
2157 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002158 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002159 if (ErrorInfo >= Operands.size())
2160 return Error(IDLoc, "too few operands for instruction");
2161
David Blaikie960ea3f2014-06-08 16:18:35 +00002162 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 if (ErrorLoc == SMLoc())
2164 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002165 }
2166
2167 return Error(ErrorLoc, "invalid operand for instruction");
2168 }
2169 case Match_MnemonicFail:
2170 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002171 case Match_RequiresDifferentSrcAndDst:
2172 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002173 }
Craig Topper589ceee2015-01-03 08:16:34 +00002174
2175 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002176}
2177
Toma Tabacu13964452014-09-04 13:23:44 +00002178void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002179 if ((RegIndex != 0) &&
2180 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002181 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002182 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002183 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002184 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002185 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002186 }
2187}
2188
Daniel Sandersef638fe2014-10-03 15:37:37 +00002189void
2190MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2191 SMRange Range, bool ShowColors) {
2192 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002193 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002194 ShowColors);
2195}
2196
Jack Carter1ac53222013-02-20 23:11:17 +00002197int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002198 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002199
Vladimir Medic4c299852013-11-06 11:27:05 +00002200 CC = StringSwitch<unsigned>(Name)
2201 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002202 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002203 .Case("a0", 4)
2204 .Case("a1", 5)
2205 .Case("a2", 6)
2206 .Case("a3", 7)
2207 .Case("v0", 2)
2208 .Case("v1", 3)
2209 .Case("s0", 16)
2210 .Case("s1", 17)
2211 .Case("s2", 18)
2212 .Case("s3", 19)
2213 .Case("s4", 20)
2214 .Case("s5", 21)
2215 .Case("s6", 22)
2216 .Case("s7", 23)
2217 .Case("k0", 26)
2218 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002219 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002220 .Case("sp", 29)
2221 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002222 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002223 .Case("ra", 31)
2224 .Case("t0", 8)
2225 .Case("t1", 9)
2226 .Case("t2", 10)
2227 .Case("t3", 11)
2228 .Case("t4", 12)
2229 .Case("t5", 13)
2230 .Case("t6", 14)
2231 .Case("t7", 15)
2232 .Case("t8", 24)
2233 .Case("t9", 25)
2234 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002235
Toma Tabacufda445c2014-09-15 15:33:01 +00002236 if (!(isABI_N32() || isABI_N64()))
2237 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002238
Daniel Sandersef638fe2014-10-03 15:37:37 +00002239 if (12 <= CC && CC <= 15) {
2240 // Name is one of t4-t7
2241 AsmToken RegTok = getLexer().peekTok();
2242 SMRange RegRange = RegTok.getLocRange();
2243
2244 StringRef FixedName = StringSwitch<StringRef>(Name)
2245 .Case("t4", "t0")
2246 .Case("t5", "t1")
2247 .Case("t6", "t2")
2248 .Case("t7", "t3")
2249 .Default("");
2250 assert(FixedName != "" && "Register name is not one of t4-t7.");
2251
2252 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2253 "Did you mean $" + FixedName + "?", RegRange);
2254 }
2255
Toma Tabacufda445c2014-09-15 15:33:01 +00002256 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2257 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2258 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2259 if (8 <= CC && CC <= 11)
2260 CC += 4;
2261
2262 if (CC == -1)
2263 CC = StringSwitch<unsigned>(Name)
2264 .Case("a4", 8)
2265 .Case("a5", 9)
2266 .Case("a6", 10)
2267 .Case("a7", 11)
2268 .Case("kt0", 26)
2269 .Case("kt1", 27)
2270 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002271
2272 return CC;
2273}
Jack Carterd0bd6422013-04-18 00:41:53 +00002274
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002275int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2276 int CC;
2277
2278 CC = StringSwitch<unsigned>(Name)
2279 .Case("hwr_cpunum", 0)
2280 .Case("hwr_synci_step", 1)
2281 .Case("hwr_cc", 2)
2282 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002283 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002284 .Default(-1);
2285
2286 return CC;
2287}
2288
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002289int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002290
Jack Cartera63b16a2012-09-07 00:23:42 +00002291 if (Name[0] == 'f') {
2292 StringRef NumString = Name.substr(1);
2293 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002294 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002295 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002296 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002297 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002298 return IntVal;
2299 }
2300 return -1;
2301}
Jack Cartera63b16a2012-09-07 00:23:42 +00002302
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002303int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2304
2305 if (Name.startswith("fcc")) {
2306 StringRef NumString = Name.substr(3);
2307 unsigned IntVal;
2308 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002309 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002310 if (IntVal > 7) // There are only 8 fcc registers.
2311 return -1;
2312 return IntVal;
2313 }
2314 return -1;
2315}
2316
2317int MipsAsmParser::matchACRegisterName(StringRef Name) {
2318
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002319 if (Name.startswith("ac")) {
2320 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002321 unsigned IntVal;
2322 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002323 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002324 if (IntVal > 3) // There are only 3 acc registers.
2325 return -1;
2326 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002327 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002328 return -1;
2329}
Jack Carterd0bd6422013-04-18 00:41:53 +00002330
Jack Carter5dc8ac92013-09-25 23:50:44 +00002331int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2332 unsigned IntVal;
2333
2334 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2335 return -1;
2336
2337 if (IntVal > 31)
2338 return -1;
2339
2340 return IntVal;
2341}
2342
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002343int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2344 int CC;
2345
2346 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002347 .Case("msair", 0)
2348 .Case("msacsr", 1)
2349 .Case("msaaccess", 2)
2350 .Case("msasave", 3)
2351 .Case("msamodify", 4)
2352 .Case("msarequest", 5)
2353 .Case("msamap", 6)
2354 .Case("msaunmap", 7)
2355 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002356
2357 return CC;
2358}
2359
Jack Carter0b744b32012-10-04 02:29:46 +00002360bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2361 if (Reg > 31)
2362 return false;
2363
Toma Tabacu3c24b042014-09-05 15:43:21 +00002364 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002365 return true;
2366}
2367
Matheus Almeida7de68e72014-06-18 14:46:05 +00002368int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002369 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002370 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002371 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002372 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002373 return AT;
2374}
Jack Carter0b744b32012-10-04 02:29:46 +00002375
Jack Carterd0bd6422013-04-18 00:41:53 +00002376unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002377 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002378}
2379
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002380unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002381 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002382 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002383}
2384
Jack Carter873c7242013-01-12 01:03:14 +00002385int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002386 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002387 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002388 return -1;
2389
Jack Carter873c7242013-01-12 01:03:14 +00002390 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002391}
2392
Toma Tabacu13964452014-09-04 13:23:44 +00002393bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002394 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002395 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002396
Jack Carter30a59822012-10-04 04:03:53 +00002397 // Check if the current operand has a custom associated parser, if so, try to
2398 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002399 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2400 if (ResTy == MatchOperand_Success)
2401 return false;
2402 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2403 // there was a match, but an error occurred, in which case, just return that
2404 // the operand parsing failed.
2405 if (ResTy == MatchOperand_ParseFail)
2406 return true;
2407
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002408 DEBUG(dbgs() << ".. Generic Parser\n");
2409
Jack Carterb4dbc172012-09-05 23:34:03 +00002410 switch (getLexer().getKind()) {
2411 default:
2412 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2413 return true;
2414 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002415 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002416 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002417
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002418 // Almost all registers have been parsed by custom parsers. There is only
2419 // one exception to this. $zero (and it's alias $0) will reach this point
2420 // for div, divu, and similar instructions because it is not an operand
2421 // to the instruction definition but an explicit register. Special case
2422 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002423 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002424 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002425
Jack Carterd0bd6422013-04-18 00:41:53 +00002426 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002427 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002428 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002429 return true;
2430
Jack Carter873c7242013-01-12 01:03:14 +00002431 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002432 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002433 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002434 const MCExpr *Res =
2435 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002436
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002437 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002438 return false;
2439 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002440 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002441 case AsmToken::LParen:
2442 case AsmToken::Minus:
2443 case AsmToken::Plus:
2444 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002445 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002446 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002448 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002449 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002450 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002451 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002452 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002453 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002454 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002455 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002456 return true;
2457
Jack Carter873c7242013-01-12 01:03:14 +00002458 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2459
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002460 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002461 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002462 } // case AsmToken::Percent
2463 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002464 return true;
2465}
2466
Vladimir Medic4c299852013-11-06 11:27:05 +00002467const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002468 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002469 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002470 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002471 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002472 // It's a constant, evaluate reloc value.
2473 int16_t Val;
2474 switch (getVariantKind(RelocStr)) {
2475 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2476 // Get the 1st 16-bits.
2477 Val = MCE->getValue() & 0xffff;
2478 break;
2479 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2480 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2481 // 16 bits being negative.
2482 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2483 break;
2484 case MCSymbolRefExpr::VK_Mips_HIGHER:
2485 // Get the 3rd 16-bits.
2486 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2487 break;
2488 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2489 // Get the 4th 16-bits.
2490 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2491 break;
2492 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002493 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002494 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002495 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002496 }
2497
Jack Carterb5cf5902013-04-17 00:18:04 +00002498 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002499 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002500 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002501 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002502 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002503 return Res;
2504 }
2505
2506 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002507 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2508
Sasa Stankovic06c47802014-04-03 10:37:45 +00002509 // Try to create target expression.
2510 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2511 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002512
Jack Carterd0bd6422013-04-18 00:41:53 +00002513 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2514 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002515 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2516 return Res;
2517 }
2518
2519 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2521 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2522 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002523 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002524 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002525 return Expr;
2526}
2527
2528bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2529
2530 switch (Expr->getKind()) {
2531 case MCExpr::Constant:
2532 return true;
2533 case MCExpr::SymbolRef:
2534 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2535 case MCExpr::Binary:
2536 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2537 if (!isEvaluated(BE->getLHS()))
2538 return false;
2539 return isEvaluated(BE->getRHS());
2540 }
2541 case MCExpr::Unary:
2542 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002543 case MCExpr::Target:
2544 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002545 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002546 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002547}
Jack Carterd0bd6422013-04-18 00:41:53 +00002548
Jack Carterb5cf5902013-04-17 00:18:04 +00002549bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002550 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002551 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002553 if (Tok.isNot(AsmToken::Identifier))
2554 return true;
2555
2556 std::string Str = Tok.getIdentifier().str();
2557
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 Parser.Lex(); // Eat the identifier.
2559 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002560 const MCExpr *IdVal;
2561 SMLoc EndLoc;
2562
2563 if (getLexer().getKind() == AsmToken::LParen) {
2564 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002566 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002568 const AsmToken &nextTok = Parser.getTok();
2569 if (nextTok.isNot(AsmToken::Identifier))
2570 return true;
2571 Str += "(%";
2572 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002573 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002574 if (getLexer().getKind() != AsmToken::LParen)
2575 return true;
2576 } else
2577 break;
2578 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002579 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002580 return true;
2581
2582 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002583 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002584
2585 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002587
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002589 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002590}
2591
Jack Carterb4dbc172012-09-05 23:34:03 +00002592bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2593 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002594 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002595 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002596 if (ResTy == MatchOperand_Success) {
2597 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002598 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002599 StartLoc = Operand.getStartLoc();
2600 EndLoc = Operand.getEndLoc();
2601
2602 // AFAIK, we only support numeric registers and named GPR's in CFI
2603 // directives.
2604 // Don't worry about eating tokens before failing. Using an unrecognised
2605 // register is a parse error.
2606 if (Operand.isGPRAsmReg()) {
2607 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002608 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002609 }
2610
2611 return (RegNo == (unsigned)-1);
2612 }
2613
2614 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002615 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002616}
2617
Jack Carterb5cf5902013-04-17 00:18:04 +00002618bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002619 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002620 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002621 bool Result = true;
2622
2623 while (getLexer().getKind() == AsmToken::LParen)
2624 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002625
Jack Carterd0bd6422013-04-18 00:41:53 +00002626 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002627 default:
2628 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002629 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002630 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002631 case AsmToken::Integer:
2632 case AsmToken::Minus:
2633 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002634 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002635 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002636 else
2637 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002638 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002639 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002640 break;
Jack Carter873c7242013-01-12 01:03:14 +00002641 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002642 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002643 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002644 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002645}
2646
David Blaikie960ea3f2014-06-08 16:18:35 +00002647MipsAsmParser::OperandMatchResultTy
2648MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002649 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002650 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002651 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002652 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002653 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002654 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002655 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002656 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002657
Jack Carterb5cf5902013-04-17 00:18:04 +00002658 if (getLexer().getKind() == AsmToken::LParen) {
2659 Parser.Lex();
2660 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002661 }
2662
Jack Carterb5cf5902013-04-17 00:18:04 +00002663 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002664 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002665 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002666
Jack Carterd0bd6422013-04-18 00:41:53 +00002667 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002668 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002669 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2670 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002671 SMLoc E =
2672 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002673 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002674 return MatchOperand_Success;
2675 }
2676 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002677 SMLoc E =
2678 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002679
Jack Carterd0bd6422013-04-18 00:41:53 +00002680 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002681 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002682 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002683 S, E, *this);
2684 Operands.push_back(
2685 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002686 return MatchOperand_Success;
2687 }
2688 Error(Parser.getTok().getLoc(), "'(' expected");
2689 return MatchOperand_ParseFail;
2690 }
2691
Jack Carterd0bd6422013-04-18 00:41:53 +00002692 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002693 }
2694
Toma Tabacu13964452014-09-04 13:23:44 +00002695 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002696 if (Res != MatchOperand_Success)
2697 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002698
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002699 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002700 Error(Parser.getTok().getLoc(), "')' expected");
2701 return MatchOperand_ParseFail;
2702 }
2703
Jack Carter873c7242013-01-12 01:03:14 +00002704 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2705
Jack Carterd0bd6422013-04-18 00:41:53 +00002706 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002707
Craig Topper062a2ba2014-04-25 05:30:21 +00002708 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002709 IdVal = MCConstantExpr::Create(0, getContext());
2710
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002712 std::unique_ptr<MipsOperand> op(
2713 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002714 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002715 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002716 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002717 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002718 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2719 int64_t Imm;
2720 if (IdVal->EvaluateAsAbsolute(Imm))
2721 IdVal = MCConstantExpr::Create(Imm, getContext());
2722 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2723 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2724 getContext());
2725 }
2726
David Blaikie960ea3f2014-06-08 16:18:35 +00002727 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002728 return MatchOperand_Success;
2729}
2730
David Blaikie960ea3f2014-06-08 16:18:35 +00002731bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002732 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002733 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2734 if (Sym) {
2735 SMLoc S = Parser.getTok().getLoc();
2736 const MCExpr *Expr;
2737 if (Sym->isVariable())
2738 Expr = Sym->getVariableValue();
2739 else
2740 return false;
2741 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002742 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002743 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002744 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002745 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002746 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002747 if (ResTy == MatchOperand_Success) {
2748 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002749 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002750 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002751 llvm_unreachable("Should never ParseFail");
2752 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002753 }
2754 } else if (Expr->getKind() == MCExpr::Constant) {
2755 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002756 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002757 Operands.push_back(
2758 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002759 return true;
2760 }
2761 }
2762 return false;
2763}
Jack Carterd0bd6422013-04-18 00:41:53 +00002764
Jack Carter873c7242013-01-12 01:03:14 +00002765MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002766MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002767 StringRef Identifier,
2768 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002769 int Index = matchCPURegisterName(Identifier);
2770 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002771 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002772 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2773 return MatchOperand_Success;
2774 }
2775
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002776 Index = matchHWRegsRegisterName(Identifier);
2777 if (Index != -1) {
2778 Operands.push_back(MipsOperand::createHWRegsReg(
2779 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2780 return MatchOperand_Success;
2781 }
2782
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002783 Index = matchFPURegisterName(Identifier);
2784 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002785 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002786 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2787 return MatchOperand_Success;
2788 }
2789
2790 Index = matchFCCRegisterName(Identifier);
2791 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002792 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002793 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2794 return MatchOperand_Success;
2795 }
2796
2797 Index = matchACRegisterName(Identifier);
2798 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002799 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002800 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2801 return MatchOperand_Success;
2802 }
2803
2804 Index = matchMSA128RegisterName(Identifier);
2805 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002806 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002807 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2808 return MatchOperand_Success;
2809 }
2810
2811 Index = matchMSA128CtrlRegisterName(Identifier);
2812 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002813 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002814 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2815 return MatchOperand_Success;
2816 }
2817
2818 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002819}
2820
2821MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002822MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002823 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002824 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002825
2826 if (Token.is(AsmToken::Identifier)) {
2827 DEBUG(dbgs() << ".. identifier\n");
2828 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002829 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002830 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002831 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002832 } else if (Token.is(AsmToken::Integer)) {
2833 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002834 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002835 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2836 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002837 return MatchOperand_Success;
2838 }
2839
2840 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2841
2842 return MatchOperand_NoMatch;
2843}
2844
David Blaikie960ea3f2014-06-08 16:18:35 +00002845MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002846MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002847 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002848 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002849
2850 auto Token = Parser.getTok();
2851
2852 SMLoc S = Token.getLoc();
2853
2854 if (Token.isNot(AsmToken::Dollar)) {
2855 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2856 if (Token.is(AsmToken::Identifier)) {
2857 if (searchSymbolAlias(Operands))
2858 return MatchOperand_Success;
2859 }
2860 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2861 return MatchOperand_NoMatch;
2862 }
2863 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002864
Toma Tabacu13964452014-09-04 13:23:44 +00002865 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002866 if (ResTy == MatchOperand_Success) {
2867 Parser.Lex(); // $
2868 Parser.Lex(); // identifier
2869 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002870 return ResTy;
2871}
2872
2873MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002874MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002875 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002876 switch (getLexer().getKind()) {
2877 default:
2878 return MatchOperand_NoMatch;
2879 case AsmToken::LParen:
2880 case AsmToken::Minus:
2881 case AsmToken::Plus:
2882 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002883 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002884 case AsmToken::String:
2885 break;
2886 }
2887
2888 const MCExpr *IdVal;
2889 SMLoc S = Parser.getTok().getLoc();
2890 if (getParser().parseExpression(IdVal))
2891 return MatchOperand_ParseFail;
2892
2893 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2894 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2895 return MatchOperand_Success;
2896}
2897
David Blaikie960ea3f2014-06-08 16:18:35 +00002898MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002899MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002900 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002901 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002902
2903 SMLoc S = getLexer().getLoc();
2904
2905 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002906 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002907 if (ResTy != MatchOperand_NoMatch)
2908 return ResTy;
2909
Daniel Sanders315386c2014-04-01 10:40:14 +00002910 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002911 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002912 if (ResTy != MatchOperand_NoMatch)
2913 return ResTy;
2914
Daniel Sandersffd84362014-04-01 10:41:48 +00002915 const MCExpr *Expr = nullptr;
2916 if (Parser.parseExpression(Expr)) {
2917 // We have no way of knowing if a symbol was consumed so we must ParseFail
2918 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002919 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002920 Operands.push_back(
2921 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002923}
2924
Vladimir Medic2b953d02013-10-01 09:48:56 +00002925MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002926MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002927 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002928 const MCExpr *IdVal;
2929 // If the first token is '$' we may have register operand.
2930 if (Parser.getTok().is(AsmToken::Dollar))
2931 return MatchOperand_NoMatch;
2932 SMLoc S = Parser.getTok().getLoc();
2933 if (getParser().parseExpression(IdVal))
2934 return MatchOperand_ParseFail;
2935 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002936 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002937 int64_t Val = MCE->getValue();
2938 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2939 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002940 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002941 return MatchOperand_Success;
2942}
2943
Matheus Almeida779c5932013-11-18 12:32:49 +00002944MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002945MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002946 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002947 switch (getLexer().getKind()) {
2948 default:
2949 return MatchOperand_NoMatch;
2950 case AsmToken::LParen:
2951 case AsmToken::Plus:
2952 case AsmToken::Minus:
2953 case AsmToken::Integer:
2954 break;
2955 }
2956
2957 const MCExpr *Expr;
2958 SMLoc S = Parser.getTok().getLoc();
2959
2960 if (getParser().parseExpression(Expr))
2961 return MatchOperand_ParseFail;
2962
2963 int64_t Val;
2964 if (!Expr->EvaluateAsAbsolute(Val)) {
2965 Error(S, "expected immediate value");
2966 return MatchOperand_ParseFail;
2967 }
2968
2969 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2970 // and because the CPU always adds one to the immediate field, the allowed
2971 // range becomes 1..4. We'll only check the range here and will deal
2972 // with the addition/subtraction when actually decoding/encoding
2973 // the instruction.
2974 if (Val < 1 || Val > 4) {
2975 Error(S, "immediate not in range (1..4)");
2976 return MatchOperand_ParseFail;
2977 }
2978
Jack Carter3b2c96e2014-01-22 23:31:38 +00002979 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002980 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002981 return MatchOperand_Success;
2982}
2983
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002984MipsAsmParser::OperandMatchResultTy
2985MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2986 MCAsmParser &Parser = getParser();
2987 SmallVector<unsigned, 10> Regs;
2988 unsigned RegNo;
2989 unsigned PrevReg = Mips::NoRegister;
2990 bool RegRange = false;
2991 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2992
2993 if (Parser.getTok().isNot(AsmToken::Dollar))
2994 return MatchOperand_ParseFail;
2995
2996 SMLoc S = Parser.getTok().getLoc();
2997 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2998 SMLoc E = getLexer().getLoc();
2999 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3000 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3001 if (RegRange) {
3002 // Remove last register operand because registers from register range
3003 // should be inserted first.
3004 if (RegNo == Mips::RA) {
3005 Regs.push_back(RegNo);
3006 } else {
3007 unsigned TmpReg = PrevReg + 1;
3008 while (TmpReg <= RegNo) {
3009 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3010 Error(E, "invalid register operand");
3011 return MatchOperand_ParseFail;
3012 }
3013
3014 PrevReg = TmpReg;
3015 Regs.push_back(TmpReg++);
3016 }
3017 }
3018
3019 RegRange = false;
3020 } else {
3021 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3022 (RegNo != Mips::RA)) {
3023 Error(E, "$16 or $31 expected");
3024 return MatchOperand_ParseFail;
3025 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3026 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3027 Error(E, "invalid register operand");
3028 return MatchOperand_ParseFail;
3029 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3030 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3031 Error(E, "consecutive register numbers expected");
3032 return MatchOperand_ParseFail;
3033 }
3034
3035 Regs.push_back(RegNo);
3036 }
3037
3038 if (Parser.getTok().is(AsmToken::Minus))
3039 RegRange = true;
3040
3041 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3042 !Parser.getTok().isNot(AsmToken::Comma)) {
3043 Error(E, "',' or '-' expected");
3044 return MatchOperand_ParseFail;
3045 }
3046
3047 Lex(); // Consume comma or minus
3048 if (Parser.getTok().isNot(AsmToken::Dollar))
3049 break;
3050
3051 PrevReg = RegNo;
3052 }
3053
3054 SMLoc E = Parser.getTok().getLoc();
3055 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3056 parseMemOperand(Operands);
3057 return MatchOperand_Success;
3058}
3059
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003060MipsAsmParser::OperandMatchResultTy
3061MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3062 MCAsmParser &Parser = getParser();
3063
3064 SMLoc S = Parser.getTok().getLoc();
3065 if (parseAnyRegister(Operands) != MatchOperand_Success)
3066 return MatchOperand_ParseFail;
3067
3068 SMLoc E = Parser.getTok().getLoc();
3069 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3070 unsigned Reg = Op.getGPR32Reg();
3071 Operands.pop_back();
3072 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3073 return MatchOperand_Success;
3074}
3075
Zoran Jovanovic41688672015-02-10 16:36:20 +00003076MipsAsmParser::OperandMatchResultTy
3077MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3078 MCAsmParser &Parser = getParser();
3079 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3080 SmallVector<unsigned, 10> Regs;
3081
3082 if (Parser.getTok().isNot(AsmToken::Dollar))
3083 return MatchOperand_ParseFail;
3084
3085 SMLoc S = Parser.getTok().getLoc();
3086
3087 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3088 return MatchOperand_ParseFail;
3089
3090 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3091 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3092 Regs.push_back(RegNo);
3093
3094 SMLoc E = Parser.getTok().getLoc();
3095 if (Parser.getTok().isNot(AsmToken::Comma)) {
3096 Error(E, "',' expected");
3097 return MatchOperand_ParseFail;
3098 }
3099
3100 // Remove comma.
3101 Parser.Lex();
3102
3103 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3104 return MatchOperand_ParseFail;
3105
3106 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3107 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3108 Regs.push_back(RegNo);
3109
3110 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3111
3112 return MatchOperand_Success;
3113}
3114
Jack Carterdc1e35d2012-09-06 20:00:02 +00003115MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3116
Vladimir Medic4c299852013-11-06 11:27:05 +00003117 MCSymbolRefExpr::VariantKind VK =
3118 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3119 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3120 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3121 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3122 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3123 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3124 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3125 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3126 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3127 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3128 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3129 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3130 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3131 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3132 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3133 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3134 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3135 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003136 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3137 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3138 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3139 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3140 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3141 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003142 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3143 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003144 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003145
Matheus Almeida2852af82014-04-22 10:15:54 +00003146 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003147
Jack Carterdc1e35d2012-09-06 20:00:02 +00003148 return VK;
3149}
Jack Cartera63b16a2012-09-07 00:23:42 +00003150
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003151/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3152/// either this.
3153/// ::= '(', register, ')'
3154/// handle it before we iterate so we don't get tripped up by the lack of
3155/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003156bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003157 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003158 if (getLexer().is(AsmToken::LParen)) {
3159 Operands.push_back(
3160 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3161 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003162 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003163 SMLoc Loc = getLexer().getLoc();
3164 Parser.eatToEndOfStatement();
3165 return Error(Loc, "unexpected token in argument list");
3166 }
3167 if (Parser.getTok().isNot(AsmToken::RParen)) {
3168 SMLoc Loc = getLexer().getLoc();
3169 Parser.eatToEndOfStatement();
3170 return Error(Loc, "unexpected token, expected ')'");
3171 }
3172 Operands.push_back(
3173 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3174 Parser.Lex();
3175 }
3176 return false;
3177}
3178
3179/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3180/// either one of these.
3181/// ::= '[', register, ']'
3182/// ::= '[', integer, ']'
3183/// handle it before we iterate so we don't get tripped up by the lack of
3184/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003185bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003186 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003187 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003188 if (getLexer().is(AsmToken::LBrac)) {
3189 Operands.push_back(
3190 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3191 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003192 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003193 SMLoc Loc = getLexer().getLoc();
3194 Parser.eatToEndOfStatement();
3195 return Error(Loc, "unexpected token in argument list");
3196 }
3197 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3198 SMLoc Loc = getLexer().getLoc();
3199 Parser.eatToEndOfStatement();
3200 return Error(Loc, "unexpected token, expected ']'");
3201 }
3202 Operands.push_back(
3203 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3204 Parser.Lex();
3205 }
3206 return false;
3207}
3208
David Blaikie960ea3f2014-06-08 16:18:35 +00003209bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3210 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003211 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003212 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003213
3214 // We have reached first instruction, module directive are now forbidden.
3215 getTargetStreamer().forbidModuleDirective();
3216
Vladimir Medic74593e62013-07-17 15:00:42 +00003217 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003218 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003219 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003220 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003221 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003222 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003223 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003224
3225 // Read the remaining operands.
3226 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3227 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003228 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003229 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003230 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003231 return Error(Loc, "unexpected token in argument list");
3232 }
Toma Tabacu13964452014-09-04 13:23:44 +00003233 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003234 return true;
3235 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003236
Jack Carterd0bd6422013-04-18 00:41:53 +00003237 while (getLexer().is(AsmToken::Comma)) {
3238 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003239 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003240 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003241 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003242 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003243 return Error(Loc, "unexpected token in argument list");
3244 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003245 // Parse bracket and parenthesis suffixes before we iterate
3246 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003247 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003248 return true;
3249 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003250 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003251 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003252 }
3253 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003254 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3255 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003256 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003257 return Error(Loc, "unexpected token in argument list");
3258 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003259 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003260 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003261}
3262
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003263bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003264 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003265 SMLoc Loc = getLexer().getLoc();
3266 Parser.eatToEndOfStatement();
3267 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003268}
3269
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003270bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003271 return Error(Loc, ErrorMsg);
3272}
3273
Jack Carter0b744b32012-10-04 02:29:46 +00003274bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003275 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003276 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003277
3278 // Set the $at register to $0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003279 AssemblerOptions.back()->setATReg(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003280
3281 Parser.Lex(); // Eat "noat".
3282
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 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003288
3289 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003290 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003291 return false;
3292}
Jack Carterd0bd6422013-04-18 00:41:53 +00003293
Jack Carter0b744b32012-10-04 02:29:46 +00003294bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003295 // Line can be: ".set at", which sets $at to $1
3296 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003297 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003298 Parser.Lex(); // Eat "at".
3299
Jack Carter0b744b32012-10-04 02:29:46 +00003300 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003301 // No register was specified, so we set $at to $1.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003302 AssemblerOptions.back()->setATReg(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003303
3304 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003305 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003306 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003307 }
3308
3309 if (getLexer().isNot(AsmToken::Equal)) {
3310 reportParseError("unexpected token, expected equals sign");
3311 return false;
3312 }
3313 Parser.Lex(); // Eat "=".
3314
3315 if (getLexer().isNot(AsmToken::Dollar)) {
3316 if (getLexer().is(AsmToken::EndOfStatement)) {
3317 reportParseError("no register specified");
3318 return false;
3319 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003320 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003321 return false;
3322 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003323 }
3324 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003325
Toma Tabacu16a74492015-02-13 10:30:57 +00003326 // Find out what "reg" is.
3327 unsigned AtRegNo;
3328 const AsmToken &Reg = Parser.getTok();
3329 if (Reg.is(AsmToken::Identifier)) {
3330 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3331 } else if (Reg.is(AsmToken::Integer)) {
3332 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003333 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003334 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003335 return false;
3336 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003337
3338 // Check if $reg is a valid register. If it is, set $at to $reg.
3339 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3340 reportParseError("invalid register");
3341 return false;
3342 }
3343 Parser.Lex(); // Eat "reg".
3344
3345 // If this is not the end of the statement, report an error.
3346 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3347 reportParseError("unexpected token, expected end of statement");
3348 return false;
3349 }
3350
3351 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3352
3353 Parser.Lex(); // Consume the EndOfStatement.
3354 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003355}
3356
3357bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003358 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003359 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003360 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003361 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003362 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003363 return false;
3364 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003365 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003366 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003367 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003368 return false;
3369}
3370
3371bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003372 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003373 Parser.Lex();
3374 // If this is not the end of the statement, report an error.
3375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003376 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003377 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003378 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003379 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003380 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003381 Parser.Lex(); // Consume the EndOfStatement.
3382 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003383}
3384
3385bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003386 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003387 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003388 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003389 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003390 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003391 return false;
3392 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003393 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003394 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003395 return false;
3396}
3397
3398bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003399 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003400 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003401 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003402 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003403 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003404 return false;
3405 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003406 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003407 reportParseError("`noreorder' must be set before `nomacro'");
3408 return false;
3409 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003410 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003411 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003412 return false;
3413}
Jack Carterd76b2372013-03-21 21:44:16 +00003414
Daniel Sanders44934432014-08-07 12:03:36 +00003415bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003416 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003417 Parser.Lex();
3418
3419 // If this is not the end of the statement, report an error.
3420 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003421 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003422
3423 setFeatureBits(Mips::FeatureMSA, "msa");
3424 getTargetStreamer().emitDirectiveSetMsa();
3425 return false;
3426}
3427
3428bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003429 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003430 Parser.Lex();
3431
3432 // If this is not the end of the statement, report an error.
3433 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003434 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003435
3436 clearFeatureBits(Mips::FeatureMSA, "msa");
3437 getTargetStreamer().emitDirectiveSetNoMsa();
3438 return false;
3439}
3440
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003441bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003442 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003443 Parser.Lex(); // Eat "nodsp".
3444
3445 // If this is not the end of the statement, report an error.
3446 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3447 reportParseError("unexpected token, expected end of statement");
3448 return false;
3449 }
3450
3451 clearFeatureBits(Mips::FeatureDSP, "dsp");
3452 getTargetStreamer().emitDirectiveSetNoDsp();
3453 return false;
3454}
3455
Toma Tabacucc2502d2014-11-04 17:18:07 +00003456bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003457 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003458 Parser.Lex(); // Eat "mips16".
3459
Jack Carter39536722014-01-22 23:08:42 +00003460 // If this is not the end of the statement, report an error.
3461 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003462 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003463 return false;
3464 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003465
3466 setFeatureBits(Mips::FeatureMips16, "mips16");
3467 getTargetStreamer().emitDirectiveSetMips16();
3468 Parser.Lex(); // Consume the EndOfStatement.
3469 return false;
3470}
3471
3472bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003473 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003474 Parser.Lex(); // Eat "nomips16".
3475
3476 // If this is not the end of the statement, report an error.
3477 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3478 reportParseError("unexpected token, expected end of statement");
3479 return false;
3480 }
3481
3482 clearFeatureBits(Mips::FeatureMips16, "mips16");
3483 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003484 Parser.Lex(); // Consume the EndOfStatement.
3485 return false;
3486}
3487
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003488bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003489 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003490 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003491 // Line can be: .set fp=32
3492 // .set fp=xx
3493 // .set fp=64
3494 Parser.Lex(); // Eat fp token
3495 AsmToken Tok = Parser.getTok();
3496 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003497 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003498 return false;
3499 }
3500 Parser.Lex(); // Eat '=' token.
3501 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003502
3503 if (!parseFpABIValue(FpAbiVal, ".set"))
3504 return false;
3505
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003507 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003508 return false;
3509 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003510 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003511 Parser.Lex(); // Consume the EndOfStatement.
3512 return false;
3513}
3514
Toma Tabacu9db22db2014-09-09 10:15:38 +00003515bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003516 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003517 SMLoc Loc = getLexer().getLoc();
3518
3519 Parser.Lex();
3520 if (getLexer().isNot(AsmToken::EndOfStatement))
3521 return reportParseError("unexpected token, expected end of statement");
3522
3523 // Always keep an element on the options "stack" to prevent the user
3524 // from changing the initial options. This is how we remember them.
3525 if (AssemblerOptions.size() == 2)
3526 return reportParseError(Loc, ".set pop with no .set push");
3527
3528 AssemblerOptions.pop_back();
3529 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3530
3531 getTargetStreamer().emitDirectiveSetPop();
3532 return false;
3533}
3534
3535bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003536 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003537 Parser.Lex();
3538 if (getLexer().isNot(AsmToken::EndOfStatement))
3539 return reportParseError("unexpected token, expected end of statement");
3540
3541 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003542 AssemblerOptions.push_back(
3543 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003544
3545 getTargetStreamer().emitDirectiveSetPush();
3546 return false;
3547}
3548
Jack Carterd76b2372013-03-21 21:44:16 +00003549bool MipsAsmParser::parseSetAssignment() {
3550 StringRef Name;
3551 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003552 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003553
3554 if (Parser.parseIdentifier(Name))
3555 reportParseError("expected identifier after .set");
3556
3557 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003558 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003559 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003560
Jack Carter3b2c96e2014-01-22 23:31:38 +00003561 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003562 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003563
Jack Carterd0bd6422013-04-18 00:41:53 +00003564 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003565 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003566 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003567 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003568 Sym = getContext().GetOrCreateSymbol(Name);
3569 Sym->setVariableValue(Value);
3570
3571 return false;
3572}
Jack Carterd0bd6422013-04-18 00:41:53 +00003573
Toma Tabacu26647792014-09-09 12:52:14 +00003574bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003575 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003576 Parser.Lex();
3577 if (getLexer().isNot(AsmToken::EndOfStatement))
3578 return reportParseError("unexpected token, expected end of statement");
3579
3580 // Reset assembler options to their initial values.
3581 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3582 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3583
3584 getTargetStreamer().emitDirectiveSetMips0();
3585 return false;
3586}
3587
Toma Tabacu85618b32014-08-19 14:22:52 +00003588bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003589 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003590 Parser.Lex();
3591 if (getLexer().isNot(AsmToken::Equal))
3592 return reportParseError("unexpected token, expected equals sign");
3593
3594 Parser.Lex();
3595 StringRef Arch;
3596 if (Parser.parseIdentifier(Arch))
3597 return reportParseError("expected arch identifier");
3598
3599 StringRef ArchFeatureName =
3600 StringSwitch<StringRef>(Arch)
3601 .Case("mips1", "mips1")
3602 .Case("mips2", "mips2")
3603 .Case("mips3", "mips3")
3604 .Case("mips4", "mips4")
3605 .Case("mips5", "mips5")
3606 .Case("mips32", "mips32")
3607 .Case("mips32r2", "mips32r2")
3608 .Case("mips32r6", "mips32r6")
3609 .Case("mips64", "mips64")
3610 .Case("mips64r2", "mips64r2")
3611 .Case("mips64r6", "mips64r6")
3612 .Case("cnmips", "cnmips")
3613 .Case("r4000", "mips3") // This is an implementation of Mips3.
3614 .Default("");
3615
3616 if (ArchFeatureName.empty())
3617 return reportParseError("unsupported architecture");
3618
3619 selectArch(ArchFeatureName);
3620 getTargetStreamer().emitDirectiveSetArch(Arch);
3621 return false;
3622}
3623
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003624bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003625 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003626 Parser.Lex();
3627 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003628 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003629
Matheus Almeida2852af82014-04-22 10:15:54 +00003630 switch (Feature) {
3631 default:
3632 llvm_unreachable("Unimplemented feature");
3633 case Mips::FeatureDSP:
3634 setFeatureBits(Mips::FeatureDSP, "dsp");
3635 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003636 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003637 case Mips::FeatureMicroMips:
3638 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003639 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003640 case Mips::FeatureMips1:
3641 selectArch("mips1");
3642 getTargetStreamer().emitDirectiveSetMips1();
3643 break;
3644 case Mips::FeatureMips2:
3645 selectArch("mips2");
3646 getTargetStreamer().emitDirectiveSetMips2();
3647 break;
3648 case Mips::FeatureMips3:
3649 selectArch("mips3");
3650 getTargetStreamer().emitDirectiveSetMips3();
3651 break;
3652 case Mips::FeatureMips4:
3653 selectArch("mips4");
3654 getTargetStreamer().emitDirectiveSetMips4();
3655 break;
3656 case Mips::FeatureMips5:
3657 selectArch("mips5");
3658 getTargetStreamer().emitDirectiveSetMips5();
3659 break;
3660 case Mips::FeatureMips32:
3661 selectArch("mips32");
3662 getTargetStreamer().emitDirectiveSetMips32();
3663 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003664 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003665 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003666 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003667 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003668 case Mips::FeatureMips32r6:
3669 selectArch("mips32r6");
3670 getTargetStreamer().emitDirectiveSetMips32R6();
3671 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003672 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003673 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003674 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003675 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003676 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003677 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003678 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003679 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003680 case Mips::FeatureMips64r6:
3681 selectArch("mips64r6");
3682 getTargetStreamer().emitDirectiveSetMips64R6();
3683 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003684 }
3685 return false;
3686}
3687
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003688bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003689 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003690 if (getLexer().isNot(AsmToken::Comma)) {
3691 SMLoc Loc = getLexer().getLoc();
3692 Parser.eatToEndOfStatement();
3693 return Error(Loc, ErrorStr);
3694 }
3695
Matheus Almeida2852af82014-04-22 10:15:54 +00003696 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003697 return true;
3698}
3699
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003700bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003701 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003702 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003703
Toma Tabacudde4c462014-11-06 10:02:45 +00003704 if (inMips16Mode()) {
3705 reportParseError(".cpload is not supported in Mips16 mode");
3706 return false;
3707 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003708
David Blaikie960ea3f2014-06-08 16:18:35 +00003709 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003710 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003711 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3712 reportParseError("expected register containing function address");
3713 return false;
3714 }
3715
David Blaikie960ea3f2014-06-08 16:18:35 +00003716 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3717 if (!RegOpnd.isGPRAsmReg()) {
3718 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003719 return false;
3720 }
3721
Toma Tabacudde4c462014-11-06 10:02:45 +00003722 // If this is not the end of the statement, report an error.
3723 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3724 reportParseError("unexpected token, expected end of statement");
3725 return false;
3726 }
3727
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003728 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003729 return false;
3730}
3731
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003732bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003733 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003734 unsigned FuncReg;
3735 unsigned Save;
3736 bool SaveIsReg = true;
3737
Matheus Almeida7e815762014-06-18 13:08:59 +00003738 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003739 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003740 if (ResTy == MatchOperand_NoMatch) {
3741 reportParseError("expected register containing function address");
3742 Parser.eatToEndOfStatement();
3743 return false;
3744 }
3745
3746 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3747 if (!FuncRegOpnd.isGPRAsmReg()) {
3748 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3749 Parser.eatToEndOfStatement();
3750 return false;
3751 }
3752
3753 FuncReg = FuncRegOpnd.getGPR32Reg();
3754 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003755
Toma Tabacu65f10572014-09-16 15:00:52 +00003756 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003757 return true;
3758
Toma Tabacu13964452014-09-04 13:23:44 +00003759 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003760 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003761 const AsmToken &Tok = Parser.getTok();
3762 if (Tok.is(AsmToken::Integer)) {
3763 Save = Tok.getIntVal();
3764 SaveIsReg = false;
3765 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003766 } else {
3767 reportParseError("expected save register or stack offset");
3768 Parser.eatToEndOfStatement();
3769 return false;
3770 }
3771 } else {
3772 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3773 if (!SaveOpnd.isGPRAsmReg()) {
3774 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3775 Parser.eatToEndOfStatement();
3776 return false;
3777 }
3778 Save = SaveOpnd.getGPR32Reg();
3779 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003780
Toma Tabacu65f10572014-09-16 15:00:52 +00003781 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003782 return true;
3783
Toma Tabacu8874eac2015-02-18 13:46:53 +00003784 const MCExpr *Expr;
3785 if (Parser.parseExpression(Expr)) {
3786 reportParseError("expected expression");
3787 return false;
3788 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003789
Toma Tabacu8874eac2015-02-18 13:46:53 +00003790 if (Expr->getKind() != MCExpr::SymbolRef) {
3791 reportParseError("expected symbol");
3792 return false;
3793 }
3794 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3795
3796 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3797 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003798 return false;
3799}
3800
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003801bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003802 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003803 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3804 const AsmToken &Tok = Parser.getTok();
3805
3806 if (Tok.getString() == "2008") {
3807 Parser.Lex();
3808 getTargetStreamer().emitDirectiveNaN2008();
3809 return false;
3810 } else if (Tok.getString() == "legacy") {
3811 Parser.Lex();
3812 getTargetStreamer().emitDirectiveNaNLegacy();
3813 return false;
3814 }
3815 }
3816 // If we don't recognize the option passed to the .nan
3817 // directive (e.g. no option or unknown option), emit an error.
3818 reportParseError("invalid option in .nan directive");
3819 return false;
3820}
3821
Jack Carter0b744b32012-10-04 02:29:46 +00003822bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003823 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003824 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003825 const AsmToken &Tok = Parser.getTok();
3826
3827 if (Tok.getString() == "noat") {
3828 return parseSetNoAtDirective();
3829 } else if (Tok.getString() == "at") {
3830 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003831 } else if (Tok.getString() == "arch") {
3832 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003833 } else if (Tok.getString() == "fp") {
3834 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003835 } else if (Tok.getString() == "pop") {
3836 return parseSetPopDirective();
3837 } else if (Tok.getString() == "push") {
3838 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003839 } else if (Tok.getString() == "reorder") {
3840 return parseSetReorderDirective();
3841 } else if (Tok.getString() == "noreorder") {
3842 return parseSetNoReorderDirective();
3843 } else if (Tok.getString() == "macro") {
3844 return parseSetMacroDirective();
3845 } else if (Tok.getString() == "nomacro") {
3846 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003847 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003848 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003849 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003850 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003851 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003852 getTargetStreamer().emitDirectiveSetNoMicroMips();
3853 Parser.eatToEndOfStatement();
3854 return false;
3855 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003856 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003857 } else if (Tok.getString() == "mips0") {
3858 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003859 } else if (Tok.getString() == "mips1") {
3860 return parseSetFeature(Mips::FeatureMips1);
3861 } else if (Tok.getString() == "mips2") {
3862 return parseSetFeature(Mips::FeatureMips2);
3863 } else if (Tok.getString() == "mips3") {
3864 return parseSetFeature(Mips::FeatureMips3);
3865 } else if (Tok.getString() == "mips4") {
3866 return parseSetFeature(Mips::FeatureMips4);
3867 } else if (Tok.getString() == "mips5") {
3868 return parseSetFeature(Mips::FeatureMips5);
3869 } else if (Tok.getString() == "mips32") {
3870 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003871 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003872 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003873 } else if (Tok.getString() == "mips32r6") {
3874 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003875 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003876 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003877 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003878 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003879 } else if (Tok.getString() == "mips64r6") {
3880 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003881 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003882 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003883 } else if (Tok.getString() == "nodsp") {
3884 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003885 } else if (Tok.getString() == "msa") {
3886 return parseSetMsaDirective();
3887 } else if (Tok.getString() == "nomsa") {
3888 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003889 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003890 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003891 parseSetAssignment();
3892 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003893 }
Jack Carter07c818d2013-01-25 01:31:34 +00003894
Jack Carter0b744b32012-10-04 02:29:46 +00003895 return true;
3896}
3897
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003898/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003899/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003900bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003901 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003902 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3903 for (;;) {
3904 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003905 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003906 return true;
3907
3908 getParser().getStreamer().EmitValue(Value, Size);
3909
3910 if (getLexer().is(AsmToken::EndOfStatement))
3911 break;
3912
Jack Carter07c818d2013-01-25 01:31:34 +00003913 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003914 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003915 Parser.Lex();
3916 }
3917 }
3918
3919 Parser.Lex();
3920 return false;
3921}
3922
Vladimir Medic4c299852013-11-06 11:27:05 +00003923/// parseDirectiveGpWord
3924/// ::= .gpword local_sym
3925bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003926 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003927 const MCExpr *Value;
3928 // EmitGPRel32Value requires an expression, so we are using base class
3929 // method to evaluate the expression.
3930 if (getParser().parseExpression(Value))
3931 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003932 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003933
Vladimir Medice10c1122013-11-13 13:18:04 +00003934 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003935 return Error(getLexer().getLoc(),
3936 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003937 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003938 return false;
3939}
3940
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003941/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003942/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003943bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003944 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003945 const MCExpr *Value;
3946 // EmitGPRel64Value requires an expression, so we are using base class
3947 // method to evaluate the expression.
3948 if (getParser().parseExpression(Value))
3949 return true;
3950 getParser().getStreamer().EmitGPRel64Value(Value);
3951
3952 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003953 return Error(getLexer().getLoc(),
3954 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003955 Parser.Lex(); // Eat EndOfStatement token.
3956 return false;
3957}
3958
Jack Carter0cd3c192014-01-06 23:27:31 +00003959bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003960 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003961 // Get the option token.
3962 AsmToken Tok = Parser.getTok();
3963 // At the moment only identifiers are supported.
3964 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003965 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003966 Parser.eatToEndOfStatement();
3967 return false;
3968 }
3969
3970 StringRef Option = Tok.getIdentifier();
3971
3972 if (Option == "pic0") {
3973 getTargetStreamer().emitDirectiveOptionPic0();
3974 Parser.Lex();
3975 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3976 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003977 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003978 Parser.eatToEndOfStatement();
3979 }
3980 return false;
3981 }
3982
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003983 if (Option == "pic2") {
3984 getTargetStreamer().emitDirectiveOptionPic2();
3985 Parser.Lex();
3986 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3987 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003988 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003989 Parser.eatToEndOfStatement();
3990 }
3991 return false;
3992 }
3993
Jack Carter0cd3c192014-01-06 23:27:31 +00003994 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003995 Warning(Parser.getTok().getLoc(),
3996 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003997 Parser.eatToEndOfStatement();
3998 return false;
3999}
4000
Daniel Sanders7e527422014-07-10 13:38:23 +00004001/// parseDirectiveModule
4002/// ::= .module oddspreg
4003/// ::= .module nooddspreg
4004/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004005bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004006 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004007 MCAsmLexer &Lexer = getLexer();
4008 SMLoc L = Lexer.getLoc();
4009
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004010 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004011 // TODO : get a better message.
4012 reportParseError(".module directive must appear before any code");
4013 return false;
4014 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004015
Toma Tabacuc405c822015-01-23 10:40:19 +00004016 StringRef Option;
4017 if (Parser.parseIdentifier(Option)) {
4018 reportParseError("expected .module option identifier");
4019 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004020 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004021
Toma Tabacuc405c822015-01-23 10:40:19 +00004022 if (Option == "oddspreg") {
4023 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4024 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4025
4026 // If this is not the end of the statement, report an error.
4027 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4028 reportParseError("unexpected token, expected end of statement");
4029 return false;
4030 }
4031
4032 return false; // parseDirectiveModule has finished successfully.
4033 } else if (Option == "nooddspreg") {
4034 if (!isABI_O32()) {
4035 Error(L, "'.module nooddspreg' requires the O32 ABI");
4036 return false;
4037 }
4038
4039 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4040 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4041
4042 // If this is not the end of the statement, report an error.
4043 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4044 reportParseError("unexpected token, expected end of statement");
4045 return false;
4046 }
4047
4048 return false; // parseDirectiveModule has finished successfully.
4049 } else if (Option == "fp") {
4050 return parseDirectiveModuleFP();
4051 } else {
4052 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4053 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004054}
4055
4056/// parseDirectiveModuleFP
4057/// ::= =32
4058/// ::= =xx
4059/// ::= =64
4060bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004061 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004062 MCAsmLexer &Lexer = getLexer();
4063
4064 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004065 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004066 return false;
4067 }
4068 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004069
Daniel Sanders7e527422014-07-10 13:38:23 +00004070 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004071 if (!parseFpABIValue(FpABI, ".module"))
4072 return false;
4073
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004074 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004075 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004076 return false;
4077 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004078
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004079 // Emit appropriate flags.
4080 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004081 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004082 return false;
4083}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004084
Daniel Sanders7e527422014-07-10 13:38:23 +00004085bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004086 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004087 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004088 MCAsmLexer &Lexer = getLexer();
4089
4090 if (Lexer.is(AsmToken::Identifier)) {
4091 StringRef Value = Parser.getTok().getString();
4092 Parser.Lex();
4093
4094 if (Value != "xx") {
4095 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4096 return false;
4097 }
4098
4099 if (!isABI_O32()) {
4100 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4101 return false;
4102 }
4103
Daniel Sanders7e527422014-07-10 13:38:23 +00004104 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004105 return true;
4106 }
4107
4108 if (Lexer.is(AsmToken::Integer)) {
4109 unsigned Value = Parser.getTok().getIntVal();
4110 Parser.Lex();
4111
4112 if (Value != 32 && Value != 64) {
4113 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4114 return false;
4115 }
4116
4117 if (Value == 32) {
4118 if (!isABI_O32()) {
4119 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4120 return false;
4121 }
4122
Daniel Sanders7e527422014-07-10 13:38:23 +00004123 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4124 } else
4125 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004126
Daniel Sanders7e527422014-07-10 13:38:23 +00004127 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004128 }
4129
4130 return false;
4131}
4132
Jack Carter0b744b32012-10-04 02:29:46 +00004133bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004134 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004135 StringRef IDVal = DirectiveID.getString();
4136
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004137 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004138 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004139 if (IDVal == ".dword") {
4140 parseDataDirective(8, DirectiveID.getLoc());
4141 return false;
4142 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004143 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004144 StringRef SymbolName;
4145
4146 if (Parser.parseIdentifier(SymbolName)) {
4147 reportParseError("expected identifier after .ent");
4148 return false;
4149 }
4150
4151 // There's an undocumented extension that allows an integer to
4152 // follow the name of the procedure which AFAICS is ignored by GAS.
4153 // Example: .ent foo,2
4154 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4155 if (getLexer().isNot(AsmToken::Comma)) {
4156 // Even though we accept this undocumented extension for compatibility
4157 // reasons, the additional integer argument does not actually change
4158 // the behaviour of the '.ent' directive, so we would like to discourage
4159 // its use. We do this by not referring to the extended version in
4160 // error messages which are not directly related to its use.
4161 reportParseError("unexpected token, expected end of statement");
4162 return false;
4163 }
4164 Parser.Lex(); // Eat the comma.
4165 const MCExpr *DummyNumber;
4166 int64_t DummyNumberVal;
4167 // If the user was explicitly trying to use the extended version,
4168 // we still give helpful extension-related error messages.
4169 if (Parser.parseExpression(DummyNumber)) {
4170 reportParseError("expected number after comma");
4171 return false;
4172 }
4173 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4174 reportParseError("expected an absolute expression after comma");
4175 return false;
4176 }
4177 }
4178
4179 // If this is not the end of the statement, report an error.
4180 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4181 reportParseError("unexpected token, expected end of statement");
4182 return false;
4183 }
4184
4185 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4186
4187 getTargetStreamer().emitDirectiveEnt(*Sym);
4188 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004189 return false;
4190 }
4191
Jack Carter07c818d2013-01-25 01:31:34 +00004192 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004193 StringRef SymbolName;
4194
4195 if (Parser.parseIdentifier(SymbolName)) {
4196 reportParseError("expected identifier after .end");
4197 return false;
4198 }
4199
4200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4201 reportParseError("unexpected token, expected end of statement");
4202 return false;
4203 }
4204
4205 if (CurrentFn == nullptr) {
4206 reportParseError(".end used without .ent");
4207 return false;
4208 }
4209
4210 if ((SymbolName != CurrentFn->getName())) {
4211 reportParseError(".end symbol does not match .ent symbol");
4212 return false;
4213 }
4214
4215 getTargetStreamer().emitDirectiveEnd(SymbolName);
4216 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004217 return false;
4218 }
4219
Jack Carter07c818d2013-01-25 01:31:34 +00004220 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004221 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4222 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004223 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004224 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4225 reportParseError("expected stack register");
4226 return false;
4227 }
4228
4229 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4230 if (!StackRegOpnd.isGPRAsmReg()) {
4231 reportParseError(StackRegOpnd.getStartLoc(),
4232 "expected general purpose register");
4233 return false;
4234 }
4235 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4236
4237 if (Parser.getTok().is(AsmToken::Comma))
4238 Parser.Lex();
4239 else {
4240 reportParseError("unexpected token, expected comma");
4241 return false;
4242 }
4243
4244 // Parse the frame size.
4245 const MCExpr *FrameSize;
4246 int64_t FrameSizeVal;
4247
4248 if (Parser.parseExpression(FrameSize)) {
4249 reportParseError("expected frame size value");
4250 return false;
4251 }
4252
4253 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4254 reportParseError("frame size not an absolute expression");
4255 return false;
4256 }
4257
4258 if (Parser.getTok().is(AsmToken::Comma))
4259 Parser.Lex();
4260 else {
4261 reportParseError("unexpected token, expected comma");
4262 return false;
4263 }
4264
4265 // Parse the return register.
4266 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004267 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004268 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4269 reportParseError("expected return register");
4270 return false;
4271 }
4272
4273 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4274 if (!ReturnRegOpnd.isGPRAsmReg()) {
4275 reportParseError(ReturnRegOpnd.getStartLoc(),
4276 "expected general purpose register");
4277 return false;
4278 }
4279
4280 // If this is not the end of the statement, report an error.
4281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4282 reportParseError("unexpected token, expected end of statement");
4283 return false;
4284 }
4285
4286 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4287 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004288 return false;
4289 }
4290
Jack Carter07c818d2013-01-25 01:31:34 +00004291 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004292 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004293 }
4294
Daniel Sandersd97a6342014-08-13 10:07:34 +00004295 if (IDVal == ".mask" || IDVal == ".fmask") {
4296 // .mask bitmask, frame_offset
4297 // bitmask: One bit for each register used.
4298 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4299 // first register is expected to be saved.
4300 // Examples:
4301 // .mask 0x80000000, -4
4302 // .fmask 0x80000000, -4
4303 //
Jack Carterbe332172012-09-07 00:48:02 +00004304
Daniel Sandersd97a6342014-08-13 10:07:34 +00004305 // Parse the bitmask
4306 const MCExpr *BitMask;
4307 int64_t BitMaskVal;
4308
4309 if (Parser.parseExpression(BitMask)) {
4310 reportParseError("expected bitmask value");
4311 return false;
4312 }
4313
4314 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4315 reportParseError("bitmask not an absolute expression");
4316 return false;
4317 }
4318
4319 if (Parser.getTok().is(AsmToken::Comma))
4320 Parser.Lex();
4321 else {
4322 reportParseError("unexpected token, expected comma");
4323 return false;
4324 }
4325
4326 // Parse the frame_offset
4327 const MCExpr *FrameOffset;
4328 int64_t FrameOffsetVal;
4329
4330 if (Parser.parseExpression(FrameOffset)) {
4331 reportParseError("expected frame offset value");
4332 return false;
4333 }
4334
4335 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4336 reportParseError("frame offset not an absolute expression");
4337 return false;
4338 }
4339
4340 // If this is not the end of the statement, report an error.
4341 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4342 reportParseError("unexpected token, expected end of statement");
4343 return false;
4344 }
4345
4346 if (IDVal == ".mask")
4347 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4348 else
4349 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004350 return false;
4351 }
4352
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004353 if (IDVal == ".nan")
4354 return parseDirectiveNaN();
4355
Jack Carter07c818d2013-01-25 01:31:34 +00004356 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004357 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004358 return false;
4359 }
4360
Rafael Espindolab59fb732014-03-28 18:50:26 +00004361 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004362 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004363 return false;
4364 }
4365
Jack Carter07c818d2013-01-25 01:31:34 +00004366 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004367 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004368 return false;
4369 }
4370
Jack Carter0cd3c192014-01-06 23:27:31 +00004371 if (IDVal == ".option")
4372 return parseDirectiveOption();
4373
4374 if (IDVal == ".abicalls") {
4375 getTargetStreamer().emitDirectiveAbiCalls();
4376 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004377 Error(Parser.getTok().getLoc(),
4378 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004379 // Clear line
4380 Parser.eatToEndOfStatement();
4381 }
4382 return false;
4383 }
4384
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004385 if (IDVal == ".cpsetup")
4386 return parseDirectiveCPSetup();
4387
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004388 if (IDVal == ".module")
4389 return parseDirectiveModule();
4390
Rafael Espindola870c4e92012-01-11 03:56:41 +00004391 return true;
4392}
4393
Rafael Espindola870c4e92012-01-11 03:56:41 +00004394extern "C" void LLVMInitializeMipsAsmParser() {
4395 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4396 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4397 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4398 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4399}
Jack Carterb4dbc172012-09-05 23:34:03 +00004400
4401#define GET_REGISTER_MATCHER
4402#define GET_MATCHER_IMPLEMENTATION
4403#include "MipsGenAsmMatcher.inc"