blob: 5f4116dd872c7057656e3663e14c0c49313313aa [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.
Michael Kupersteinefd7a962015-02-19 11:38:11 +000074 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::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
80 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
81 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
82 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000088 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
92namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000093class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000095 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000096 return static_cast<MipsTargetStreamer &>(TS);
97 }
98
Jack Carterb4dbc172012-09-05 23:34:03 +000099 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000100 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000101 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000102 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
103 // nullptr, which indicates that no function is currently
104 // selected. This usually happens after an '.end func'
105 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000106
Daniel Sandersef638fe2014-10-03 15:37:37 +0000107 // Print a warning along with its fix-it message at the given range.
108 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
109 SMRange Range, bool ShowColors = true);
110
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000111#define GET_ASSEMBLER_HEADER
112#include "MipsGenAsmMatcher.inc"
113
Matheus Almeida595fcab2014-06-11 15:05:56 +0000114 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
115
Chad Rosier49963552012-10-13 00:26:04 +0000116 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000117 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000118 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000121 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000122 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000123
Toma Tabacu13964452014-09-04 13:23:44 +0000124 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000125
Toma Tabacu13964452014-09-04 13:23:44 +0000126 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000127
David Blaikie960ea3f2014-06-08 16:18:35 +0000128 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
129 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Craig Topper56c590a2014-04-29 07:58:02 +0000131 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000132
David Blaikie960ea3f2014-06-08 16:18:35 +0000133 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000134
135 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000136 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000137 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000138
Jack Carter873c7242013-01-12 01:03:14 +0000139 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000140 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000145
Toma Tabacu13964452014-09-04 13:23:44 +0000146 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000147
David Blaikie960ea3f2014-06-08 16:18:35 +0000148 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000149
Toma Tabacu13964452014-09-04 13:23:44 +0000150 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000151
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000152 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000153 parseRegisterPair (OperandVector &Operands);
154
155 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000156 parseMovePRegPair(OperandVector &Operands);
157
158 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 parseRegisterList (OperandVector &Operands);
160
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 bool searchSymbolAlias(OperandVector &Operands);
162
Toma Tabacu13964452014-09-04 13:23:44 +0000163 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000164
Jack Carter30a59822012-10-04 04:03:53 +0000165 bool needsExpansion(MCInst &Inst);
166
Matheus Almeida3813d572014-06-19 14:39:14 +0000167 // Expands assembly pseudo instructions.
168 // Returns false on success, true otherwise.
169 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000172 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
173 SmallVectorImpl<MCInst> &Instructions);
174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000176 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000177
178 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000179 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000180
181 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000182 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000183 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000185
Toma Tabacu0d64b202014-08-14 10:29:17 +0000186 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
187 SmallVectorImpl<MCInst> &Instructions);
188
Jack Carter9e65aa32013-03-22 00:05:30 +0000189 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000190 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
191 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000192
193 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
195
Toma Tabacu234482a2015-03-16 12:03:39 +0000196 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
197 SmallVectorImpl<MCInst> &Instructions);
198
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000199 bool reportParseError(Twine ErrorMsg);
200 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000201
Jack Carterb5cf5902013-04-17 00:18:04 +0000202 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000203 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000204
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000206
207 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000208 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000209 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000210 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000211 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000212 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000213 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000214 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000215 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000216
217 bool parseSetAtDirective();
218 bool parseSetNoAtDirective();
219 bool parseSetMacroDirective();
220 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000221 bool parseSetMsaDirective();
222 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000223 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000224 bool parseSetReorderDirective();
225 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000226 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000227 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000228 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000229 bool parseSetPopDirective();
230 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000231
Jack Carterd76b2372013-03-21 21:44:16 +0000232 bool parseSetAssignment();
233
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000234 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000235 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000236 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000237 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000238 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000239 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
240 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000241
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000242 bool parseInternalDirectiveReallowModule();
243
Jack Carterdc1e35d2012-09-06 20:00:02 +0000244 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000245
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000246 bool eatComma(StringRef ErrorStr);
247
Jack Carter1ac53222013-02-20 23:11:17 +0000248 int matchCPURegisterName(StringRef Symbol);
249
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000250 int matchHWRegsRegisterName(StringRef Symbol);
251
Jack Carter873c7242013-01-12 01:03:14 +0000252 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000253
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000254 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000255
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000256 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000257
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000258 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000259
Jack Carter5dc8ac92013-09-25 23:50:44 +0000260 int matchMSA128RegisterName(StringRef Name);
261
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000262 int matchMSA128CtrlRegisterName(StringRef Name);
263
Jack Carterd0bd6422013-04-18 00:41:53 +0000264 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000265
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000266 unsigned getGPR(int RegNo);
267
Matheus Almeida7de68e72014-06-18 14:46:05 +0000268 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000269
270 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000271 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000272
273 // Helper function that checks if the value of a vector index is within the
274 // boundaries of accepted values for each RegisterKind
275 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
276 bool validateMSAIndex(int Val, int RegKind);
277
Daniel Sandersf0df2212014-08-04 12:20:00 +0000278 // Selects a new architecture by updating the FeatureBits with the necessary
279 // info including implied dependencies.
280 // Internally, it clears all the feature bits related to *any* architecture
281 // and selects the new one using the ToggleFeature functionality of the
282 // MCSubtargetInfo object that handles implied dependencies. The reason we
283 // clear all the arch related bits manually is because ToggleFeature only
284 // clears the features that imply the feature being cleared and not the
285 // features implied by the feature being cleared. This is easier to see
286 // with an example:
287 // --------------------------------------------------
288 // | Feature | Implies |
289 // | -------------------------------------------------|
290 // | FeatureMips1 | None |
291 // | FeatureMips2 | FeatureMips1 |
292 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
293 // | FeatureMips4 | FeatureMips3 |
294 // | ... | |
295 // --------------------------------------------------
296 //
297 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
298 // FeatureMipsGP64 | FeatureMips1)
299 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
300 void selectArch(StringRef ArchFeature) {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000301 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000302 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
303 STI.setFeatureBits(FeatureBits);
304 setAvailableFeatures(
305 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000306 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000307 }
308
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000309 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000310 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000311 setAvailableFeatures(
312 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000313 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000314 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000315 }
316
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000317 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000318 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000319 setAvailableFeatures(
320 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000321 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000322 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000323 }
324
Rafael Espindola870c4e92012-01-11 03:56:41 +0000325public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000326 enum MipsMatchResultTy {
327 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
328#define GET_OPERAND_DIAGNOSTIC_TYPES
329#include "MipsGenAsmMatcher.inc"
330#undef GET_OPERAND_DIAGNOSTIC_TYPES
331
332 };
333
Joey Gouly0e76fa72013-09-12 10:28:05 +0000334 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000335 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000336 : MCTargetAsmParser(), STI(sti),
337 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
338 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000339 MCAsmParserExtension::Initialize(parser);
340
Jack Carterb4dbc172012-09-05 23:34:03 +0000341 // Initialize the set of available features.
342 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000343
344 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000345 AssemblerOptions.push_back(
346 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000347
348 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000349 AssemblerOptions.push_back(
350 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000351
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000352 getTargetStreamer().updateABIInfo(*this);
353
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000354 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000355 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000356
357 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000358 }
359
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000360 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
361 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
362
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000363 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
364 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000365 const MipsABIInfo &getABI() const { return ABI; }
366 bool isABI_N32() const { return ABI.IsN32(); }
367 bool isABI_N64() const { return ABI.IsN64(); }
368 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000369 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000370
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000371 bool useOddSPReg() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000372 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000373 }
374
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000375 bool inMicroMipsMode() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000376 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000377 }
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000378 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
379 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
380 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
381 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
382 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000383 bool hasMips32() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000384 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000385 }
386 bool hasMips64() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000387 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000388 }
389 bool hasMips32r2() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000390 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000391 }
392 bool hasMips64r2() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000393 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000394 }
Daniel Sanders17793142015-02-18 16:24:50 +0000395 bool hasMips32r3() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000396 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000397 }
398 bool hasMips64r3() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000399 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000400 }
401 bool hasMips32r5() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000402 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000403 }
404 bool hasMips64r5() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000405 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000406 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 bool hasMips32r6() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000408 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
410 bool hasMips64r6() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000411 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 }
Kai Nackee0245392015-01-27 19:11:28 +0000413 bool hasCnMips() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000414 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000415 }
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000416 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
417 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
418 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000419
420 bool inMips16Mode() const {
Michael Kupersteinefd7a962015-02-19 11:38:11 +0000421 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000422 }
423 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000424 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000425
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000426 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000427 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000428};
429}
430
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000431namespace {
432
433/// MipsOperand - Instances of this class represent a parsed Mips machine
434/// instruction.
435class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000436public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000437 /// Broad categories of register classes
438 /// The exact class is finalized by the render method.
439 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000441 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000442 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 RegKind_FCC = 4, /// FCC
444 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
445 RegKind_MSACtrl = 16, /// MSA control registers
446 RegKind_COP2 = 32, /// COP2
447 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
448 /// context).
449 RegKind_CCR = 128, /// CCR
450 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000451 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000452
453 /// Potentially any (e.g. $1)
454 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
455 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000456 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000457 };
458
459private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000460 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000461 k_Immediate, /// An immediate (possibly involving symbol references)
462 k_Memory, /// Base + Offset Memory Address
463 k_PhysRegister, /// A physical register from the Mips namespace
464 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000465 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000466 k_RegList, /// A physical register list
467 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000468 } Kind;
469
David Blaikie960ea3f2014-06-08 16:18:35 +0000470public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000471 MipsOperand(KindTy K, MipsAsmParser &Parser)
472 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
473
David Blaikie960ea3f2014-06-08 16:18:35 +0000474private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000475 /// For diagnostics, and checking the assembler temporary
476 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000477
Eric Christopher8996c5d2013-03-15 00:42:55 +0000478 struct Token {
479 const char *Data;
480 unsigned Length;
481 };
482
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000483 struct PhysRegOp {
484 unsigned Num; /// Register Number
485 };
486
487 struct RegIdxOp {
488 unsigned Index; /// Index into the register class
489 RegKind Kind; /// Bitfield of the kinds it could possibly be
490 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000491 };
492
493 struct ImmOp {
494 const MCExpr *Val;
495 };
496
497 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000499 const MCExpr *Off;
500 };
501
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000502 struct RegListOp {
503 SmallVector<unsigned, 10> *List;
504 };
505
Jack Carterb4dbc172012-09-05 23:34:03 +0000506 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000507 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 struct PhysRegOp PhysReg;
509 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000510 struct ImmOp Imm;
511 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000512 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000513 };
514
515 SMLoc StartLoc, EndLoc;
516
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000518 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
519 const MCRegisterInfo *RegInfo,
520 SMLoc S, SMLoc E,
521 MipsAsmParser &Parser) {
522 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000523 Op->RegIdx.Index = Index;
524 Op->RegIdx.RegInfo = RegInfo;
525 Op->RegIdx.Kind = RegKind;
526 Op->StartLoc = S;
527 Op->EndLoc = E;
528 return Op;
529 }
530
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000531public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000532 /// Coerce the register to GPR32 and return the real register for the current
533 /// target.
534 unsigned getGPR32Reg() const {
535 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000536 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000537 unsigned ClassID = Mips::GPR32RegClassID;
538 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000539 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000540
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000541 /// Coerce the register to GPR32 and return the real register for the current
542 /// target.
543 unsigned getGPRMM16Reg() const {
544 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
545 unsigned ClassID = Mips::GPR32RegClassID;
546 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
547 }
548
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000549 /// Coerce the register to GPR64 and return the real register for the current
550 /// target.
551 unsigned getGPR64Reg() const {
552 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
553 unsigned ClassID = Mips::GPR64RegClassID;
554 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000555 }
556
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000557private:
558 /// Coerce the register to AFGR64 and return the real register for the current
559 /// target.
560 unsigned getAFGR64Reg() const {
561 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
562 if (RegIdx.Index % 2 != 0)
563 AsmParser.Warning(StartLoc, "Float register should be even.");
564 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
565 .getRegister(RegIdx.Index / 2);
566 }
567
568 /// Coerce the register to FGR64 and return the real register for the current
569 /// target.
570 unsigned getFGR64Reg() const {
571 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
572 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
573 .getRegister(RegIdx.Index);
574 }
575
576 /// Coerce the register to FGR32 and return the real register for the current
577 /// target.
578 unsigned getFGR32Reg() const {
579 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
580 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
581 .getRegister(RegIdx.Index);
582 }
583
584 /// Coerce the register to FGRH32 and return the real register for the current
585 /// target.
586 unsigned getFGRH32Reg() const {
587 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
588 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
589 .getRegister(RegIdx.Index);
590 }
591
592 /// Coerce the register to FCC and return the real register for the current
593 /// target.
594 unsigned getFCCReg() const {
595 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
596 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
597 .getRegister(RegIdx.Index);
598 }
599
600 /// Coerce the register to MSA128 and return the real register for the current
601 /// target.
602 unsigned getMSA128Reg() const {
603 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
604 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
605 // identical
606 unsigned ClassID = Mips::MSA128BRegClassID;
607 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
608 }
609
610 /// Coerce the register to MSACtrl and return the real register for the
611 /// current target.
612 unsigned getMSACtrlReg() const {
613 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
614 unsigned ClassID = Mips::MSACtrlRegClassID;
615 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
616 }
617
618 /// Coerce the register to COP2 and return the real register for the
619 /// current target.
620 unsigned getCOP2Reg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
622 unsigned ClassID = Mips::COP2RegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
624 }
625
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000626 /// Coerce the register to COP3 and return the real register for the
627 /// current target.
628 unsigned getCOP3Reg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
630 unsigned ClassID = Mips::COP3RegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 /// Coerce the register to ACC64DSP and return the real register for the
635 /// current target.
636 unsigned getACC64DSPReg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
638 unsigned ClassID = Mips::ACC64DSPRegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
640 }
641
642 /// Coerce the register to HI32DSP and return the real register for the
643 /// current target.
644 unsigned getHI32DSPReg() const {
645 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
646 unsigned ClassID = Mips::HI32DSPRegClassID;
647 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
648 }
649
650 /// Coerce the register to LO32DSP and return the real register for the
651 /// current target.
652 unsigned getLO32DSPReg() const {
653 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
654 unsigned ClassID = Mips::LO32DSPRegClassID;
655 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
656 }
657
658 /// Coerce the register to CCR and return the real register for the
659 /// current target.
660 unsigned getCCRReg() const {
661 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
662 unsigned ClassID = Mips::CCRRegClassID;
663 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
664 }
665
666 /// Coerce the register to HWRegs and return the real register for the
667 /// current target.
668 unsigned getHWRegsReg() const {
669 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
670 unsigned ClassID = Mips::HWRegsRegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
672 }
673
674public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000675 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000676 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000677 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000678 Inst.addOperand(MCOperand::CreateImm(0));
679 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
680 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
681 else
682 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000683 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000684
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000685 void addRegOperands(MCInst &Inst, unsigned N) const {
686 llvm_unreachable("Use a custom parser instead");
687 }
688
Daniel Sanders21bce302014-04-01 12:35:23 +0000689 /// Render the operand to an MCInst as a GPR32
690 /// Asserts if the wrong number of operands are requested, or the operand
691 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000692 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
693 assert(N == 1 && "Invalid number of operands!");
694 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
695 }
696
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000697 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
698 assert(N == 1 && "Invalid number of operands!");
699 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
700 }
701
Jozef Kolek1904fa22014-11-24 14:25:53 +0000702 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
703 assert(N == 1 && "Invalid number of operands!");
704 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
705 }
706
Zoran Jovanovic41688672015-02-10 16:36:20 +0000707 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
708 assert(N == 1 && "Invalid number of operands!");
709 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
710 }
711
Daniel Sanders21bce302014-04-01 12:35:23 +0000712 /// Render the operand to an MCInst as a GPR64
713 /// Asserts if the wrong number of operands are requested, or the operand
714 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
717 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
718 }
719
720 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
722 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
723 }
724
725 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
726 assert(N == 1 && "Invalid number of operands!");
727 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
728 }
729
730 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
731 assert(N == 1 && "Invalid number of operands!");
732 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000733 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000734 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000735 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
736 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000737 }
738
739 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
740 assert(N == 1 && "Invalid number of operands!");
741 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
742 }
743
744 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
746 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
747 }
748
749 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
750 assert(N == 1 && "Invalid number of operands!");
751 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
752 }
753
754 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
755 assert(N == 1 && "Invalid number of operands!");
756 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
757 }
758
759 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
760 assert(N == 1 && "Invalid number of operands!");
761 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
762 }
763
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000764 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
765 assert(N == 1 && "Invalid number of operands!");
766 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
767 }
768
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
770 assert(N == 1 && "Invalid number of operands!");
771 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
772 }
773
774 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
775 assert(N == 1 && "Invalid number of operands!");
776 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
777 }
778
779 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
780 assert(N == 1 && "Invalid number of operands!");
781 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
782 }
783
784 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
785 assert(N == 1 && "Invalid number of operands!");
786 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
787 }
788
789 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
790 assert(N == 1 && "Invalid number of operands!");
791 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
792 }
793
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000794 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000795 assert(N == 1 && "Invalid number of operands!");
796 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000797 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000798 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000799
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000800 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000801 assert(N == 2 && "Invalid number of operands!");
802
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000804
805 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000806 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000807 }
808
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000809 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
810 assert(N == 2 && "Invalid number of operands!");
811
812 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
813
814 const MCExpr *Expr = getMemOff();
815 addExpr(Inst, Expr);
816 }
817
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000818 void addRegListOperands(MCInst &Inst, unsigned N) const {
819 assert(N == 1 && "Invalid number of operands!");
820
821 for (auto RegNo : getRegList())
822 Inst.addOperand(MCOperand::CreateReg(RegNo));
823 }
824
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000825 void addRegPairOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 2 && "Invalid number of operands!");
827 unsigned RegNo = getRegPair();
828 Inst.addOperand(MCOperand::CreateReg(RegNo++));
829 Inst.addOperand(MCOperand::CreateReg(RegNo));
830 }
831
Zoran Jovanovic41688672015-02-10 16:36:20 +0000832 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 2 && "Invalid number of operands!");
834 for (auto RegNo : getRegList())
835 Inst.addOperand(MCOperand::CreateReg(RegNo));
836 }
837
Craig Topper56c590a2014-04-29 07:58:02 +0000838 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 // As a special case until we sort out the definition of div/divu, pretend
840 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
841 if (isGPRAsmReg() && RegIdx.Index == 0)
842 return true;
843
844 return Kind == k_PhysRegister;
845 }
846 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000847 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 bool isConstantImm() const {
849 return isImm() && dyn_cast<MCConstantExpr>(getImm());
850 }
Craig Topper56c590a2014-04-29 07:58:02 +0000851 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000852 // Note: It's not possible to pretend that other operand kinds are tokens.
853 // The matcher emitter checks tokens first.
854 return Kind == k_Token;
855 }
Craig Topper56c590a2014-04-29 07:58:02 +0000856 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000857 bool isConstantMemOff() const {
858 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
859 }
860 template <unsigned Bits> bool isMemWithSimmOffset() const {
861 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
862 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000863 bool isMemWithGRPMM16Base() const {
864 return isMem() && getMemBase()->isMM16AsmReg();
865 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000866 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
867 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
868 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
869 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000870 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
871 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
872 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
873 && (getMemBase()->getGPR32Reg() == Mips::SP);
874 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000875 bool isRegList16() const {
876 if (!isRegList())
877 return false;
878
879 int Size = RegList.List->size();
880 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
881 RegList.List->back() != Mips::RA)
882 return false;
883
884 int PrevReg = *RegList.List->begin();
885 for (int i = 1; i < Size - 1; i++) {
886 int Reg = (*(RegList.List))[i];
887 if ( Reg != PrevReg + 1)
888 return false;
889 PrevReg = Reg;
890 }
891
892 return true;
893 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000894 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000895 bool isLSAImm() const {
896 if (!isConstantImm())
897 return false;
898 int64_t Val = getConstantImm();
899 return 1 <= Val && Val <= 4;
900 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000902 bool isMovePRegPair() const {
903 if (Kind != k_RegList || RegList.List->size() != 2)
904 return false;
905
906 unsigned R0 = RegList.List->front();
907 unsigned R1 = RegList.List->back();
908
909 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
910 (R0 == Mips::A1 && R1 == Mips::A3) ||
911 (R0 == Mips::A2 && R1 == Mips::A3) ||
912 (R0 == Mips::A0 && R1 == Mips::S5) ||
913 (R0 == Mips::A0 && R1 == Mips::S6) ||
914 (R0 == Mips::A0 && R1 == Mips::A1) ||
915 (R0 == Mips::A0 && R1 == Mips::A2) ||
916 (R0 == Mips::A0 && R1 == Mips::A3))
917 return true;
918
919 return false;
920 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000921
922 StringRef getToken() const {
923 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000924 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000925 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000926 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000927
Craig Topper56c590a2014-04-29 07:58:02 +0000928 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 // As a special case until we sort out the definition of div/divu, pretend
930 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
931 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
932 RegIdx.Kind & RegKind_GPR)
933 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000934
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 assert(Kind == k_PhysRegister && "Invalid access!");
936 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000937 }
938
Jack Carterb4dbc172012-09-05 23:34:03 +0000939 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000940 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000941 return Imm.Val;
942 }
943
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000944 int64_t getConstantImm() const {
945 const MCExpr *Val = getImm();
946 return static_cast<const MCConstantExpr *>(Val)->getValue();
947 }
948
949 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000950 assert((Kind == k_Memory) && "Invalid access!");
951 return Mem.Base;
952 }
953
954 const MCExpr *getMemOff() const {
955 assert((Kind == k_Memory) && "Invalid access!");
956 return Mem.Off;
957 }
958
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000959 int64_t getConstantMemOff() const {
960 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
961 }
962
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000963 const SmallVectorImpl<unsigned> &getRegList() const {
964 assert((Kind == k_RegList) && "Invalid access!");
965 return *(RegList.List);
966 }
967
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000968 unsigned getRegPair() const {
969 assert((Kind == k_RegPair) && "Invalid access!");
970 return RegIdx.Index;
971 }
972
David Blaikie960ea3f2014-06-08 16:18:35 +0000973 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
974 MipsAsmParser &Parser) {
975 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000976 Op->Tok.Data = Str.data();
977 Op->Tok.Length = Str.size();
978 Op->StartLoc = S;
979 Op->EndLoc = S;
980 return Op;
981 }
982
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000983 /// Create a numeric register (e.g. $1). The exact register remains
984 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000985 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000986 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000987 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000988 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000989 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000990 }
991
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 /// Create a register that is definitely a GPR.
993 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000994 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000995 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000996 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000998 }
999
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 /// Create a register that is definitely a FGR.
1001 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001002 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001003 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001004 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001005 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1006 }
1007
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001008 /// Create a register that is definitely a HWReg.
1009 /// This is typically only used for named registers such as $hwr_cpunum.
1010 static std::unique_ptr<MipsOperand>
1011 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1012 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1013 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1014 }
1015
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 /// Create a register that is definitely an FCC.
1017 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001018 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001019 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001020 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1022 }
1023
1024 /// Create a register that is definitely an ACC.
1025 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001026 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001027 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001028 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1030 }
1031
1032 /// Create a register that is definitely an MSA128.
1033 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001034 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001035 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001036 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1038 }
1039
1040 /// Create a register that is definitely an MSACtrl.
1041 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001042 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001043 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001044 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1046 }
1047
David Blaikie960ea3f2014-06-08 16:18:35 +00001048 static std::unique_ptr<MipsOperand>
1049 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1050 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001051 Op->Imm.Val = Val;
1052 Op->StartLoc = S;
1053 Op->EndLoc = E;
1054 return Op;
1055 }
1056
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 static std::unique_ptr<MipsOperand>
1058 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1059 SMLoc E, MipsAsmParser &Parser) {
1060 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1061 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001062 Op->Mem.Off = Off;
1063 Op->StartLoc = S;
1064 Op->EndLoc = E;
1065 return Op;
1066 }
1067
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001068 static std::unique_ptr<MipsOperand>
1069 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1070 MipsAsmParser &Parser) {
1071 assert (Regs.size() > 0 && "Empty list not allowed");
1072
1073 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001074 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001075 Op->StartLoc = StartLoc;
1076 Op->EndLoc = EndLoc;
1077 return Op;
1078 }
1079
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001080 static std::unique_ptr<MipsOperand>
1081 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1082 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1083 Op->RegIdx.Index = RegNo;
1084 Op->StartLoc = S;
1085 Op->EndLoc = E;
1086 return Op;
1087 }
1088
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001089 bool isGPRAsmReg() const {
1090 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001091 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001092 bool isMM16AsmReg() const {
1093 if (!(isRegIdx() && RegIdx.Kind))
1094 return false;
1095 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1096 || RegIdx.Index == 16 || RegIdx.Index == 17);
1097 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001098 bool isMM16AsmRegZero() const {
1099 if (!(isRegIdx() && RegIdx.Kind))
1100 return false;
1101 return (RegIdx.Index == 0 ||
1102 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1103 RegIdx.Index == 17);
1104 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001105 bool isMM16AsmRegMoveP() const {
1106 if (!(isRegIdx() && RegIdx.Kind))
1107 return false;
1108 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1109 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1110 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 bool isFGRAsmReg() const {
1112 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1113 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001114 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 bool isHWRegsAsmReg() const {
1116 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001117 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 bool isCCRAsmReg() const {
1119 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001120 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001121 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001122 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1123 return false;
1124 if (!AsmParser.hasEightFccRegisters())
1125 return RegIdx.Index == 0;
1126 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001127 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 bool isACCAsmReg() const {
1129 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001130 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001131 bool isCOP2AsmReg() const {
1132 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001133 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001134 bool isCOP3AsmReg() const {
1135 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1136 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 bool isMSA128AsmReg() const {
1138 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001139 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 bool isMSACtrlAsmReg() const {
1141 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001142 }
1143
Jack Carterb4dbc172012-09-05 23:34:03 +00001144 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001145 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001146 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001147 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001148
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001149 virtual ~MipsOperand() {
1150 switch (Kind) {
1151 case k_Immediate:
1152 break;
1153 case k_Memory:
1154 delete Mem.Base;
1155 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001156 case k_RegList:
1157 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001158 case k_PhysRegister:
1159 case k_RegisterIndex:
1160 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001161 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001162 break;
1163 }
1164 }
1165
Craig Topper56c590a2014-04-29 07:58:02 +00001166 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 switch (Kind) {
1168 case k_Immediate:
1169 OS << "Imm<";
1170 Imm.Val->print(OS);
1171 OS << ">";
1172 break;
1173 case k_Memory:
1174 OS << "Mem<";
1175 Mem.Base->print(OS);
1176 OS << ", ";
1177 Mem.Off->print(OS);
1178 OS << ">";
1179 break;
1180 case k_PhysRegister:
1181 OS << "PhysReg<" << PhysReg.Num << ">";
1182 break;
1183 case k_RegisterIndex:
1184 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1185 break;
1186 case k_Token:
1187 OS << Tok.Data;
1188 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001189 case k_RegList:
1190 OS << "RegList< ";
1191 for (auto Reg : (*RegList.List))
1192 OS << Reg << " ";
1193 OS << ">";
1194 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001195 case k_RegPair:
1196 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1197 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001198 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001199 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001200}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001201} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001202
Jack Carter9e65aa32013-03-22 00:05:30 +00001203namespace llvm {
1204extern const MCInstrDesc MipsInsts[];
1205}
1206static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1207 return MipsInsts[Opcode];
1208}
1209
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001210static bool hasShortDelaySlot(unsigned Opcode) {
1211 switch (Opcode) {
1212 case Mips::JALS_MM:
1213 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001214 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001215 case Mips::BGEZALS_MM:
1216 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001217 return true;
1218 default:
1219 return false;
1220 }
1221}
1222
Jack Carter9e65aa32013-03-22 00:05:30 +00001223bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001224 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001225 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001226
Jack Carter9e65aa32013-03-22 00:05:30 +00001227 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001228
1229 if (MCID.isBranch() || MCID.isCall()) {
1230 const unsigned Opcode = Inst.getOpcode();
1231 MCOperand Offset;
1232
1233 switch (Opcode) {
1234 default:
1235 break;
Kai Nackee0245392015-01-27 19:11:28 +00001236 case Mips::BBIT0:
1237 case Mips::BBIT032:
1238 case Mips::BBIT1:
1239 case Mips::BBIT132:
1240 assert(hasCnMips() && "instruction only valid for octeon cpus");
1241 // Fall through
1242
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001243 case Mips::BEQ:
1244 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 case Mips::BEQ_MM:
1246 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001247 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001248 Offset = Inst.getOperand(2);
1249 if (!Offset.isImm())
1250 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001251 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001252 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001253 if (OffsetToAlignment(Offset.getImm(),
1254 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001255 return Error(IDLoc, "branch to misaligned address");
1256 break;
1257 case Mips::BGEZ:
1258 case Mips::BGTZ:
1259 case Mips::BLEZ:
1260 case Mips::BLTZ:
1261 case Mips::BGEZAL:
1262 case Mips::BLTZAL:
1263 case Mips::BC1F:
1264 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001265 case Mips::BGEZ_MM:
1266 case Mips::BGTZ_MM:
1267 case Mips::BLEZ_MM:
1268 case Mips::BLTZ_MM:
1269 case Mips::BGEZAL_MM:
1270 case Mips::BLTZAL_MM:
1271 case Mips::BC1F_MM:
1272 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001273 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001274 Offset = Inst.getOperand(1);
1275 if (!Offset.isImm())
1276 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001277 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001278 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001279 if (OffsetToAlignment(Offset.getImm(),
1280 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001281 return Error(IDLoc, "branch to misaligned address");
1282 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001283 case Mips::BEQZ16_MM:
1284 case Mips::BNEZ16_MM:
1285 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1286 Offset = Inst.getOperand(1);
1287 if (!Offset.isImm())
1288 break; // We'll deal with this situation later on when applying fixups.
1289 if (!isIntN(8, Offset.getImm()))
1290 return Error(IDLoc, "branch target out of range");
1291 if (OffsetToAlignment(Offset.getImm(), 2LL))
1292 return Error(IDLoc, "branch to misaligned address");
1293 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001294 }
1295 }
1296
Daniel Sandersa84989a2014-06-16 13:25:35 +00001297 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1298 // We still accept it but it is a normal nop.
1299 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1300 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1301 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1302 "nop instruction");
1303 }
1304
Kai Nackee0245392015-01-27 19:11:28 +00001305 if (hasCnMips()) {
1306 const unsigned Opcode = Inst.getOpcode();
1307 MCOperand Opnd;
1308 int Imm;
1309
1310 switch (Opcode) {
1311 default:
1312 break;
1313
1314 case Mips::BBIT0:
1315 case Mips::BBIT032:
1316 case Mips::BBIT1:
1317 case Mips::BBIT132:
1318 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1319 // The offset is handled above
1320 Opnd = Inst.getOperand(1);
1321 if (!Opnd.isImm())
1322 return Error(IDLoc, "expected immediate operand kind");
1323 Imm = Opnd.getImm();
1324 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1325 Opcode == Mips::BBIT1 ? 63 : 31))
1326 return Error(IDLoc, "immediate operand value out of range");
1327 if (Imm > 31) {
1328 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1329 : Mips::BBIT132);
1330 Inst.getOperand(1).setImm(Imm - 32);
1331 }
1332 break;
1333
1334 case Mips::CINS:
1335 case Mips::CINS32:
1336 case Mips::EXTS:
1337 case Mips::EXTS32:
1338 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1339 // Check length
1340 Opnd = Inst.getOperand(3);
1341 if (!Opnd.isImm())
1342 return Error(IDLoc, "expected immediate operand kind");
1343 Imm = Opnd.getImm();
1344 if (Imm < 0 || Imm > 31)
1345 return Error(IDLoc, "immediate operand value out of range");
1346 // Check position
1347 Opnd = Inst.getOperand(2);
1348 if (!Opnd.isImm())
1349 return Error(IDLoc, "expected immediate operand kind");
1350 Imm = Opnd.getImm();
1351 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1352 Opcode == Mips::EXTS ? 63 : 31))
1353 return Error(IDLoc, "immediate operand value out of range");
1354 if (Imm > 31) {
1355 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1356 Inst.getOperand(2).setImm(Imm - 32);
1357 }
1358 break;
1359
1360 case Mips::SEQi:
1361 case Mips::SNEi:
1362 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1363 Opnd = Inst.getOperand(2);
1364 if (!Opnd.isImm())
1365 return Error(IDLoc, "expected immediate operand kind");
1366 Imm = Opnd.getImm();
1367 if (!isInt<10>(Imm))
1368 return Error(IDLoc, "immediate operand value out of range");
1369 break;
1370 }
1371 }
1372
Toma Tabacu234482a2015-03-16 12:03:39 +00001373 // If this instruction has a delay slot and .set reorder is active,
1374 // emit a NOP after it.
Toma Tabacu9db22db2014-09-09 10:15:38 +00001375 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001376 Instructions.push_back(Inst);
Toma Tabacu234482a2015-03-16 12:03:39 +00001377 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
Jack Carterc15c1d22013-04-25 23:31:35 +00001378 return false;
1379 }
1380
Jack Carter9e65aa32013-03-22 00:05:30 +00001381 if (MCID.mayLoad() || MCID.mayStore()) {
1382 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001383 // reference or immediate we may have to expand instructions.
1384 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001385 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001386 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1387 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001388 MCOperand &Op = Inst.getOperand(i);
1389 if (Op.isImm()) {
1390 int MemOffset = Op.getImm();
1391 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001392 // Offset can't exceed 16bit value.
1393 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001394 return false;
1395 }
1396 } else if (Op.isExpr()) {
1397 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001400 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001401 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001402 // Expand symbol.
1403 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001404 return false;
1405 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001406 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001408 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 }
1410 }
1411 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001413 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001414
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001415 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001416 if (MCID.mayLoad()) {
1417 // Try to create 16-bit GP relative load instruction.
1418 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1419 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1420 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1421 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1422 MCOperand &Op = Inst.getOperand(i);
1423 if (Op.isImm()) {
1424 int MemOffset = Op.getImm();
1425 MCOperand &DstReg = Inst.getOperand(0);
1426 MCOperand &BaseReg = Inst.getOperand(1);
1427 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1428 getContext().getRegisterInfo()->getRegClass(
1429 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1430 BaseReg.getReg() == Mips::GP) {
1431 MCInst TmpInst;
1432 TmpInst.setLoc(IDLoc);
1433 TmpInst.setOpcode(Mips::LWGP_MM);
1434 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1435 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1436 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1437 Instructions.push_back(TmpInst);
1438 return false;
1439 }
1440 }
1441 }
1442 } // for
1443 } // if load
1444
1445 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1446
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001447 MCOperand Opnd;
1448 int Imm;
1449
1450 switch (Inst.getOpcode()) {
1451 default:
1452 break;
1453 case Mips::ADDIUS5_MM:
1454 Opnd = Inst.getOperand(2);
1455 if (!Opnd.isImm())
1456 return Error(IDLoc, "expected immediate operand kind");
1457 Imm = Opnd.getImm();
1458 if (Imm < -8 || Imm > 7)
1459 return Error(IDLoc, "immediate operand value out of range");
1460 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001461 case Mips::ADDIUSP_MM:
1462 Opnd = Inst.getOperand(0);
1463 if (!Opnd.isImm())
1464 return Error(IDLoc, "expected immediate operand kind");
1465 Imm = Opnd.getImm();
1466 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1467 Imm % 4 != 0)
1468 return Error(IDLoc, "immediate operand value out of range");
1469 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001470 case Mips::SLL16_MM:
1471 case Mips::SRL16_MM:
1472 Opnd = Inst.getOperand(2);
1473 if (!Opnd.isImm())
1474 return Error(IDLoc, "expected immediate operand kind");
1475 Imm = Opnd.getImm();
1476 if (Imm < 1 || Imm > 8)
1477 return Error(IDLoc, "immediate operand value out of range");
1478 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001479 case Mips::LI16_MM:
1480 Opnd = Inst.getOperand(1);
1481 if (!Opnd.isImm())
1482 return Error(IDLoc, "expected immediate operand kind");
1483 Imm = Opnd.getImm();
1484 if (Imm < -1 || Imm > 126)
1485 return Error(IDLoc, "immediate operand value out of range");
1486 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001487 case Mips::ADDIUR2_MM:
1488 Opnd = Inst.getOperand(2);
1489 if (!Opnd.isImm())
1490 return Error(IDLoc, "expected immediate operand kind");
1491 Imm = Opnd.getImm();
1492 if (!(Imm == 1 || Imm == -1 ||
1493 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1494 return Error(IDLoc, "immediate operand value out of range");
1495 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001496 case Mips::ADDIUR1SP_MM:
1497 Opnd = Inst.getOperand(1);
1498 if (!Opnd.isImm())
1499 return Error(IDLoc, "expected immediate operand kind");
1500 Imm = Opnd.getImm();
1501 if (OffsetToAlignment(Imm, 4LL))
1502 return Error(IDLoc, "misaligned immediate operand value");
1503 if (Imm < 0 || Imm > 255)
1504 return Error(IDLoc, "immediate operand value out of range");
1505 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001506 case Mips::ANDI16_MM:
1507 Opnd = Inst.getOperand(2);
1508 if (!Opnd.isImm())
1509 return Error(IDLoc, "expected immediate operand kind");
1510 Imm = Opnd.getImm();
1511 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1512 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1513 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1514 return Error(IDLoc, "immediate operand value out of range");
1515 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001516 case Mips::LBU16_MM:
1517 Opnd = Inst.getOperand(2);
1518 if (!Opnd.isImm())
1519 return Error(IDLoc, "expected immediate operand kind");
1520 Imm = Opnd.getImm();
1521 if (Imm < -1 || Imm > 14)
1522 return Error(IDLoc, "immediate operand value out of range");
1523 break;
1524 case Mips::SB16_MM:
1525 Opnd = Inst.getOperand(2);
1526 if (!Opnd.isImm())
1527 return Error(IDLoc, "expected immediate operand kind");
1528 Imm = Opnd.getImm();
1529 if (Imm < 0 || Imm > 15)
1530 return Error(IDLoc, "immediate operand value out of range");
1531 break;
1532 case Mips::LHU16_MM:
1533 case Mips::SH16_MM:
1534 Opnd = Inst.getOperand(2);
1535 if (!Opnd.isImm())
1536 return Error(IDLoc, "expected immediate operand kind");
1537 Imm = Opnd.getImm();
1538 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1539 return Error(IDLoc, "immediate operand value out of range");
1540 break;
1541 case Mips::LW16_MM:
1542 case Mips::SW16_MM:
1543 Opnd = Inst.getOperand(2);
1544 if (!Opnd.isImm())
1545 return Error(IDLoc, "expected immediate operand kind");
1546 Imm = Opnd.getImm();
1547 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1548 return Error(IDLoc, "immediate operand value out of range");
1549 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001550 case Mips::CACHE:
1551 case Mips::PREF:
1552 Opnd = Inst.getOperand(2);
1553 if (!Opnd.isImm())
1554 return Error(IDLoc, "expected immediate operand kind");
1555 Imm = Opnd.getImm();
1556 if (!isUInt<5>(Imm))
1557 return Error(IDLoc, "immediate operand value out of range");
1558 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001559 case Mips::ADDIUPC_MM:
1560 MCOperand Opnd = Inst.getOperand(1);
1561 if (!Opnd.isImm())
1562 return Error(IDLoc, "expected immediate operand kind");
1563 int Imm = Opnd.getImm();
1564 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1565 return Error(IDLoc, "immediate operand value out of range");
1566 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001567 }
1568 }
1569
Jack Carter9e65aa32013-03-22 00:05:30 +00001570 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001571 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001572 else
1573 Instructions.push_back(Inst);
1574
1575 return false;
1576}
1577
Jack Carter30a59822012-10-04 04:03:53 +00001578bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1579
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001581 case Mips::LoadImm32:
1582 case Mips::LoadImm64:
1583 case Mips::LoadAddrImm32:
1584 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001585 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001586 case Mips::LWM_MM:
1587 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001588 case Mips::JalOneReg:
1589 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001590 return true;
1591 default:
1592 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001593 }
1594}
Jack Carter92995f12012-10-06 00:53:28 +00001595
Matheus Almeida3813d572014-06-19 14:39:14 +00001596bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001597 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001598 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001599 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001600 case Mips::LoadImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001602 case Mips::LoadImm64:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001603 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001604 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001605 return true;
1606 }
1607 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001608 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001610 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001612 case Mips::B_MM_Pseudo:
1613 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001614 case Mips::SWM_MM:
1615 case Mips::LWM_MM:
1616 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001617 case Mips::JalOneReg:
1618 case Mips::JalTwoReg:
1619 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 }
Jack Carter30a59822012-10-04 04:03:53 +00001621}
Jack Carter92995f12012-10-06 00:53:28 +00001622
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001623namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001624template <bool PerformShift>
1625void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001626 SmallVectorImpl<MCInst> &Instructions) {
1627 MCInst tmpInst;
1628 if (PerformShift) {
1629 tmpInst.setOpcode(Mips::DSLL);
1630 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1631 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1632 tmpInst.addOperand(MCOperand::CreateImm(16));
1633 tmpInst.setLoc(IDLoc);
1634 Instructions.push_back(tmpInst);
1635 tmpInst.clear();
1636 }
1637 tmpInst.setOpcode(Mips::ORi);
1638 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1639 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001640 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001641 tmpInst.setLoc(IDLoc);
1642 Instructions.push_back(tmpInst);
1643}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001644
1645template <int Shift, bool PerformShift>
1646void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1647 SmallVectorImpl<MCInst> &Instructions) {
1648 createShiftOr<PerformShift>(
1649 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1650 IDLoc, Instructions);
1651}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001652}
1653
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001654bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1655 SmallVectorImpl<MCInst> &Instructions) {
1656 // Create a JALR instruction which is going to replace the pseudo-JAL.
1657 MCInst JalrInst;
1658 JalrInst.setLoc(IDLoc);
1659 const MCOperand FirstRegOp = Inst.getOperand(0);
1660 const unsigned Opcode = Inst.getOpcode();
1661
1662 if (Opcode == Mips::JalOneReg) {
1663 // jal $rs => jalr $rs
1664 if (inMicroMipsMode()) {
1665 JalrInst.setOpcode(Mips::JALR16_MM);
1666 JalrInst.addOperand(FirstRegOp);
1667 } else {
1668 JalrInst.setOpcode(Mips::JALR);
1669 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1670 JalrInst.addOperand(FirstRegOp);
1671 }
1672 } else if (Opcode == Mips::JalTwoReg) {
1673 // jal $rd, $rs => jalr $rd, $rs
1674 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1675 JalrInst.addOperand(FirstRegOp);
1676 const MCOperand SecondRegOp = Inst.getOperand(1);
1677 JalrInst.addOperand(SecondRegOp);
1678 }
1679 Instructions.push_back(JalrInst);
1680
1681 // If .set reorder is active, emit a NOP after it.
1682 if (AssemblerOptions.back()->isReorder()) {
1683 // This is a 32-bit NOP because these 2 pseudo-instructions
1684 // do not have a short delay slot.
1685 MCInst NopInst;
1686 NopInst.setOpcode(Mips::SLL);
1687 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1688 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1689 NopInst.addOperand(MCOperand::CreateImm(0));
1690 Instructions.push_back(NopInst);
1691 }
1692
1693 return false;
1694}
1695
Matheus Almeida3813d572014-06-19 14:39:14 +00001696bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001697 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001698 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001699 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001700 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001701 const MCOperand &RegOp = Inst.getOperand(0);
1702 assert(RegOp.isReg() && "expected register operand kind");
1703
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001704 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001705 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001706 // FIXME: gas has a special case for values that are 000...1111, which
1707 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 if (0 <= ImmValue && ImmValue <= 65535) {
1709 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001710 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001711 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001712 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001713 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001714 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001715 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 } else if (ImmValue < 0 && ImmValue >= -32768) {
1717 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001718 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001719 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001720 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001721 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001722 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001723 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001724 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1725 // For any value of j that is representable as a 32-bit integer, create
1726 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001727 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001728 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001729 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001730 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1731 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001732 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001733 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1734 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001735 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001736 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001737 return true;
1738 }
1739
1740 // <------- lo32 ------>
1741 // <------- hi32 ------>
1742 // <- hi16 -> <- lo16 ->
1743 // _________________________________
1744 // | | | |
1745 // | 16-bytes | 16-bytes | 16-bytes |
1746 // |__________|__________|__________|
1747 //
1748 // For any value of j that is representable as a 48-bit integer, create
1749 // a sequence of:
1750 // li d,j => lui d,hi16(j)
1751 // ori d,d,hi16(lo32(j))
1752 // dsll d,d,16
1753 // ori d,d,lo16(lo32(j))
1754 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001755 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001756 tmpInst.addOperand(
1757 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001758 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001759 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1760 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1761 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001762 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001763 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001764 return true;
1765 }
1766
1767 // <------- hi32 ------> <------- lo32 ------>
1768 // <- hi16 -> <- lo16 ->
1769 // ___________________________________________
1770 // | | | | |
1771 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1772 // |__________|__________|__________|__________|
1773 //
1774 // For any value of j that isn't representable as a 48-bit integer.
1775 // li d,j => lui d,hi16(j)
1776 // ori d,d,lo16(hi32(j))
1777 // dsll d,d,16
1778 // ori d,d,hi16(lo32(j))
1779 // dsll d,d,16
1780 // ori d,d,lo16(lo32(j))
1781 tmpInst.setOpcode(Mips::LUi);
1782 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1783 tmpInst.addOperand(
1784 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1785 Instructions.push_back(tmpInst);
1786 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1787 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1788 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001789 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001790 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001791}
Jack Carter92995f12012-10-06 00:53:28 +00001792
Matheus Almeida3813d572014-06-19 14:39:14 +00001793bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001794MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1795 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001796 MCInst tmpInst;
1797 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001798 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1799 "expected immediate operand kind");
1800 if (!ImmOp.isImm()) {
1801 expandLoadAddressSym(Inst, IDLoc, Instructions);
1802 return false;
1803 }
Jack Carter543fdf82012-10-09 23:29:45 +00001804 const MCOperand &SrcRegOp = Inst.getOperand(1);
1805 assert(SrcRegOp.isReg() && "expected register operand kind");
1806 const MCOperand &DstRegOp = Inst.getOperand(0);
1807 assert(DstRegOp.isReg() && "expected register operand kind");
1808 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001809 if (-32768 <= ImmValue && ImmValue <= 65535) {
1810 // For -32768 <= j <= 65535.
1811 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001812 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001813 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1814 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1815 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1816 Instructions.push_back(tmpInst);
1817 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001818 // For any other value of j that is representable as a 32-bit integer.
1819 // la d,j(s) => lui d,hi16(j)
1820 // ori d,d,lo16(j)
1821 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001822 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001823 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1824 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1825 Instructions.push_back(tmpInst);
1826 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001827 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001828 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1829 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1830 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1831 Instructions.push_back(tmpInst);
1832 tmpInst.clear();
1833 tmpInst.setOpcode(Mips::ADDu);
1834 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1835 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1836 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1837 Instructions.push_back(tmpInst);
1838 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001839 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001840}
1841
Matheus Almeida3813d572014-06-19 14:39:14 +00001842bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001843MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1844 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001845 MCInst tmpInst;
1846 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001847 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1848 "expected immediate operand kind");
1849 if (!ImmOp.isImm()) {
1850 expandLoadAddressSym(Inst, IDLoc, Instructions);
1851 return false;
1852 }
Jack Carter543fdf82012-10-09 23:29:45 +00001853 const MCOperand &RegOp = Inst.getOperand(0);
1854 assert(RegOp.isReg() && "expected register operand kind");
1855 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 if (-32768 <= ImmValue && ImmValue <= 65535) {
1857 // For -32768 <= j <= 65535.
1858 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001859 tmpInst.setOpcode(Mips::ADDiu);
1860 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001861 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001862 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1863 Instructions.push_back(tmpInst);
1864 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001865 // For any other value of j that is representable as a 32-bit integer.
1866 // la d,j => lui d,hi16(j)
1867 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001868 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001869 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1870 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1871 Instructions.push_back(tmpInst);
1872 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001873 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001874 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1875 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1876 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1877 Instructions.push_back(tmpInst);
1878 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001879 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001880}
1881
Toma Tabacu0d64b202014-08-14 10:29:17 +00001882void
1883MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1884 SmallVectorImpl<MCInst> &Instructions) {
1885 // FIXME: If we do have a valid at register to use, we should generate a
1886 // slightly shorter sequence here.
1887 MCInst tmpInst;
1888 int ExprOperandNo = 1;
1889 // Sometimes the assembly parser will get the immediate expression as
1890 // a $zero + an immediate.
1891 if (Inst.getNumOperands() == 3) {
1892 assert(Inst.getOperand(1).getReg() ==
1893 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1894 ExprOperandNo = 2;
1895 }
1896 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1897 assert(SymOp.isExpr() && "expected symbol operand kind");
1898 const MCOperand &RegOp = Inst.getOperand(0);
1899 unsigned RegNo = RegOp.getReg();
1900 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1901 const MCSymbolRefExpr *HiExpr =
1902 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1903 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1904 const MCSymbolRefExpr *LoExpr =
1905 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1906 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1907 if (isGP64bit()) {
1908 // If it's a 64-bit architecture, expand to:
1909 // la d,sym => lui d,highest(sym)
1910 // ori d,d,higher(sym)
1911 // dsll d,d,16
1912 // ori d,d,hi16(sym)
1913 // dsll d,d,16
1914 // ori d,d,lo16(sym)
1915 const MCSymbolRefExpr *HighestExpr =
1916 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1917 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1918 const MCSymbolRefExpr *HigherExpr =
1919 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1920 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1921
1922 tmpInst.setOpcode(Mips::LUi);
1923 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1924 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1925 Instructions.push_back(tmpInst);
1926
1927 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1928 Instructions);
1929 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1930 Instructions);
1931 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1932 Instructions);
1933 } else {
1934 // Otherwise, expand to:
1935 // la d,sym => lui d,hi16(sym)
1936 // ori d,d,lo16(sym)
1937 tmpInst.setOpcode(Mips::LUi);
1938 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1939 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1940 Instructions.push_back(tmpInst);
1941
1942 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1943 Instructions);
1944 }
1945}
1946
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001947bool MipsAsmParser::expandUncondBranchMMPseudo(
1948 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001949 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1950 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001951
1952 MCOperand Offset = Inst.getOperand(0);
1953 if (Offset.isExpr()) {
1954 Inst.clear();
1955 Inst.setOpcode(Mips::BEQ_MM);
1956 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1957 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1958 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1959 } else {
1960 assert(Offset.isImm() && "expected immediate operand kind");
1961 if (isIntN(11, Offset.getImm())) {
1962 // If offset fits into 11 bits then this instruction becomes microMIPS
1963 // 16-bit unconditional branch instruction.
1964 Inst.setOpcode(Mips::B16_MM);
1965 } else {
1966 if (!isIntN(17, Offset.getImm()))
1967 Error(IDLoc, "branch target out of range");
1968 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1969 Error(IDLoc, "branch to misaligned address");
1970 Inst.clear();
1971 Inst.setOpcode(Mips::BEQ_MM);
1972 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1973 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1974 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1975 }
1976 }
1977 Instructions.push_back(Inst);
1978
Toma Tabacu234482a2015-03-16 12:03:39 +00001979 // If .set reorder is active, emit a NOP after the branch instruction.
1980 if (AssemblerOptions.back()->isReorder())
1981 createNop(true, IDLoc, Instructions);
1982
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001983 return false;
1984}
1985
Jack Carter9e65aa32013-03-22 00:05:30 +00001986void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001987 SmallVectorImpl<MCInst> &Instructions,
1988 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001989 const MCSymbolRefExpr *SR;
1990 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001991 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001992 const MCExpr *ExprOffset;
1993 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001994 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001995 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1996 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001997 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001998 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1999 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002000 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002001 if (isImmOpnd) {
2002 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2003 ImmOffset = Inst.getOperand(2).getImm();
2004 LoOffset = ImmOffset & 0x0000ffff;
2005 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002006 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002007 if (LoOffset & 0x8000)
2008 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002010 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002012 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002013 // These are some of the types of expansions we perform here:
2014 // 1) lw $8, sym => lui $8, %hi(sym)
2015 // lw $8, %lo(sym)($8)
2016 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2017 // add $8, $8, $9
2018 // lw $8, %lo(offset)($9)
2019 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2020 // add $at, $at, $8
2021 // lw $8, %lo(offset)($at)
2022 // 4) sw $8, sym => lui $at, %hi(sym)
2023 // sw $8, %lo(sym)($at)
2024 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2025 // add $at, $at, $8
2026 // sw $8, %lo(offset)($at)
2027 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2028 // ldc1 $f0, %lo(sym)($at)
2029 //
2030 // For load instructions we can use the destination register as a temporary
2031 // if base and dst are different (examples 1 and 2) and if the base register
2032 // is general purpose otherwise we must use $at (example 6) and error if it's
2033 // not available. For stores we must use $at (examples 4 and 5) because we
2034 // must not clobber the source register setting up the offset.
2035 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2036 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2037 unsigned RegClassIDOp0 =
2038 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2039 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2040 (RegClassIDOp0 == Mips::GPR64RegClassID);
2041 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002042 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002043 else {
2044 int AT = getATReg(IDLoc);
2045 // At this point we need AT to perform the expansions and we exit if it is
2046 // not available.
2047 if (!AT)
2048 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002049 TmpRegNum = getReg(
2050 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002051 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002052
Jack Carter9e65aa32013-03-22 00:05:30 +00002053 TempInst.setOpcode(Mips::LUi);
2054 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2055 if (isImmOpnd)
2056 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2057 else {
2058 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002059 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002060 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2061 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2062 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002063 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002064 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002065 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002066 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002067 }
2068 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002069 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002070 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002071 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002072 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002073 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002074 TempInst.setOpcode(Mips::ADDu);
2075 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2076 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2077 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2078 Instructions.push_back(TempInst);
2079 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00002080 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002082 TempInst.setOpcode(Inst.getOpcode());
2083 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2084 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2085 if (isImmOpnd)
2086 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2087 else {
2088 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2090 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2091 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002092 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002093 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002094 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002095 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 }
2097 }
2098 Instructions.push_back(TempInst);
2099 TempInst.clear();
2100}
2101
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002102bool
2103MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2104 SmallVectorImpl<MCInst> &Instructions) {
2105 unsigned OpNum = Inst.getNumOperands();
2106 unsigned Opcode = Inst.getOpcode();
2107 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2108
2109 assert (Inst.getOperand(OpNum - 1).isImm() &&
2110 Inst.getOperand(OpNum - 2).isReg() &&
2111 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2112
2113 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2114 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2115 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2116 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2117 // It can be implemented as SWM16 or LWM16 instruction.
2118 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2119
2120 Inst.setOpcode(NewOpcode);
2121 Instructions.push_back(Inst);
2122 return false;
2123}
2124
Toma Tabacu234482a2015-03-16 12:03:39 +00002125void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2126 SmallVectorImpl<MCInst> &Instructions) {
2127 MCInst NopInst;
2128 if (hasShortDelaySlot) {
2129 NopInst.setOpcode(Mips::MOVE16_MM);
2130 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2131 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2132 } else {
2133 NopInst.setOpcode(Mips::SLL);
2134 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2135 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2136 NopInst.addOperand(MCOperand::CreateImm(0));
2137 }
2138 Instructions.push_back(NopInst);
2139}
2140
Matheus Almeida595fcab2014-06-11 15:05:56 +00002141unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2142 // As described by the Mips32r2 spec, the registers Rd and Rs for
2143 // jalr.hb must be different.
2144 unsigned Opcode = Inst.getOpcode();
2145
2146 if (Opcode == Mips::JALR_HB &&
2147 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2148 return Match_RequiresDifferentSrcAndDst;
2149
2150 return Match_Success;
2151}
2152
David Blaikie960ea3f2014-06-08 16:18:35 +00002153bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2154 OperandVector &Operands,
2155 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002156 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002157 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002158
Jack Carterb4dbc172012-09-05 23:34:03 +00002159 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002160 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002161 unsigned MatchResult =
2162 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002163
2164 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002165 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002167 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002169 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002170 return false;
2171 }
2172 case Match_MissingFeature:
2173 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2174 return true;
2175 case Match_InvalidOperand: {
2176 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002177 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002178 if (ErrorInfo >= Operands.size())
2179 return Error(IDLoc, "too few operands for instruction");
2180
David Blaikie960ea3f2014-06-08 16:18:35 +00002181 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002182 if (ErrorLoc == SMLoc())
2183 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002184 }
2185
2186 return Error(ErrorLoc, "invalid operand for instruction");
2187 }
2188 case Match_MnemonicFail:
2189 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002190 case Match_RequiresDifferentSrcAndDst:
2191 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002192 }
Craig Topper589ceee2015-01-03 08:16:34 +00002193
2194 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002195}
2196
Toma Tabacu13964452014-09-04 13:23:44 +00002197void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002198 if ((RegIndex != 0) &&
2199 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002200 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002201 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002202 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002203 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002204 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002205 }
2206}
2207
Daniel Sandersef638fe2014-10-03 15:37:37 +00002208void
2209MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2210 SMRange Range, bool ShowColors) {
2211 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002212 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002213 ShowColors);
2214}
2215
Jack Carter1ac53222013-02-20 23:11:17 +00002216int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002217 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002218
Vladimir Medic4c299852013-11-06 11:27:05 +00002219 CC = StringSwitch<unsigned>(Name)
2220 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002221 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002222 .Case("a0", 4)
2223 .Case("a1", 5)
2224 .Case("a2", 6)
2225 .Case("a3", 7)
2226 .Case("v0", 2)
2227 .Case("v1", 3)
2228 .Case("s0", 16)
2229 .Case("s1", 17)
2230 .Case("s2", 18)
2231 .Case("s3", 19)
2232 .Case("s4", 20)
2233 .Case("s5", 21)
2234 .Case("s6", 22)
2235 .Case("s7", 23)
2236 .Case("k0", 26)
2237 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002238 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002239 .Case("sp", 29)
2240 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002241 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002242 .Case("ra", 31)
2243 .Case("t0", 8)
2244 .Case("t1", 9)
2245 .Case("t2", 10)
2246 .Case("t3", 11)
2247 .Case("t4", 12)
2248 .Case("t5", 13)
2249 .Case("t6", 14)
2250 .Case("t7", 15)
2251 .Case("t8", 24)
2252 .Case("t9", 25)
2253 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002254
Toma Tabacufda445c2014-09-15 15:33:01 +00002255 if (!(isABI_N32() || isABI_N64()))
2256 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002257
Daniel Sandersef638fe2014-10-03 15:37:37 +00002258 if (12 <= CC && CC <= 15) {
2259 // Name is one of t4-t7
2260 AsmToken RegTok = getLexer().peekTok();
2261 SMRange RegRange = RegTok.getLocRange();
2262
2263 StringRef FixedName = StringSwitch<StringRef>(Name)
2264 .Case("t4", "t0")
2265 .Case("t5", "t1")
2266 .Case("t6", "t2")
2267 .Case("t7", "t3")
2268 .Default("");
2269 assert(FixedName != "" && "Register name is not one of t4-t7.");
2270
2271 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2272 "Did you mean $" + FixedName + "?", RegRange);
2273 }
2274
Toma Tabacufda445c2014-09-15 15:33:01 +00002275 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2276 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2277 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2278 if (8 <= CC && CC <= 11)
2279 CC += 4;
2280
2281 if (CC == -1)
2282 CC = StringSwitch<unsigned>(Name)
2283 .Case("a4", 8)
2284 .Case("a5", 9)
2285 .Case("a6", 10)
2286 .Case("a7", 11)
2287 .Case("kt0", 26)
2288 .Case("kt1", 27)
2289 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002290
2291 return CC;
2292}
Jack Carterd0bd6422013-04-18 00:41:53 +00002293
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002294int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2295 int CC;
2296
2297 CC = StringSwitch<unsigned>(Name)
2298 .Case("hwr_cpunum", 0)
2299 .Case("hwr_synci_step", 1)
2300 .Case("hwr_cc", 2)
2301 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002302 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002303 .Default(-1);
2304
2305 return CC;
2306}
2307
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002308int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002309
Jack Cartera63b16a2012-09-07 00:23:42 +00002310 if (Name[0] == 'f') {
2311 StringRef NumString = Name.substr(1);
2312 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002313 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002314 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002315 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002316 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002317 return IntVal;
2318 }
2319 return -1;
2320}
Jack Cartera63b16a2012-09-07 00:23:42 +00002321
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002322int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2323
2324 if (Name.startswith("fcc")) {
2325 StringRef NumString = Name.substr(3);
2326 unsigned IntVal;
2327 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002328 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002329 if (IntVal > 7) // There are only 8 fcc registers.
2330 return -1;
2331 return IntVal;
2332 }
2333 return -1;
2334}
2335
2336int MipsAsmParser::matchACRegisterName(StringRef Name) {
2337
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002338 if (Name.startswith("ac")) {
2339 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002340 unsigned IntVal;
2341 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002342 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002343 if (IntVal > 3) // There are only 3 acc registers.
2344 return -1;
2345 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002346 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002347 return -1;
2348}
Jack Carterd0bd6422013-04-18 00:41:53 +00002349
Jack Carter5dc8ac92013-09-25 23:50:44 +00002350int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2351 unsigned IntVal;
2352
2353 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2354 return -1;
2355
2356 if (IntVal > 31)
2357 return -1;
2358
2359 return IntVal;
2360}
2361
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002362int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2363 int CC;
2364
2365 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002366 .Case("msair", 0)
2367 .Case("msacsr", 1)
2368 .Case("msaaccess", 2)
2369 .Case("msasave", 3)
2370 .Case("msamodify", 4)
2371 .Case("msarequest", 5)
2372 .Case("msamap", 6)
2373 .Case("msaunmap", 7)
2374 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002375
2376 return CC;
2377}
2378
Jack Carter0b744b32012-10-04 02:29:46 +00002379bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2380 if (Reg > 31)
2381 return false;
2382
Toma Tabacu3c24b042014-09-05 15:43:21 +00002383 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002384 return true;
2385}
2386
Matheus Almeida7de68e72014-06-18 14:46:05 +00002387int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002388 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002389 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002390 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002391 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002392 return AT;
2393}
Jack Carter0b744b32012-10-04 02:29:46 +00002394
Jack Carterd0bd6422013-04-18 00:41:53 +00002395unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002396 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002397}
2398
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002399unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002400 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002401 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002402}
2403
Jack Carter873c7242013-01-12 01:03:14 +00002404int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002405 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002406 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002407 return -1;
2408
Jack Carter873c7242013-01-12 01:03:14 +00002409 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002410}
2411
Toma Tabacu13964452014-09-04 13:23:44 +00002412bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002413 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002414 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002415
Jack Carter30a59822012-10-04 04:03:53 +00002416 // Check if the current operand has a custom associated parser, if so, try to
2417 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002418 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2419 if (ResTy == MatchOperand_Success)
2420 return false;
2421 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2422 // there was a match, but an error occurred, in which case, just return that
2423 // the operand parsing failed.
2424 if (ResTy == MatchOperand_ParseFail)
2425 return true;
2426
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002427 DEBUG(dbgs() << ".. Generic Parser\n");
2428
Jack Carterb4dbc172012-09-05 23:34:03 +00002429 switch (getLexer().getKind()) {
2430 default:
2431 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2432 return true;
2433 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002434 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002435 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002436
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002437 // Almost all registers have been parsed by custom parsers. There is only
2438 // one exception to this. $zero (and it's alias $0) will reach this point
2439 // for div, divu, and similar instructions because it is not an operand
2440 // to the instruction definition but an explicit register. Special case
2441 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002442 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002443 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002444
Jack Carterd0bd6422013-04-18 00:41:53 +00002445 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002446 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002447 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002448 return true;
2449
Jack Carter873c7242013-01-12 01:03:14 +00002450 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002451 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002452 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002453 const MCExpr *Res =
2454 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002455
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002456 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002457 return false;
2458 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002459 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002460 case AsmToken::LParen:
2461 case AsmToken::Minus:
2462 case AsmToken::Plus:
2463 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002464 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002466 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002467 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002469 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002470 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002471 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002472 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002473 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002474 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002475 return true;
2476
Jack Carter873c7242013-01-12 01:03:14 +00002477 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2478
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002479 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002480 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002481 } // case AsmToken::Percent
2482 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002483 return true;
2484}
2485
Vladimir Medic4c299852013-11-06 11:27:05 +00002486const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002487 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002488 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002490 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002491 // It's a constant, evaluate reloc value.
2492 int16_t Val;
2493 switch (getVariantKind(RelocStr)) {
2494 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2495 // Get the 1st 16-bits.
2496 Val = MCE->getValue() & 0xffff;
2497 break;
2498 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2499 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2500 // 16 bits being negative.
2501 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2502 break;
2503 case MCSymbolRefExpr::VK_Mips_HIGHER:
2504 // Get the 3rd 16-bits.
2505 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2506 break;
2507 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2508 // Get the 4th 16-bits.
2509 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2510 break;
2511 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002512 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002513 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002514 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002515 }
2516
Jack Carterb5cf5902013-04-17 00:18:04 +00002517 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002519 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002520 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002522 return Res;
2523 }
2524
2525 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002526 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2527
Sasa Stankovic06c47802014-04-03 10:37:45 +00002528 // Try to create target expression.
2529 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2530 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002531
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2533 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002534 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2535 return Res;
2536 }
2537
2538 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2540 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2541 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002542 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002544 return Expr;
2545}
2546
2547bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2548
2549 switch (Expr->getKind()) {
2550 case MCExpr::Constant:
2551 return true;
2552 case MCExpr::SymbolRef:
2553 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2554 case MCExpr::Binary:
2555 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2556 if (!isEvaluated(BE->getLHS()))
2557 return false;
2558 return isEvaluated(BE->getRHS());
2559 }
2560 case MCExpr::Unary:
2561 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002562 case MCExpr::Target:
2563 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002564 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002565 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002566}
Jack Carterd0bd6422013-04-18 00:41:53 +00002567
Jack Carterb5cf5902013-04-17 00:18:04 +00002568bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002569 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002570 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002572 if (Tok.isNot(AsmToken::Identifier))
2573 return true;
2574
2575 std::string Str = Tok.getIdentifier().str();
2576
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 Parser.Lex(); // Eat the identifier.
2578 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002579 const MCExpr *IdVal;
2580 SMLoc EndLoc;
2581
2582 if (getLexer().getKind() == AsmToken::LParen) {
2583 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002584 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002585 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002587 const AsmToken &nextTok = Parser.getTok();
2588 if (nextTok.isNot(AsmToken::Identifier))
2589 return true;
2590 Str += "(%";
2591 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002592 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002593 if (getLexer().getKind() != AsmToken::LParen)
2594 return true;
2595 } else
2596 break;
2597 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002598 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002599 return true;
2600
2601 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002603
2604 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002605 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002606
Jack Carterd0bd6422013-04-18 00:41:53 +00002607 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002608 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002609}
2610
Jack Carterb4dbc172012-09-05 23:34:03 +00002611bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2612 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002613 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002614 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002615 if (ResTy == MatchOperand_Success) {
2616 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002617 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002618 StartLoc = Operand.getStartLoc();
2619 EndLoc = Operand.getEndLoc();
2620
2621 // AFAIK, we only support numeric registers and named GPR's in CFI
2622 // directives.
2623 // Don't worry about eating tokens before failing. Using an unrecognised
2624 // register is a parse error.
2625 if (Operand.isGPRAsmReg()) {
2626 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002627 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002628 }
2629
2630 return (RegNo == (unsigned)-1);
2631 }
2632
2633 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002634 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002635}
2636
Jack Carterb5cf5902013-04-17 00:18:04 +00002637bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002638 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002639 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002640 bool Result = true;
2641
2642 while (getLexer().getKind() == AsmToken::LParen)
2643 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002644
Jack Carterd0bd6422013-04-18 00:41:53 +00002645 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002646 default:
2647 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002648 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002649 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002650 case AsmToken::Integer:
2651 case AsmToken::Minus:
2652 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002653 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002654 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002655 else
2656 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002657 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002658 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002659 break;
Jack Carter873c7242013-01-12 01:03:14 +00002660 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002661 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002662 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002663 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002664}
2665
David Blaikie960ea3f2014-06-08 16:18:35 +00002666MipsAsmParser::OperandMatchResultTy
2667MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002668 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002669 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002670 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002671 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002672 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002673 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002674 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002675 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002676
Jack Carterb5cf5902013-04-17 00:18:04 +00002677 if (getLexer().getKind() == AsmToken::LParen) {
2678 Parser.Lex();
2679 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002680 }
2681
Jack Carterb5cf5902013-04-17 00:18:04 +00002682 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002683 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002684 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002685
Jack Carterd0bd6422013-04-18 00:41:53 +00002686 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002688 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2689 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002690 SMLoc E =
2691 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002692 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002693 return MatchOperand_Success;
2694 }
2695 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002696 SMLoc E =
2697 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002698
Jack Carterd0bd6422013-04-18 00:41:53 +00002699 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002700 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002701 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002702 S, E, *this);
2703 Operands.push_back(
2704 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002705 return MatchOperand_Success;
2706 }
2707 Error(Parser.getTok().getLoc(), "'(' expected");
2708 return MatchOperand_ParseFail;
2709 }
2710
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002712 }
2713
Toma Tabacu13964452014-09-04 13:23:44 +00002714 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002715 if (Res != MatchOperand_Success)
2716 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002717
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002718 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002719 Error(Parser.getTok().getLoc(), "')' expected");
2720 return MatchOperand_ParseFail;
2721 }
2722
Jack Carter873c7242013-01-12 01:03:14 +00002723 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2724
Jack Carterd0bd6422013-04-18 00:41:53 +00002725 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002726
Craig Topper062a2ba2014-04-25 05:30:21 +00002727 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002728 IdVal = MCConstantExpr::Create(0, getContext());
2729
Jack Carterd0bd6422013-04-18 00:41:53 +00002730 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002731 std::unique_ptr<MipsOperand> op(
2732 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002733 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002734 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002735 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002736 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002737 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2738 int64_t Imm;
2739 if (IdVal->EvaluateAsAbsolute(Imm))
2740 IdVal = MCConstantExpr::Create(Imm, getContext());
2741 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2742 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2743 getContext());
2744 }
2745
David Blaikie960ea3f2014-06-08 16:18:35 +00002746 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002747 return MatchOperand_Success;
2748}
2749
David Blaikie960ea3f2014-06-08 16:18:35 +00002750bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002751 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002752 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2753 if (Sym) {
2754 SMLoc S = Parser.getTok().getLoc();
2755 const MCExpr *Expr;
2756 if (Sym->isVariable())
2757 Expr = Sym->getVariableValue();
2758 else
2759 return false;
2760 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002761 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002762 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002763 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002764 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002765 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002766 if (ResTy == MatchOperand_Success) {
2767 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002768 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002769 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002770 llvm_unreachable("Should never ParseFail");
2771 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002772 }
2773 } else if (Expr->getKind() == MCExpr::Constant) {
2774 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002775 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002776 Operands.push_back(
2777 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002778 return true;
2779 }
2780 }
2781 return false;
2782}
Jack Carterd0bd6422013-04-18 00:41:53 +00002783
Jack Carter873c7242013-01-12 01:03:14 +00002784MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002785MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002786 StringRef Identifier,
2787 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002788 int Index = matchCPURegisterName(Identifier);
2789 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002790 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002791 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2792 return MatchOperand_Success;
2793 }
2794
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002795 Index = matchHWRegsRegisterName(Identifier);
2796 if (Index != -1) {
2797 Operands.push_back(MipsOperand::createHWRegsReg(
2798 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2799 return MatchOperand_Success;
2800 }
2801
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002802 Index = matchFPURegisterName(Identifier);
2803 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002804 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002805 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2806 return MatchOperand_Success;
2807 }
2808
2809 Index = matchFCCRegisterName(Identifier);
2810 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002811 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002812 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2813 return MatchOperand_Success;
2814 }
2815
2816 Index = matchACRegisterName(Identifier);
2817 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002818 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002819 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2820 return MatchOperand_Success;
2821 }
2822
2823 Index = matchMSA128RegisterName(Identifier);
2824 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002825 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002826 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2827 return MatchOperand_Success;
2828 }
2829
2830 Index = matchMSA128CtrlRegisterName(Identifier);
2831 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002832 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002833 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2834 return MatchOperand_Success;
2835 }
2836
2837 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002838}
2839
2840MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002841MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002842 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002843 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002844
2845 if (Token.is(AsmToken::Identifier)) {
2846 DEBUG(dbgs() << ".. identifier\n");
2847 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002848 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002849 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002850 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002851 } else if (Token.is(AsmToken::Integer)) {
2852 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002853 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002854 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2855 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002856 return MatchOperand_Success;
2857 }
2858
2859 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2860
2861 return MatchOperand_NoMatch;
2862}
2863
David Blaikie960ea3f2014-06-08 16:18:35 +00002864MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002865MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002866 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002867 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002868
2869 auto Token = Parser.getTok();
2870
2871 SMLoc S = Token.getLoc();
2872
2873 if (Token.isNot(AsmToken::Dollar)) {
2874 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2875 if (Token.is(AsmToken::Identifier)) {
2876 if (searchSymbolAlias(Operands))
2877 return MatchOperand_Success;
2878 }
2879 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2880 return MatchOperand_NoMatch;
2881 }
2882 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883
Toma Tabacu13964452014-09-04 13:23:44 +00002884 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002885 if (ResTy == MatchOperand_Success) {
2886 Parser.Lex(); // $
2887 Parser.Lex(); // identifier
2888 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002889 return ResTy;
2890}
2891
2892MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002893MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002894 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002895 switch (getLexer().getKind()) {
2896 default:
2897 return MatchOperand_NoMatch;
2898 case AsmToken::LParen:
2899 case AsmToken::Minus:
2900 case AsmToken::Plus:
2901 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002902 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002903 case AsmToken::String:
2904 break;
2905 }
2906
2907 const MCExpr *IdVal;
2908 SMLoc S = Parser.getTok().getLoc();
2909 if (getParser().parseExpression(IdVal))
2910 return MatchOperand_ParseFail;
2911
2912 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2913 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2914 return MatchOperand_Success;
2915}
2916
David Blaikie960ea3f2014-06-08 16:18:35 +00002917MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002918MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002919 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002920 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002921
2922 SMLoc S = getLexer().getLoc();
2923
2924 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002925 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002926 if (ResTy != MatchOperand_NoMatch)
2927 return ResTy;
2928
Daniel Sanders315386c2014-04-01 10:40:14 +00002929 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002930 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002931 if (ResTy != MatchOperand_NoMatch)
2932 return ResTy;
2933
Daniel Sandersffd84362014-04-01 10:41:48 +00002934 const MCExpr *Expr = nullptr;
2935 if (Parser.parseExpression(Expr)) {
2936 // We have no way of knowing if a symbol was consumed so we must ParseFail
2937 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002938 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002939 Operands.push_back(
2940 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002941 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002942}
2943
Vladimir Medic2b953d02013-10-01 09:48:56 +00002944MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002945MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002946 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002947 const MCExpr *IdVal;
2948 // If the first token is '$' we may have register operand.
2949 if (Parser.getTok().is(AsmToken::Dollar))
2950 return MatchOperand_NoMatch;
2951 SMLoc S = Parser.getTok().getLoc();
2952 if (getParser().parseExpression(IdVal))
2953 return MatchOperand_ParseFail;
2954 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002955 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002956 int64_t Val = MCE->getValue();
2957 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2958 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002959 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002960 return MatchOperand_Success;
2961}
2962
Matheus Almeida779c5932013-11-18 12:32:49 +00002963MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002964MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002965 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002966 switch (getLexer().getKind()) {
2967 default:
2968 return MatchOperand_NoMatch;
2969 case AsmToken::LParen:
2970 case AsmToken::Plus:
2971 case AsmToken::Minus:
2972 case AsmToken::Integer:
2973 break;
2974 }
2975
2976 const MCExpr *Expr;
2977 SMLoc S = Parser.getTok().getLoc();
2978
2979 if (getParser().parseExpression(Expr))
2980 return MatchOperand_ParseFail;
2981
2982 int64_t Val;
2983 if (!Expr->EvaluateAsAbsolute(Val)) {
2984 Error(S, "expected immediate value");
2985 return MatchOperand_ParseFail;
2986 }
2987
2988 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2989 // and because the CPU always adds one to the immediate field, the allowed
2990 // range becomes 1..4. We'll only check the range here and will deal
2991 // with the addition/subtraction when actually decoding/encoding
2992 // the instruction.
2993 if (Val < 1 || Val > 4) {
2994 Error(S, "immediate not in range (1..4)");
2995 return MatchOperand_ParseFail;
2996 }
2997
Jack Carter3b2c96e2014-01-22 23:31:38 +00002998 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002999 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003000 return MatchOperand_Success;
3001}
3002
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003003MipsAsmParser::OperandMatchResultTy
3004MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3005 MCAsmParser &Parser = getParser();
3006 SmallVector<unsigned, 10> Regs;
3007 unsigned RegNo;
3008 unsigned PrevReg = Mips::NoRegister;
3009 bool RegRange = false;
3010 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3011
3012 if (Parser.getTok().isNot(AsmToken::Dollar))
3013 return MatchOperand_ParseFail;
3014
3015 SMLoc S = Parser.getTok().getLoc();
3016 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3017 SMLoc E = getLexer().getLoc();
3018 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3019 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3020 if (RegRange) {
3021 // Remove last register operand because registers from register range
3022 // should be inserted first.
3023 if (RegNo == Mips::RA) {
3024 Regs.push_back(RegNo);
3025 } else {
3026 unsigned TmpReg = PrevReg + 1;
3027 while (TmpReg <= RegNo) {
3028 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3029 Error(E, "invalid register operand");
3030 return MatchOperand_ParseFail;
3031 }
3032
3033 PrevReg = TmpReg;
3034 Regs.push_back(TmpReg++);
3035 }
3036 }
3037
3038 RegRange = false;
3039 } else {
3040 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3041 (RegNo != Mips::RA)) {
3042 Error(E, "$16 or $31 expected");
3043 return MatchOperand_ParseFail;
3044 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3045 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3046 Error(E, "invalid register operand");
3047 return MatchOperand_ParseFail;
3048 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3049 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3050 Error(E, "consecutive register numbers expected");
3051 return MatchOperand_ParseFail;
3052 }
3053
3054 Regs.push_back(RegNo);
3055 }
3056
3057 if (Parser.getTok().is(AsmToken::Minus))
3058 RegRange = true;
3059
3060 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3061 !Parser.getTok().isNot(AsmToken::Comma)) {
3062 Error(E, "',' or '-' expected");
3063 return MatchOperand_ParseFail;
3064 }
3065
3066 Lex(); // Consume comma or minus
3067 if (Parser.getTok().isNot(AsmToken::Dollar))
3068 break;
3069
3070 PrevReg = RegNo;
3071 }
3072
3073 SMLoc E = Parser.getTok().getLoc();
3074 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3075 parseMemOperand(Operands);
3076 return MatchOperand_Success;
3077}
3078
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003079MipsAsmParser::OperandMatchResultTy
3080MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3081 MCAsmParser &Parser = getParser();
3082
3083 SMLoc S = Parser.getTok().getLoc();
3084 if (parseAnyRegister(Operands) != MatchOperand_Success)
3085 return MatchOperand_ParseFail;
3086
3087 SMLoc E = Parser.getTok().getLoc();
3088 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3089 unsigned Reg = Op.getGPR32Reg();
3090 Operands.pop_back();
3091 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3092 return MatchOperand_Success;
3093}
3094
Zoran Jovanovic41688672015-02-10 16:36:20 +00003095MipsAsmParser::OperandMatchResultTy
3096MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3097 MCAsmParser &Parser = getParser();
3098 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3099 SmallVector<unsigned, 10> Regs;
3100
3101 if (Parser.getTok().isNot(AsmToken::Dollar))
3102 return MatchOperand_ParseFail;
3103
3104 SMLoc S = Parser.getTok().getLoc();
3105
3106 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3107 return MatchOperand_ParseFail;
3108
3109 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3110 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3111 Regs.push_back(RegNo);
3112
3113 SMLoc E = Parser.getTok().getLoc();
3114 if (Parser.getTok().isNot(AsmToken::Comma)) {
3115 Error(E, "',' expected");
3116 return MatchOperand_ParseFail;
3117 }
3118
3119 // Remove comma.
3120 Parser.Lex();
3121
3122 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3123 return MatchOperand_ParseFail;
3124
3125 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3126 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3127 Regs.push_back(RegNo);
3128
3129 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3130
3131 return MatchOperand_Success;
3132}
3133
Jack Carterdc1e35d2012-09-06 20:00:02 +00003134MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3135
Vladimir Medic4c299852013-11-06 11:27:05 +00003136 MCSymbolRefExpr::VariantKind VK =
3137 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3138 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3139 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3140 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3141 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3142 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3143 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3144 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3145 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3146 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3147 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3148 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3149 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3150 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3151 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3152 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3153 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3154 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003155 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3156 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3157 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3158 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3159 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3160 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003161 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3162 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003163 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003164
Matheus Almeida2852af82014-04-22 10:15:54 +00003165 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003166
Jack Carterdc1e35d2012-09-06 20:00:02 +00003167 return VK;
3168}
Jack Cartera63b16a2012-09-07 00:23:42 +00003169
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003170/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3171/// either this.
3172/// ::= '(', register, ')'
3173/// handle it before we iterate so we don't get tripped up by the lack of
3174/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003175bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003176 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003177 if (getLexer().is(AsmToken::LParen)) {
3178 Operands.push_back(
3179 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3180 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003181 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003182 SMLoc Loc = getLexer().getLoc();
3183 Parser.eatToEndOfStatement();
3184 return Error(Loc, "unexpected token in argument list");
3185 }
3186 if (Parser.getTok().isNot(AsmToken::RParen)) {
3187 SMLoc Loc = getLexer().getLoc();
3188 Parser.eatToEndOfStatement();
3189 return Error(Loc, "unexpected token, expected ')'");
3190 }
3191 Operands.push_back(
3192 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3193 Parser.Lex();
3194 }
3195 return false;
3196}
3197
3198/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3199/// either one of these.
3200/// ::= '[', register, ']'
3201/// ::= '[', integer, ']'
3202/// handle it before we iterate so we don't get tripped up by the lack of
3203/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003204bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003205 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003206 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003207 if (getLexer().is(AsmToken::LBrac)) {
3208 Operands.push_back(
3209 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3210 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003211 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003212 SMLoc Loc = getLexer().getLoc();
3213 Parser.eatToEndOfStatement();
3214 return Error(Loc, "unexpected token in argument list");
3215 }
3216 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3217 SMLoc Loc = getLexer().getLoc();
3218 Parser.eatToEndOfStatement();
3219 return Error(Loc, "unexpected token, expected ']'");
3220 }
3221 Operands.push_back(
3222 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3223 Parser.Lex();
3224 }
3225 return false;
3226}
3227
David Blaikie960ea3f2014-06-08 16:18:35 +00003228bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3229 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003230 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003231 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003232
3233 // We have reached first instruction, module directive are now forbidden.
3234 getTargetStreamer().forbidModuleDirective();
3235
Vladimir Medic74593e62013-07-17 15:00:42 +00003236 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003237 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003238 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003239 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003240 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003241 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003242 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003243
3244 // Read the remaining operands.
3245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3246 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003247 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003248 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003249 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003250 return Error(Loc, "unexpected token in argument list");
3251 }
Toma Tabacu13964452014-09-04 13:23:44 +00003252 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003253 return true;
3254 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003255
Jack Carterd0bd6422013-04-18 00:41:53 +00003256 while (getLexer().is(AsmToken::Comma)) {
3257 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003258 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003259 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003260 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003261 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003262 return Error(Loc, "unexpected token in argument list");
3263 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003264 // Parse bracket and parenthesis suffixes before we iterate
3265 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003266 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003267 return true;
3268 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003269 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003270 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003271 }
3272 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3274 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003275 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003276 return Error(Loc, "unexpected token in argument list");
3277 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003278 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003279 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003280}
3281
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003282bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003283 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003284 SMLoc Loc = getLexer().getLoc();
3285 Parser.eatToEndOfStatement();
3286 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003287}
3288
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003289bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003290 return Error(Loc, ErrorMsg);
3291}
3292
Jack Carter0b744b32012-10-04 02:29:46 +00003293bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003294 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003295 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003296
3297 // Set the $at register to $0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003298 AssemblerOptions.back()->setATReg(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003299
3300 Parser.Lex(); // Eat "noat".
3301
Jack Carterd0bd6422013-04-18 00:41:53 +00003302 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003303 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003304 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003305 return false;
3306 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003307
3308 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003309 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003310 return false;
3311}
Jack Carterd0bd6422013-04-18 00:41:53 +00003312
Jack Carter0b744b32012-10-04 02:29:46 +00003313bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003314 // Line can be: ".set at", which sets $at to $1
3315 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003316 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003317 Parser.Lex(); // Eat "at".
3318
Jack Carter0b744b32012-10-04 02:29:46 +00003319 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003320 // No register was specified, so we set $at to $1.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003321 AssemblerOptions.back()->setATReg(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003322
3323 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003324 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003325 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003326 }
3327
3328 if (getLexer().isNot(AsmToken::Equal)) {
3329 reportParseError("unexpected token, expected equals sign");
3330 return false;
3331 }
3332 Parser.Lex(); // Eat "=".
3333
3334 if (getLexer().isNot(AsmToken::Dollar)) {
3335 if (getLexer().is(AsmToken::EndOfStatement)) {
3336 reportParseError("no register specified");
3337 return false;
3338 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003339 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003340 return false;
3341 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003342 }
3343 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003344
Toma Tabacu16a74492015-02-13 10:30:57 +00003345 // Find out what "reg" is.
3346 unsigned AtRegNo;
3347 const AsmToken &Reg = Parser.getTok();
3348 if (Reg.is(AsmToken::Identifier)) {
3349 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3350 } else if (Reg.is(AsmToken::Integer)) {
3351 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003352 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003353 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003354 return false;
3355 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003356
3357 // Check if $reg is a valid register. If it is, set $at to $reg.
3358 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3359 reportParseError("invalid register");
3360 return false;
3361 }
3362 Parser.Lex(); // Eat "reg".
3363
3364 // If this is not the end of the statement, report an error.
3365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3366 reportParseError("unexpected token, expected end of statement");
3367 return false;
3368 }
3369
3370 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3371
3372 Parser.Lex(); // Consume the EndOfStatement.
3373 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003374}
3375
3376bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003377 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003378 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003379 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003380 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003381 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003382 return false;
3383 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003384 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003385 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003386 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003387 return false;
3388}
3389
3390bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003391 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003392 Parser.Lex();
3393 // If this is not the end of the statement, report an error.
3394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003395 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003396 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003397 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003398 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003399 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003400 Parser.Lex(); // Consume the EndOfStatement.
3401 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003402}
3403
3404bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003405 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003406 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003407 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003409 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003410 return false;
3411 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003412 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003413 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003414 return false;
3415}
3416
3417bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003418 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003419 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003420 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003422 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003423 return false;
3424 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003425 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003426 reportParseError("`noreorder' must be set before `nomacro'");
3427 return false;
3428 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003429 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003430 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003431 return false;
3432}
Jack Carterd76b2372013-03-21 21:44:16 +00003433
Daniel Sanders44934432014-08-07 12:03:36 +00003434bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003435 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003436 Parser.Lex();
3437
3438 // If this is not the end of the statement, report an error.
3439 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003440 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003441
3442 setFeatureBits(Mips::FeatureMSA, "msa");
3443 getTargetStreamer().emitDirectiveSetMsa();
3444 return false;
3445}
3446
3447bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003448 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003449 Parser.Lex();
3450
3451 // If this is not the end of the statement, report an error.
3452 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003453 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003454
3455 clearFeatureBits(Mips::FeatureMSA, "msa");
3456 getTargetStreamer().emitDirectiveSetNoMsa();
3457 return false;
3458}
3459
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003460bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003461 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003462 Parser.Lex(); // Eat "nodsp".
3463
3464 // If this is not the end of the statement, report an error.
3465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3466 reportParseError("unexpected token, expected end of statement");
3467 return false;
3468 }
3469
3470 clearFeatureBits(Mips::FeatureDSP, "dsp");
3471 getTargetStreamer().emitDirectiveSetNoDsp();
3472 return false;
3473}
3474
Toma Tabacucc2502d2014-11-04 17:18:07 +00003475bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003476 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003477 Parser.Lex(); // Eat "mips16".
3478
Jack Carter39536722014-01-22 23:08:42 +00003479 // If this is not the end of the statement, report an error.
3480 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003481 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003482 return false;
3483 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003484
3485 setFeatureBits(Mips::FeatureMips16, "mips16");
3486 getTargetStreamer().emitDirectiveSetMips16();
3487 Parser.Lex(); // Consume the EndOfStatement.
3488 return false;
3489}
3490
3491bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003492 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003493 Parser.Lex(); // Eat "nomips16".
3494
3495 // If this is not the end of the statement, report an error.
3496 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3497 reportParseError("unexpected token, expected end of statement");
3498 return false;
3499 }
3500
3501 clearFeatureBits(Mips::FeatureMips16, "mips16");
3502 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003503 Parser.Lex(); // Consume the EndOfStatement.
3504 return false;
3505}
3506
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003507bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003508 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003509 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003510 // Line can be: .set fp=32
3511 // .set fp=xx
3512 // .set fp=64
3513 Parser.Lex(); // Eat fp token
3514 AsmToken Tok = Parser.getTok();
3515 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003516 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003517 return false;
3518 }
3519 Parser.Lex(); // Eat '=' token.
3520 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003521
3522 if (!parseFpABIValue(FpAbiVal, ".set"))
3523 return false;
3524
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003525 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003526 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003527 return false;
3528 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003529 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003530 Parser.Lex(); // Consume the EndOfStatement.
3531 return false;
3532}
3533
Toma Tabacu9db22db2014-09-09 10:15:38 +00003534bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003535 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003536 SMLoc Loc = getLexer().getLoc();
3537
3538 Parser.Lex();
3539 if (getLexer().isNot(AsmToken::EndOfStatement))
3540 return reportParseError("unexpected token, expected end of statement");
3541
3542 // Always keep an element on the options "stack" to prevent the user
3543 // from changing the initial options. This is how we remember them.
3544 if (AssemblerOptions.size() == 2)
3545 return reportParseError(Loc, ".set pop with no .set push");
3546
3547 AssemblerOptions.pop_back();
3548 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3549
3550 getTargetStreamer().emitDirectiveSetPop();
3551 return false;
3552}
3553
3554bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003555 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003556 Parser.Lex();
3557 if (getLexer().isNot(AsmToken::EndOfStatement))
3558 return reportParseError("unexpected token, expected end of statement");
3559
3560 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003561 AssemblerOptions.push_back(
3562 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003563
3564 getTargetStreamer().emitDirectiveSetPush();
3565 return false;
3566}
3567
Jack Carterd76b2372013-03-21 21:44:16 +00003568bool MipsAsmParser::parseSetAssignment() {
3569 StringRef Name;
3570 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003571 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003572
3573 if (Parser.parseIdentifier(Name))
3574 reportParseError("expected identifier after .set");
3575
3576 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003577 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003578 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003579
Jack Carter3b2c96e2014-01-22 23:31:38 +00003580 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003581 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003582
Jack Carterd0bd6422013-04-18 00:41:53 +00003583 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003584 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003585 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003586 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003587 Sym = getContext().GetOrCreateSymbol(Name);
3588 Sym->setVariableValue(Value);
3589
3590 return false;
3591}
Jack Carterd0bd6422013-04-18 00:41:53 +00003592
Toma Tabacu26647792014-09-09 12:52:14 +00003593bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003594 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003595 Parser.Lex();
3596 if (getLexer().isNot(AsmToken::EndOfStatement))
3597 return reportParseError("unexpected token, expected end of statement");
3598
3599 // Reset assembler options to their initial values.
3600 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3601 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3602
3603 getTargetStreamer().emitDirectiveSetMips0();
3604 return false;
3605}
3606
Toma Tabacu85618b32014-08-19 14:22:52 +00003607bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003608 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003609 Parser.Lex();
3610 if (getLexer().isNot(AsmToken::Equal))
3611 return reportParseError("unexpected token, expected equals sign");
3612
3613 Parser.Lex();
3614 StringRef Arch;
3615 if (Parser.parseIdentifier(Arch))
3616 return reportParseError("expected arch identifier");
3617
3618 StringRef ArchFeatureName =
3619 StringSwitch<StringRef>(Arch)
3620 .Case("mips1", "mips1")
3621 .Case("mips2", "mips2")
3622 .Case("mips3", "mips3")
3623 .Case("mips4", "mips4")
3624 .Case("mips5", "mips5")
3625 .Case("mips32", "mips32")
3626 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003627 .Case("mips32r3", "mips32r3")
3628 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003629 .Case("mips32r6", "mips32r6")
3630 .Case("mips64", "mips64")
3631 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003632 .Case("mips64r3", "mips64r3")
3633 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003634 .Case("mips64r6", "mips64r6")
3635 .Case("cnmips", "cnmips")
3636 .Case("r4000", "mips3") // This is an implementation of Mips3.
3637 .Default("");
3638
3639 if (ArchFeatureName.empty())
3640 return reportParseError("unsupported architecture");
3641
3642 selectArch(ArchFeatureName);
3643 getTargetStreamer().emitDirectiveSetArch(Arch);
3644 return false;
3645}
3646
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003647bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003648 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003649 Parser.Lex();
3650 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003651 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003652
Matheus Almeida2852af82014-04-22 10:15:54 +00003653 switch (Feature) {
3654 default:
3655 llvm_unreachable("Unimplemented feature");
3656 case Mips::FeatureDSP:
3657 setFeatureBits(Mips::FeatureDSP, "dsp");
3658 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003659 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003660 case Mips::FeatureMicroMips:
3661 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003662 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003663 case Mips::FeatureMips1:
3664 selectArch("mips1");
3665 getTargetStreamer().emitDirectiveSetMips1();
3666 break;
3667 case Mips::FeatureMips2:
3668 selectArch("mips2");
3669 getTargetStreamer().emitDirectiveSetMips2();
3670 break;
3671 case Mips::FeatureMips3:
3672 selectArch("mips3");
3673 getTargetStreamer().emitDirectiveSetMips3();
3674 break;
3675 case Mips::FeatureMips4:
3676 selectArch("mips4");
3677 getTargetStreamer().emitDirectiveSetMips4();
3678 break;
3679 case Mips::FeatureMips5:
3680 selectArch("mips5");
3681 getTargetStreamer().emitDirectiveSetMips5();
3682 break;
3683 case Mips::FeatureMips32:
3684 selectArch("mips32");
3685 getTargetStreamer().emitDirectiveSetMips32();
3686 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003687 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003688 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003689 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003690 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003691 case Mips::FeatureMips32r3:
3692 selectArch("mips32r3");
3693 getTargetStreamer().emitDirectiveSetMips32R3();
3694 break;
3695 case Mips::FeatureMips32r5:
3696 selectArch("mips32r5");
3697 getTargetStreamer().emitDirectiveSetMips32R5();
3698 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003699 case Mips::FeatureMips32r6:
3700 selectArch("mips32r6");
3701 getTargetStreamer().emitDirectiveSetMips32R6();
3702 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003703 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003704 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003705 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003706 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003707 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003708 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003709 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003710 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003711 case Mips::FeatureMips64r3:
3712 selectArch("mips64r3");
3713 getTargetStreamer().emitDirectiveSetMips64R3();
3714 break;
3715 case Mips::FeatureMips64r5:
3716 selectArch("mips64r5");
3717 getTargetStreamer().emitDirectiveSetMips64R5();
3718 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003719 case Mips::FeatureMips64r6:
3720 selectArch("mips64r6");
3721 getTargetStreamer().emitDirectiveSetMips64R6();
3722 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003723 }
3724 return false;
3725}
3726
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003727bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003728 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003729 if (getLexer().isNot(AsmToken::Comma)) {
3730 SMLoc Loc = getLexer().getLoc();
3731 Parser.eatToEndOfStatement();
3732 return Error(Loc, ErrorStr);
3733 }
3734
Matheus Almeida2852af82014-04-22 10:15:54 +00003735 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003736 return true;
3737}
3738
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003739bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003740 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003741 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003742
Toma Tabacudde4c462014-11-06 10:02:45 +00003743 if (inMips16Mode()) {
3744 reportParseError(".cpload is not supported in Mips16 mode");
3745 return false;
3746 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003747
David Blaikie960ea3f2014-06-08 16:18:35 +00003748 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003749 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003750 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3751 reportParseError("expected register containing function address");
3752 return false;
3753 }
3754
David Blaikie960ea3f2014-06-08 16:18:35 +00003755 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3756 if (!RegOpnd.isGPRAsmReg()) {
3757 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003758 return false;
3759 }
3760
Toma Tabacudde4c462014-11-06 10:02:45 +00003761 // If this is not the end of the statement, report an error.
3762 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3763 reportParseError("unexpected token, expected end of statement");
3764 return false;
3765 }
3766
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003767 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003768 return false;
3769}
3770
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003771bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003772 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003773 unsigned FuncReg;
3774 unsigned Save;
3775 bool SaveIsReg = true;
3776
Matheus Almeida7e815762014-06-18 13:08:59 +00003777 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003778 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003779 if (ResTy == MatchOperand_NoMatch) {
3780 reportParseError("expected register containing function address");
3781 Parser.eatToEndOfStatement();
3782 return false;
3783 }
3784
3785 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3786 if (!FuncRegOpnd.isGPRAsmReg()) {
3787 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3788 Parser.eatToEndOfStatement();
3789 return false;
3790 }
3791
3792 FuncReg = FuncRegOpnd.getGPR32Reg();
3793 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003794
Toma Tabacu65f10572014-09-16 15:00:52 +00003795 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003796 return true;
3797
Toma Tabacu13964452014-09-04 13:23:44 +00003798 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003799 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003800 const AsmToken &Tok = Parser.getTok();
3801 if (Tok.is(AsmToken::Integer)) {
3802 Save = Tok.getIntVal();
3803 SaveIsReg = false;
3804 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003805 } else {
3806 reportParseError("expected save register or stack offset");
3807 Parser.eatToEndOfStatement();
3808 return false;
3809 }
3810 } else {
3811 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3812 if (!SaveOpnd.isGPRAsmReg()) {
3813 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3814 Parser.eatToEndOfStatement();
3815 return false;
3816 }
3817 Save = SaveOpnd.getGPR32Reg();
3818 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003819
Toma Tabacu65f10572014-09-16 15:00:52 +00003820 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003821 return true;
3822
Toma Tabacu8874eac2015-02-18 13:46:53 +00003823 const MCExpr *Expr;
3824 if (Parser.parseExpression(Expr)) {
3825 reportParseError("expected expression");
3826 return false;
3827 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003828
Toma Tabacu8874eac2015-02-18 13:46:53 +00003829 if (Expr->getKind() != MCExpr::SymbolRef) {
3830 reportParseError("expected symbol");
3831 return false;
3832 }
3833 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3834
3835 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3836 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003837 return false;
3838}
3839
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003840bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003841 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003842 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3843 const AsmToken &Tok = Parser.getTok();
3844
3845 if (Tok.getString() == "2008") {
3846 Parser.Lex();
3847 getTargetStreamer().emitDirectiveNaN2008();
3848 return false;
3849 } else if (Tok.getString() == "legacy") {
3850 Parser.Lex();
3851 getTargetStreamer().emitDirectiveNaNLegacy();
3852 return false;
3853 }
3854 }
3855 // If we don't recognize the option passed to the .nan
3856 // directive (e.g. no option or unknown option), emit an error.
3857 reportParseError("invalid option in .nan directive");
3858 return false;
3859}
3860
Jack Carter0b744b32012-10-04 02:29:46 +00003861bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003862 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003863 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003864 const AsmToken &Tok = Parser.getTok();
3865
3866 if (Tok.getString() == "noat") {
3867 return parseSetNoAtDirective();
3868 } else if (Tok.getString() == "at") {
3869 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003870 } else if (Tok.getString() == "arch") {
3871 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003872 } else if (Tok.getString() == "fp") {
3873 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003874 } else if (Tok.getString() == "pop") {
3875 return parseSetPopDirective();
3876 } else if (Tok.getString() == "push") {
3877 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003878 } else if (Tok.getString() == "reorder") {
3879 return parseSetReorderDirective();
3880 } else if (Tok.getString() == "noreorder") {
3881 return parseSetNoReorderDirective();
3882 } else if (Tok.getString() == "macro") {
3883 return parseSetMacroDirective();
3884 } else if (Tok.getString() == "nomacro") {
3885 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003886 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003887 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003888 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003889 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003890 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003891 getTargetStreamer().emitDirectiveSetNoMicroMips();
3892 Parser.eatToEndOfStatement();
3893 return false;
3894 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003895 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003896 } else if (Tok.getString() == "mips0") {
3897 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003898 } else if (Tok.getString() == "mips1") {
3899 return parseSetFeature(Mips::FeatureMips1);
3900 } else if (Tok.getString() == "mips2") {
3901 return parseSetFeature(Mips::FeatureMips2);
3902 } else if (Tok.getString() == "mips3") {
3903 return parseSetFeature(Mips::FeatureMips3);
3904 } else if (Tok.getString() == "mips4") {
3905 return parseSetFeature(Mips::FeatureMips4);
3906 } else if (Tok.getString() == "mips5") {
3907 return parseSetFeature(Mips::FeatureMips5);
3908 } else if (Tok.getString() == "mips32") {
3909 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003910 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003911 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003912 } else if (Tok.getString() == "mips32r3") {
3913 return parseSetFeature(Mips::FeatureMips32r3);
3914 } else if (Tok.getString() == "mips32r5") {
3915 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003916 } else if (Tok.getString() == "mips32r6") {
3917 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003918 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003919 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003920 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003921 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003922 } else if (Tok.getString() == "mips64r3") {
3923 return parseSetFeature(Mips::FeatureMips64r3);
3924 } else if (Tok.getString() == "mips64r5") {
3925 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003926 } else if (Tok.getString() == "mips64r6") {
3927 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003928 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003929 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003930 } else if (Tok.getString() == "nodsp") {
3931 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003932 } else if (Tok.getString() == "msa") {
3933 return parseSetMsaDirective();
3934 } else if (Tok.getString() == "nomsa") {
3935 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003936 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003937 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003938 parseSetAssignment();
3939 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003940 }
Jack Carter07c818d2013-01-25 01:31:34 +00003941
Jack Carter0b744b32012-10-04 02:29:46 +00003942 return true;
3943}
3944
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003945/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003946/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003947bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003948 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003949 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3950 for (;;) {
3951 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003952 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003953 return true;
3954
3955 getParser().getStreamer().EmitValue(Value, Size);
3956
3957 if (getLexer().is(AsmToken::EndOfStatement))
3958 break;
3959
Jack Carter07c818d2013-01-25 01:31:34 +00003960 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003961 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003962 Parser.Lex();
3963 }
3964 }
3965
3966 Parser.Lex();
3967 return false;
3968}
3969
Vladimir Medic4c299852013-11-06 11:27:05 +00003970/// parseDirectiveGpWord
3971/// ::= .gpword local_sym
3972bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003973 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003974 const MCExpr *Value;
3975 // EmitGPRel32Value requires an expression, so we are using base class
3976 // method to evaluate the expression.
3977 if (getParser().parseExpression(Value))
3978 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003979 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003980
Vladimir Medice10c1122013-11-13 13:18:04 +00003981 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003982 return Error(getLexer().getLoc(),
3983 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003984 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003985 return false;
3986}
3987
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003988/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003989/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003990bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003991 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003992 const MCExpr *Value;
3993 // EmitGPRel64Value requires an expression, so we are using base class
3994 // method to evaluate the expression.
3995 if (getParser().parseExpression(Value))
3996 return true;
3997 getParser().getStreamer().EmitGPRel64Value(Value);
3998
3999 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004000 return Error(getLexer().getLoc(),
4001 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004002 Parser.Lex(); // Eat EndOfStatement token.
4003 return false;
4004}
4005
Jack Carter0cd3c192014-01-06 23:27:31 +00004006bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004007 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004008 // Get the option token.
4009 AsmToken Tok = Parser.getTok();
4010 // At the moment only identifiers are supported.
4011 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004012 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004013 Parser.eatToEndOfStatement();
4014 return false;
4015 }
4016
4017 StringRef Option = Tok.getIdentifier();
4018
4019 if (Option == "pic0") {
4020 getTargetStreamer().emitDirectiveOptionPic0();
4021 Parser.Lex();
4022 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4023 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004024 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004025 Parser.eatToEndOfStatement();
4026 }
4027 return false;
4028 }
4029
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004030 if (Option == "pic2") {
4031 getTargetStreamer().emitDirectiveOptionPic2();
4032 Parser.Lex();
4033 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4034 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004035 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004036 Parser.eatToEndOfStatement();
4037 }
4038 return false;
4039 }
4040
Jack Carter0cd3c192014-01-06 23:27:31 +00004041 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004042 Warning(Parser.getTok().getLoc(),
4043 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004044 Parser.eatToEndOfStatement();
4045 return false;
4046}
4047
Daniel Sanders7e527422014-07-10 13:38:23 +00004048/// parseDirectiveModule
4049/// ::= .module oddspreg
4050/// ::= .module nooddspreg
4051/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004052bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004053 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004054 MCAsmLexer &Lexer = getLexer();
4055 SMLoc L = Lexer.getLoc();
4056
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004057 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004058 // TODO : get a better message.
4059 reportParseError(".module directive must appear before any code");
4060 return false;
4061 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004062
Toma Tabacuc405c822015-01-23 10:40:19 +00004063 StringRef Option;
4064 if (Parser.parseIdentifier(Option)) {
4065 reportParseError("expected .module option identifier");
4066 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004067 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004068
Toma Tabacuc405c822015-01-23 10:40:19 +00004069 if (Option == "oddspreg") {
4070 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4071 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4072
4073 // If this is not the end of the statement, report an error.
4074 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4075 reportParseError("unexpected token, expected end of statement");
4076 return false;
4077 }
4078
4079 return false; // parseDirectiveModule has finished successfully.
4080 } else if (Option == "nooddspreg") {
4081 if (!isABI_O32()) {
4082 Error(L, "'.module nooddspreg' requires the O32 ABI");
4083 return false;
4084 }
4085
4086 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4087 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4088
4089 // If this is not the end of the statement, report an error.
4090 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4091 reportParseError("unexpected token, expected end of statement");
4092 return false;
4093 }
4094
4095 return false; // parseDirectiveModule has finished successfully.
4096 } else if (Option == "fp") {
4097 return parseDirectiveModuleFP();
4098 } else {
4099 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4100 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004101}
4102
4103/// parseDirectiveModuleFP
4104/// ::= =32
4105/// ::= =xx
4106/// ::= =64
4107bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004108 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004109 MCAsmLexer &Lexer = getLexer();
4110
4111 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004112 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004113 return false;
4114 }
4115 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004116
Daniel Sanders7e527422014-07-10 13:38:23 +00004117 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004118 if (!parseFpABIValue(FpABI, ".module"))
4119 return false;
4120
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004122 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004123 return false;
4124 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004125
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004126 // Emit appropriate flags.
4127 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004128 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004129 return false;
4130}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004131
Daniel Sanders7e527422014-07-10 13:38:23 +00004132bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004133 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004134 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004135 MCAsmLexer &Lexer = getLexer();
4136
4137 if (Lexer.is(AsmToken::Identifier)) {
4138 StringRef Value = Parser.getTok().getString();
4139 Parser.Lex();
4140
4141 if (Value != "xx") {
4142 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4143 return false;
4144 }
4145
4146 if (!isABI_O32()) {
4147 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4148 return false;
4149 }
4150
Daniel Sanders7e527422014-07-10 13:38:23 +00004151 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004152 return true;
4153 }
4154
4155 if (Lexer.is(AsmToken::Integer)) {
4156 unsigned Value = Parser.getTok().getIntVal();
4157 Parser.Lex();
4158
4159 if (Value != 32 && Value != 64) {
4160 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4161 return false;
4162 }
4163
4164 if (Value == 32) {
4165 if (!isABI_O32()) {
4166 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4167 return false;
4168 }
4169
Daniel Sanders7e527422014-07-10 13:38:23 +00004170 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4171 } else
4172 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004173
Daniel Sanders7e527422014-07-10 13:38:23 +00004174 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004175 }
4176
4177 return false;
4178}
4179
Jack Carter0b744b32012-10-04 02:29:46 +00004180bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004181 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004182 StringRef IDVal = DirectiveID.getString();
4183
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004184 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004185 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004186 if (IDVal == ".dword") {
4187 parseDataDirective(8, DirectiveID.getLoc());
4188 return false;
4189 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004190 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004191 StringRef SymbolName;
4192
4193 if (Parser.parseIdentifier(SymbolName)) {
4194 reportParseError("expected identifier after .ent");
4195 return false;
4196 }
4197
4198 // There's an undocumented extension that allows an integer to
4199 // follow the name of the procedure which AFAICS is ignored by GAS.
4200 // Example: .ent foo,2
4201 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4202 if (getLexer().isNot(AsmToken::Comma)) {
4203 // Even though we accept this undocumented extension for compatibility
4204 // reasons, the additional integer argument does not actually change
4205 // the behaviour of the '.ent' directive, so we would like to discourage
4206 // its use. We do this by not referring to the extended version in
4207 // error messages which are not directly related to its use.
4208 reportParseError("unexpected token, expected end of statement");
4209 return false;
4210 }
4211 Parser.Lex(); // Eat the comma.
4212 const MCExpr *DummyNumber;
4213 int64_t DummyNumberVal;
4214 // If the user was explicitly trying to use the extended version,
4215 // we still give helpful extension-related error messages.
4216 if (Parser.parseExpression(DummyNumber)) {
4217 reportParseError("expected number after comma");
4218 return false;
4219 }
4220 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4221 reportParseError("expected an absolute expression after comma");
4222 return false;
4223 }
4224 }
4225
4226 // If this is not the end of the statement, report an error.
4227 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4228 reportParseError("unexpected token, expected end of statement");
4229 return false;
4230 }
4231
4232 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4233
4234 getTargetStreamer().emitDirectiveEnt(*Sym);
4235 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004236 return false;
4237 }
4238
Jack Carter07c818d2013-01-25 01:31:34 +00004239 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004240 StringRef SymbolName;
4241
4242 if (Parser.parseIdentifier(SymbolName)) {
4243 reportParseError("expected identifier after .end");
4244 return false;
4245 }
4246
4247 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4248 reportParseError("unexpected token, expected end of statement");
4249 return false;
4250 }
4251
4252 if (CurrentFn == nullptr) {
4253 reportParseError(".end used without .ent");
4254 return false;
4255 }
4256
4257 if ((SymbolName != CurrentFn->getName())) {
4258 reportParseError(".end symbol does not match .ent symbol");
4259 return false;
4260 }
4261
4262 getTargetStreamer().emitDirectiveEnd(SymbolName);
4263 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004264 return false;
4265 }
4266
Jack Carter07c818d2013-01-25 01:31:34 +00004267 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004268 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4269 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004270 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004271 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4272 reportParseError("expected stack register");
4273 return false;
4274 }
4275
4276 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4277 if (!StackRegOpnd.isGPRAsmReg()) {
4278 reportParseError(StackRegOpnd.getStartLoc(),
4279 "expected general purpose register");
4280 return false;
4281 }
4282 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4283
4284 if (Parser.getTok().is(AsmToken::Comma))
4285 Parser.Lex();
4286 else {
4287 reportParseError("unexpected token, expected comma");
4288 return false;
4289 }
4290
4291 // Parse the frame size.
4292 const MCExpr *FrameSize;
4293 int64_t FrameSizeVal;
4294
4295 if (Parser.parseExpression(FrameSize)) {
4296 reportParseError("expected frame size value");
4297 return false;
4298 }
4299
4300 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4301 reportParseError("frame size not an absolute expression");
4302 return false;
4303 }
4304
4305 if (Parser.getTok().is(AsmToken::Comma))
4306 Parser.Lex();
4307 else {
4308 reportParseError("unexpected token, expected comma");
4309 return false;
4310 }
4311
4312 // Parse the return register.
4313 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004314 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004315 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4316 reportParseError("expected return register");
4317 return false;
4318 }
4319
4320 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4321 if (!ReturnRegOpnd.isGPRAsmReg()) {
4322 reportParseError(ReturnRegOpnd.getStartLoc(),
4323 "expected general purpose register");
4324 return false;
4325 }
4326
4327 // If this is not the end of the statement, report an error.
4328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4329 reportParseError("unexpected token, expected end of statement");
4330 return false;
4331 }
4332
4333 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4334 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004335 return false;
4336 }
4337
Jack Carter07c818d2013-01-25 01:31:34 +00004338 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004339 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004340 }
4341
Daniel Sandersd97a6342014-08-13 10:07:34 +00004342 if (IDVal == ".mask" || IDVal == ".fmask") {
4343 // .mask bitmask, frame_offset
4344 // bitmask: One bit for each register used.
4345 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4346 // first register is expected to be saved.
4347 // Examples:
4348 // .mask 0x80000000, -4
4349 // .fmask 0x80000000, -4
4350 //
Jack Carterbe332172012-09-07 00:48:02 +00004351
Daniel Sandersd97a6342014-08-13 10:07:34 +00004352 // Parse the bitmask
4353 const MCExpr *BitMask;
4354 int64_t BitMaskVal;
4355
4356 if (Parser.parseExpression(BitMask)) {
4357 reportParseError("expected bitmask value");
4358 return false;
4359 }
4360
4361 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4362 reportParseError("bitmask not an absolute expression");
4363 return false;
4364 }
4365
4366 if (Parser.getTok().is(AsmToken::Comma))
4367 Parser.Lex();
4368 else {
4369 reportParseError("unexpected token, expected comma");
4370 return false;
4371 }
4372
4373 // Parse the frame_offset
4374 const MCExpr *FrameOffset;
4375 int64_t FrameOffsetVal;
4376
4377 if (Parser.parseExpression(FrameOffset)) {
4378 reportParseError("expected frame offset value");
4379 return false;
4380 }
4381
4382 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4383 reportParseError("frame offset not an absolute expression");
4384 return false;
4385 }
4386
4387 // If this is not the end of the statement, report an error.
4388 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4389 reportParseError("unexpected token, expected end of statement");
4390 return false;
4391 }
4392
4393 if (IDVal == ".mask")
4394 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4395 else
4396 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004397 return false;
4398 }
4399
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004400 if (IDVal == ".nan")
4401 return parseDirectiveNaN();
4402
Jack Carter07c818d2013-01-25 01:31:34 +00004403 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004404 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004405 return false;
4406 }
4407
Rafael Espindolab59fb732014-03-28 18:50:26 +00004408 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004409 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004410 return false;
4411 }
4412
Jack Carter07c818d2013-01-25 01:31:34 +00004413 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004414 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004415 return false;
4416 }
4417
Jack Carter0cd3c192014-01-06 23:27:31 +00004418 if (IDVal == ".option")
4419 return parseDirectiveOption();
4420
4421 if (IDVal == ".abicalls") {
4422 getTargetStreamer().emitDirectiveAbiCalls();
4423 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004424 Error(Parser.getTok().getLoc(),
4425 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004426 // Clear line
4427 Parser.eatToEndOfStatement();
4428 }
4429 return false;
4430 }
4431
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004432 if (IDVal == ".cpsetup")
4433 return parseDirectiveCPSetup();
4434
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004435 if (IDVal == ".module")
4436 return parseDirectiveModule();
4437
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004438 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4439 return parseInternalDirectiveReallowModule();
4440
Rafael Espindola870c4e92012-01-11 03:56:41 +00004441 return true;
4442}
4443
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004444bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4445 // If this is not the end of the statement, report an error.
4446 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4447 reportParseError("unexpected token, expected end of statement");
4448 return false;
4449 }
4450
4451 getTargetStreamer().reallowModuleDirective();
4452
4453 getParser().Lex(); // Eat EndOfStatement token.
4454 return false;
4455}
4456
Rafael Espindola870c4e92012-01-11 03:56:41 +00004457extern "C" void LLVMInitializeMipsAsmParser() {
4458 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4459 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4460 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4461 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4462}
Jack Carterb4dbc172012-09-05 23:34:03 +00004463
4464#define GET_REGISTER_MATCHER
4465#define GET_MATCHER_IMPLEMENTATION
4466#include "MipsGenAsmMatcher.inc"