blob: 4af2b136b31e2862086c524df5edceb21bce44aa [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"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(uint64_t Features_) :
47 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
50 ATReg = Opts->getATRegNum();
51 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
56 unsigned getATRegNum() const { return ATReg; }
Toma Tabacu92dbbf12015-03-26 13:08:55 +000057 bool setATReg(unsigned Reg) {
58 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 uint64_t getFeatures() const { return Features; }
74 void setFeatures(uint64_t Features_) { Features = Features_; }
75
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kuperstein29704e72015-03-24 12:56:59 +000081 static const uint64_t AllArchRelatedMask =
82 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
83 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
84 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
85 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
86 Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
87 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
88 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
89 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000090
Jack Carter0b744b32012-10-04 02:29:46 +000091private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000092 unsigned ATReg;
93 bool Reorder;
94 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000095 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000096};
97}
98
99namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000100class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000101 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000102 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000103 return static_cast<MipsTargetStreamer &>(TS);
104 }
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000107 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000108 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000109 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
110 // nullptr, which indicates that no function is currently
111 // selected. This usually happens after an '.end func'
112 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000113
Daniel Sandersef638fe2014-10-03 15:37:37 +0000114 // Print a warning along with its fix-it message at the given range.
115 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
116 SMRange Range, bool ShowColors = true);
117
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000118#define GET_ASSEMBLER_HEADER
119#include "MipsGenAsmMatcher.inc"
120
Matheus Almeida595fcab2014-06-11 15:05:56 +0000121 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
122
Chad Rosier49963552012-10-13 00:26:04 +0000123 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000124 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000125 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000126 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000128 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Toma Tabacu13964452014-09-04 13:23:44 +0000131 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132
Toma Tabacu13964452014-09-04 13:23:44 +0000133 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
136 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
David Blaikie960ea3f2014-06-08 16:18:35 +0000140 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000141
142 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000143 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
Jack Carter873c7242013-01-12 01:03:14 +0000146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000150
Toma Tabacu13964452014-09-04 13:23:44 +0000151 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000158
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000160 parseRegisterPair (OperandVector &Operands);
161
162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000163 parseMovePRegPair(OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166 parseRegisterList (OperandVector &Operands);
167
David Blaikie960ea3f2014-06-08 16:18:35 +0000168 bool searchSymbolAlias(OperandVector &Operands);
169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Jack Carter30a59822012-10-04 04:03:53 +0000172 bool needsExpansion(MCInst &Inst);
173
Matheus Almeida3813d572014-06-19 14:39:14 +0000174 // Expands assembly pseudo instructions.
175 // Returns false on success, true otherwise.
176 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000179 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Matheus Almeida3813d572014-06-19 14:39:14 +0000182 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000183 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000184
185 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000186 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000187
188 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000189 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000190 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000192
Toma Tabacu0d64b202014-08-14 10:29:17 +0000193 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
195
Jack Carter9e65aa32013-03-22 00:05:30 +0000196 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000197 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
198 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000199
200 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
202
Toma Tabacu234482a2015-03-16 12:03:39 +0000203 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
205
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000206 bool reportParseError(Twine ErrorMsg);
207 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000208
Jack Carterb5cf5902013-04-17 00:18:04 +0000209 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000210 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000211
Vladimir Medic4c299852013-11-06 11:27:05 +0000212 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000213
214 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000215 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000216 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000217 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000218 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000219 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000220 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000221 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000222 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000223
224 bool parseSetAtDirective();
225 bool parseSetNoAtDirective();
226 bool parseSetMacroDirective();
227 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000228 bool parseSetMsaDirective();
229 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000230 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000231 bool parseSetReorderDirective();
232 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000233 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000234 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000235 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000236 bool parseSetPopDirective();
237 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Jack Carterd76b2372013-03-21 21:44:16 +0000239 bool parseSetAssignment();
240
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000241 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000242 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000243 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000244 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000245 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000246 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
247 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000248
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000249 bool parseInternalDirectiveReallowModule();
250
Jack Carterdc1e35d2012-09-06 20:00:02 +0000251 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000252
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000253 bool eatComma(StringRef ErrorStr);
254
Jack Carter1ac53222013-02-20 23:11:17 +0000255 int matchCPURegisterName(StringRef Symbol);
256
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000257 int matchHWRegsRegisterName(StringRef Symbol);
258
Jack Carter873c7242013-01-12 01:03:14 +0000259 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000260
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000261 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000262
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000263 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000264
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000265 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000266
Jack Carter5dc8ac92013-09-25 23:50:44 +0000267 int matchMSA128RegisterName(StringRef Name);
268
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000269 int matchMSA128CtrlRegisterName(StringRef Name);
270
Jack Carterd0bd6422013-04-18 00:41:53 +0000271 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000272
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000273 unsigned getGPR(int RegNo);
274
Matheus Almeida7de68e72014-06-18 14:46:05 +0000275 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000276
277 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000278 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000279
280 // Helper function that checks if the value of a vector index is within the
281 // boundaries of accepted values for each RegisterKind
282 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
283 bool validateMSAIndex(int Val, int RegKind);
284
Daniel Sandersf0df2212014-08-04 12:20:00 +0000285 // Selects a new architecture by updating the FeatureBits with the necessary
286 // info including implied dependencies.
287 // Internally, it clears all the feature bits related to *any* architecture
288 // and selects the new one using the ToggleFeature functionality of the
289 // MCSubtargetInfo object that handles implied dependencies. The reason we
290 // clear all the arch related bits manually is because ToggleFeature only
291 // clears the features that imply the feature being cleared and not the
292 // features implied by the feature being cleared. This is easier to see
293 // with an example:
294 // --------------------------------------------------
295 // | Feature | Implies |
296 // | -------------------------------------------------|
297 // | FeatureMips1 | None |
298 // | FeatureMips2 | FeatureMips1 |
299 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
300 // | FeatureMips4 | FeatureMips3 |
301 // | ... | |
302 // --------------------------------------------------
303 //
304 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
305 // FeatureMipsGP64 | FeatureMips1)
306 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
307 void selectArch(StringRef ArchFeature) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000308 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000309 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
310 STI.setFeatureBits(FeatureBits);
311 setAvailableFeatures(
312 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000313 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000314 }
315
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000316 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000317 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000318 setAvailableFeatures(
319 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000320 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000321 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000322 }
323
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000324 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000325 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000326 setAvailableFeatures(
327 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000328 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000329 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000330 }
331
Rafael Espindola870c4e92012-01-11 03:56:41 +0000332public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000333 enum MipsMatchResultTy {
334 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
335#define GET_OPERAND_DIAGNOSTIC_TYPES
336#include "MipsGenAsmMatcher.inc"
337#undef GET_OPERAND_DIAGNOSTIC_TYPES
338
339 };
340
Joey Gouly0e76fa72013-09-12 10:28:05 +0000341 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000342 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000343 : MCTargetAsmParser(), STI(sti),
344 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
345 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000346 MCAsmParserExtension::Initialize(parser);
347
Jack Carterb4dbc172012-09-05 23:34:03 +0000348 // Initialize the set of available features.
349 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000350
351 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000352 AssemblerOptions.push_back(
353 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000354
355 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000356 AssemblerOptions.push_back(
357 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000358
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000359 getTargetStreamer().updateABIInfo(*this);
360
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000361 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000362 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000363
364 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000365 }
366
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000367 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
368 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
369
Michael Kuperstein29704e72015-03-24 12:56:59 +0000370 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
371 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000372 const MipsABIInfo &getABI() const { return ABI; }
373 bool isABI_N32() const { return ABI.IsN32(); }
374 bool isABI_N64() const { return ABI.IsN64(); }
375 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000376 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000377
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000378 bool useOddSPReg() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000379 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000380 }
381
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000382 bool inMicroMipsMode() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000383 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000384 }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000385 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
386 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
387 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
388 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
389 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 bool hasMips32() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000391 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000392 }
393 bool hasMips64() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000394 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395 }
396 bool hasMips32r2() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000397 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 }
399 bool hasMips64r2() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000400 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 }
Daniel Sanders17793142015-02-18 16:24:50 +0000402 bool hasMips32r3() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000403 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000404 }
405 bool hasMips64r3() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000406 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000407 }
408 bool hasMips32r5() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000409 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000410 }
411 bool hasMips64r5() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000412 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000413 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000414 bool hasMips32r6() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000415 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000416 }
417 bool hasMips64r6() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000418 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000419 }
Kai Nackee0245392015-01-27 19:11:28 +0000420 bool hasCnMips() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000421 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000422 }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000423 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
424 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
425 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000426
427 bool inMips16Mode() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000428 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000429 }
430 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000431 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000433 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000434 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000435};
436}
437
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000438namespace {
439
440/// MipsOperand - Instances of this class represent a parsed Mips machine
441/// instruction.
442class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000443public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000444 /// Broad categories of register classes
445 /// The exact class is finalized by the render method.
446 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000448 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000449 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000450 RegKind_FCC = 4, /// FCC
451 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
452 RegKind_MSACtrl = 16, /// MSA control registers
453 RegKind_COP2 = 32, /// COP2
454 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
455 /// context).
456 RegKind_CCR = 128, /// CCR
457 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000458 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000459
460 /// Potentially any (e.g. $1)
461 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
462 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000463 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000464 };
465
466private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000467 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000468 k_Immediate, /// An immediate (possibly involving symbol references)
469 k_Memory, /// Base + Offset Memory Address
470 k_PhysRegister, /// A physical register from the Mips namespace
471 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000472 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000473 k_RegList, /// A physical register list
474 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000475 } Kind;
476
David Blaikie960ea3f2014-06-08 16:18:35 +0000477public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000478 MipsOperand(KindTy K, MipsAsmParser &Parser)
479 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
480
David Blaikie960ea3f2014-06-08 16:18:35 +0000481private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000482 /// For diagnostics, and checking the assembler temporary
483 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000484
Eric Christopher8996c5d2013-03-15 00:42:55 +0000485 struct Token {
486 const char *Data;
487 unsigned Length;
488 };
489
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 struct PhysRegOp {
491 unsigned Num; /// Register Number
492 };
493
494 struct RegIdxOp {
495 unsigned Index; /// Index into the register class
496 RegKind Kind; /// Bitfield of the kinds it could possibly be
497 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000498 };
499
500 struct ImmOp {
501 const MCExpr *Val;
502 };
503
504 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000506 const MCExpr *Off;
507 };
508
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000509 struct RegListOp {
510 SmallVector<unsigned, 10> *List;
511 };
512
Jack Carterb4dbc172012-09-05 23:34:03 +0000513 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000514 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000515 struct PhysRegOp PhysReg;
516 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000517 struct ImmOp Imm;
518 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000519 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000520 };
521
522 SMLoc StartLoc, EndLoc;
523
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000524 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000525 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
526 const MCRegisterInfo *RegInfo,
527 SMLoc S, SMLoc E,
528 MipsAsmParser &Parser) {
529 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000530 Op->RegIdx.Index = Index;
531 Op->RegIdx.RegInfo = RegInfo;
532 Op->RegIdx.Kind = RegKind;
533 Op->StartLoc = S;
534 Op->EndLoc = E;
535 return Op;
536 }
537
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000538public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 /// Coerce the register to GPR32 and return the real register for the current
540 /// target.
541 unsigned getGPR32Reg() const {
542 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000543 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000544 unsigned ClassID = Mips::GPR32RegClassID;
545 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000546 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000547
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000548 /// Coerce the register to GPR32 and return the real register for the current
549 /// target.
550 unsigned getGPRMM16Reg() const {
551 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
552 unsigned ClassID = Mips::GPR32RegClassID;
553 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
554 }
555
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 /// Coerce the register to GPR64 and return the real register for the current
557 /// target.
558 unsigned getGPR64Reg() const {
559 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
560 unsigned ClassID = Mips::GPR64RegClassID;
561 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000562 }
563
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564private:
565 /// Coerce the register to AFGR64 and return the real register for the current
566 /// target.
567 unsigned getAFGR64Reg() const {
568 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
569 if (RegIdx.Index % 2 != 0)
570 AsmParser.Warning(StartLoc, "Float register should be even.");
571 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
572 .getRegister(RegIdx.Index / 2);
573 }
574
575 /// Coerce the register to FGR64 and return the real register for the current
576 /// target.
577 unsigned getFGR64Reg() const {
578 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
579 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
580 .getRegister(RegIdx.Index);
581 }
582
583 /// Coerce the register to FGR32 and return the real register for the current
584 /// target.
585 unsigned getFGR32Reg() const {
586 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
587 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
588 .getRegister(RegIdx.Index);
589 }
590
591 /// Coerce the register to FGRH32 and return the real register for the current
592 /// target.
593 unsigned getFGRH32Reg() const {
594 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
595 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
596 .getRegister(RegIdx.Index);
597 }
598
599 /// Coerce the register to FCC and return the real register for the current
600 /// target.
601 unsigned getFCCReg() const {
602 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
603 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
604 .getRegister(RegIdx.Index);
605 }
606
607 /// Coerce the register to MSA128 and return the real register for the current
608 /// target.
609 unsigned getMSA128Reg() const {
610 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
611 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
612 // identical
613 unsigned ClassID = Mips::MSA128BRegClassID;
614 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
615 }
616
617 /// Coerce the register to MSACtrl and return the real register for the
618 /// current target.
619 unsigned getMSACtrlReg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
621 unsigned ClassID = Mips::MSACtrlRegClassID;
622 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
623 }
624
625 /// Coerce the register to COP2 and return the real register for the
626 /// current target.
627 unsigned getCOP2Reg() const {
628 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
629 unsigned ClassID = Mips::COP2RegClassID;
630 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
631 }
632
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000633 /// Coerce the register to COP3 and return the real register for the
634 /// current target.
635 unsigned getCOP3Reg() const {
636 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
637 unsigned ClassID = Mips::COP3RegClassID;
638 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
639 }
640
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 /// Coerce the register to ACC64DSP and return the real register for the
642 /// current target.
643 unsigned getACC64DSPReg() const {
644 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
645 unsigned ClassID = Mips::ACC64DSPRegClassID;
646 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
647 }
648
649 /// Coerce the register to HI32DSP and return the real register for the
650 /// current target.
651 unsigned getHI32DSPReg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
653 unsigned ClassID = Mips::HI32DSPRegClassID;
654 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
655 }
656
657 /// Coerce the register to LO32DSP and return the real register for the
658 /// current target.
659 unsigned getLO32DSPReg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
661 unsigned ClassID = Mips::LO32DSPRegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to CCR and return the real register for the
666 /// current target.
667 unsigned getCCRReg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
669 unsigned ClassID = Mips::CCRRegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
673 /// Coerce the register to HWRegs and return the real register for the
674 /// current target.
675 unsigned getHWRegsReg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
677 unsigned ClassID = Mips::HWRegsRegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
679 }
680
681public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000682 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000683 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000684 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000685 Inst.addOperand(MCOperand::CreateImm(0));
686 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
687 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
688 else
689 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000690 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000691
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000692 void addRegOperands(MCInst &Inst, unsigned N) const {
693 llvm_unreachable("Use a custom parser instead");
694 }
695
Daniel Sanders21bce302014-04-01 12:35:23 +0000696 /// Render the operand to an MCInst as a GPR32
697 /// Asserts if the wrong number of operands are requested, or the operand
698 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000699 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
700 assert(N == 1 && "Invalid number of operands!");
701 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
702 }
703
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000704 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
705 assert(N == 1 && "Invalid number of operands!");
706 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
707 }
708
Jozef Kolek1904fa22014-11-24 14:25:53 +0000709 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
710 assert(N == 1 && "Invalid number of operands!");
711 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
712 }
713
Zoran Jovanovic41688672015-02-10 16:36:20 +0000714 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
715 assert(N == 1 && "Invalid number of operands!");
716 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
717 }
718
Daniel Sanders21bce302014-04-01 12:35:23 +0000719 /// Render the operand to an MCInst as a GPR64
720 /// Asserts if the wrong number of operands are requested, or the operand
721 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
724 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
725 }
726
727 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
728 assert(N == 1 && "Invalid number of operands!");
729 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
730 }
731
732 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
733 assert(N == 1 && "Invalid number of operands!");
734 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
735 }
736
737 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
738 assert(N == 1 && "Invalid number of operands!");
739 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000740 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000741 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000742 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
743 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 }
745
746 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
747 assert(N == 1 && "Invalid number of operands!");
748 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
749 }
750
751 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
752 assert(N == 1 && "Invalid number of operands!");
753 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
754 }
755
756 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
757 assert(N == 1 && "Invalid number of operands!");
758 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
759 }
760
761 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
762 assert(N == 1 && "Invalid number of operands!");
763 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
764 }
765
766 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
767 assert(N == 1 && "Invalid number of operands!");
768 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
769 }
770
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000771 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
772 assert(N == 1 && "Invalid number of operands!");
773 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
774 }
775
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
777 assert(N == 1 && "Invalid number of operands!");
778 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
779 }
780
781 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
783 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
784 }
785
786 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
788 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
789 }
790
791 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
793 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
794 }
795
796 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
798 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
799 }
800
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000801 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000802 assert(N == 1 && "Invalid number of operands!");
803 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000804 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000805 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000806
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000807 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000808 assert(N == 2 && "Invalid number of operands!");
809
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000811
812 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000813 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000814 }
815
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000816 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
817 assert(N == 2 && "Invalid number of operands!");
818
819 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
820
821 const MCExpr *Expr = getMemOff();
822 addExpr(Inst, Expr);
823 }
824
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000825 void addRegListOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 1 && "Invalid number of operands!");
827
828 for (auto RegNo : getRegList())
829 Inst.addOperand(MCOperand::CreateReg(RegNo));
830 }
831
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000832 void addRegPairOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 2 && "Invalid number of operands!");
834 unsigned RegNo = getRegPair();
835 Inst.addOperand(MCOperand::CreateReg(RegNo++));
836 Inst.addOperand(MCOperand::CreateReg(RegNo));
837 }
838
Zoran Jovanovic41688672015-02-10 16:36:20 +0000839 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
840 assert(N == 2 && "Invalid number of operands!");
841 for (auto RegNo : getRegList())
842 Inst.addOperand(MCOperand::CreateReg(RegNo));
843 }
844
Craig Topper56c590a2014-04-29 07:58:02 +0000845 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 // As a special case until we sort out the definition of div/divu, pretend
847 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
848 if (isGPRAsmReg() && RegIdx.Index == 0)
849 return true;
850
851 return Kind == k_PhysRegister;
852 }
853 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000854 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 bool isConstantImm() const {
856 return isImm() && dyn_cast<MCConstantExpr>(getImm());
857 }
Craig Topper56c590a2014-04-29 07:58:02 +0000858 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 // Note: It's not possible to pretend that other operand kinds are tokens.
860 // The matcher emitter checks tokens first.
861 return Kind == k_Token;
862 }
Craig Topper56c590a2014-04-29 07:58:02 +0000863 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000864 bool isConstantMemOff() const {
865 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
866 }
867 template <unsigned Bits> bool isMemWithSimmOffset() const {
868 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
869 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000870 bool isMemWithGRPMM16Base() const {
871 return isMem() && getMemBase()->isMM16AsmReg();
872 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000873 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
874 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
875 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
876 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000877 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
878 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
879 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
880 && (getMemBase()->getGPR32Reg() == Mips::SP);
881 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000882 bool isRegList16() const {
883 if (!isRegList())
884 return false;
885
886 int Size = RegList.List->size();
887 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
888 RegList.List->back() != Mips::RA)
889 return false;
890
891 int PrevReg = *RegList.List->begin();
892 for (int i = 1; i < Size - 1; i++) {
893 int Reg = (*(RegList.List))[i];
894 if ( Reg != PrevReg + 1)
895 return false;
896 PrevReg = Reg;
897 }
898
899 return true;
900 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000901 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 bool isLSAImm() const {
903 if (!isConstantImm())
904 return false;
905 int64_t Val = getConstantImm();
906 return 1 <= Val && Val <= 4;
907 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000908 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000909 bool isMovePRegPair() const {
910 if (Kind != k_RegList || RegList.List->size() != 2)
911 return false;
912
913 unsigned R0 = RegList.List->front();
914 unsigned R1 = RegList.List->back();
915
916 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
917 (R0 == Mips::A1 && R1 == Mips::A3) ||
918 (R0 == Mips::A2 && R1 == Mips::A3) ||
919 (R0 == Mips::A0 && R1 == Mips::S5) ||
920 (R0 == Mips::A0 && R1 == Mips::S6) ||
921 (R0 == Mips::A0 && R1 == Mips::A1) ||
922 (R0 == Mips::A0 && R1 == Mips::A2) ||
923 (R0 == Mips::A0 && R1 == Mips::A3))
924 return true;
925
926 return false;
927 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000928
929 StringRef getToken() const {
930 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000931 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000932 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000933 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000934
Craig Topper56c590a2014-04-29 07:58:02 +0000935 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000936 // As a special case until we sort out the definition of div/divu, pretend
937 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
938 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
939 RegIdx.Kind & RegKind_GPR)
940 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000941
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 assert(Kind == k_PhysRegister && "Invalid access!");
943 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000944 }
945
Jack Carterb4dbc172012-09-05 23:34:03 +0000946 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000947 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 return Imm.Val;
949 }
950
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 int64_t getConstantImm() const {
952 const MCExpr *Val = getImm();
953 return static_cast<const MCConstantExpr *>(Val)->getValue();
954 }
955
956 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000957 assert((Kind == k_Memory) && "Invalid access!");
958 return Mem.Base;
959 }
960
961 const MCExpr *getMemOff() const {
962 assert((Kind == k_Memory) && "Invalid access!");
963 return Mem.Off;
964 }
965
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000966 int64_t getConstantMemOff() const {
967 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
968 }
969
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000970 const SmallVectorImpl<unsigned> &getRegList() const {
971 assert((Kind == k_RegList) && "Invalid access!");
972 return *(RegList.List);
973 }
974
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000975 unsigned getRegPair() const {
976 assert((Kind == k_RegPair) && "Invalid access!");
977 return RegIdx.Index;
978 }
979
David Blaikie960ea3f2014-06-08 16:18:35 +0000980 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
981 MipsAsmParser &Parser) {
982 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000983 Op->Tok.Data = Str.data();
984 Op->Tok.Length = Str.size();
985 Op->StartLoc = S;
986 Op->EndLoc = S;
987 return Op;
988 }
989
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000990 /// Create a numeric register (e.g. $1). The exact register remains
991 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000992 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000993 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000994 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000995 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000997 }
998
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000999 /// Create a register that is definitely a GPR.
1000 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001001 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001002 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001003 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001004 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001005 }
1006
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 /// Create a register that is definitely a FGR.
1008 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001009 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001010 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001011 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1013 }
1014
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001015 /// Create a register that is definitely a HWReg.
1016 /// This is typically only used for named registers such as $hwr_cpunum.
1017 static std::unique_ptr<MipsOperand>
1018 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1019 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1020 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1021 }
1022
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 /// Create a register that is definitely an FCC.
1024 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001026 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001027 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001028 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1029 }
1030
1031 /// Create a register that is definitely an ACC.
1032 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001033 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001034 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001035 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001036 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1037 }
1038
1039 /// Create a register that is definitely an MSA128.
1040 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001042 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001043 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001044 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1045 }
1046
1047 /// Create a register that is definitely an MSACtrl.
1048 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001050 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001051 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1053 }
1054
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 static std::unique_ptr<MipsOperand>
1056 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1057 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001058 Op->Imm.Val = Val;
1059 Op->StartLoc = S;
1060 Op->EndLoc = E;
1061 return Op;
1062 }
1063
David Blaikie960ea3f2014-06-08 16:18:35 +00001064 static std::unique_ptr<MipsOperand>
1065 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1066 SMLoc E, MipsAsmParser &Parser) {
1067 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1068 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001069 Op->Mem.Off = Off;
1070 Op->StartLoc = S;
1071 Op->EndLoc = E;
1072 return Op;
1073 }
1074
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001075 static std::unique_ptr<MipsOperand>
1076 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1077 MipsAsmParser &Parser) {
1078 assert (Regs.size() > 0 && "Empty list not allowed");
1079
1080 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001081 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001082 Op->StartLoc = StartLoc;
1083 Op->EndLoc = EndLoc;
1084 return Op;
1085 }
1086
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001087 static std::unique_ptr<MipsOperand>
1088 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1089 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1090 Op->RegIdx.Index = RegNo;
1091 Op->StartLoc = S;
1092 Op->EndLoc = E;
1093 return Op;
1094 }
1095
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 bool isGPRAsmReg() const {
1097 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001098 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001099 bool isMM16AsmReg() const {
1100 if (!(isRegIdx() && RegIdx.Kind))
1101 return false;
1102 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1103 || RegIdx.Index == 16 || RegIdx.Index == 17);
1104 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001105 bool isMM16AsmRegZero() const {
1106 if (!(isRegIdx() && RegIdx.Kind))
1107 return false;
1108 return (RegIdx.Index == 0 ||
1109 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1110 RegIdx.Index == 17);
1111 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001112 bool isMM16AsmRegMoveP() const {
1113 if (!(isRegIdx() && RegIdx.Kind))
1114 return false;
1115 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1116 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1117 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 bool isFGRAsmReg() const {
1119 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1120 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001121 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 bool isHWRegsAsmReg() const {
1123 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001124 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 bool isCCRAsmReg() const {
1126 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001127 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001129 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1130 return false;
1131 if (!AsmParser.hasEightFccRegisters())
1132 return RegIdx.Index == 0;
1133 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001134 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 bool isACCAsmReg() const {
1136 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001137 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 bool isCOP2AsmReg() const {
1139 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001140 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001141 bool isCOP3AsmReg() const {
1142 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1143 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 bool isMSA128AsmReg() const {
1145 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001146 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 bool isMSACtrlAsmReg() const {
1148 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001149 }
1150
Jack Carterb4dbc172012-09-05 23:34:03 +00001151 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001152 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001153 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001154 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001155
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001156 virtual ~MipsOperand() {
1157 switch (Kind) {
1158 case k_Immediate:
1159 break;
1160 case k_Memory:
1161 delete Mem.Base;
1162 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001163 case k_RegList:
1164 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001165 case k_PhysRegister:
1166 case k_RegisterIndex:
1167 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001168 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001169 break;
1170 }
1171 }
1172
Craig Topper56c590a2014-04-29 07:58:02 +00001173 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001174 switch (Kind) {
1175 case k_Immediate:
1176 OS << "Imm<";
1177 Imm.Val->print(OS);
1178 OS << ">";
1179 break;
1180 case k_Memory:
1181 OS << "Mem<";
1182 Mem.Base->print(OS);
1183 OS << ", ";
1184 Mem.Off->print(OS);
1185 OS << ">";
1186 break;
1187 case k_PhysRegister:
1188 OS << "PhysReg<" << PhysReg.Num << ">";
1189 break;
1190 case k_RegisterIndex:
1191 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1192 break;
1193 case k_Token:
1194 OS << Tok.Data;
1195 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001196 case k_RegList:
1197 OS << "RegList< ";
1198 for (auto Reg : (*RegList.List))
1199 OS << Reg << " ";
1200 OS << ">";
1201 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001202 case k_RegPair:
1203 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1204 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001206 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001207}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001208} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001209
Jack Carter9e65aa32013-03-22 00:05:30 +00001210namespace llvm {
1211extern const MCInstrDesc MipsInsts[];
1212}
1213static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1214 return MipsInsts[Opcode];
1215}
1216
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001217static bool hasShortDelaySlot(unsigned Opcode) {
1218 switch (Opcode) {
1219 case Mips::JALS_MM:
1220 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001221 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001222 case Mips::BGEZALS_MM:
1223 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001224 return true;
1225 default:
1226 return false;
1227 }
1228}
1229
Jack Carter9e65aa32013-03-22 00:05:30 +00001230bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001231 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001232 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001233
Jack Carter9e65aa32013-03-22 00:05:30 +00001234 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001235
1236 if (MCID.isBranch() || MCID.isCall()) {
1237 const unsigned Opcode = Inst.getOpcode();
1238 MCOperand Offset;
1239
1240 switch (Opcode) {
1241 default:
1242 break;
Kai Nackee0245392015-01-27 19:11:28 +00001243 case Mips::BBIT0:
1244 case Mips::BBIT032:
1245 case Mips::BBIT1:
1246 case Mips::BBIT132:
1247 assert(hasCnMips() && "instruction only valid for octeon cpus");
1248 // Fall through
1249
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001250 case Mips::BEQ:
1251 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 case Mips::BEQ_MM:
1253 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001254 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001255 Offset = Inst.getOperand(2);
1256 if (!Offset.isImm())
1257 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001258 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001259 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001260 if (OffsetToAlignment(Offset.getImm(),
1261 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001262 return Error(IDLoc, "branch to misaligned address");
1263 break;
1264 case Mips::BGEZ:
1265 case Mips::BGTZ:
1266 case Mips::BLEZ:
1267 case Mips::BLTZ:
1268 case Mips::BGEZAL:
1269 case Mips::BLTZAL:
1270 case Mips::BC1F:
1271 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001272 case Mips::BGEZ_MM:
1273 case Mips::BGTZ_MM:
1274 case Mips::BLEZ_MM:
1275 case Mips::BLTZ_MM:
1276 case Mips::BGEZAL_MM:
1277 case Mips::BLTZAL_MM:
1278 case Mips::BC1F_MM:
1279 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001280 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001281 Offset = Inst.getOperand(1);
1282 if (!Offset.isImm())
1283 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001284 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001285 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001286 if (OffsetToAlignment(Offset.getImm(),
1287 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001288 return Error(IDLoc, "branch to misaligned address");
1289 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001290 case Mips::BEQZ16_MM:
1291 case Mips::BNEZ16_MM:
1292 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1293 Offset = Inst.getOperand(1);
1294 if (!Offset.isImm())
1295 break; // We'll deal with this situation later on when applying fixups.
1296 if (!isIntN(8, Offset.getImm()))
1297 return Error(IDLoc, "branch target out of range");
1298 if (OffsetToAlignment(Offset.getImm(), 2LL))
1299 return Error(IDLoc, "branch to misaligned address");
1300 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001301 }
1302 }
1303
Daniel Sandersa84989a2014-06-16 13:25:35 +00001304 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1305 // We still accept it but it is a normal nop.
1306 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1307 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1308 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1309 "nop instruction");
1310 }
1311
Kai Nackee0245392015-01-27 19:11:28 +00001312 if (hasCnMips()) {
1313 const unsigned Opcode = Inst.getOpcode();
1314 MCOperand Opnd;
1315 int Imm;
1316
1317 switch (Opcode) {
1318 default:
1319 break;
1320
1321 case Mips::BBIT0:
1322 case Mips::BBIT032:
1323 case Mips::BBIT1:
1324 case Mips::BBIT132:
1325 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1326 // The offset is handled above
1327 Opnd = Inst.getOperand(1);
1328 if (!Opnd.isImm())
1329 return Error(IDLoc, "expected immediate operand kind");
1330 Imm = Opnd.getImm();
1331 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1332 Opcode == Mips::BBIT1 ? 63 : 31))
1333 return Error(IDLoc, "immediate operand value out of range");
1334 if (Imm > 31) {
1335 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1336 : Mips::BBIT132);
1337 Inst.getOperand(1).setImm(Imm - 32);
1338 }
1339 break;
1340
1341 case Mips::CINS:
1342 case Mips::CINS32:
1343 case Mips::EXTS:
1344 case Mips::EXTS32:
1345 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1346 // Check length
1347 Opnd = Inst.getOperand(3);
1348 if (!Opnd.isImm())
1349 return Error(IDLoc, "expected immediate operand kind");
1350 Imm = Opnd.getImm();
1351 if (Imm < 0 || Imm > 31)
1352 return Error(IDLoc, "immediate operand value out of range");
1353 // Check position
1354 Opnd = Inst.getOperand(2);
1355 if (!Opnd.isImm())
1356 return Error(IDLoc, "expected immediate operand kind");
1357 Imm = Opnd.getImm();
1358 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1359 Opcode == Mips::EXTS ? 63 : 31))
1360 return Error(IDLoc, "immediate operand value out of range");
1361 if (Imm > 31) {
1362 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1363 Inst.getOperand(2).setImm(Imm - 32);
1364 }
1365 break;
1366
1367 case Mips::SEQi:
1368 case Mips::SNEi:
1369 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1370 Opnd = Inst.getOperand(2);
1371 if (!Opnd.isImm())
1372 return Error(IDLoc, "expected immediate operand kind");
1373 Imm = Opnd.getImm();
1374 if (!isInt<10>(Imm))
1375 return Error(IDLoc, "immediate operand value out of range");
1376 break;
1377 }
1378 }
1379
Toma Tabacu234482a2015-03-16 12:03:39 +00001380 // If this instruction has a delay slot and .set reorder is active,
1381 // emit a NOP after it.
Toma Tabacu9db22db2014-09-09 10:15:38 +00001382 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001383 Instructions.push_back(Inst);
Toma Tabacu234482a2015-03-16 12:03:39 +00001384 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
Jack Carterc15c1d22013-04-25 23:31:35 +00001385 return false;
1386 }
1387
Jack Carter9e65aa32013-03-22 00:05:30 +00001388 if (MCID.mayLoad() || MCID.mayStore()) {
1389 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 // reference or immediate we may have to expand instructions.
1391 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001392 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001393 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1394 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001395 MCOperand &Op = Inst.getOperand(i);
1396 if (Op.isImm()) {
1397 int MemOffset = Op.getImm();
1398 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001399 // Offset can't exceed 16bit value.
1400 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001401 return false;
1402 }
1403 } else if (Op.isExpr()) {
1404 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001406 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001407 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001408 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 // Expand symbol.
1410 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001411 return false;
1412 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001413 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001415 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001416 }
1417 }
1418 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001419 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001420 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001421
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001422 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001423 if (MCID.mayLoad()) {
1424 // Try to create 16-bit GP relative load instruction.
1425 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1426 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1427 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1428 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1429 MCOperand &Op = Inst.getOperand(i);
1430 if (Op.isImm()) {
1431 int MemOffset = Op.getImm();
1432 MCOperand &DstReg = Inst.getOperand(0);
1433 MCOperand &BaseReg = Inst.getOperand(1);
1434 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1435 getContext().getRegisterInfo()->getRegClass(
1436 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1437 BaseReg.getReg() == Mips::GP) {
1438 MCInst TmpInst;
1439 TmpInst.setLoc(IDLoc);
1440 TmpInst.setOpcode(Mips::LWGP_MM);
1441 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1442 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1443 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1444 Instructions.push_back(TmpInst);
1445 return false;
1446 }
1447 }
1448 }
1449 } // for
1450 } // if load
1451
1452 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1453
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001454 MCOperand Opnd;
1455 int Imm;
1456
1457 switch (Inst.getOpcode()) {
1458 default:
1459 break;
1460 case Mips::ADDIUS5_MM:
1461 Opnd = Inst.getOperand(2);
1462 if (!Opnd.isImm())
1463 return Error(IDLoc, "expected immediate operand kind");
1464 Imm = Opnd.getImm();
1465 if (Imm < -8 || Imm > 7)
1466 return Error(IDLoc, "immediate operand value out of range");
1467 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001468 case Mips::ADDIUSP_MM:
1469 Opnd = Inst.getOperand(0);
1470 if (!Opnd.isImm())
1471 return Error(IDLoc, "expected immediate operand kind");
1472 Imm = Opnd.getImm();
1473 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1474 Imm % 4 != 0)
1475 return Error(IDLoc, "immediate operand value out of range");
1476 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001477 case Mips::SLL16_MM:
1478 case Mips::SRL16_MM:
1479 Opnd = Inst.getOperand(2);
1480 if (!Opnd.isImm())
1481 return Error(IDLoc, "expected immediate operand kind");
1482 Imm = Opnd.getImm();
1483 if (Imm < 1 || Imm > 8)
1484 return Error(IDLoc, "immediate operand value out of range");
1485 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001486 case Mips::LI16_MM:
1487 Opnd = Inst.getOperand(1);
1488 if (!Opnd.isImm())
1489 return Error(IDLoc, "expected immediate operand kind");
1490 Imm = Opnd.getImm();
1491 if (Imm < -1 || Imm > 126)
1492 return Error(IDLoc, "immediate operand value out of range");
1493 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001494 case Mips::ADDIUR2_MM:
1495 Opnd = Inst.getOperand(2);
1496 if (!Opnd.isImm())
1497 return Error(IDLoc, "expected immediate operand kind");
1498 Imm = Opnd.getImm();
1499 if (!(Imm == 1 || Imm == -1 ||
1500 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1501 return Error(IDLoc, "immediate operand value out of range");
1502 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001503 case Mips::ADDIUR1SP_MM:
1504 Opnd = Inst.getOperand(1);
1505 if (!Opnd.isImm())
1506 return Error(IDLoc, "expected immediate operand kind");
1507 Imm = Opnd.getImm();
1508 if (OffsetToAlignment(Imm, 4LL))
1509 return Error(IDLoc, "misaligned immediate operand value");
1510 if (Imm < 0 || Imm > 255)
1511 return Error(IDLoc, "immediate operand value out of range");
1512 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001513 case Mips::ANDI16_MM:
1514 Opnd = Inst.getOperand(2);
1515 if (!Opnd.isImm())
1516 return Error(IDLoc, "expected immediate operand kind");
1517 Imm = Opnd.getImm();
1518 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1519 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1520 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1521 return Error(IDLoc, "immediate operand value out of range");
1522 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001523 case Mips::LBU16_MM:
1524 Opnd = Inst.getOperand(2);
1525 if (!Opnd.isImm())
1526 return Error(IDLoc, "expected immediate operand kind");
1527 Imm = Opnd.getImm();
1528 if (Imm < -1 || Imm > 14)
1529 return Error(IDLoc, "immediate operand value out of range");
1530 break;
1531 case Mips::SB16_MM:
1532 Opnd = Inst.getOperand(2);
1533 if (!Opnd.isImm())
1534 return Error(IDLoc, "expected immediate operand kind");
1535 Imm = Opnd.getImm();
1536 if (Imm < 0 || Imm > 15)
1537 return Error(IDLoc, "immediate operand value out of range");
1538 break;
1539 case Mips::LHU16_MM:
1540 case Mips::SH16_MM:
1541 Opnd = Inst.getOperand(2);
1542 if (!Opnd.isImm())
1543 return Error(IDLoc, "expected immediate operand kind");
1544 Imm = Opnd.getImm();
1545 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1546 return Error(IDLoc, "immediate operand value out of range");
1547 break;
1548 case Mips::LW16_MM:
1549 case Mips::SW16_MM:
1550 Opnd = Inst.getOperand(2);
1551 if (!Opnd.isImm())
1552 return Error(IDLoc, "expected immediate operand kind");
1553 Imm = Opnd.getImm();
1554 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1555 return Error(IDLoc, "immediate operand value out of range");
1556 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001557 case Mips::CACHE:
1558 case Mips::PREF:
1559 Opnd = Inst.getOperand(2);
1560 if (!Opnd.isImm())
1561 return Error(IDLoc, "expected immediate operand kind");
1562 Imm = Opnd.getImm();
1563 if (!isUInt<5>(Imm))
1564 return Error(IDLoc, "immediate operand value out of range");
1565 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001566 case Mips::ADDIUPC_MM:
1567 MCOperand Opnd = Inst.getOperand(1);
1568 if (!Opnd.isImm())
1569 return Error(IDLoc, "expected immediate operand kind");
1570 int Imm = Opnd.getImm();
1571 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1572 return Error(IDLoc, "immediate operand value out of range");
1573 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001574 }
1575 }
1576
Jack Carter9e65aa32013-03-22 00:05:30 +00001577 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001578 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001579 else
1580 Instructions.push_back(Inst);
1581
1582 return false;
1583}
1584
Jack Carter30a59822012-10-04 04:03:53 +00001585bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1586
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001588 case Mips::LoadImm32:
1589 case Mips::LoadImm64:
1590 case Mips::LoadAddrImm32:
1591 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001592 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001593 case Mips::LWM_MM:
1594 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001595 case Mips::JalOneReg:
1596 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 return true;
1598 default:
1599 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001600 }
1601}
Jack Carter92995f12012-10-06 00:53:28 +00001602
Matheus Almeida3813d572014-06-19 14:39:14 +00001603bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001604 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001605 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001606 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001607 case Mips::LoadImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001609 case Mips::LoadImm64:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001610 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001611 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001612 return true;
1613 }
1614 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001615 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001617 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001619 case Mips::B_MM_Pseudo:
1620 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001621 case Mips::SWM_MM:
1622 case Mips::LWM_MM:
1623 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001624 case Mips::JalOneReg:
1625 case Mips::JalTwoReg:
1626 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 }
Jack Carter30a59822012-10-04 04:03:53 +00001628}
Jack Carter92995f12012-10-06 00:53:28 +00001629
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001630namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001631template <bool PerformShift>
1632void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001633 SmallVectorImpl<MCInst> &Instructions) {
1634 MCInst tmpInst;
1635 if (PerformShift) {
1636 tmpInst.setOpcode(Mips::DSLL);
1637 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1638 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1639 tmpInst.addOperand(MCOperand::CreateImm(16));
1640 tmpInst.setLoc(IDLoc);
1641 Instructions.push_back(tmpInst);
1642 tmpInst.clear();
1643 }
1644 tmpInst.setOpcode(Mips::ORi);
1645 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1646 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001647 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001648 tmpInst.setLoc(IDLoc);
1649 Instructions.push_back(tmpInst);
1650}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001651
1652template <int Shift, bool PerformShift>
1653void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1654 SmallVectorImpl<MCInst> &Instructions) {
1655 createShiftOr<PerformShift>(
1656 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1657 IDLoc, Instructions);
1658}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001659}
1660
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001661bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1662 SmallVectorImpl<MCInst> &Instructions) {
1663 // Create a JALR instruction which is going to replace the pseudo-JAL.
1664 MCInst JalrInst;
1665 JalrInst.setLoc(IDLoc);
1666 const MCOperand FirstRegOp = Inst.getOperand(0);
1667 const unsigned Opcode = Inst.getOpcode();
1668
1669 if (Opcode == Mips::JalOneReg) {
1670 // jal $rs => jalr $rs
1671 if (inMicroMipsMode()) {
1672 JalrInst.setOpcode(Mips::JALR16_MM);
1673 JalrInst.addOperand(FirstRegOp);
1674 } else {
1675 JalrInst.setOpcode(Mips::JALR);
1676 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1677 JalrInst.addOperand(FirstRegOp);
1678 }
1679 } else if (Opcode == Mips::JalTwoReg) {
1680 // jal $rd, $rs => jalr $rd, $rs
1681 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1682 JalrInst.addOperand(FirstRegOp);
1683 const MCOperand SecondRegOp = Inst.getOperand(1);
1684 JalrInst.addOperand(SecondRegOp);
1685 }
1686 Instructions.push_back(JalrInst);
1687
1688 // If .set reorder is active, emit a NOP after it.
1689 if (AssemblerOptions.back()->isReorder()) {
1690 // This is a 32-bit NOP because these 2 pseudo-instructions
1691 // do not have a short delay slot.
1692 MCInst NopInst;
1693 NopInst.setOpcode(Mips::SLL);
1694 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1695 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1696 NopInst.addOperand(MCOperand::CreateImm(0));
1697 Instructions.push_back(NopInst);
1698 }
1699
1700 return false;
1701}
1702
Matheus Almeida3813d572014-06-19 14:39:14 +00001703bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001704 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001705 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001706 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001707 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001708 const MCOperand &RegOp = Inst.getOperand(0);
1709 assert(RegOp.isReg() && "expected register operand kind");
1710
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001711 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001712 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001713 // FIXME: gas has a special case for values that are 000...1111, which
1714 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 if (0 <= ImmValue && ImmValue <= 65535) {
1716 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001717 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001718 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001719 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001720 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001721 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001722 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001723 } else if (ImmValue < 0 && ImmValue >= -32768) {
1724 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001725 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001726 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001727 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001729 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001730 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001731 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1732 // For any value of j that is representable as a 32-bit integer, create
1733 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001734 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001735 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001736 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001737 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1738 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001739 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001740 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1741 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001742 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001743 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001744 return true;
1745 }
1746
1747 // <------- lo32 ------>
1748 // <------- hi32 ------>
1749 // <- hi16 -> <- lo16 ->
1750 // _________________________________
1751 // | | | |
1752 // | 16-bytes | 16-bytes | 16-bytes |
1753 // |__________|__________|__________|
1754 //
1755 // For any value of j that is representable as a 48-bit integer, create
1756 // a sequence of:
1757 // li d,j => lui d,hi16(j)
1758 // ori d,d,hi16(lo32(j))
1759 // dsll d,d,16
1760 // ori d,d,lo16(lo32(j))
1761 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001762 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001763 tmpInst.addOperand(
1764 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001765 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001766 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1767 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1768 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001769 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001770 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001771 return true;
1772 }
1773
1774 // <------- hi32 ------> <------- lo32 ------>
1775 // <- hi16 -> <- lo16 ->
1776 // ___________________________________________
1777 // | | | | |
1778 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1779 // |__________|__________|__________|__________|
1780 //
1781 // For any value of j that isn't representable as a 48-bit integer.
1782 // li d,j => lui d,hi16(j)
1783 // ori d,d,lo16(hi32(j))
1784 // dsll d,d,16
1785 // ori d,d,hi16(lo32(j))
1786 // dsll d,d,16
1787 // ori d,d,lo16(lo32(j))
1788 tmpInst.setOpcode(Mips::LUi);
1789 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1790 tmpInst.addOperand(
1791 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1792 Instructions.push_back(tmpInst);
1793 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1794 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1795 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001796 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001797 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001798}
Jack Carter92995f12012-10-06 00:53:28 +00001799
Matheus Almeida3813d572014-06-19 14:39:14 +00001800bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001801MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1802 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001803 MCInst tmpInst;
1804 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001805 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1806 "expected immediate operand kind");
1807 if (!ImmOp.isImm()) {
1808 expandLoadAddressSym(Inst, IDLoc, Instructions);
1809 return false;
1810 }
Jack Carter543fdf82012-10-09 23:29:45 +00001811 const MCOperand &SrcRegOp = Inst.getOperand(1);
1812 assert(SrcRegOp.isReg() && "expected register operand kind");
1813 const MCOperand &DstRegOp = Inst.getOperand(0);
1814 assert(DstRegOp.isReg() && "expected register operand kind");
1815 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001816 if (-32768 <= ImmValue && ImmValue <= 65535) {
1817 // For -32768 <= j <= 65535.
1818 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001819 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001820 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1821 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1822 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1823 Instructions.push_back(tmpInst);
1824 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001825 // For any other value of j that is representable as a 32-bit integer.
1826 // la d,j(s) => lui d,hi16(j)
1827 // ori d,d,lo16(j)
1828 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001829 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001830 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1831 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1832 Instructions.push_back(tmpInst);
1833 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001834 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001835 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1836 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1837 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1838 Instructions.push_back(tmpInst);
1839 tmpInst.clear();
1840 tmpInst.setOpcode(Mips::ADDu);
1841 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1842 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1843 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1844 Instructions.push_back(tmpInst);
1845 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001846 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001847}
1848
Matheus Almeida3813d572014-06-19 14:39:14 +00001849bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001850MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1851 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001852 MCInst tmpInst;
1853 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001854 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1855 "expected immediate operand kind");
1856 if (!ImmOp.isImm()) {
1857 expandLoadAddressSym(Inst, IDLoc, Instructions);
1858 return false;
1859 }
Jack Carter543fdf82012-10-09 23:29:45 +00001860 const MCOperand &RegOp = Inst.getOperand(0);
1861 assert(RegOp.isReg() && "expected register operand kind");
1862 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001863 if (-32768 <= ImmValue && ImmValue <= 65535) {
1864 // For -32768 <= j <= 65535.
1865 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001866 tmpInst.setOpcode(Mips::ADDiu);
1867 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001868 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001869 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1870 Instructions.push_back(tmpInst);
1871 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001872 // For any other value of j that is representable as a 32-bit integer.
1873 // la d,j => lui d,hi16(j)
1874 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001875 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001876 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1877 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1878 Instructions.push_back(tmpInst);
1879 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001880 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001881 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1882 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1883 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1884 Instructions.push_back(tmpInst);
1885 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001886 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001887}
1888
Toma Tabacu0d64b202014-08-14 10:29:17 +00001889void
1890MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1891 SmallVectorImpl<MCInst> &Instructions) {
1892 // FIXME: If we do have a valid at register to use, we should generate a
1893 // slightly shorter sequence here.
1894 MCInst tmpInst;
1895 int ExprOperandNo = 1;
1896 // Sometimes the assembly parser will get the immediate expression as
1897 // a $zero + an immediate.
1898 if (Inst.getNumOperands() == 3) {
1899 assert(Inst.getOperand(1).getReg() ==
1900 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1901 ExprOperandNo = 2;
1902 }
1903 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1904 assert(SymOp.isExpr() && "expected symbol operand kind");
1905 const MCOperand &RegOp = Inst.getOperand(0);
1906 unsigned RegNo = RegOp.getReg();
1907 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1908 const MCSymbolRefExpr *HiExpr =
1909 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1910 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1911 const MCSymbolRefExpr *LoExpr =
1912 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1913 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1914 if (isGP64bit()) {
1915 // If it's a 64-bit architecture, expand to:
1916 // la d,sym => lui d,highest(sym)
1917 // ori d,d,higher(sym)
1918 // dsll d,d,16
1919 // ori d,d,hi16(sym)
1920 // dsll d,d,16
1921 // ori d,d,lo16(sym)
1922 const MCSymbolRefExpr *HighestExpr =
1923 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1924 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1925 const MCSymbolRefExpr *HigherExpr =
1926 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1927 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1928
1929 tmpInst.setOpcode(Mips::LUi);
1930 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1931 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1932 Instructions.push_back(tmpInst);
1933
1934 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1935 Instructions);
1936 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1937 Instructions);
1938 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1939 Instructions);
1940 } else {
1941 // Otherwise, expand to:
1942 // la d,sym => lui d,hi16(sym)
1943 // ori d,d,lo16(sym)
1944 tmpInst.setOpcode(Mips::LUi);
1945 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1946 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1947 Instructions.push_back(tmpInst);
1948
1949 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1950 Instructions);
1951 }
1952}
1953
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001954bool MipsAsmParser::expandUncondBranchMMPseudo(
1955 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001956 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1957 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001958
1959 MCOperand Offset = Inst.getOperand(0);
1960 if (Offset.isExpr()) {
1961 Inst.clear();
1962 Inst.setOpcode(Mips::BEQ_MM);
1963 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1964 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1965 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1966 } else {
1967 assert(Offset.isImm() && "expected immediate operand kind");
1968 if (isIntN(11, Offset.getImm())) {
1969 // If offset fits into 11 bits then this instruction becomes microMIPS
1970 // 16-bit unconditional branch instruction.
1971 Inst.setOpcode(Mips::B16_MM);
1972 } else {
1973 if (!isIntN(17, Offset.getImm()))
1974 Error(IDLoc, "branch target out of range");
1975 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1976 Error(IDLoc, "branch to misaligned address");
1977 Inst.clear();
1978 Inst.setOpcode(Mips::BEQ_MM);
1979 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1980 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1981 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1982 }
1983 }
1984 Instructions.push_back(Inst);
1985
Toma Tabacu234482a2015-03-16 12:03:39 +00001986 // If .set reorder is active, emit a NOP after the branch instruction.
1987 if (AssemblerOptions.back()->isReorder())
1988 createNop(true, IDLoc, Instructions);
1989
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001990 return false;
1991}
1992
Jack Carter9e65aa32013-03-22 00:05:30 +00001993void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001994 SmallVectorImpl<MCInst> &Instructions,
1995 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001996 const MCSymbolRefExpr *SR;
1997 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001998 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001999 const MCExpr *ExprOffset;
2000 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002001 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002002 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2003 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002004 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002005 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2006 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002007 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002008 if (isImmOpnd) {
2009 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2010 ImmOffset = Inst.getOperand(2).getImm();
2011 LoOffset = ImmOffset & 0x0000ffff;
2012 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002013 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002014 if (LoOffset & 0x8000)
2015 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002016 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002017 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002018 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002019 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002020 // These are some of the types of expansions we perform here:
2021 // 1) lw $8, sym => lui $8, %hi(sym)
2022 // lw $8, %lo(sym)($8)
2023 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2024 // add $8, $8, $9
2025 // lw $8, %lo(offset)($9)
2026 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2027 // add $at, $at, $8
2028 // lw $8, %lo(offset)($at)
2029 // 4) sw $8, sym => lui $at, %hi(sym)
2030 // sw $8, %lo(sym)($at)
2031 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2032 // add $at, $at, $8
2033 // sw $8, %lo(offset)($at)
2034 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2035 // ldc1 $f0, %lo(sym)($at)
2036 //
2037 // For load instructions we can use the destination register as a temporary
2038 // if base and dst are different (examples 1 and 2) and if the base register
2039 // is general purpose otherwise we must use $at (example 6) and error if it's
2040 // not available. For stores we must use $at (examples 4 and 5) because we
2041 // must not clobber the source register setting up the offset.
2042 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2043 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2044 unsigned RegClassIDOp0 =
2045 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2046 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2047 (RegClassIDOp0 == Mips::GPR64RegClassID);
2048 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002049 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002050 else {
2051 int AT = getATReg(IDLoc);
2052 // At this point we need AT to perform the expansions and we exit if it is
2053 // not available.
2054 if (!AT)
2055 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002056 TmpRegNum = getReg(
2057 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002058 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002059
Jack Carter9e65aa32013-03-22 00:05:30 +00002060 TempInst.setOpcode(Mips::LUi);
2061 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2062 if (isImmOpnd)
2063 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2064 else {
2065 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002066 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2068 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2069 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002070 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002071 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002073 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002074 }
2075 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002077 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002078 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002081 if (BaseRegNum != Mips::ZERO) {
2082 TempInst.setOpcode(Mips::ADDu);
2083 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2084 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2085 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2086 Instructions.push_back(TempInst);
2087 TempInst.clear();
2088 }
Alp Tokercb402912014-01-24 17:20:08 +00002089 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002090 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 TempInst.setOpcode(Inst.getOpcode());
2092 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2093 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2094 if (isImmOpnd)
2095 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2096 else {
2097 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2099 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2100 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002101 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002102 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002104 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002105 }
2106 }
2107 Instructions.push_back(TempInst);
2108 TempInst.clear();
2109}
2110
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002111bool
2112MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2113 SmallVectorImpl<MCInst> &Instructions) {
2114 unsigned OpNum = Inst.getNumOperands();
2115 unsigned Opcode = Inst.getOpcode();
2116 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2117
2118 assert (Inst.getOperand(OpNum - 1).isImm() &&
2119 Inst.getOperand(OpNum - 2).isReg() &&
2120 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2121
2122 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2123 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2124 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2125 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2126 // It can be implemented as SWM16 or LWM16 instruction.
2127 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2128
2129 Inst.setOpcode(NewOpcode);
2130 Instructions.push_back(Inst);
2131 return false;
2132}
2133
Toma Tabacu234482a2015-03-16 12:03:39 +00002134void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2135 SmallVectorImpl<MCInst> &Instructions) {
2136 MCInst NopInst;
2137 if (hasShortDelaySlot) {
2138 NopInst.setOpcode(Mips::MOVE16_MM);
2139 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2140 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2141 } else {
2142 NopInst.setOpcode(Mips::SLL);
2143 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2144 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2145 NopInst.addOperand(MCOperand::CreateImm(0));
2146 }
2147 Instructions.push_back(NopInst);
2148}
2149
Matheus Almeida595fcab2014-06-11 15:05:56 +00002150unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2151 // As described by the Mips32r2 spec, the registers Rd and Rs for
2152 // jalr.hb must be different.
2153 unsigned Opcode = Inst.getOpcode();
2154
2155 if (Opcode == Mips::JALR_HB &&
2156 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2157 return Match_RequiresDifferentSrcAndDst;
2158
2159 return Match_Success;
2160}
2161
David Blaikie960ea3f2014-06-08 16:18:35 +00002162bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2163 OperandVector &Operands,
2164 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002165 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002166 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002167
Jack Carterb4dbc172012-09-05 23:34:03 +00002168 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002169 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002170 unsigned MatchResult =
2171 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002172
2173 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002174 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002175 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002176 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002177 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002178 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002179 return false;
2180 }
2181 case Match_MissingFeature:
2182 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2183 return true;
2184 case Match_InvalidOperand: {
2185 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002186 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002187 if (ErrorInfo >= Operands.size())
2188 return Error(IDLoc, "too few operands for instruction");
2189
David Blaikie960ea3f2014-06-08 16:18:35 +00002190 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002191 if (ErrorLoc == SMLoc())
2192 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002193 }
2194
2195 return Error(ErrorLoc, "invalid operand for instruction");
2196 }
2197 case Match_MnemonicFail:
2198 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002199 case Match_RequiresDifferentSrcAndDst:
2200 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002201 }
Craig Topper589ceee2015-01-03 08:16:34 +00002202
2203 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002204}
2205
Toma Tabacu13964452014-09-04 13:23:44 +00002206void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002207 if ((RegIndex != 0) &&
2208 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002209 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002210 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002211 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002212 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002213 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002214 }
2215}
2216
Daniel Sandersef638fe2014-10-03 15:37:37 +00002217void
2218MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2219 SMRange Range, bool ShowColors) {
2220 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002221 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002222 ShowColors);
2223}
2224
Jack Carter1ac53222013-02-20 23:11:17 +00002225int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002226 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002227
Vladimir Medic4c299852013-11-06 11:27:05 +00002228 CC = StringSwitch<unsigned>(Name)
2229 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002230 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002231 .Case("a0", 4)
2232 .Case("a1", 5)
2233 .Case("a2", 6)
2234 .Case("a3", 7)
2235 .Case("v0", 2)
2236 .Case("v1", 3)
2237 .Case("s0", 16)
2238 .Case("s1", 17)
2239 .Case("s2", 18)
2240 .Case("s3", 19)
2241 .Case("s4", 20)
2242 .Case("s5", 21)
2243 .Case("s6", 22)
2244 .Case("s7", 23)
2245 .Case("k0", 26)
2246 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002247 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002248 .Case("sp", 29)
2249 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002250 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002251 .Case("ra", 31)
2252 .Case("t0", 8)
2253 .Case("t1", 9)
2254 .Case("t2", 10)
2255 .Case("t3", 11)
2256 .Case("t4", 12)
2257 .Case("t5", 13)
2258 .Case("t6", 14)
2259 .Case("t7", 15)
2260 .Case("t8", 24)
2261 .Case("t9", 25)
2262 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002263
Toma Tabacufda445c2014-09-15 15:33:01 +00002264 if (!(isABI_N32() || isABI_N64()))
2265 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002266
Daniel Sandersef638fe2014-10-03 15:37:37 +00002267 if (12 <= CC && CC <= 15) {
2268 // Name is one of t4-t7
2269 AsmToken RegTok = getLexer().peekTok();
2270 SMRange RegRange = RegTok.getLocRange();
2271
2272 StringRef FixedName = StringSwitch<StringRef>(Name)
2273 .Case("t4", "t0")
2274 .Case("t5", "t1")
2275 .Case("t6", "t2")
2276 .Case("t7", "t3")
2277 .Default("");
2278 assert(FixedName != "" && "Register name is not one of t4-t7.");
2279
2280 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2281 "Did you mean $" + FixedName + "?", RegRange);
2282 }
2283
Toma Tabacufda445c2014-09-15 15:33:01 +00002284 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2285 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2286 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2287 if (8 <= CC && CC <= 11)
2288 CC += 4;
2289
2290 if (CC == -1)
2291 CC = StringSwitch<unsigned>(Name)
2292 .Case("a4", 8)
2293 .Case("a5", 9)
2294 .Case("a6", 10)
2295 .Case("a7", 11)
2296 .Case("kt0", 26)
2297 .Case("kt1", 27)
2298 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002299
2300 return CC;
2301}
Jack Carterd0bd6422013-04-18 00:41:53 +00002302
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002303int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2304 int CC;
2305
2306 CC = StringSwitch<unsigned>(Name)
2307 .Case("hwr_cpunum", 0)
2308 .Case("hwr_synci_step", 1)
2309 .Case("hwr_cc", 2)
2310 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002311 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002312 .Default(-1);
2313
2314 return CC;
2315}
2316
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002317int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002318
Jack Cartera63b16a2012-09-07 00:23:42 +00002319 if (Name[0] == 'f') {
2320 StringRef NumString = Name.substr(1);
2321 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002322 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002323 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002324 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002325 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002326 return IntVal;
2327 }
2328 return -1;
2329}
Jack Cartera63b16a2012-09-07 00:23:42 +00002330
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002331int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2332
2333 if (Name.startswith("fcc")) {
2334 StringRef NumString = Name.substr(3);
2335 unsigned IntVal;
2336 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002337 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002338 if (IntVal > 7) // There are only 8 fcc registers.
2339 return -1;
2340 return IntVal;
2341 }
2342 return -1;
2343}
2344
2345int MipsAsmParser::matchACRegisterName(StringRef Name) {
2346
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002347 if (Name.startswith("ac")) {
2348 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002349 unsigned IntVal;
2350 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002351 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002352 if (IntVal > 3) // There are only 3 acc registers.
2353 return -1;
2354 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002355 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002356 return -1;
2357}
Jack Carterd0bd6422013-04-18 00:41:53 +00002358
Jack Carter5dc8ac92013-09-25 23:50:44 +00002359int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2360 unsigned IntVal;
2361
2362 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2363 return -1;
2364
2365 if (IntVal > 31)
2366 return -1;
2367
2368 return IntVal;
2369}
2370
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002371int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2372 int CC;
2373
2374 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002375 .Case("msair", 0)
2376 .Case("msacsr", 1)
2377 .Case("msaaccess", 2)
2378 .Case("msasave", 3)
2379 .Case("msamodify", 4)
2380 .Case("msarequest", 5)
2381 .Case("msamap", 6)
2382 .Case("msaunmap", 7)
2383 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002384
2385 return CC;
2386}
2387
Matheus Almeida7de68e72014-06-18 14:46:05 +00002388int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002389 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002390 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002391 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002392 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002393 return AT;
2394}
Jack Carter0b744b32012-10-04 02:29:46 +00002395
Jack Carterd0bd6422013-04-18 00:41:53 +00002396unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002397 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002398}
2399
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002400unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002401 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002402 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002403}
2404
Jack Carter873c7242013-01-12 01:03:14 +00002405int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002406 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002407 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002408 return -1;
2409
Jack Carter873c7242013-01-12 01:03:14 +00002410 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002411}
2412
Toma Tabacu13964452014-09-04 13:23:44 +00002413bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002414 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002415 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002416
Jack Carter30a59822012-10-04 04:03:53 +00002417 // Check if the current operand has a custom associated parser, if so, try to
2418 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002419 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2420 if (ResTy == MatchOperand_Success)
2421 return false;
2422 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2423 // there was a match, but an error occurred, in which case, just return that
2424 // the operand parsing failed.
2425 if (ResTy == MatchOperand_ParseFail)
2426 return true;
2427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002428 DEBUG(dbgs() << ".. Generic Parser\n");
2429
Jack Carterb4dbc172012-09-05 23:34:03 +00002430 switch (getLexer().getKind()) {
2431 default:
2432 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2433 return true;
2434 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002435 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002436 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002437
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002438 // Almost all registers have been parsed by custom parsers. There is only
2439 // one exception to this. $zero (and it's alias $0) will reach this point
2440 // for div, divu, and similar instructions because it is not an operand
2441 // to the instruction definition but an explicit register. Special case
2442 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002443 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002444 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002445
Jack Carterd0bd6422013-04-18 00:41:53 +00002446 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002447 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002448 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002449 return true;
2450
Jack Carter873c7242013-01-12 01:03:14 +00002451 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002452 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002453 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002454 const MCExpr *Res =
2455 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002456
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002457 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002458 return false;
2459 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002460 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002461 case AsmToken::LParen:
2462 case AsmToken::Minus:
2463 case AsmToken::Plus:
2464 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002465 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002466 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002467 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002468 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002469 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002470 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002471 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002472 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002473 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002474 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002475 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002476 return true;
2477
Jack Carter873c7242013-01-12 01:03:14 +00002478 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2479
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002481 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002482 } // case AsmToken::Percent
2483 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002484 return true;
2485}
2486
Vladimir Medic4c299852013-11-06 11:27:05 +00002487const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002488 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002489 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002490 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002491 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002492 // It's a constant, evaluate reloc value.
2493 int16_t Val;
2494 switch (getVariantKind(RelocStr)) {
2495 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2496 // Get the 1st 16-bits.
2497 Val = MCE->getValue() & 0xffff;
2498 break;
2499 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2500 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2501 // 16 bits being negative.
2502 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2503 break;
2504 case MCSymbolRefExpr::VK_Mips_HIGHER:
2505 // Get the 3rd 16-bits.
2506 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2507 break;
2508 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2509 // Get the 4th 16-bits.
2510 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2511 break;
2512 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002513 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002514 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002515 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002516 }
2517
Jack Carterb5cf5902013-04-17 00:18:04 +00002518 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002519 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002520 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002521 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002522 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002523 return Res;
2524 }
2525
2526 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002527 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2528
Sasa Stankovic06c47802014-04-03 10:37:45 +00002529 // Try to create target expression.
2530 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2531 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002532
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2534 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002535 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2536 return Res;
2537 }
2538
2539 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002540 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2541 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2542 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002543 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002544 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002545 return Expr;
2546}
2547
2548bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2549
2550 switch (Expr->getKind()) {
2551 case MCExpr::Constant:
2552 return true;
2553 case MCExpr::SymbolRef:
2554 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2555 case MCExpr::Binary:
2556 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2557 if (!isEvaluated(BE->getLHS()))
2558 return false;
2559 return isEvaluated(BE->getRHS());
2560 }
2561 case MCExpr::Unary:
2562 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002563 case MCExpr::Target:
2564 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002565 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002566 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002567}
Jack Carterd0bd6422013-04-18 00:41:53 +00002568
Jack Carterb5cf5902013-04-17 00:18:04 +00002569bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002570 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002571 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002573 if (Tok.isNot(AsmToken::Identifier))
2574 return true;
2575
Yaron Keren075759a2015-03-30 15:42:36 +00002576 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002577
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 Parser.Lex(); // Eat the identifier.
2579 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002580 const MCExpr *IdVal;
2581 SMLoc EndLoc;
2582
2583 if (getLexer().getKind() == AsmToken::LParen) {
2584 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002585 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002586 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002587 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002588 const AsmToken &nextTok = Parser.getTok();
2589 if (nextTok.isNot(AsmToken::Identifier))
2590 return true;
2591 Str += "(%";
2592 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002594 if (getLexer().getKind() != AsmToken::LParen)
2595 return true;
2596 } else
2597 break;
2598 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002600 return true;
2601
2602 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002604
2605 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002607
Jack Carterd0bd6422013-04-18 00:41:53 +00002608 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002609 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002610}
2611
Jack Carterb4dbc172012-09-05 23:34:03 +00002612bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2613 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002614 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002615 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002616 if (ResTy == MatchOperand_Success) {
2617 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002618 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002619 StartLoc = Operand.getStartLoc();
2620 EndLoc = Operand.getEndLoc();
2621
2622 // AFAIK, we only support numeric registers and named GPR's in CFI
2623 // directives.
2624 // Don't worry about eating tokens before failing. Using an unrecognised
2625 // register is a parse error.
2626 if (Operand.isGPRAsmReg()) {
2627 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002628 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002629 }
2630
2631 return (RegNo == (unsigned)-1);
2632 }
2633
2634 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002635 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002636}
2637
Jack Carterb5cf5902013-04-17 00:18:04 +00002638bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002639 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002640 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002641 bool Result = true;
2642
2643 while (getLexer().getKind() == AsmToken::LParen)
2644 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002645
Jack Carterd0bd6422013-04-18 00:41:53 +00002646 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002647 default:
2648 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002649 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002650 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002651 case AsmToken::Integer:
2652 case AsmToken::Minus:
2653 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002654 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002655 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002656 else
2657 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002659 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002660 break;
Jack Carter873c7242013-01-12 01:03:14 +00002661 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002662 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002663 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002664 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002665}
2666
David Blaikie960ea3f2014-06-08 16:18:35 +00002667MipsAsmParser::OperandMatchResultTy
2668MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002669 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002670 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002671 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002672 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002673 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002674 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002675 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002676 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002677
Jack Carterb5cf5902013-04-17 00:18:04 +00002678 if (getLexer().getKind() == AsmToken::LParen) {
2679 Parser.Lex();
2680 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002681 }
2682
Jack Carterb5cf5902013-04-17 00:18:04 +00002683 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002684 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002685 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002686
Jack Carterd0bd6422013-04-18 00:41:53 +00002687 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002688 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002689 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2690 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002691 SMLoc E =
2692 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002693 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002694 return MatchOperand_Success;
2695 }
2696 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002697 SMLoc E =
2698 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002699
Jack Carterd0bd6422013-04-18 00:41:53 +00002700 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002701 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002702 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002703 S, E, *this);
2704 Operands.push_back(
2705 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002706 return MatchOperand_Success;
2707 }
2708 Error(Parser.getTok().getLoc(), "'(' expected");
2709 return MatchOperand_ParseFail;
2710 }
2711
Jack Carterd0bd6422013-04-18 00:41:53 +00002712 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002713 }
2714
Toma Tabacu13964452014-09-04 13:23:44 +00002715 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002716 if (Res != MatchOperand_Success)
2717 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002718
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002719 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002720 Error(Parser.getTok().getLoc(), "')' expected");
2721 return MatchOperand_ParseFail;
2722 }
2723
Jack Carter873c7242013-01-12 01:03:14 +00002724 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2725
Jack Carterd0bd6422013-04-18 00:41:53 +00002726 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002727
Craig Topper062a2ba2014-04-25 05:30:21 +00002728 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002729 IdVal = MCConstantExpr::Create(0, getContext());
2730
Jack Carterd0bd6422013-04-18 00:41:53 +00002731 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002732 std::unique_ptr<MipsOperand> op(
2733 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002734 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002735 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002736 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002737 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002738 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2739 int64_t Imm;
2740 if (IdVal->EvaluateAsAbsolute(Imm))
2741 IdVal = MCConstantExpr::Create(Imm, getContext());
2742 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2743 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2744 getContext());
2745 }
2746
David Blaikie960ea3f2014-06-08 16:18:35 +00002747 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002748 return MatchOperand_Success;
2749}
2750
David Blaikie960ea3f2014-06-08 16:18:35 +00002751bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002752 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002753 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2754 if (Sym) {
2755 SMLoc S = Parser.getTok().getLoc();
2756 const MCExpr *Expr;
2757 if (Sym->isVariable())
2758 Expr = Sym->getVariableValue();
2759 else
2760 return false;
2761 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002762 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002763 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002764 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002765 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002766 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002767 if (ResTy == MatchOperand_Success) {
2768 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002769 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002770 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002771 llvm_unreachable("Should never ParseFail");
2772 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002773 }
2774 } else if (Expr->getKind() == MCExpr::Constant) {
2775 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002776 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002777 Operands.push_back(
2778 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002779 return true;
2780 }
2781 }
2782 return false;
2783}
Jack Carterd0bd6422013-04-18 00:41:53 +00002784
Jack Carter873c7242013-01-12 01:03:14 +00002785MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002786MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002787 StringRef Identifier,
2788 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002789 int Index = matchCPURegisterName(Identifier);
2790 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002791 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002792 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2793 return MatchOperand_Success;
2794 }
2795
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002796 Index = matchHWRegsRegisterName(Identifier);
2797 if (Index != -1) {
2798 Operands.push_back(MipsOperand::createHWRegsReg(
2799 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2800 return MatchOperand_Success;
2801 }
2802
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002803 Index = matchFPURegisterName(Identifier);
2804 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002805 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002806 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2807 return MatchOperand_Success;
2808 }
2809
2810 Index = matchFCCRegisterName(Identifier);
2811 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002812 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002813 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2814 return MatchOperand_Success;
2815 }
2816
2817 Index = matchACRegisterName(Identifier);
2818 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002819 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2821 return MatchOperand_Success;
2822 }
2823
2824 Index = matchMSA128RegisterName(Identifier);
2825 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002826 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002827 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2828 return MatchOperand_Success;
2829 }
2830
2831 Index = matchMSA128CtrlRegisterName(Identifier);
2832 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002833 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2835 return MatchOperand_Success;
2836 }
2837
2838 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002839}
2840
2841MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002842MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002843 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002844 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845
2846 if (Token.is(AsmToken::Identifier)) {
2847 DEBUG(dbgs() << ".. identifier\n");
2848 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002849 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002850 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002851 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002852 } else if (Token.is(AsmToken::Integer)) {
2853 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002854 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2856 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002857 return MatchOperand_Success;
2858 }
2859
2860 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2861
2862 return MatchOperand_NoMatch;
2863}
2864
David Blaikie960ea3f2014-06-08 16:18:35 +00002865MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002866MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002867 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002868 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002869
2870 auto Token = Parser.getTok();
2871
2872 SMLoc S = Token.getLoc();
2873
2874 if (Token.isNot(AsmToken::Dollar)) {
2875 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2876 if (Token.is(AsmToken::Identifier)) {
2877 if (searchSymbolAlias(Operands))
2878 return MatchOperand_Success;
2879 }
2880 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2881 return MatchOperand_NoMatch;
2882 }
2883 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002884
Toma Tabacu13964452014-09-04 13:23:44 +00002885 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002886 if (ResTy == MatchOperand_Success) {
2887 Parser.Lex(); // $
2888 Parser.Lex(); // identifier
2889 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002890 return ResTy;
2891}
2892
2893MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002894MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002895 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002896 switch (getLexer().getKind()) {
2897 default:
2898 return MatchOperand_NoMatch;
2899 case AsmToken::LParen:
2900 case AsmToken::Minus:
2901 case AsmToken::Plus:
2902 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002903 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002904 case AsmToken::String:
2905 break;
2906 }
2907
2908 const MCExpr *IdVal;
2909 SMLoc S = Parser.getTok().getLoc();
2910 if (getParser().parseExpression(IdVal))
2911 return MatchOperand_ParseFail;
2912
2913 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2914 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2915 return MatchOperand_Success;
2916}
2917
David Blaikie960ea3f2014-06-08 16:18:35 +00002918MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002919MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002920 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002921 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922
2923 SMLoc S = getLexer().getLoc();
2924
2925 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002926 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002927 if (ResTy != MatchOperand_NoMatch)
2928 return ResTy;
2929
Daniel Sanders315386c2014-04-01 10:40:14 +00002930 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002931 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002932 if (ResTy != MatchOperand_NoMatch)
2933 return ResTy;
2934
Daniel Sandersffd84362014-04-01 10:41:48 +00002935 const MCExpr *Expr = nullptr;
2936 if (Parser.parseExpression(Expr)) {
2937 // We have no way of knowing if a symbol was consumed so we must ParseFail
2938 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002939 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002940 Operands.push_back(
2941 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002942 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002943}
2944
Vladimir Medic2b953d02013-10-01 09:48:56 +00002945MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002946MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002947 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002948 const MCExpr *IdVal;
2949 // If the first token is '$' we may have register operand.
2950 if (Parser.getTok().is(AsmToken::Dollar))
2951 return MatchOperand_NoMatch;
2952 SMLoc S = Parser.getTok().getLoc();
2953 if (getParser().parseExpression(IdVal))
2954 return MatchOperand_ParseFail;
2955 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002956 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002957 int64_t Val = MCE->getValue();
2958 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2959 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002960 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002961 return MatchOperand_Success;
2962}
2963
Matheus Almeida779c5932013-11-18 12:32:49 +00002964MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002965MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002966 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002967 switch (getLexer().getKind()) {
2968 default:
2969 return MatchOperand_NoMatch;
2970 case AsmToken::LParen:
2971 case AsmToken::Plus:
2972 case AsmToken::Minus:
2973 case AsmToken::Integer:
2974 break;
2975 }
2976
2977 const MCExpr *Expr;
2978 SMLoc S = Parser.getTok().getLoc();
2979
2980 if (getParser().parseExpression(Expr))
2981 return MatchOperand_ParseFail;
2982
2983 int64_t Val;
2984 if (!Expr->EvaluateAsAbsolute(Val)) {
2985 Error(S, "expected immediate value");
2986 return MatchOperand_ParseFail;
2987 }
2988
2989 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2990 // and because the CPU always adds one to the immediate field, the allowed
2991 // range becomes 1..4. We'll only check the range here and will deal
2992 // with the addition/subtraction when actually decoding/encoding
2993 // the instruction.
2994 if (Val < 1 || Val > 4) {
2995 Error(S, "immediate not in range (1..4)");
2996 return MatchOperand_ParseFail;
2997 }
2998
Jack Carter3b2c96e2014-01-22 23:31:38 +00002999 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003000 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003001 return MatchOperand_Success;
3002}
3003
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003004MipsAsmParser::OperandMatchResultTy
3005MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3006 MCAsmParser &Parser = getParser();
3007 SmallVector<unsigned, 10> Regs;
3008 unsigned RegNo;
3009 unsigned PrevReg = Mips::NoRegister;
3010 bool RegRange = false;
3011 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3012
3013 if (Parser.getTok().isNot(AsmToken::Dollar))
3014 return MatchOperand_ParseFail;
3015
3016 SMLoc S = Parser.getTok().getLoc();
3017 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3018 SMLoc E = getLexer().getLoc();
3019 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3020 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3021 if (RegRange) {
3022 // Remove last register operand because registers from register range
3023 // should be inserted first.
3024 if (RegNo == Mips::RA) {
3025 Regs.push_back(RegNo);
3026 } else {
3027 unsigned TmpReg = PrevReg + 1;
3028 while (TmpReg <= RegNo) {
3029 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3030 Error(E, "invalid register operand");
3031 return MatchOperand_ParseFail;
3032 }
3033
3034 PrevReg = TmpReg;
3035 Regs.push_back(TmpReg++);
3036 }
3037 }
3038
3039 RegRange = false;
3040 } else {
3041 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3042 (RegNo != Mips::RA)) {
3043 Error(E, "$16 or $31 expected");
3044 return MatchOperand_ParseFail;
3045 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3046 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3047 Error(E, "invalid register operand");
3048 return MatchOperand_ParseFail;
3049 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3050 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3051 Error(E, "consecutive register numbers expected");
3052 return MatchOperand_ParseFail;
3053 }
3054
3055 Regs.push_back(RegNo);
3056 }
3057
3058 if (Parser.getTok().is(AsmToken::Minus))
3059 RegRange = true;
3060
3061 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3062 !Parser.getTok().isNot(AsmToken::Comma)) {
3063 Error(E, "',' or '-' expected");
3064 return MatchOperand_ParseFail;
3065 }
3066
3067 Lex(); // Consume comma or minus
3068 if (Parser.getTok().isNot(AsmToken::Dollar))
3069 break;
3070
3071 PrevReg = RegNo;
3072 }
3073
3074 SMLoc E = Parser.getTok().getLoc();
3075 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3076 parseMemOperand(Operands);
3077 return MatchOperand_Success;
3078}
3079
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003080MipsAsmParser::OperandMatchResultTy
3081MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3082 MCAsmParser &Parser = getParser();
3083
3084 SMLoc S = Parser.getTok().getLoc();
3085 if (parseAnyRegister(Operands) != MatchOperand_Success)
3086 return MatchOperand_ParseFail;
3087
3088 SMLoc E = Parser.getTok().getLoc();
3089 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3090 unsigned Reg = Op.getGPR32Reg();
3091 Operands.pop_back();
3092 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3093 return MatchOperand_Success;
3094}
3095
Zoran Jovanovic41688672015-02-10 16:36:20 +00003096MipsAsmParser::OperandMatchResultTy
3097MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3098 MCAsmParser &Parser = getParser();
3099 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3100 SmallVector<unsigned, 10> Regs;
3101
3102 if (Parser.getTok().isNot(AsmToken::Dollar))
3103 return MatchOperand_ParseFail;
3104
3105 SMLoc S = Parser.getTok().getLoc();
3106
3107 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3108 return MatchOperand_ParseFail;
3109
3110 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3111 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3112 Regs.push_back(RegNo);
3113
3114 SMLoc E = Parser.getTok().getLoc();
3115 if (Parser.getTok().isNot(AsmToken::Comma)) {
3116 Error(E, "',' expected");
3117 return MatchOperand_ParseFail;
3118 }
3119
3120 // Remove comma.
3121 Parser.Lex();
3122
3123 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3124 return MatchOperand_ParseFail;
3125
3126 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3127 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3128 Regs.push_back(RegNo);
3129
3130 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3131
3132 return MatchOperand_Success;
3133}
3134
Jack Carterdc1e35d2012-09-06 20:00:02 +00003135MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3136
Vladimir Medic4c299852013-11-06 11:27:05 +00003137 MCSymbolRefExpr::VariantKind VK =
3138 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3139 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3140 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3141 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3142 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3143 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3144 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3145 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3146 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3147 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3148 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3149 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3150 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3151 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3152 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3153 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3154 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3155 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003156 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3157 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3158 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3159 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3160 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3161 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003162 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3163 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003164 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003165
Matheus Almeida2852af82014-04-22 10:15:54 +00003166 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003167
Jack Carterdc1e35d2012-09-06 20:00:02 +00003168 return VK;
3169}
Jack Cartera63b16a2012-09-07 00:23:42 +00003170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003171/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3172/// either this.
3173/// ::= '(', register, ')'
3174/// handle it before we iterate so we don't get tripped up by the lack of
3175/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003176bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003177 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003178 if (getLexer().is(AsmToken::LParen)) {
3179 Operands.push_back(
3180 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3181 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003182 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003183 SMLoc Loc = getLexer().getLoc();
3184 Parser.eatToEndOfStatement();
3185 return Error(Loc, "unexpected token in argument list");
3186 }
3187 if (Parser.getTok().isNot(AsmToken::RParen)) {
3188 SMLoc Loc = getLexer().getLoc();
3189 Parser.eatToEndOfStatement();
3190 return Error(Loc, "unexpected token, expected ')'");
3191 }
3192 Operands.push_back(
3193 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3194 Parser.Lex();
3195 }
3196 return false;
3197}
3198
3199/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3200/// either one of these.
3201/// ::= '[', register, ']'
3202/// ::= '[', integer, ']'
3203/// handle it before we iterate so we don't get tripped up by the lack of
3204/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003205bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003206 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003207 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003208 if (getLexer().is(AsmToken::LBrac)) {
3209 Operands.push_back(
3210 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3211 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003212 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003213 SMLoc Loc = getLexer().getLoc();
3214 Parser.eatToEndOfStatement();
3215 return Error(Loc, "unexpected token in argument list");
3216 }
3217 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3218 SMLoc Loc = getLexer().getLoc();
3219 Parser.eatToEndOfStatement();
3220 return Error(Loc, "unexpected token, expected ']'");
3221 }
3222 Operands.push_back(
3223 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3224 Parser.Lex();
3225 }
3226 return false;
3227}
3228
David Blaikie960ea3f2014-06-08 16:18:35 +00003229bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3230 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003231 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003232 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003233
3234 // We have reached first instruction, module directive are now forbidden.
3235 getTargetStreamer().forbidModuleDirective();
3236
Vladimir Medic74593e62013-07-17 15:00:42 +00003237 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003238 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003239 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003240 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003241 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003242 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003243 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003244
3245 // Read the remaining operands.
3246 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3247 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003248 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003249 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003250 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003251 return Error(Loc, "unexpected token in argument list");
3252 }
Toma Tabacu13964452014-09-04 13:23:44 +00003253 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003254 return true;
3255 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003256
Jack Carterd0bd6422013-04-18 00:41:53 +00003257 while (getLexer().is(AsmToken::Comma)) {
3258 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003259 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003260 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003261 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003262 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003263 return Error(Loc, "unexpected token in argument list");
3264 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003265 // Parse bracket and parenthesis suffixes before we iterate
3266 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003267 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003268 return true;
3269 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003270 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003271 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003272 }
3273 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3275 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003276 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003277 return Error(Loc, "unexpected token in argument list");
3278 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003279 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003280 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003281}
3282
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003283bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003284 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003285 SMLoc Loc = getLexer().getLoc();
3286 Parser.eatToEndOfStatement();
3287 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003288}
3289
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003290bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003291 return Error(Loc, ErrorMsg);
3292}
3293
Jack Carter0b744b32012-10-04 02:29:46 +00003294bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003295 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003296 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003297
3298 // Set the $at register to $0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003299 AssemblerOptions.back()->setATReg(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003300
3301 Parser.Lex(); // Eat "noat".
3302
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003304 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003305 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003306 return false;
3307 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003308
3309 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003310 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003311 return false;
3312}
Jack Carterd0bd6422013-04-18 00:41:53 +00003313
Jack Carter0b744b32012-10-04 02:29:46 +00003314bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003315 // Line can be: ".set at", which sets $at to $1
3316 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003317 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003318 Parser.Lex(); // Eat "at".
3319
Jack Carter0b744b32012-10-04 02:29:46 +00003320 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003321 // No register was specified, so we set $at to $1.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003322 AssemblerOptions.back()->setATReg(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003323
3324 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003325 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003326 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003327 }
3328
3329 if (getLexer().isNot(AsmToken::Equal)) {
3330 reportParseError("unexpected token, expected equals sign");
3331 return false;
3332 }
3333 Parser.Lex(); // Eat "=".
3334
3335 if (getLexer().isNot(AsmToken::Dollar)) {
3336 if (getLexer().is(AsmToken::EndOfStatement)) {
3337 reportParseError("no register specified");
3338 return false;
3339 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003340 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003341 return false;
3342 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003343 }
3344 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003345
Toma Tabacu16a74492015-02-13 10:30:57 +00003346 // Find out what "reg" is.
3347 unsigned AtRegNo;
3348 const AsmToken &Reg = Parser.getTok();
3349 if (Reg.is(AsmToken::Identifier)) {
3350 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3351 } else if (Reg.is(AsmToken::Integer)) {
3352 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003353 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003354 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003355 return false;
3356 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003357
3358 // Check if $reg is a valid register. If it is, set $at to $reg.
3359 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3360 reportParseError("invalid register");
3361 return false;
3362 }
3363 Parser.Lex(); // Eat "reg".
3364
3365 // If this is not the end of the statement, report an error.
3366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3367 reportParseError("unexpected token, expected end of statement");
3368 return false;
3369 }
3370
3371 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3372
3373 Parser.Lex(); // Consume the EndOfStatement.
3374 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003375}
3376
3377bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003378 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003379 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003380 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003382 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003383 return false;
3384 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003385 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003386 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003387 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003388 return false;
3389}
3390
3391bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003392 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003393 Parser.Lex();
3394 // If this is not the end of the statement, report an error.
3395 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003396 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003397 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003398 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003399 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003400 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003401 Parser.Lex(); // Consume the EndOfStatement.
3402 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003403}
3404
3405bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003406 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003407 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003408 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003410 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003411 return false;
3412 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003413 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003414 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003415 return false;
3416}
3417
3418bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003419 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003420 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003421 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003423 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003424 return false;
3425 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003426 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003427 reportParseError("`noreorder' must be set before `nomacro'");
3428 return false;
3429 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003430 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003431 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003432 return false;
3433}
Jack Carterd76b2372013-03-21 21:44:16 +00003434
Daniel Sanders44934432014-08-07 12:03:36 +00003435bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003436 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003437 Parser.Lex();
3438
3439 // If this is not the end of the statement, report an error.
3440 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003441 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003442
3443 setFeatureBits(Mips::FeatureMSA, "msa");
3444 getTargetStreamer().emitDirectiveSetMsa();
3445 return false;
3446}
3447
3448bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003449 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003450 Parser.Lex();
3451
3452 // If this is not the end of the statement, report an error.
3453 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003454 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003455
3456 clearFeatureBits(Mips::FeatureMSA, "msa");
3457 getTargetStreamer().emitDirectiveSetNoMsa();
3458 return false;
3459}
3460
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003461bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003462 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003463 Parser.Lex(); // Eat "nodsp".
3464
3465 // If this is not the end of the statement, report an error.
3466 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3467 reportParseError("unexpected token, expected end of statement");
3468 return false;
3469 }
3470
3471 clearFeatureBits(Mips::FeatureDSP, "dsp");
3472 getTargetStreamer().emitDirectiveSetNoDsp();
3473 return false;
3474}
3475
Toma Tabacucc2502d2014-11-04 17:18:07 +00003476bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003477 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003478 Parser.Lex(); // Eat "mips16".
3479
Jack Carter39536722014-01-22 23:08:42 +00003480 // If this is not the end of the statement, report an error.
3481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003482 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003483 return false;
3484 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003485
3486 setFeatureBits(Mips::FeatureMips16, "mips16");
3487 getTargetStreamer().emitDirectiveSetMips16();
3488 Parser.Lex(); // Consume the EndOfStatement.
3489 return false;
3490}
3491
3492bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003493 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003494 Parser.Lex(); // Eat "nomips16".
3495
3496 // If this is not the end of the statement, report an error.
3497 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3498 reportParseError("unexpected token, expected end of statement");
3499 return false;
3500 }
3501
3502 clearFeatureBits(Mips::FeatureMips16, "mips16");
3503 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003504 Parser.Lex(); // Consume the EndOfStatement.
3505 return false;
3506}
3507
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003508bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003509 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003510 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003511 // Line can be: .set fp=32
3512 // .set fp=xx
3513 // .set fp=64
3514 Parser.Lex(); // Eat fp token
3515 AsmToken Tok = Parser.getTok();
3516 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003517 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003518 return false;
3519 }
3520 Parser.Lex(); // Eat '=' token.
3521 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003522
3523 if (!parseFpABIValue(FpAbiVal, ".set"))
3524 return false;
3525
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003526 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003527 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003528 return false;
3529 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003530 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003531 Parser.Lex(); // Consume the EndOfStatement.
3532 return false;
3533}
3534
Toma Tabacu9db22db2014-09-09 10:15:38 +00003535bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003536 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003537 SMLoc Loc = getLexer().getLoc();
3538
3539 Parser.Lex();
3540 if (getLexer().isNot(AsmToken::EndOfStatement))
3541 return reportParseError("unexpected token, expected end of statement");
3542
3543 // Always keep an element on the options "stack" to prevent the user
3544 // from changing the initial options. This is how we remember them.
3545 if (AssemblerOptions.size() == 2)
3546 return reportParseError(Loc, ".set pop with no .set push");
3547
3548 AssemblerOptions.pop_back();
3549 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3550
3551 getTargetStreamer().emitDirectiveSetPop();
3552 return false;
3553}
3554
3555bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003556 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003557 Parser.Lex();
3558 if (getLexer().isNot(AsmToken::EndOfStatement))
3559 return reportParseError("unexpected token, expected end of statement");
3560
3561 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003562 AssemblerOptions.push_back(
3563 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003564
3565 getTargetStreamer().emitDirectiveSetPush();
3566 return false;
3567}
3568
Jack Carterd76b2372013-03-21 21:44:16 +00003569bool MipsAsmParser::parseSetAssignment() {
3570 StringRef Name;
3571 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003572 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003573
3574 if (Parser.parseIdentifier(Name))
3575 reportParseError("expected identifier after .set");
3576
3577 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003578 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003579 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003580
Jack Carter3b2c96e2014-01-22 23:31:38 +00003581 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003582 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003583
Toma Tabacuf25949b2015-04-07 13:59:39 +00003584 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003585 Sym->setVariableValue(Value);
3586
3587 return false;
3588}
Jack Carterd0bd6422013-04-18 00:41:53 +00003589
Toma Tabacu26647792014-09-09 12:52:14 +00003590bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003591 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003592 Parser.Lex();
3593 if (getLexer().isNot(AsmToken::EndOfStatement))
3594 return reportParseError("unexpected token, expected end of statement");
3595
3596 // Reset assembler options to their initial values.
3597 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3598 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3599
3600 getTargetStreamer().emitDirectiveSetMips0();
3601 return false;
3602}
3603
Toma Tabacu85618b32014-08-19 14:22:52 +00003604bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003605 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003606 Parser.Lex();
3607 if (getLexer().isNot(AsmToken::Equal))
3608 return reportParseError("unexpected token, expected equals sign");
3609
3610 Parser.Lex();
3611 StringRef Arch;
3612 if (Parser.parseIdentifier(Arch))
3613 return reportParseError("expected arch identifier");
3614
3615 StringRef ArchFeatureName =
3616 StringSwitch<StringRef>(Arch)
3617 .Case("mips1", "mips1")
3618 .Case("mips2", "mips2")
3619 .Case("mips3", "mips3")
3620 .Case("mips4", "mips4")
3621 .Case("mips5", "mips5")
3622 .Case("mips32", "mips32")
3623 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003624 .Case("mips32r3", "mips32r3")
3625 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003626 .Case("mips32r6", "mips32r6")
3627 .Case("mips64", "mips64")
3628 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003629 .Case("mips64r3", "mips64r3")
3630 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003631 .Case("mips64r6", "mips64r6")
3632 .Case("cnmips", "cnmips")
3633 .Case("r4000", "mips3") // This is an implementation of Mips3.
3634 .Default("");
3635
3636 if (ArchFeatureName.empty())
3637 return reportParseError("unsupported architecture");
3638
3639 selectArch(ArchFeatureName);
3640 getTargetStreamer().emitDirectiveSetArch(Arch);
3641 return false;
3642}
3643
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003644bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003645 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003646 Parser.Lex();
3647 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003648 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003649
Matheus Almeida2852af82014-04-22 10:15:54 +00003650 switch (Feature) {
3651 default:
3652 llvm_unreachable("Unimplemented feature");
3653 case Mips::FeatureDSP:
3654 setFeatureBits(Mips::FeatureDSP, "dsp");
3655 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003656 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003657 case Mips::FeatureMicroMips:
3658 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003659 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003660 case Mips::FeatureMips1:
3661 selectArch("mips1");
3662 getTargetStreamer().emitDirectiveSetMips1();
3663 break;
3664 case Mips::FeatureMips2:
3665 selectArch("mips2");
3666 getTargetStreamer().emitDirectiveSetMips2();
3667 break;
3668 case Mips::FeatureMips3:
3669 selectArch("mips3");
3670 getTargetStreamer().emitDirectiveSetMips3();
3671 break;
3672 case Mips::FeatureMips4:
3673 selectArch("mips4");
3674 getTargetStreamer().emitDirectiveSetMips4();
3675 break;
3676 case Mips::FeatureMips5:
3677 selectArch("mips5");
3678 getTargetStreamer().emitDirectiveSetMips5();
3679 break;
3680 case Mips::FeatureMips32:
3681 selectArch("mips32");
3682 getTargetStreamer().emitDirectiveSetMips32();
3683 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003684 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003685 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003686 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003687 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003688 case Mips::FeatureMips32r3:
3689 selectArch("mips32r3");
3690 getTargetStreamer().emitDirectiveSetMips32R3();
3691 break;
3692 case Mips::FeatureMips32r5:
3693 selectArch("mips32r5");
3694 getTargetStreamer().emitDirectiveSetMips32R5();
3695 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003696 case Mips::FeatureMips32r6:
3697 selectArch("mips32r6");
3698 getTargetStreamer().emitDirectiveSetMips32R6();
3699 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003700 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003701 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003702 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003703 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003704 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003705 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003706 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003707 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003708 case Mips::FeatureMips64r3:
3709 selectArch("mips64r3");
3710 getTargetStreamer().emitDirectiveSetMips64R3();
3711 break;
3712 case Mips::FeatureMips64r5:
3713 selectArch("mips64r5");
3714 getTargetStreamer().emitDirectiveSetMips64R5();
3715 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003716 case Mips::FeatureMips64r6:
3717 selectArch("mips64r6");
3718 getTargetStreamer().emitDirectiveSetMips64R6();
3719 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003720 }
3721 return false;
3722}
3723
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003724bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003725 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003726 if (getLexer().isNot(AsmToken::Comma)) {
3727 SMLoc Loc = getLexer().getLoc();
3728 Parser.eatToEndOfStatement();
3729 return Error(Loc, ErrorStr);
3730 }
3731
Matheus Almeida2852af82014-04-22 10:15:54 +00003732 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003733 return true;
3734}
3735
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003736bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003737 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003738 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003739
Toma Tabacudde4c462014-11-06 10:02:45 +00003740 if (inMips16Mode()) {
3741 reportParseError(".cpload is not supported in Mips16 mode");
3742 return false;
3743 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003744
David Blaikie960ea3f2014-06-08 16:18:35 +00003745 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003746 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003747 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3748 reportParseError("expected register containing function address");
3749 return false;
3750 }
3751
David Blaikie960ea3f2014-06-08 16:18:35 +00003752 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3753 if (!RegOpnd.isGPRAsmReg()) {
3754 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003755 return false;
3756 }
3757
Toma Tabacudde4c462014-11-06 10:02:45 +00003758 // If this is not the end of the statement, report an error.
3759 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3760 reportParseError("unexpected token, expected end of statement");
3761 return false;
3762 }
3763
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003764 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003765 return false;
3766}
3767
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003768bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003769 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003770 unsigned FuncReg;
3771 unsigned Save;
3772 bool SaveIsReg = true;
3773
Matheus Almeida7e815762014-06-18 13:08:59 +00003774 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003775 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003776 if (ResTy == MatchOperand_NoMatch) {
3777 reportParseError("expected register containing function address");
3778 Parser.eatToEndOfStatement();
3779 return false;
3780 }
3781
3782 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3783 if (!FuncRegOpnd.isGPRAsmReg()) {
3784 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3785 Parser.eatToEndOfStatement();
3786 return false;
3787 }
3788
3789 FuncReg = FuncRegOpnd.getGPR32Reg();
3790 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003791
Toma Tabacu65f10572014-09-16 15:00:52 +00003792 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003793 return true;
3794
Toma Tabacu13964452014-09-04 13:23:44 +00003795 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003796 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003797 const AsmToken &Tok = Parser.getTok();
3798 if (Tok.is(AsmToken::Integer)) {
3799 Save = Tok.getIntVal();
3800 SaveIsReg = false;
3801 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003802 } else {
3803 reportParseError("expected save register or stack offset");
3804 Parser.eatToEndOfStatement();
3805 return false;
3806 }
3807 } else {
3808 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3809 if (!SaveOpnd.isGPRAsmReg()) {
3810 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3811 Parser.eatToEndOfStatement();
3812 return false;
3813 }
3814 Save = SaveOpnd.getGPR32Reg();
3815 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003816
Toma Tabacu65f10572014-09-16 15:00:52 +00003817 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003818 return true;
3819
Toma Tabacu8874eac2015-02-18 13:46:53 +00003820 const MCExpr *Expr;
3821 if (Parser.parseExpression(Expr)) {
3822 reportParseError("expected expression");
3823 return false;
3824 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003825
Toma Tabacu8874eac2015-02-18 13:46:53 +00003826 if (Expr->getKind() != MCExpr::SymbolRef) {
3827 reportParseError("expected symbol");
3828 return false;
3829 }
3830 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3831
3832 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3833 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003834 return false;
3835}
3836
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003837bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003838 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003839 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3840 const AsmToken &Tok = Parser.getTok();
3841
3842 if (Tok.getString() == "2008") {
3843 Parser.Lex();
3844 getTargetStreamer().emitDirectiveNaN2008();
3845 return false;
3846 } else if (Tok.getString() == "legacy") {
3847 Parser.Lex();
3848 getTargetStreamer().emitDirectiveNaNLegacy();
3849 return false;
3850 }
3851 }
3852 // If we don't recognize the option passed to the .nan
3853 // directive (e.g. no option or unknown option), emit an error.
3854 reportParseError("invalid option in .nan directive");
3855 return false;
3856}
3857
Jack Carter0b744b32012-10-04 02:29:46 +00003858bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003859 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003860 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003861 const AsmToken &Tok = Parser.getTok();
3862
3863 if (Tok.getString() == "noat") {
3864 return parseSetNoAtDirective();
3865 } else if (Tok.getString() == "at") {
3866 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003867 } else if (Tok.getString() == "arch") {
3868 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003869 } else if (Tok.getString() == "fp") {
3870 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003871 } else if (Tok.getString() == "pop") {
3872 return parseSetPopDirective();
3873 } else if (Tok.getString() == "push") {
3874 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003875 } else if (Tok.getString() == "reorder") {
3876 return parseSetReorderDirective();
3877 } else if (Tok.getString() == "noreorder") {
3878 return parseSetNoReorderDirective();
3879 } else if (Tok.getString() == "macro") {
3880 return parseSetMacroDirective();
3881 } else if (Tok.getString() == "nomacro") {
3882 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003883 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003884 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003885 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003886 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003887 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003888 getTargetStreamer().emitDirectiveSetNoMicroMips();
3889 Parser.eatToEndOfStatement();
3890 return false;
3891 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003892 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003893 } else if (Tok.getString() == "mips0") {
3894 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003895 } else if (Tok.getString() == "mips1") {
3896 return parseSetFeature(Mips::FeatureMips1);
3897 } else if (Tok.getString() == "mips2") {
3898 return parseSetFeature(Mips::FeatureMips2);
3899 } else if (Tok.getString() == "mips3") {
3900 return parseSetFeature(Mips::FeatureMips3);
3901 } else if (Tok.getString() == "mips4") {
3902 return parseSetFeature(Mips::FeatureMips4);
3903 } else if (Tok.getString() == "mips5") {
3904 return parseSetFeature(Mips::FeatureMips5);
3905 } else if (Tok.getString() == "mips32") {
3906 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003907 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003908 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003909 } else if (Tok.getString() == "mips32r3") {
3910 return parseSetFeature(Mips::FeatureMips32r3);
3911 } else if (Tok.getString() == "mips32r5") {
3912 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003913 } else if (Tok.getString() == "mips32r6") {
3914 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003915 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003916 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003917 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003918 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003919 } else if (Tok.getString() == "mips64r3") {
3920 return parseSetFeature(Mips::FeatureMips64r3);
3921 } else if (Tok.getString() == "mips64r5") {
3922 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003923 } else if (Tok.getString() == "mips64r6") {
3924 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003925 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003926 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003927 } else if (Tok.getString() == "nodsp") {
3928 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003929 } else if (Tok.getString() == "msa") {
3930 return parseSetMsaDirective();
3931 } else if (Tok.getString() == "nomsa") {
3932 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003933 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003934 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003935 parseSetAssignment();
3936 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003937 }
Jack Carter07c818d2013-01-25 01:31:34 +00003938
Jack Carter0b744b32012-10-04 02:29:46 +00003939 return true;
3940}
3941
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003942/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003943/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003944bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003945 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003946 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3947 for (;;) {
3948 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003949 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003950 return true;
3951
3952 getParser().getStreamer().EmitValue(Value, Size);
3953
3954 if (getLexer().is(AsmToken::EndOfStatement))
3955 break;
3956
Jack Carter07c818d2013-01-25 01:31:34 +00003957 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003958 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003959 Parser.Lex();
3960 }
3961 }
3962
3963 Parser.Lex();
3964 return false;
3965}
3966
Vladimir Medic4c299852013-11-06 11:27:05 +00003967/// parseDirectiveGpWord
3968/// ::= .gpword local_sym
3969bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003970 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003971 const MCExpr *Value;
3972 // EmitGPRel32Value requires an expression, so we are using base class
3973 // method to evaluate the expression.
3974 if (getParser().parseExpression(Value))
3975 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003976 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003977
Vladimir Medice10c1122013-11-13 13:18:04 +00003978 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003979 return Error(getLexer().getLoc(),
3980 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003981 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003982 return false;
3983}
3984
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003985/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003986/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003987bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003988 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003989 const MCExpr *Value;
3990 // EmitGPRel64Value requires an expression, so we are using base class
3991 // method to evaluate the expression.
3992 if (getParser().parseExpression(Value))
3993 return true;
3994 getParser().getStreamer().EmitGPRel64Value(Value);
3995
3996 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003997 return Error(getLexer().getLoc(),
3998 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003999 Parser.Lex(); // Eat EndOfStatement token.
4000 return false;
4001}
4002
Jack Carter0cd3c192014-01-06 23:27:31 +00004003bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004004 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004005 // Get the option token.
4006 AsmToken Tok = Parser.getTok();
4007 // At the moment only identifiers are supported.
4008 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004009 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004010 Parser.eatToEndOfStatement();
4011 return false;
4012 }
4013
4014 StringRef Option = Tok.getIdentifier();
4015
4016 if (Option == "pic0") {
4017 getTargetStreamer().emitDirectiveOptionPic0();
4018 Parser.Lex();
4019 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4020 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004021 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004022 Parser.eatToEndOfStatement();
4023 }
4024 return false;
4025 }
4026
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004027 if (Option == "pic2") {
4028 getTargetStreamer().emitDirectiveOptionPic2();
4029 Parser.Lex();
4030 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4031 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004032 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004033 Parser.eatToEndOfStatement();
4034 }
4035 return false;
4036 }
4037
Jack Carter0cd3c192014-01-06 23:27:31 +00004038 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004039 Warning(Parser.getTok().getLoc(),
4040 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004041 Parser.eatToEndOfStatement();
4042 return false;
4043}
4044
Daniel Sanders7e527422014-07-10 13:38:23 +00004045/// parseDirectiveModule
4046/// ::= .module oddspreg
4047/// ::= .module nooddspreg
4048/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004049bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004050 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004051 MCAsmLexer &Lexer = getLexer();
4052 SMLoc L = Lexer.getLoc();
4053
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004054 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004055 // TODO : get a better message.
4056 reportParseError(".module directive must appear before any code");
4057 return false;
4058 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004059
Toma Tabacuc405c822015-01-23 10:40:19 +00004060 StringRef Option;
4061 if (Parser.parseIdentifier(Option)) {
4062 reportParseError("expected .module option identifier");
4063 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004064 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004065
Toma Tabacuc405c822015-01-23 10:40:19 +00004066 if (Option == "oddspreg") {
4067 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4068 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4069
4070 // If this is not the end of the statement, report an error.
4071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4072 reportParseError("unexpected token, expected end of statement");
4073 return false;
4074 }
4075
4076 return false; // parseDirectiveModule has finished successfully.
4077 } else if (Option == "nooddspreg") {
4078 if (!isABI_O32()) {
4079 Error(L, "'.module nooddspreg' requires the O32 ABI");
4080 return false;
4081 }
4082
4083 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4084 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4085
4086 // If this is not the end of the statement, report an error.
4087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4088 reportParseError("unexpected token, expected end of statement");
4089 return false;
4090 }
4091
4092 return false; // parseDirectiveModule has finished successfully.
4093 } else if (Option == "fp") {
4094 return parseDirectiveModuleFP();
4095 } else {
4096 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4097 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004098}
4099
4100/// parseDirectiveModuleFP
4101/// ::= =32
4102/// ::= =xx
4103/// ::= =64
4104bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004105 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004106 MCAsmLexer &Lexer = getLexer();
4107
4108 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004109 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004110 return false;
4111 }
4112 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004113
Daniel Sanders7e527422014-07-10 13:38:23 +00004114 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004115 if (!parseFpABIValue(FpABI, ".module"))
4116 return false;
4117
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004118 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004119 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004120 return false;
4121 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004122
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004123 // Emit appropriate flags.
4124 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004125 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004126 return false;
4127}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004128
Daniel Sanders7e527422014-07-10 13:38:23 +00004129bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004130 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004131 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004132 MCAsmLexer &Lexer = getLexer();
4133
4134 if (Lexer.is(AsmToken::Identifier)) {
4135 StringRef Value = Parser.getTok().getString();
4136 Parser.Lex();
4137
4138 if (Value != "xx") {
4139 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4140 return false;
4141 }
4142
4143 if (!isABI_O32()) {
4144 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4145 return false;
4146 }
4147
Daniel Sanders7e527422014-07-10 13:38:23 +00004148 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004149 return true;
4150 }
4151
4152 if (Lexer.is(AsmToken::Integer)) {
4153 unsigned Value = Parser.getTok().getIntVal();
4154 Parser.Lex();
4155
4156 if (Value != 32 && Value != 64) {
4157 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4158 return false;
4159 }
4160
4161 if (Value == 32) {
4162 if (!isABI_O32()) {
4163 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4164 return false;
4165 }
4166
Daniel Sanders7e527422014-07-10 13:38:23 +00004167 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4168 } else
4169 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004170
Daniel Sanders7e527422014-07-10 13:38:23 +00004171 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004172 }
4173
4174 return false;
4175}
4176
Jack Carter0b744b32012-10-04 02:29:46 +00004177bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004178 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004179 StringRef IDVal = DirectiveID.getString();
4180
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004181 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004182 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004183 if (IDVal == ".dword") {
4184 parseDataDirective(8, DirectiveID.getLoc());
4185 return false;
4186 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004187 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004188 StringRef SymbolName;
4189
4190 if (Parser.parseIdentifier(SymbolName)) {
4191 reportParseError("expected identifier after .ent");
4192 return false;
4193 }
4194
4195 // There's an undocumented extension that allows an integer to
4196 // follow the name of the procedure which AFAICS is ignored by GAS.
4197 // Example: .ent foo,2
4198 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4199 if (getLexer().isNot(AsmToken::Comma)) {
4200 // Even though we accept this undocumented extension for compatibility
4201 // reasons, the additional integer argument does not actually change
4202 // the behaviour of the '.ent' directive, so we would like to discourage
4203 // its use. We do this by not referring to the extended version in
4204 // error messages which are not directly related to its use.
4205 reportParseError("unexpected token, expected end of statement");
4206 return false;
4207 }
4208 Parser.Lex(); // Eat the comma.
4209 const MCExpr *DummyNumber;
4210 int64_t DummyNumberVal;
4211 // If the user was explicitly trying to use the extended version,
4212 // we still give helpful extension-related error messages.
4213 if (Parser.parseExpression(DummyNumber)) {
4214 reportParseError("expected number after comma");
4215 return false;
4216 }
4217 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4218 reportParseError("expected an absolute expression after comma");
4219 return false;
4220 }
4221 }
4222
4223 // If this is not the end of the statement, report an error.
4224 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4225 reportParseError("unexpected token, expected end of statement");
4226 return false;
4227 }
4228
4229 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4230
4231 getTargetStreamer().emitDirectiveEnt(*Sym);
4232 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004233 return false;
4234 }
4235
Jack Carter07c818d2013-01-25 01:31:34 +00004236 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004237 StringRef SymbolName;
4238
4239 if (Parser.parseIdentifier(SymbolName)) {
4240 reportParseError("expected identifier after .end");
4241 return false;
4242 }
4243
4244 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4245 reportParseError("unexpected token, expected end of statement");
4246 return false;
4247 }
4248
4249 if (CurrentFn == nullptr) {
4250 reportParseError(".end used without .ent");
4251 return false;
4252 }
4253
4254 if ((SymbolName != CurrentFn->getName())) {
4255 reportParseError(".end symbol does not match .ent symbol");
4256 return false;
4257 }
4258
4259 getTargetStreamer().emitDirectiveEnd(SymbolName);
4260 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004261 return false;
4262 }
4263
Jack Carter07c818d2013-01-25 01:31:34 +00004264 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004265 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4266 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004267 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004268 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4269 reportParseError("expected stack register");
4270 return false;
4271 }
4272
4273 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4274 if (!StackRegOpnd.isGPRAsmReg()) {
4275 reportParseError(StackRegOpnd.getStartLoc(),
4276 "expected general purpose register");
4277 return false;
4278 }
4279 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4280
4281 if (Parser.getTok().is(AsmToken::Comma))
4282 Parser.Lex();
4283 else {
4284 reportParseError("unexpected token, expected comma");
4285 return false;
4286 }
4287
4288 // Parse the frame size.
4289 const MCExpr *FrameSize;
4290 int64_t FrameSizeVal;
4291
4292 if (Parser.parseExpression(FrameSize)) {
4293 reportParseError("expected frame size value");
4294 return false;
4295 }
4296
4297 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4298 reportParseError("frame size not an absolute expression");
4299 return false;
4300 }
4301
4302 if (Parser.getTok().is(AsmToken::Comma))
4303 Parser.Lex();
4304 else {
4305 reportParseError("unexpected token, expected comma");
4306 return false;
4307 }
4308
4309 // Parse the return register.
4310 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004311 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004312 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4313 reportParseError("expected return register");
4314 return false;
4315 }
4316
4317 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4318 if (!ReturnRegOpnd.isGPRAsmReg()) {
4319 reportParseError(ReturnRegOpnd.getStartLoc(),
4320 "expected general purpose register");
4321 return false;
4322 }
4323
4324 // If this is not the end of the statement, report an error.
4325 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4326 reportParseError("unexpected token, expected end of statement");
4327 return false;
4328 }
4329
4330 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4331 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004332 return false;
4333 }
4334
Jack Carter07c818d2013-01-25 01:31:34 +00004335 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004336 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004337 }
4338
Daniel Sandersd97a6342014-08-13 10:07:34 +00004339 if (IDVal == ".mask" || IDVal == ".fmask") {
4340 // .mask bitmask, frame_offset
4341 // bitmask: One bit for each register used.
4342 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4343 // first register is expected to be saved.
4344 // Examples:
4345 // .mask 0x80000000, -4
4346 // .fmask 0x80000000, -4
4347 //
Jack Carterbe332172012-09-07 00:48:02 +00004348
Daniel Sandersd97a6342014-08-13 10:07:34 +00004349 // Parse the bitmask
4350 const MCExpr *BitMask;
4351 int64_t BitMaskVal;
4352
4353 if (Parser.parseExpression(BitMask)) {
4354 reportParseError("expected bitmask value");
4355 return false;
4356 }
4357
4358 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4359 reportParseError("bitmask not an absolute expression");
4360 return false;
4361 }
4362
4363 if (Parser.getTok().is(AsmToken::Comma))
4364 Parser.Lex();
4365 else {
4366 reportParseError("unexpected token, expected comma");
4367 return false;
4368 }
4369
4370 // Parse the frame_offset
4371 const MCExpr *FrameOffset;
4372 int64_t FrameOffsetVal;
4373
4374 if (Parser.parseExpression(FrameOffset)) {
4375 reportParseError("expected frame offset value");
4376 return false;
4377 }
4378
4379 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4380 reportParseError("frame offset not an absolute expression");
4381 return false;
4382 }
4383
4384 // If this is not the end of the statement, report an error.
4385 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4386 reportParseError("unexpected token, expected end of statement");
4387 return false;
4388 }
4389
4390 if (IDVal == ".mask")
4391 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4392 else
4393 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004394 return false;
4395 }
4396
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004397 if (IDVal == ".nan")
4398 return parseDirectiveNaN();
4399
Jack Carter07c818d2013-01-25 01:31:34 +00004400 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004401 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004402 return false;
4403 }
4404
Rafael Espindolab59fb732014-03-28 18:50:26 +00004405 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004406 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004407 return false;
4408 }
4409
Jack Carter07c818d2013-01-25 01:31:34 +00004410 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004411 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004412 return false;
4413 }
4414
Jack Carter0cd3c192014-01-06 23:27:31 +00004415 if (IDVal == ".option")
4416 return parseDirectiveOption();
4417
4418 if (IDVal == ".abicalls") {
4419 getTargetStreamer().emitDirectiveAbiCalls();
4420 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004421 Error(Parser.getTok().getLoc(),
4422 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004423 // Clear line
4424 Parser.eatToEndOfStatement();
4425 }
4426 return false;
4427 }
4428
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004429 if (IDVal == ".cpsetup")
4430 return parseDirectiveCPSetup();
4431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004432 if (IDVal == ".module")
4433 return parseDirectiveModule();
4434
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004435 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4436 return parseInternalDirectiveReallowModule();
4437
Rafael Espindola870c4e92012-01-11 03:56:41 +00004438 return true;
4439}
4440
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004441bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4442 // If this is not the end of the statement, report an error.
4443 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4444 reportParseError("unexpected token, expected end of statement");
4445 return false;
4446 }
4447
4448 getTargetStreamer().reallowModuleDirective();
4449
4450 getParser().Lex(); // Eat EndOfStatement token.
4451 return false;
4452}
4453
Rafael Espindola870c4e92012-01-11 03:56:41 +00004454extern "C" void LLVMInitializeMipsAsmParser() {
4455 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4456 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4457 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4458 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4459}
Jack Carterb4dbc172012-09-05 23:34:03 +00004460
4461#define GET_REGISTER_MATCHER
4462#define GET_MATCHER_IMPLEMENTATION
4463#include "MipsGenAsmMatcher.inc"