blob: 5018086954881a977b55c3dbbc6525d59c428201 [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) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001716 // For unsigned and positive signed 16-bit values (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) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001724 // For negative signed 16-bit values (-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) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001732 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001733 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001734 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001735 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001736 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1737 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001738 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001739 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1740 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001741 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001742 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001743 return true;
1744 }
1745
1746 // <------- lo32 ------>
1747 // <------- hi32 ------>
1748 // <- hi16 -> <- lo16 ->
1749 // _________________________________
1750 // | | | |
1751 // | 16-bytes | 16-bytes | 16-bytes |
1752 // |__________|__________|__________|
1753 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001754 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001755 // li d,j => lui d,hi16(j)
1756 // ori d,d,hi16(lo32(j))
1757 // dsll d,d,16
1758 // ori d,d,lo16(lo32(j))
1759 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001760 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001761 tmpInst.addOperand(
1762 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001763 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001764 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1765 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1766 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001767 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001768 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001769 return true;
1770 }
1771
1772 // <------- hi32 ------> <------- lo32 ------>
1773 // <- hi16 -> <- lo16 ->
1774 // ___________________________________________
1775 // | | | | |
1776 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1777 // |__________|__________|__________|__________|
1778 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001779 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001780 // li d,j => lui d,hi16(j)
1781 // ori d,d,lo16(hi32(j))
1782 // dsll d,d,16
1783 // ori d,d,hi16(lo32(j))
1784 // dsll d,d,16
1785 // ori d,d,lo16(lo32(j))
1786 tmpInst.setOpcode(Mips::LUi);
1787 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1788 tmpInst.addOperand(
1789 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1790 Instructions.push_back(tmpInst);
1791 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1792 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1793 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001794 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001795 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001796}
Jack Carter92995f12012-10-06 00:53:28 +00001797
Matheus Almeida3813d572014-06-19 14:39:14 +00001798bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001799MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1800 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001801 MCInst tmpInst;
1802 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001803 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1804 "expected immediate operand kind");
1805 if (!ImmOp.isImm()) {
1806 expandLoadAddressSym(Inst, IDLoc, Instructions);
1807 return false;
1808 }
Jack Carter543fdf82012-10-09 23:29:45 +00001809 const MCOperand &SrcRegOp = Inst.getOperand(1);
1810 assert(SrcRegOp.isReg() && "expected register operand kind");
1811 const MCOperand &DstRegOp = Inst.getOperand(0);
1812 assert(DstRegOp.isReg() && "expected register operand kind");
1813 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001814 if (-32768 <= ImmValue && ImmValue <= 65535) {
1815 // For -32768 <= j <= 65535.
1816 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001817 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001818 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1819 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1820 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1821 Instructions.push_back(tmpInst);
1822 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001823 // For any other value of j that is representable as a 32-bit integer.
1824 // la d,j(s) => lui d,hi16(j)
1825 // ori d,d,lo16(j)
1826 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001827 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001828 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1829 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1830 Instructions.push_back(tmpInst);
1831 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001832 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001833 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1834 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1835 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1836 Instructions.push_back(tmpInst);
1837 tmpInst.clear();
1838 tmpInst.setOpcode(Mips::ADDu);
1839 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1840 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1841 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1842 Instructions.push_back(tmpInst);
1843 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001844 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001845}
1846
Matheus Almeida3813d572014-06-19 14:39:14 +00001847bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001848MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1849 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001850 MCInst tmpInst;
1851 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001852 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1853 "expected immediate operand kind");
1854 if (!ImmOp.isImm()) {
1855 expandLoadAddressSym(Inst, IDLoc, Instructions);
1856 return false;
1857 }
Jack Carter543fdf82012-10-09 23:29:45 +00001858 const MCOperand &RegOp = Inst.getOperand(0);
1859 assert(RegOp.isReg() && "expected register operand kind");
1860 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001861 if (-32768 <= ImmValue && ImmValue <= 65535) {
1862 // For -32768 <= j <= 65535.
1863 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001864 tmpInst.setOpcode(Mips::ADDiu);
1865 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001866 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001867 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1868 Instructions.push_back(tmpInst);
1869 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001870 // For any other value of j that is representable as a 32-bit integer.
1871 // la d,j => lui d,hi16(j)
1872 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001873 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001874 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1875 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1876 Instructions.push_back(tmpInst);
1877 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001878 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001879 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1880 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1881 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1882 Instructions.push_back(tmpInst);
1883 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001884 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001885}
1886
Toma Tabacu0d64b202014-08-14 10:29:17 +00001887void
1888MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1889 SmallVectorImpl<MCInst> &Instructions) {
1890 // FIXME: If we do have a valid at register to use, we should generate a
1891 // slightly shorter sequence here.
1892 MCInst tmpInst;
1893 int ExprOperandNo = 1;
1894 // Sometimes the assembly parser will get the immediate expression as
1895 // a $zero + an immediate.
1896 if (Inst.getNumOperands() == 3) {
1897 assert(Inst.getOperand(1).getReg() ==
1898 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1899 ExprOperandNo = 2;
1900 }
1901 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1902 assert(SymOp.isExpr() && "expected symbol operand kind");
1903 const MCOperand &RegOp = Inst.getOperand(0);
1904 unsigned RegNo = RegOp.getReg();
1905 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1906 const MCSymbolRefExpr *HiExpr =
1907 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1908 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1909 const MCSymbolRefExpr *LoExpr =
1910 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1911 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1912 if (isGP64bit()) {
1913 // If it's a 64-bit architecture, expand to:
1914 // la d,sym => lui d,highest(sym)
1915 // ori d,d,higher(sym)
1916 // dsll d,d,16
1917 // ori d,d,hi16(sym)
1918 // dsll d,d,16
1919 // ori d,d,lo16(sym)
1920 const MCSymbolRefExpr *HighestExpr =
1921 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1922 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1923 const MCSymbolRefExpr *HigherExpr =
1924 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1925 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1926
1927 tmpInst.setOpcode(Mips::LUi);
1928 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1929 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1930 Instructions.push_back(tmpInst);
1931
1932 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1933 Instructions);
1934 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1935 Instructions);
1936 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1937 Instructions);
1938 } else {
1939 // Otherwise, expand to:
1940 // la d,sym => lui d,hi16(sym)
1941 // ori d,d,lo16(sym)
1942 tmpInst.setOpcode(Mips::LUi);
1943 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1944 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1945 Instructions.push_back(tmpInst);
1946
1947 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1948 Instructions);
1949 }
1950}
1951
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001952bool MipsAsmParser::expandUncondBranchMMPseudo(
1953 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001954 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1955 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001956
1957 MCOperand Offset = Inst.getOperand(0);
1958 if (Offset.isExpr()) {
1959 Inst.clear();
1960 Inst.setOpcode(Mips::BEQ_MM);
1961 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1962 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1963 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1964 } else {
1965 assert(Offset.isImm() && "expected immediate operand kind");
1966 if (isIntN(11, Offset.getImm())) {
1967 // If offset fits into 11 bits then this instruction becomes microMIPS
1968 // 16-bit unconditional branch instruction.
1969 Inst.setOpcode(Mips::B16_MM);
1970 } else {
1971 if (!isIntN(17, Offset.getImm()))
1972 Error(IDLoc, "branch target out of range");
1973 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1974 Error(IDLoc, "branch to misaligned address");
1975 Inst.clear();
1976 Inst.setOpcode(Mips::BEQ_MM);
1977 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1978 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1979 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1980 }
1981 }
1982 Instructions.push_back(Inst);
1983
Toma Tabacu234482a2015-03-16 12:03:39 +00001984 // If .set reorder is active, emit a NOP after the branch instruction.
1985 if (AssemblerOptions.back()->isReorder())
1986 createNop(true, IDLoc, Instructions);
1987
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001988 return false;
1989}
1990
Jack Carter9e65aa32013-03-22 00:05:30 +00001991void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001992 SmallVectorImpl<MCInst> &Instructions,
1993 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001994 const MCSymbolRefExpr *SR;
1995 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001997 const MCExpr *ExprOffset;
1998 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001999 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002000 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2001 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002002 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002003 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2004 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002005 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002006 if (isImmOpnd) {
2007 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2008 ImmOffset = Inst.getOperand(2).getImm();
2009 LoOffset = ImmOffset & 0x0000ffff;
2010 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002012 if (LoOffset & 0x8000)
2013 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002014 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002015 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002016 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002017 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002018 // These are some of the types of expansions we perform here:
2019 // 1) lw $8, sym => lui $8, %hi(sym)
2020 // lw $8, %lo(sym)($8)
2021 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2022 // add $8, $8, $9
2023 // lw $8, %lo(offset)($9)
2024 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2025 // add $at, $at, $8
2026 // lw $8, %lo(offset)($at)
2027 // 4) sw $8, sym => lui $at, %hi(sym)
2028 // sw $8, %lo(sym)($at)
2029 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2030 // add $at, $at, $8
2031 // sw $8, %lo(offset)($at)
2032 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2033 // ldc1 $f0, %lo(sym)($at)
2034 //
2035 // For load instructions we can use the destination register as a temporary
2036 // if base and dst are different (examples 1 and 2) and if the base register
2037 // is general purpose otherwise we must use $at (example 6) and error if it's
2038 // not available. For stores we must use $at (examples 4 and 5) because we
2039 // must not clobber the source register setting up the offset.
2040 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2041 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2042 unsigned RegClassIDOp0 =
2043 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2044 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2045 (RegClassIDOp0 == Mips::GPR64RegClassID);
2046 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002047 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002048 else {
2049 int AT = getATReg(IDLoc);
2050 // At this point we need AT to perform the expansions and we exit if it is
2051 // not available.
2052 if (!AT)
2053 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002054 TmpRegNum = getReg(
2055 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00002056 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002057
Jack Carter9e65aa32013-03-22 00:05:30 +00002058 TempInst.setOpcode(Mips::LUi);
2059 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2060 if (isImmOpnd)
2061 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2062 else {
2063 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002064 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002065 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2066 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2067 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002068 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002069 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002070 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002071 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002072 }
2073 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002074 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002075 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002077 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002078 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002079 if (BaseRegNum != Mips::ZERO) {
2080 TempInst.setOpcode(Mips::ADDu);
2081 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2082 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2083 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2084 Instructions.push_back(TempInst);
2085 TempInst.clear();
2086 }
Alp Tokercb402912014-01-24 17:20:08 +00002087 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002089 TempInst.setOpcode(Inst.getOpcode());
2090 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2091 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2092 if (isImmOpnd)
2093 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2094 else {
2095 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2097 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2098 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002099 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002100 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002102 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 }
2104 }
2105 Instructions.push_back(TempInst);
2106 TempInst.clear();
2107}
2108
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002109bool
2110MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2111 SmallVectorImpl<MCInst> &Instructions) {
2112 unsigned OpNum = Inst.getNumOperands();
2113 unsigned Opcode = Inst.getOpcode();
2114 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2115
2116 assert (Inst.getOperand(OpNum - 1).isImm() &&
2117 Inst.getOperand(OpNum - 2).isReg() &&
2118 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2119
2120 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2121 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2122 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2123 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2124 // It can be implemented as SWM16 or LWM16 instruction.
2125 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2126
2127 Inst.setOpcode(NewOpcode);
2128 Instructions.push_back(Inst);
2129 return false;
2130}
2131
Toma Tabacu234482a2015-03-16 12:03:39 +00002132void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2133 SmallVectorImpl<MCInst> &Instructions) {
2134 MCInst NopInst;
2135 if (hasShortDelaySlot) {
2136 NopInst.setOpcode(Mips::MOVE16_MM);
2137 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2138 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2139 } else {
2140 NopInst.setOpcode(Mips::SLL);
2141 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2142 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2143 NopInst.addOperand(MCOperand::CreateImm(0));
2144 }
2145 Instructions.push_back(NopInst);
2146}
2147
Matheus Almeida595fcab2014-06-11 15:05:56 +00002148unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2149 // As described by the Mips32r2 spec, the registers Rd and Rs for
2150 // jalr.hb must be different.
2151 unsigned Opcode = Inst.getOpcode();
2152
2153 if (Opcode == Mips::JALR_HB &&
2154 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2155 return Match_RequiresDifferentSrcAndDst;
2156
2157 return Match_Success;
2158}
2159
David Blaikie960ea3f2014-06-08 16:18:35 +00002160bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2161 OperandVector &Operands,
2162 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002163 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002164 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002165
Jack Carterb4dbc172012-09-05 23:34:03 +00002166 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002167 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002168 unsigned MatchResult =
2169 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002170
2171 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002172 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002173 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002174 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002175 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002176 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002177 return false;
2178 }
2179 case Match_MissingFeature:
2180 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2181 return true;
2182 case Match_InvalidOperand: {
2183 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002184 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002185 if (ErrorInfo >= Operands.size())
2186 return Error(IDLoc, "too few operands for instruction");
2187
David Blaikie960ea3f2014-06-08 16:18:35 +00002188 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002189 if (ErrorLoc == SMLoc())
2190 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002191 }
2192
2193 return Error(ErrorLoc, "invalid operand for instruction");
2194 }
2195 case Match_MnemonicFail:
2196 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002197 case Match_RequiresDifferentSrcAndDst:
2198 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002199 }
Craig Topper589ceee2015-01-03 08:16:34 +00002200
2201 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002202}
2203
Toma Tabacu13964452014-09-04 13:23:44 +00002204void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002205 if ((RegIndex != 0) &&
2206 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002207 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00002208 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002209 else
Toma Tabacu65f10572014-09-16 15:00:52 +00002210 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002211 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002212 }
2213}
2214
Daniel Sandersef638fe2014-10-03 15:37:37 +00002215void
2216MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2217 SMRange Range, bool ShowColors) {
2218 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002219 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002220 ShowColors);
2221}
2222
Jack Carter1ac53222013-02-20 23:11:17 +00002223int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002224 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002225
Vladimir Medic4c299852013-11-06 11:27:05 +00002226 CC = StringSwitch<unsigned>(Name)
2227 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002228 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002229 .Case("a0", 4)
2230 .Case("a1", 5)
2231 .Case("a2", 6)
2232 .Case("a3", 7)
2233 .Case("v0", 2)
2234 .Case("v1", 3)
2235 .Case("s0", 16)
2236 .Case("s1", 17)
2237 .Case("s2", 18)
2238 .Case("s3", 19)
2239 .Case("s4", 20)
2240 .Case("s5", 21)
2241 .Case("s6", 22)
2242 .Case("s7", 23)
2243 .Case("k0", 26)
2244 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002245 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002246 .Case("sp", 29)
2247 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002248 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002249 .Case("ra", 31)
2250 .Case("t0", 8)
2251 .Case("t1", 9)
2252 .Case("t2", 10)
2253 .Case("t3", 11)
2254 .Case("t4", 12)
2255 .Case("t5", 13)
2256 .Case("t6", 14)
2257 .Case("t7", 15)
2258 .Case("t8", 24)
2259 .Case("t9", 25)
2260 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002261
Toma Tabacufda445c2014-09-15 15:33:01 +00002262 if (!(isABI_N32() || isABI_N64()))
2263 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002264
Daniel Sandersef638fe2014-10-03 15:37:37 +00002265 if (12 <= CC && CC <= 15) {
2266 // Name is one of t4-t7
2267 AsmToken RegTok = getLexer().peekTok();
2268 SMRange RegRange = RegTok.getLocRange();
2269
2270 StringRef FixedName = StringSwitch<StringRef>(Name)
2271 .Case("t4", "t0")
2272 .Case("t5", "t1")
2273 .Case("t6", "t2")
2274 .Case("t7", "t3")
2275 .Default("");
2276 assert(FixedName != "" && "Register name is not one of t4-t7.");
2277
2278 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2279 "Did you mean $" + FixedName + "?", RegRange);
2280 }
2281
Toma Tabacufda445c2014-09-15 15:33:01 +00002282 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2283 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2284 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2285 if (8 <= CC && CC <= 11)
2286 CC += 4;
2287
2288 if (CC == -1)
2289 CC = StringSwitch<unsigned>(Name)
2290 .Case("a4", 8)
2291 .Case("a5", 9)
2292 .Case("a6", 10)
2293 .Case("a7", 11)
2294 .Case("kt0", 26)
2295 .Case("kt1", 27)
2296 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002297
2298 return CC;
2299}
Jack Carterd0bd6422013-04-18 00:41:53 +00002300
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002301int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2302 int CC;
2303
2304 CC = StringSwitch<unsigned>(Name)
2305 .Case("hwr_cpunum", 0)
2306 .Case("hwr_synci_step", 1)
2307 .Case("hwr_cc", 2)
2308 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002309 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002310 .Default(-1);
2311
2312 return CC;
2313}
2314
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002315int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002316
Jack Cartera63b16a2012-09-07 00:23:42 +00002317 if (Name[0] == 'f') {
2318 StringRef NumString = Name.substr(1);
2319 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002320 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002321 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002322 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002323 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002324 return IntVal;
2325 }
2326 return -1;
2327}
Jack Cartera63b16a2012-09-07 00:23:42 +00002328
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002329int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2330
2331 if (Name.startswith("fcc")) {
2332 StringRef NumString = Name.substr(3);
2333 unsigned IntVal;
2334 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002335 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002336 if (IntVal > 7) // There are only 8 fcc registers.
2337 return -1;
2338 return IntVal;
2339 }
2340 return -1;
2341}
2342
2343int MipsAsmParser::matchACRegisterName(StringRef Name) {
2344
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002345 if (Name.startswith("ac")) {
2346 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002347 unsigned IntVal;
2348 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002349 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002350 if (IntVal > 3) // There are only 3 acc registers.
2351 return -1;
2352 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002353 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002354 return -1;
2355}
Jack Carterd0bd6422013-04-18 00:41:53 +00002356
Jack Carter5dc8ac92013-09-25 23:50:44 +00002357int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2358 unsigned IntVal;
2359
2360 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2361 return -1;
2362
2363 if (IntVal > 31)
2364 return -1;
2365
2366 return IntVal;
2367}
2368
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002369int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2370 int CC;
2371
2372 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002373 .Case("msair", 0)
2374 .Case("msacsr", 1)
2375 .Case("msaaccess", 2)
2376 .Case("msasave", 3)
2377 .Case("msamodify", 4)
2378 .Case("msarequest", 5)
2379 .Case("msamap", 6)
2380 .Case("msaunmap", 7)
2381 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002382
2383 return CC;
2384}
2385
Matheus Almeida7de68e72014-06-18 14:46:05 +00002386int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002387 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002388 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002389 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002390 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002391 return AT;
2392}
Jack Carter0b744b32012-10-04 02:29:46 +00002393
Jack Carterd0bd6422013-04-18 00:41:53 +00002394unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002395 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002396}
2397
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002398unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002399 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002400 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002401}
2402
Jack Carter873c7242013-01-12 01:03:14 +00002403int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002404 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002405 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002406 return -1;
2407
Jack Carter873c7242013-01-12 01:03:14 +00002408 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002409}
2410
Toma Tabacu13964452014-09-04 13:23:44 +00002411bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002412 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002413 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002414
Jack Carter30a59822012-10-04 04:03:53 +00002415 // Check if the current operand has a custom associated parser, if so, try to
2416 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002417 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2418 if (ResTy == MatchOperand_Success)
2419 return false;
2420 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2421 // there was a match, but an error occurred, in which case, just return that
2422 // the operand parsing failed.
2423 if (ResTy == MatchOperand_ParseFail)
2424 return true;
2425
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002426 DEBUG(dbgs() << ".. Generic Parser\n");
2427
Jack Carterb4dbc172012-09-05 23:34:03 +00002428 switch (getLexer().getKind()) {
2429 default:
2430 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2431 return true;
2432 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002433 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002434 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002435
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002436 // Almost all registers have been parsed by custom parsers. There is only
2437 // one exception to this. $zero (and it's alias $0) will reach this point
2438 // for div, divu, and similar instructions because it is not an operand
2439 // to the instruction definition but an explicit register. Special case
2440 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002441 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002442 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002443
Jack Carterd0bd6422013-04-18 00:41:53 +00002444 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002445 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002446 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002447 return true;
2448
Jack Carter873c7242013-01-12 01:03:14 +00002449 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002450 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002451 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002452 const MCExpr *Res =
2453 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002454
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002455 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002456 return false;
2457 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002458 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002459 case AsmToken::LParen:
2460 case AsmToken::Minus:
2461 case AsmToken::Plus:
2462 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002463 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002464 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002465 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002466 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002467 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002468 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002469 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002470 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002471 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002472 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002473 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002474 return true;
2475
Jack Carter873c7242013-01-12 01:03:14 +00002476 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2477
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002478 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002479 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002480 } // case AsmToken::Percent
2481 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002482 return true;
2483}
2484
Vladimir Medic4c299852013-11-06 11:27:05 +00002485const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002486 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002487 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002488 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002489 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002490 // It's a constant, evaluate reloc value.
2491 int16_t Val;
2492 switch (getVariantKind(RelocStr)) {
2493 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2494 // Get the 1st 16-bits.
2495 Val = MCE->getValue() & 0xffff;
2496 break;
2497 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2498 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2499 // 16 bits being negative.
2500 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2501 break;
2502 case MCSymbolRefExpr::VK_Mips_HIGHER:
2503 // Get the 3rd 16-bits.
2504 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2505 break;
2506 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2507 // Get the 4th 16-bits.
2508 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2509 break;
2510 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002511 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002512 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002513 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002514 }
2515
Jack Carterb5cf5902013-04-17 00:18:04 +00002516 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002518 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002519 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002521 return Res;
2522 }
2523
2524 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002525 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2526
Sasa Stankovic06c47802014-04-03 10:37:45 +00002527 // Try to create target expression.
2528 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2529 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002530
Jack Carterd0bd6422013-04-18 00:41:53 +00002531 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2532 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002533 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2534 return Res;
2535 }
2536
2537 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002538 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2539 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2540 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002541 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002543 return Expr;
2544}
2545
2546bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2547
2548 switch (Expr->getKind()) {
2549 case MCExpr::Constant:
2550 return true;
2551 case MCExpr::SymbolRef:
2552 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2553 case MCExpr::Binary:
2554 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2555 if (!isEvaluated(BE->getLHS()))
2556 return false;
2557 return isEvaluated(BE->getRHS());
2558 }
2559 case MCExpr::Unary:
2560 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002561 case MCExpr::Target:
2562 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002563 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002564 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002565}
Jack Carterd0bd6422013-04-18 00:41:53 +00002566
Jack Carterb5cf5902013-04-17 00:18:04 +00002567bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002568 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002569 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002570 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002571 if (Tok.isNot(AsmToken::Identifier))
2572 return true;
2573
Yaron Keren075759a2015-03-30 15:42:36 +00002574 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002575
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 Parser.Lex(); // Eat the identifier.
2577 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002578 const MCExpr *IdVal;
2579 SMLoc EndLoc;
2580
2581 if (getLexer().getKind() == AsmToken::LParen) {
2582 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002583 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002584 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002585 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002586 const AsmToken &nextTok = Parser.getTok();
2587 if (nextTok.isNot(AsmToken::Identifier))
2588 return true;
2589 Str += "(%";
2590 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002591 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002592 if (getLexer().getKind() != AsmToken::LParen)
2593 return true;
2594 } else
2595 break;
2596 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002598 return true;
2599
2600 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002601 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002602
2603 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002604 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002605
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002607 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002608}
2609
Jack Carterb4dbc172012-09-05 23:34:03 +00002610bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2611 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002612 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002613 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002614 if (ResTy == MatchOperand_Success) {
2615 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002616 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002617 StartLoc = Operand.getStartLoc();
2618 EndLoc = Operand.getEndLoc();
2619
2620 // AFAIK, we only support numeric registers and named GPR's in CFI
2621 // directives.
2622 // Don't worry about eating tokens before failing. Using an unrecognised
2623 // register is a parse error.
2624 if (Operand.isGPRAsmReg()) {
2625 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002626 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002627 }
2628
2629 return (RegNo == (unsigned)-1);
2630 }
2631
2632 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002633 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002634}
2635
Jack Carterb5cf5902013-04-17 00:18:04 +00002636bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002637 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002638 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002639 bool Result = true;
2640
2641 while (getLexer().getKind() == AsmToken::LParen)
2642 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002643
Jack Carterd0bd6422013-04-18 00:41:53 +00002644 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002645 default:
2646 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002647 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002648 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002649 case AsmToken::Integer:
2650 case AsmToken::Minus:
2651 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002652 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002653 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002654 else
2655 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002656 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002657 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 break;
Jack Carter873c7242013-01-12 01:03:14 +00002659 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002660 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002661 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002662 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002663}
2664
David Blaikie960ea3f2014-06-08 16:18:35 +00002665MipsAsmParser::OperandMatchResultTy
2666MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002667 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002668 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002669 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002670 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002671 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002672 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002673 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002674 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002675
Jack Carterb5cf5902013-04-17 00:18:04 +00002676 if (getLexer().getKind() == AsmToken::LParen) {
2677 Parser.Lex();
2678 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002679 }
2680
Jack Carterb5cf5902013-04-17 00:18:04 +00002681 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002682 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002683 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002684
Jack Carterd0bd6422013-04-18 00:41:53 +00002685 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002686 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002687 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2688 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002689 SMLoc E =
2690 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002691 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002692 return MatchOperand_Success;
2693 }
2694 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002695 SMLoc E =
2696 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002697
Jack Carterd0bd6422013-04-18 00:41:53 +00002698 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002699 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002700 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002701 S, E, *this);
2702 Operands.push_back(
2703 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002704 return MatchOperand_Success;
2705 }
2706 Error(Parser.getTok().getLoc(), "'(' expected");
2707 return MatchOperand_ParseFail;
2708 }
2709
Jack Carterd0bd6422013-04-18 00:41:53 +00002710 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002711 }
2712
Toma Tabacu13964452014-09-04 13:23:44 +00002713 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002714 if (Res != MatchOperand_Success)
2715 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002716
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002717 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002718 Error(Parser.getTok().getLoc(), "')' expected");
2719 return MatchOperand_ParseFail;
2720 }
2721
Jack Carter873c7242013-01-12 01:03:14 +00002722 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2723
Jack Carterd0bd6422013-04-18 00:41:53 +00002724 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002725
Craig Topper062a2ba2014-04-25 05:30:21 +00002726 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002727 IdVal = MCConstantExpr::Create(0, getContext());
2728
Jack Carterd0bd6422013-04-18 00:41:53 +00002729 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002730 std::unique_ptr<MipsOperand> op(
2731 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002732 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002733 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002734 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002735 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002736 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2737 int64_t Imm;
2738 if (IdVal->EvaluateAsAbsolute(Imm))
2739 IdVal = MCConstantExpr::Create(Imm, getContext());
2740 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2741 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2742 getContext());
2743 }
2744
David Blaikie960ea3f2014-06-08 16:18:35 +00002745 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002746 return MatchOperand_Success;
2747}
2748
David Blaikie960ea3f2014-06-08 16:18:35 +00002749bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002750 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002751 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2752 if (Sym) {
2753 SMLoc S = Parser.getTok().getLoc();
2754 const MCExpr *Expr;
2755 if (Sym->isVariable())
2756 Expr = Sym->getVariableValue();
2757 else
2758 return false;
2759 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002760 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002761 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002762 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002763 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002764 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002765 if (ResTy == MatchOperand_Success) {
2766 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002767 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002768 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002769 llvm_unreachable("Should never ParseFail");
2770 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002771 }
2772 } else if (Expr->getKind() == MCExpr::Constant) {
2773 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002774 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002775 Operands.push_back(
2776 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002777 return true;
2778 }
2779 }
2780 return false;
2781}
Jack Carterd0bd6422013-04-18 00:41:53 +00002782
Jack Carter873c7242013-01-12 01:03:14 +00002783MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002784MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002785 StringRef Identifier,
2786 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002787 int Index = matchCPURegisterName(Identifier);
2788 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002789 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002790 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2791 return MatchOperand_Success;
2792 }
2793
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002794 Index = matchHWRegsRegisterName(Identifier);
2795 if (Index != -1) {
2796 Operands.push_back(MipsOperand::createHWRegsReg(
2797 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2798 return MatchOperand_Success;
2799 }
2800
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002801 Index = matchFPURegisterName(Identifier);
2802 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002803 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002804 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2805 return MatchOperand_Success;
2806 }
2807
2808 Index = matchFCCRegisterName(Identifier);
2809 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002810 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002811 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2812 return MatchOperand_Success;
2813 }
2814
2815 Index = matchACRegisterName(Identifier);
2816 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002817 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002818 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2819 return MatchOperand_Success;
2820 }
2821
2822 Index = matchMSA128RegisterName(Identifier);
2823 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002824 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002825 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2826 return MatchOperand_Success;
2827 }
2828
2829 Index = matchMSA128CtrlRegisterName(Identifier);
2830 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002831 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002832 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2833 return MatchOperand_Success;
2834 }
2835
2836 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002837}
2838
2839MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002840MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002841 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002842 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002843
2844 if (Token.is(AsmToken::Identifier)) {
2845 DEBUG(dbgs() << ".. identifier\n");
2846 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002847 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002848 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002849 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 } else if (Token.is(AsmToken::Integer)) {
2851 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002852 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002853 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2854 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 return MatchOperand_Success;
2856 }
2857
2858 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2859
2860 return MatchOperand_NoMatch;
2861}
2862
David Blaikie960ea3f2014-06-08 16:18:35 +00002863MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002864MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002865 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002866 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002867
2868 auto Token = Parser.getTok();
2869
2870 SMLoc S = Token.getLoc();
2871
2872 if (Token.isNot(AsmToken::Dollar)) {
2873 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2874 if (Token.is(AsmToken::Identifier)) {
2875 if (searchSymbolAlias(Operands))
2876 return MatchOperand_Success;
2877 }
2878 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2879 return MatchOperand_NoMatch;
2880 }
2881 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002882
Toma Tabacu13964452014-09-04 13:23:44 +00002883 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002884 if (ResTy == MatchOperand_Success) {
2885 Parser.Lex(); // $
2886 Parser.Lex(); // identifier
2887 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002888 return ResTy;
2889}
2890
2891MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002892MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002893 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002894 switch (getLexer().getKind()) {
2895 default:
2896 return MatchOperand_NoMatch;
2897 case AsmToken::LParen:
2898 case AsmToken::Minus:
2899 case AsmToken::Plus:
2900 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002901 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002902 case AsmToken::String:
2903 break;
2904 }
2905
2906 const MCExpr *IdVal;
2907 SMLoc S = Parser.getTok().getLoc();
2908 if (getParser().parseExpression(IdVal))
2909 return MatchOperand_ParseFail;
2910
2911 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2912 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2913 return MatchOperand_Success;
2914}
2915
David Blaikie960ea3f2014-06-08 16:18:35 +00002916MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002917MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002918 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002919 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002920
2921 SMLoc S = getLexer().getLoc();
2922
2923 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002924 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002925 if (ResTy != MatchOperand_NoMatch)
2926 return ResTy;
2927
Daniel Sanders315386c2014-04-01 10:40:14 +00002928 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002929 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002930 if (ResTy != MatchOperand_NoMatch)
2931 return ResTy;
2932
Daniel Sandersffd84362014-04-01 10:41:48 +00002933 const MCExpr *Expr = nullptr;
2934 if (Parser.parseExpression(Expr)) {
2935 // We have no way of knowing if a symbol was consumed so we must ParseFail
2936 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002937 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002938 Operands.push_back(
2939 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002940 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002941}
2942
Vladimir Medic2b953d02013-10-01 09:48:56 +00002943MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002944MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002945 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002946 const MCExpr *IdVal;
2947 // If the first token is '$' we may have register operand.
2948 if (Parser.getTok().is(AsmToken::Dollar))
2949 return MatchOperand_NoMatch;
2950 SMLoc S = Parser.getTok().getLoc();
2951 if (getParser().parseExpression(IdVal))
2952 return MatchOperand_ParseFail;
2953 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002954 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002955 int64_t Val = MCE->getValue();
2956 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2957 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002958 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002959 return MatchOperand_Success;
2960}
2961
Matheus Almeida779c5932013-11-18 12:32:49 +00002962MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002963MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002964 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002965 switch (getLexer().getKind()) {
2966 default:
2967 return MatchOperand_NoMatch;
2968 case AsmToken::LParen:
2969 case AsmToken::Plus:
2970 case AsmToken::Minus:
2971 case AsmToken::Integer:
2972 break;
2973 }
2974
2975 const MCExpr *Expr;
2976 SMLoc S = Parser.getTok().getLoc();
2977
2978 if (getParser().parseExpression(Expr))
2979 return MatchOperand_ParseFail;
2980
2981 int64_t Val;
2982 if (!Expr->EvaluateAsAbsolute(Val)) {
2983 Error(S, "expected immediate value");
2984 return MatchOperand_ParseFail;
2985 }
2986
2987 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2988 // and because the CPU always adds one to the immediate field, the allowed
2989 // range becomes 1..4. We'll only check the range here and will deal
2990 // with the addition/subtraction when actually decoding/encoding
2991 // the instruction.
2992 if (Val < 1 || Val > 4) {
2993 Error(S, "immediate not in range (1..4)");
2994 return MatchOperand_ParseFail;
2995 }
2996
Jack Carter3b2c96e2014-01-22 23:31:38 +00002997 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002998 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002999 return MatchOperand_Success;
3000}
3001
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003002MipsAsmParser::OperandMatchResultTy
3003MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3004 MCAsmParser &Parser = getParser();
3005 SmallVector<unsigned, 10> Regs;
3006 unsigned RegNo;
3007 unsigned PrevReg = Mips::NoRegister;
3008 bool RegRange = false;
3009 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3010
3011 if (Parser.getTok().isNot(AsmToken::Dollar))
3012 return MatchOperand_ParseFail;
3013
3014 SMLoc S = Parser.getTok().getLoc();
3015 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3016 SMLoc E = getLexer().getLoc();
3017 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3018 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3019 if (RegRange) {
3020 // Remove last register operand because registers from register range
3021 // should be inserted first.
3022 if (RegNo == Mips::RA) {
3023 Regs.push_back(RegNo);
3024 } else {
3025 unsigned TmpReg = PrevReg + 1;
3026 while (TmpReg <= RegNo) {
3027 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3028 Error(E, "invalid register operand");
3029 return MatchOperand_ParseFail;
3030 }
3031
3032 PrevReg = TmpReg;
3033 Regs.push_back(TmpReg++);
3034 }
3035 }
3036
3037 RegRange = false;
3038 } else {
3039 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3040 (RegNo != Mips::RA)) {
3041 Error(E, "$16 or $31 expected");
3042 return MatchOperand_ParseFail;
3043 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3044 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3045 Error(E, "invalid register operand");
3046 return MatchOperand_ParseFail;
3047 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3048 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3049 Error(E, "consecutive register numbers expected");
3050 return MatchOperand_ParseFail;
3051 }
3052
3053 Regs.push_back(RegNo);
3054 }
3055
3056 if (Parser.getTok().is(AsmToken::Minus))
3057 RegRange = true;
3058
3059 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3060 !Parser.getTok().isNot(AsmToken::Comma)) {
3061 Error(E, "',' or '-' expected");
3062 return MatchOperand_ParseFail;
3063 }
3064
3065 Lex(); // Consume comma or minus
3066 if (Parser.getTok().isNot(AsmToken::Dollar))
3067 break;
3068
3069 PrevReg = RegNo;
3070 }
3071
3072 SMLoc E = Parser.getTok().getLoc();
3073 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3074 parseMemOperand(Operands);
3075 return MatchOperand_Success;
3076}
3077
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003078MipsAsmParser::OperandMatchResultTy
3079MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3080 MCAsmParser &Parser = getParser();
3081
3082 SMLoc S = Parser.getTok().getLoc();
3083 if (parseAnyRegister(Operands) != MatchOperand_Success)
3084 return MatchOperand_ParseFail;
3085
3086 SMLoc E = Parser.getTok().getLoc();
3087 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3088 unsigned Reg = Op.getGPR32Reg();
3089 Operands.pop_back();
3090 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3091 return MatchOperand_Success;
3092}
3093
Zoran Jovanovic41688672015-02-10 16:36:20 +00003094MipsAsmParser::OperandMatchResultTy
3095MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3096 MCAsmParser &Parser = getParser();
3097 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3098 SmallVector<unsigned, 10> Regs;
3099
3100 if (Parser.getTok().isNot(AsmToken::Dollar))
3101 return MatchOperand_ParseFail;
3102
3103 SMLoc S = Parser.getTok().getLoc();
3104
3105 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3106 return MatchOperand_ParseFail;
3107
3108 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3109 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3110 Regs.push_back(RegNo);
3111
3112 SMLoc E = Parser.getTok().getLoc();
3113 if (Parser.getTok().isNot(AsmToken::Comma)) {
3114 Error(E, "',' expected");
3115 return MatchOperand_ParseFail;
3116 }
3117
3118 // Remove comma.
3119 Parser.Lex();
3120
3121 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3122 return MatchOperand_ParseFail;
3123
3124 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3125 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3126 Regs.push_back(RegNo);
3127
3128 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3129
3130 return MatchOperand_Success;
3131}
3132
Jack Carterdc1e35d2012-09-06 20:00:02 +00003133MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3134
Vladimir Medic4c299852013-11-06 11:27:05 +00003135 MCSymbolRefExpr::VariantKind VK =
3136 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3137 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3138 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3139 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3140 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3141 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3142 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3143 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3144 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3145 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3146 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3147 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3148 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3149 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3150 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3151 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3152 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3153 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003154 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3155 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3156 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3157 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3158 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3159 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003160 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3161 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003162 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003163
Matheus Almeida2852af82014-04-22 10:15:54 +00003164 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003165
Jack Carterdc1e35d2012-09-06 20:00:02 +00003166 return VK;
3167}
Jack Cartera63b16a2012-09-07 00:23:42 +00003168
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003169/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3170/// either this.
3171/// ::= '(', register, ')'
3172/// handle it before we iterate so we don't get tripped up by the lack of
3173/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003174bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003175 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003176 if (getLexer().is(AsmToken::LParen)) {
3177 Operands.push_back(
3178 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3179 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003180 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003181 SMLoc Loc = getLexer().getLoc();
3182 Parser.eatToEndOfStatement();
3183 return Error(Loc, "unexpected token in argument list");
3184 }
3185 if (Parser.getTok().isNot(AsmToken::RParen)) {
3186 SMLoc Loc = getLexer().getLoc();
3187 Parser.eatToEndOfStatement();
3188 return Error(Loc, "unexpected token, expected ')'");
3189 }
3190 Operands.push_back(
3191 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3192 Parser.Lex();
3193 }
3194 return false;
3195}
3196
3197/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3198/// either one of these.
3199/// ::= '[', register, ']'
3200/// ::= '[', integer, ']'
3201/// handle it before we iterate so we don't get tripped up by the lack of
3202/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003203bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003204 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003205 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003206 if (getLexer().is(AsmToken::LBrac)) {
3207 Operands.push_back(
3208 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3209 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003210 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003211 SMLoc Loc = getLexer().getLoc();
3212 Parser.eatToEndOfStatement();
3213 return Error(Loc, "unexpected token in argument list");
3214 }
3215 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3216 SMLoc Loc = getLexer().getLoc();
3217 Parser.eatToEndOfStatement();
3218 return Error(Loc, "unexpected token, expected ']'");
3219 }
3220 Operands.push_back(
3221 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3222 Parser.Lex();
3223 }
3224 return false;
3225}
3226
David Blaikie960ea3f2014-06-08 16:18:35 +00003227bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3228 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003229 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003230 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003231
3232 // We have reached first instruction, module directive are now forbidden.
3233 getTargetStreamer().forbidModuleDirective();
3234
Vladimir Medic74593e62013-07-17 15:00:42 +00003235 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003236 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003237 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003238 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003239 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003240 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003241 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003242
3243 // Read the remaining operands.
3244 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3245 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003246 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003247 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003248 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003249 return Error(Loc, "unexpected token in argument list");
3250 }
Toma Tabacu13964452014-09-04 13:23:44 +00003251 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003252 return true;
3253 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003254
Jack Carterd0bd6422013-04-18 00:41:53 +00003255 while (getLexer().is(AsmToken::Comma)) {
3256 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003257 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003258 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003259 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003260 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003261 return Error(Loc, "unexpected token in argument list");
3262 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003263 // Parse bracket and parenthesis suffixes before we iterate
3264 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003265 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003266 return true;
3267 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003268 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003269 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003270 }
3271 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003272 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3273 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003274 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003275 return Error(Loc, "unexpected token in argument list");
3276 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003277 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003278 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003279}
3280
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003281bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003282 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003283 SMLoc Loc = getLexer().getLoc();
3284 Parser.eatToEndOfStatement();
3285 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003286}
3287
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003288bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003289 return Error(Loc, ErrorMsg);
3290}
3291
Jack Carter0b744b32012-10-04 02:29:46 +00003292bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003293 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003294 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003295
3296 // Set the $at register to $0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003297 AssemblerOptions.back()->setATReg(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003298
3299 Parser.Lex(); // Eat "noat".
3300
Jack Carterd0bd6422013-04-18 00:41:53 +00003301 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003302 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003303 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003304 return false;
3305 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003306
3307 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003308 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003309 return false;
3310}
Jack Carterd0bd6422013-04-18 00:41:53 +00003311
Jack Carter0b744b32012-10-04 02:29:46 +00003312bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003313 // Line can be: ".set at", which sets $at to $1
3314 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003315 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003316 Parser.Lex(); // Eat "at".
3317
Jack Carter0b744b32012-10-04 02:29:46 +00003318 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003319 // No register was specified, so we set $at to $1.
Toma Tabacu9db22db2014-09-09 10:15:38 +00003320 AssemblerOptions.back()->setATReg(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003321
3322 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003323 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003324 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003325 }
3326
3327 if (getLexer().isNot(AsmToken::Equal)) {
3328 reportParseError("unexpected token, expected equals sign");
3329 return false;
3330 }
3331 Parser.Lex(); // Eat "=".
3332
3333 if (getLexer().isNot(AsmToken::Dollar)) {
3334 if (getLexer().is(AsmToken::EndOfStatement)) {
3335 reportParseError("no register specified");
3336 return false;
3337 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003338 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003339 return false;
3340 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003341 }
3342 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003343
Toma Tabacu16a74492015-02-13 10:30:57 +00003344 // Find out what "reg" is.
3345 unsigned AtRegNo;
3346 const AsmToken &Reg = Parser.getTok();
3347 if (Reg.is(AsmToken::Identifier)) {
3348 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3349 } else if (Reg.is(AsmToken::Integer)) {
3350 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003351 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003352 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003353 return false;
3354 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003355
3356 // Check if $reg is a valid register. If it is, set $at to $reg.
3357 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
3358 reportParseError("invalid register");
3359 return false;
3360 }
3361 Parser.Lex(); // Eat "reg".
3362
3363 // If this is not the end of the statement, report an error.
3364 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3365 reportParseError("unexpected token, expected end of statement");
3366 return false;
3367 }
3368
3369 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3370
3371 Parser.Lex(); // Consume the EndOfStatement.
3372 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003373}
3374
3375bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003376 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003377 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003378 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003379 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003380 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003381 return false;
3382 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003383 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003384 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003385 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003386 return false;
3387}
3388
3389bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003390 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003391 Parser.Lex();
3392 // If this is not the end of the statement, report an error.
3393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003394 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003395 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003396 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003397 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003398 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003399 Parser.Lex(); // Consume the EndOfStatement.
3400 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003401}
3402
3403bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003404 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003405 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003406 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003408 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003409 return false;
3410 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003411 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003412 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003413 return false;
3414}
3415
3416bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003417 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003418 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003419 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003421 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003422 return false;
3423 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003424 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003425 reportParseError("`noreorder' must be set before `nomacro'");
3426 return false;
3427 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003428 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003429 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003430 return false;
3431}
Jack Carterd76b2372013-03-21 21:44:16 +00003432
Daniel Sanders44934432014-08-07 12:03:36 +00003433bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003434 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003435 Parser.Lex();
3436
3437 // If this is not the end of the statement, report an error.
3438 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003439 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003440
3441 setFeatureBits(Mips::FeatureMSA, "msa");
3442 getTargetStreamer().emitDirectiveSetMsa();
3443 return false;
3444}
3445
3446bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003447 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003448 Parser.Lex();
3449
3450 // If this is not the end of the statement, report an error.
3451 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003452 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003453
3454 clearFeatureBits(Mips::FeatureMSA, "msa");
3455 getTargetStreamer().emitDirectiveSetNoMsa();
3456 return false;
3457}
3458
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003459bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003460 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003461 Parser.Lex(); // Eat "nodsp".
3462
3463 // If this is not the end of the statement, report an error.
3464 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3465 reportParseError("unexpected token, expected end of statement");
3466 return false;
3467 }
3468
3469 clearFeatureBits(Mips::FeatureDSP, "dsp");
3470 getTargetStreamer().emitDirectiveSetNoDsp();
3471 return false;
3472}
3473
Toma Tabacucc2502d2014-11-04 17:18:07 +00003474bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003475 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003476 Parser.Lex(); // Eat "mips16".
3477
Jack Carter39536722014-01-22 23:08:42 +00003478 // If this is not the end of the statement, report an error.
3479 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003480 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003481 return false;
3482 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003483
3484 setFeatureBits(Mips::FeatureMips16, "mips16");
3485 getTargetStreamer().emitDirectiveSetMips16();
3486 Parser.Lex(); // Consume the EndOfStatement.
3487 return false;
3488}
3489
3490bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003491 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003492 Parser.Lex(); // Eat "nomips16".
3493
3494 // If this is not the end of the statement, report an error.
3495 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3496 reportParseError("unexpected token, expected end of statement");
3497 return false;
3498 }
3499
3500 clearFeatureBits(Mips::FeatureMips16, "mips16");
3501 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003502 Parser.Lex(); // Consume the EndOfStatement.
3503 return false;
3504}
3505
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003506bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003507 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003508 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003509 // Line can be: .set fp=32
3510 // .set fp=xx
3511 // .set fp=64
3512 Parser.Lex(); // Eat fp token
3513 AsmToken Tok = Parser.getTok();
3514 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003515 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003516 return false;
3517 }
3518 Parser.Lex(); // Eat '=' token.
3519 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003520
3521 if (!parseFpABIValue(FpAbiVal, ".set"))
3522 return false;
3523
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003525 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003526 return false;
3527 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003528 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003529 Parser.Lex(); // Consume the EndOfStatement.
3530 return false;
3531}
3532
Toma Tabacu9db22db2014-09-09 10:15:38 +00003533bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003534 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003535 SMLoc Loc = getLexer().getLoc();
3536
3537 Parser.Lex();
3538 if (getLexer().isNot(AsmToken::EndOfStatement))
3539 return reportParseError("unexpected token, expected end of statement");
3540
3541 // Always keep an element on the options "stack" to prevent the user
3542 // from changing the initial options. This is how we remember them.
3543 if (AssemblerOptions.size() == 2)
3544 return reportParseError(Loc, ".set pop with no .set push");
3545
3546 AssemblerOptions.pop_back();
3547 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3548
3549 getTargetStreamer().emitDirectiveSetPop();
3550 return false;
3551}
3552
3553bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003554 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003555 Parser.Lex();
3556 if (getLexer().isNot(AsmToken::EndOfStatement))
3557 return reportParseError("unexpected token, expected end of statement");
3558
3559 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003560 AssemblerOptions.push_back(
3561 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003562
3563 getTargetStreamer().emitDirectiveSetPush();
3564 return false;
3565}
3566
Jack Carterd76b2372013-03-21 21:44:16 +00003567bool MipsAsmParser::parseSetAssignment() {
3568 StringRef Name;
3569 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003570 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003571
3572 if (Parser.parseIdentifier(Name))
3573 reportParseError("expected identifier after .set");
3574
3575 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003576 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003577 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003578
Jack Carter3b2c96e2014-01-22 23:31:38 +00003579 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003580 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003581
Toma Tabacuf25949b2015-04-07 13:59:39 +00003582 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003583 Sym->setVariableValue(Value);
3584
3585 return false;
3586}
Jack Carterd0bd6422013-04-18 00:41:53 +00003587
Toma Tabacu26647792014-09-09 12:52:14 +00003588bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003589 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003590 Parser.Lex();
3591 if (getLexer().isNot(AsmToken::EndOfStatement))
3592 return reportParseError("unexpected token, expected end of statement");
3593
3594 // Reset assembler options to their initial values.
3595 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3596 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3597
3598 getTargetStreamer().emitDirectiveSetMips0();
3599 return false;
3600}
3601
Toma Tabacu85618b32014-08-19 14:22:52 +00003602bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003603 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003604 Parser.Lex();
3605 if (getLexer().isNot(AsmToken::Equal))
3606 return reportParseError("unexpected token, expected equals sign");
3607
3608 Parser.Lex();
3609 StringRef Arch;
3610 if (Parser.parseIdentifier(Arch))
3611 return reportParseError("expected arch identifier");
3612
3613 StringRef ArchFeatureName =
3614 StringSwitch<StringRef>(Arch)
3615 .Case("mips1", "mips1")
3616 .Case("mips2", "mips2")
3617 .Case("mips3", "mips3")
3618 .Case("mips4", "mips4")
3619 .Case("mips5", "mips5")
3620 .Case("mips32", "mips32")
3621 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003622 .Case("mips32r3", "mips32r3")
3623 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003624 .Case("mips32r6", "mips32r6")
3625 .Case("mips64", "mips64")
3626 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003627 .Case("mips64r3", "mips64r3")
3628 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003629 .Case("mips64r6", "mips64r6")
3630 .Case("cnmips", "cnmips")
3631 .Case("r4000", "mips3") // This is an implementation of Mips3.
3632 .Default("");
3633
3634 if (ArchFeatureName.empty())
3635 return reportParseError("unsupported architecture");
3636
3637 selectArch(ArchFeatureName);
3638 getTargetStreamer().emitDirectiveSetArch(Arch);
3639 return false;
3640}
3641
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003642bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003643 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003644 Parser.Lex();
3645 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003646 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003647
Matheus Almeida2852af82014-04-22 10:15:54 +00003648 switch (Feature) {
3649 default:
3650 llvm_unreachable("Unimplemented feature");
3651 case Mips::FeatureDSP:
3652 setFeatureBits(Mips::FeatureDSP, "dsp");
3653 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003654 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003655 case Mips::FeatureMicroMips:
3656 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003657 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003658 case Mips::FeatureMips1:
3659 selectArch("mips1");
3660 getTargetStreamer().emitDirectiveSetMips1();
3661 break;
3662 case Mips::FeatureMips2:
3663 selectArch("mips2");
3664 getTargetStreamer().emitDirectiveSetMips2();
3665 break;
3666 case Mips::FeatureMips3:
3667 selectArch("mips3");
3668 getTargetStreamer().emitDirectiveSetMips3();
3669 break;
3670 case Mips::FeatureMips4:
3671 selectArch("mips4");
3672 getTargetStreamer().emitDirectiveSetMips4();
3673 break;
3674 case Mips::FeatureMips5:
3675 selectArch("mips5");
3676 getTargetStreamer().emitDirectiveSetMips5();
3677 break;
3678 case Mips::FeatureMips32:
3679 selectArch("mips32");
3680 getTargetStreamer().emitDirectiveSetMips32();
3681 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003682 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003683 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003684 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003685 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003686 case Mips::FeatureMips32r3:
3687 selectArch("mips32r3");
3688 getTargetStreamer().emitDirectiveSetMips32R3();
3689 break;
3690 case Mips::FeatureMips32r5:
3691 selectArch("mips32r5");
3692 getTargetStreamer().emitDirectiveSetMips32R5();
3693 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003694 case Mips::FeatureMips32r6:
3695 selectArch("mips32r6");
3696 getTargetStreamer().emitDirectiveSetMips32R6();
3697 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003698 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003699 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003700 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003701 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003702 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003703 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003704 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003705 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003706 case Mips::FeatureMips64r3:
3707 selectArch("mips64r3");
3708 getTargetStreamer().emitDirectiveSetMips64R3();
3709 break;
3710 case Mips::FeatureMips64r5:
3711 selectArch("mips64r5");
3712 getTargetStreamer().emitDirectiveSetMips64R5();
3713 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003714 case Mips::FeatureMips64r6:
3715 selectArch("mips64r6");
3716 getTargetStreamer().emitDirectiveSetMips64R6();
3717 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003718 }
3719 return false;
3720}
3721
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003722bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003723 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003724 if (getLexer().isNot(AsmToken::Comma)) {
3725 SMLoc Loc = getLexer().getLoc();
3726 Parser.eatToEndOfStatement();
3727 return Error(Loc, ErrorStr);
3728 }
3729
Matheus Almeida2852af82014-04-22 10:15:54 +00003730 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003731 return true;
3732}
3733
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003734bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003735 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003736 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003737
Toma Tabacudde4c462014-11-06 10:02:45 +00003738 if (inMips16Mode()) {
3739 reportParseError(".cpload is not supported in Mips16 mode");
3740 return false;
3741 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003742
David Blaikie960ea3f2014-06-08 16:18:35 +00003743 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003744 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003745 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3746 reportParseError("expected register containing function address");
3747 return false;
3748 }
3749
David Blaikie960ea3f2014-06-08 16:18:35 +00003750 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3751 if (!RegOpnd.isGPRAsmReg()) {
3752 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003753 return false;
3754 }
3755
Toma Tabacudde4c462014-11-06 10:02:45 +00003756 // If this is not the end of the statement, report an error.
3757 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3758 reportParseError("unexpected token, expected end of statement");
3759 return false;
3760 }
3761
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003762 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003763 return false;
3764}
3765
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003766bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003767 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003768 unsigned FuncReg;
3769 unsigned Save;
3770 bool SaveIsReg = true;
3771
Matheus Almeida7e815762014-06-18 13:08:59 +00003772 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003773 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003774 if (ResTy == MatchOperand_NoMatch) {
3775 reportParseError("expected register containing function address");
3776 Parser.eatToEndOfStatement();
3777 return false;
3778 }
3779
3780 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3781 if (!FuncRegOpnd.isGPRAsmReg()) {
3782 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3783 Parser.eatToEndOfStatement();
3784 return false;
3785 }
3786
3787 FuncReg = FuncRegOpnd.getGPR32Reg();
3788 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003789
Toma Tabacu65f10572014-09-16 15:00:52 +00003790 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003791 return true;
3792
Toma Tabacu13964452014-09-04 13:23:44 +00003793 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003794 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003795 const AsmToken &Tok = Parser.getTok();
3796 if (Tok.is(AsmToken::Integer)) {
3797 Save = Tok.getIntVal();
3798 SaveIsReg = false;
3799 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003800 } else {
3801 reportParseError("expected save register or stack offset");
3802 Parser.eatToEndOfStatement();
3803 return false;
3804 }
3805 } else {
3806 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3807 if (!SaveOpnd.isGPRAsmReg()) {
3808 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3809 Parser.eatToEndOfStatement();
3810 return false;
3811 }
3812 Save = SaveOpnd.getGPR32Reg();
3813 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003814
Toma Tabacu65f10572014-09-16 15:00:52 +00003815 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003816 return true;
3817
Toma Tabacu8874eac2015-02-18 13:46:53 +00003818 const MCExpr *Expr;
3819 if (Parser.parseExpression(Expr)) {
3820 reportParseError("expected expression");
3821 return false;
3822 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003823
Toma Tabacu8874eac2015-02-18 13:46:53 +00003824 if (Expr->getKind() != MCExpr::SymbolRef) {
3825 reportParseError("expected symbol");
3826 return false;
3827 }
3828 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3829
3830 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3831 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003832 return false;
3833}
3834
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003835bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003836 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003837 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3838 const AsmToken &Tok = Parser.getTok();
3839
3840 if (Tok.getString() == "2008") {
3841 Parser.Lex();
3842 getTargetStreamer().emitDirectiveNaN2008();
3843 return false;
3844 } else if (Tok.getString() == "legacy") {
3845 Parser.Lex();
3846 getTargetStreamer().emitDirectiveNaNLegacy();
3847 return false;
3848 }
3849 }
3850 // If we don't recognize the option passed to the .nan
3851 // directive (e.g. no option or unknown option), emit an error.
3852 reportParseError("invalid option in .nan directive");
3853 return false;
3854}
3855
Jack Carter0b744b32012-10-04 02:29:46 +00003856bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003857 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003858 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003859 const AsmToken &Tok = Parser.getTok();
3860
3861 if (Tok.getString() == "noat") {
3862 return parseSetNoAtDirective();
3863 } else if (Tok.getString() == "at") {
3864 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003865 } else if (Tok.getString() == "arch") {
3866 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003867 } else if (Tok.getString() == "fp") {
3868 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003869 } else if (Tok.getString() == "pop") {
3870 return parseSetPopDirective();
3871 } else if (Tok.getString() == "push") {
3872 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003873 } else if (Tok.getString() == "reorder") {
3874 return parseSetReorderDirective();
3875 } else if (Tok.getString() == "noreorder") {
3876 return parseSetNoReorderDirective();
3877 } else if (Tok.getString() == "macro") {
3878 return parseSetMacroDirective();
3879 } else if (Tok.getString() == "nomacro") {
3880 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003881 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003882 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003883 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003884 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003885 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003886 getTargetStreamer().emitDirectiveSetNoMicroMips();
3887 Parser.eatToEndOfStatement();
3888 return false;
3889 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003890 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003891 } else if (Tok.getString() == "mips0") {
3892 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003893 } else if (Tok.getString() == "mips1") {
3894 return parseSetFeature(Mips::FeatureMips1);
3895 } else if (Tok.getString() == "mips2") {
3896 return parseSetFeature(Mips::FeatureMips2);
3897 } else if (Tok.getString() == "mips3") {
3898 return parseSetFeature(Mips::FeatureMips3);
3899 } else if (Tok.getString() == "mips4") {
3900 return parseSetFeature(Mips::FeatureMips4);
3901 } else if (Tok.getString() == "mips5") {
3902 return parseSetFeature(Mips::FeatureMips5);
3903 } else if (Tok.getString() == "mips32") {
3904 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003905 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003906 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003907 } else if (Tok.getString() == "mips32r3") {
3908 return parseSetFeature(Mips::FeatureMips32r3);
3909 } else if (Tok.getString() == "mips32r5") {
3910 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003911 } else if (Tok.getString() == "mips32r6") {
3912 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003913 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003914 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003915 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003916 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003917 } else if (Tok.getString() == "mips64r3") {
3918 return parseSetFeature(Mips::FeatureMips64r3);
3919 } else if (Tok.getString() == "mips64r5") {
3920 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003921 } else if (Tok.getString() == "mips64r6") {
3922 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003923 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003924 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003925 } else if (Tok.getString() == "nodsp") {
3926 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003927 } else if (Tok.getString() == "msa") {
3928 return parseSetMsaDirective();
3929 } else if (Tok.getString() == "nomsa") {
3930 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003931 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003932 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003933 parseSetAssignment();
3934 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003935 }
Jack Carter07c818d2013-01-25 01:31:34 +00003936
Jack Carter0b744b32012-10-04 02:29:46 +00003937 return true;
3938}
3939
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003940/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003941/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003942bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003943 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003944 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3945 for (;;) {
3946 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003947 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003948 return true;
3949
3950 getParser().getStreamer().EmitValue(Value, Size);
3951
3952 if (getLexer().is(AsmToken::EndOfStatement))
3953 break;
3954
Jack Carter07c818d2013-01-25 01:31:34 +00003955 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003956 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003957 Parser.Lex();
3958 }
3959 }
3960
3961 Parser.Lex();
3962 return false;
3963}
3964
Vladimir Medic4c299852013-11-06 11:27:05 +00003965/// parseDirectiveGpWord
3966/// ::= .gpword local_sym
3967bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003968 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003969 const MCExpr *Value;
3970 // EmitGPRel32Value requires an expression, so we are using base class
3971 // method to evaluate the expression.
3972 if (getParser().parseExpression(Value))
3973 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003974 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003975
Vladimir Medice10c1122013-11-13 13:18:04 +00003976 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003977 return Error(getLexer().getLoc(),
3978 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003979 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003980 return false;
3981}
3982
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003983/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003984/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003985bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003986 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003987 const MCExpr *Value;
3988 // EmitGPRel64Value requires an expression, so we are using base class
3989 // method to evaluate the expression.
3990 if (getParser().parseExpression(Value))
3991 return true;
3992 getParser().getStreamer().EmitGPRel64Value(Value);
3993
3994 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003995 return Error(getLexer().getLoc(),
3996 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003997 Parser.Lex(); // Eat EndOfStatement token.
3998 return false;
3999}
4000
Jack Carter0cd3c192014-01-06 23:27:31 +00004001bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004002 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004003 // Get the option token.
4004 AsmToken Tok = Parser.getTok();
4005 // At the moment only identifiers are supported.
4006 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004007 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004008 Parser.eatToEndOfStatement();
4009 return false;
4010 }
4011
4012 StringRef Option = Tok.getIdentifier();
4013
4014 if (Option == "pic0") {
4015 getTargetStreamer().emitDirectiveOptionPic0();
4016 Parser.Lex();
4017 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4018 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004019 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004020 Parser.eatToEndOfStatement();
4021 }
4022 return false;
4023 }
4024
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004025 if (Option == "pic2") {
4026 getTargetStreamer().emitDirectiveOptionPic2();
4027 Parser.Lex();
4028 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4029 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004030 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004031 Parser.eatToEndOfStatement();
4032 }
4033 return false;
4034 }
4035
Jack Carter0cd3c192014-01-06 23:27:31 +00004036 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004037 Warning(Parser.getTok().getLoc(),
4038 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004039 Parser.eatToEndOfStatement();
4040 return false;
4041}
4042
Daniel Sanders7e527422014-07-10 13:38:23 +00004043/// parseDirectiveModule
4044/// ::= .module oddspreg
4045/// ::= .module nooddspreg
4046/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004047bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004048 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004049 MCAsmLexer &Lexer = getLexer();
4050 SMLoc L = Lexer.getLoc();
4051
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004052 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004053 // TODO : get a better message.
4054 reportParseError(".module directive must appear before any code");
4055 return false;
4056 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004057
Toma Tabacuc405c822015-01-23 10:40:19 +00004058 StringRef Option;
4059 if (Parser.parseIdentifier(Option)) {
4060 reportParseError("expected .module option identifier");
4061 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004062 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004063
Toma Tabacuc405c822015-01-23 10:40:19 +00004064 if (Option == "oddspreg") {
4065 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4066 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4067
4068 // If this is not the end of the statement, report an error.
4069 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4070 reportParseError("unexpected token, expected end of statement");
4071 return false;
4072 }
4073
4074 return false; // parseDirectiveModule has finished successfully.
4075 } else if (Option == "nooddspreg") {
4076 if (!isABI_O32()) {
4077 Error(L, "'.module nooddspreg' requires the O32 ABI");
4078 return false;
4079 }
4080
4081 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4082 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4083
4084 // If this is not the end of the statement, report an error.
4085 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4086 reportParseError("unexpected token, expected end of statement");
4087 return false;
4088 }
4089
4090 return false; // parseDirectiveModule has finished successfully.
4091 } else if (Option == "fp") {
4092 return parseDirectiveModuleFP();
4093 } else {
4094 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4095 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004096}
4097
4098/// parseDirectiveModuleFP
4099/// ::= =32
4100/// ::= =xx
4101/// ::= =64
4102bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004103 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004104 MCAsmLexer &Lexer = getLexer();
4105
4106 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004107 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004108 return false;
4109 }
4110 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004111
Daniel Sanders7e527422014-07-10 13:38:23 +00004112 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004113 if (!parseFpABIValue(FpABI, ".module"))
4114 return false;
4115
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004117 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004118 return false;
4119 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004120
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004121 // Emit appropriate flags.
4122 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004123 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004124 return false;
4125}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004126
Daniel Sanders7e527422014-07-10 13:38:23 +00004127bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004128 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004129 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004130 MCAsmLexer &Lexer = getLexer();
4131
4132 if (Lexer.is(AsmToken::Identifier)) {
4133 StringRef Value = Parser.getTok().getString();
4134 Parser.Lex();
4135
4136 if (Value != "xx") {
4137 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4138 return false;
4139 }
4140
4141 if (!isABI_O32()) {
4142 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4143 return false;
4144 }
4145
Daniel Sanders7e527422014-07-10 13:38:23 +00004146 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004147 return true;
4148 }
4149
4150 if (Lexer.is(AsmToken::Integer)) {
4151 unsigned Value = Parser.getTok().getIntVal();
4152 Parser.Lex();
4153
4154 if (Value != 32 && Value != 64) {
4155 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4156 return false;
4157 }
4158
4159 if (Value == 32) {
4160 if (!isABI_O32()) {
4161 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4162 return false;
4163 }
4164
Daniel Sanders7e527422014-07-10 13:38:23 +00004165 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4166 } else
4167 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004168
Daniel Sanders7e527422014-07-10 13:38:23 +00004169 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004170 }
4171
4172 return false;
4173}
4174
Jack Carter0b744b32012-10-04 02:29:46 +00004175bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004176 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004177 StringRef IDVal = DirectiveID.getString();
4178
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004179 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004180 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004181 if (IDVal == ".dword") {
4182 parseDataDirective(8, DirectiveID.getLoc());
4183 return false;
4184 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004185 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004186 StringRef SymbolName;
4187
4188 if (Parser.parseIdentifier(SymbolName)) {
4189 reportParseError("expected identifier after .ent");
4190 return false;
4191 }
4192
4193 // There's an undocumented extension that allows an integer to
4194 // follow the name of the procedure which AFAICS is ignored by GAS.
4195 // Example: .ent foo,2
4196 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4197 if (getLexer().isNot(AsmToken::Comma)) {
4198 // Even though we accept this undocumented extension for compatibility
4199 // reasons, the additional integer argument does not actually change
4200 // the behaviour of the '.ent' directive, so we would like to discourage
4201 // its use. We do this by not referring to the extended version in
4202 // error messages which are not directly related to its use.
4203 reportParseError("unexpected token, expected end of statement");
4204 return false;
4205 }
4206 Parser.Lex(); // Eat the comma.
4207 const MCExpr *DummyNumber;
4208 int64_t DummyNumberVal;
4209 // If the user was explicitly trying to use the extended version,
4210 // we still give helpful extension-related error messages.
4211 if (Parser.parseExpression(DummyNumber)) {
4212 reportParseError("expected number after comma");
4213 return false;
4214 }
4215 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4216 reportParseError("expected an absolute expression after comma");
4217 return false;
4218 }
4219 }
4220
4221 // If this is not the end of the statement, report an error.
4222 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4223 reportParseError("unexpected token, expected end of statement");
4224 return false;
4225 }
4226
4227 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4228
4229 getTargetStreamer().emitDirectiveEnt(*Sym);
4230 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004231 return false;
4232 }
4233
Jack Carter07c818d2013-01-25 01:31:34 +00004234 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004235 StringRef SymbolName;
4236
4237 if (Parser.parseIdentifier(SymbolName)) {
4238 reportParseError("expected identifier after .end");
4239 return false;
4240 }
4241
4242 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4243 reportParseError("unexpected token, expected end of statement");
4244 return false;
4245 }
4246
4247 if (CurrentFn == nullptr) {
4248 reportParseError(".end used without .ent");
4249 return false;
4250 }
4251
4252 if ((SymbolName != CurrentFn->getName())) {
4253 reportParseError(".end symbol does not match .ent symbol");
4254 return false;
4255 }
4256
4257 getTargetStreamer().emitDirectiveEnd(SymbolName);
4258 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004259 return false;
4260 }
4261
Jack Carter07c818d2013-01-25 01:31:34 +00004262 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004263 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4264 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004265 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004266 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4267 reportParseError("expected stack register");
4268 return false;
4269 }
4270
4271 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4272 if (!StackRegOpnd.isGPRAsmReg()) {
4273 reportParseError(StackRegOpnd.getStartLoc(),
4274 "expected general purpose register");
4275 return false;
4276 }
4277 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4278
4279 if (Parser.getTok().is(AsmToken::Comma))
4280 Parser.Lex();
4281 else {
4282 reportParseError("unexpected token, expected comma");
4283 return false;
4284 }
4285
4286 // Parse the frame size.
4287 const MCExpr *FrameSize;
4288 int64_t FrameSizeVal;
4289
4290 if (Parser.parseExpression(FrameSize)) {
4291 reportParseError("expected frame size value");
4292 return false;
4293 }
4294
4295 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4296 reportParseError("frame size not an absolute expression");
4297 return false;
4298 }
4299
4300 if (Parser.getTok().is(AsmToken::Comma))
4301 Parser.Lex();
4302 else {
4303 reportParseError("unexpected token, expected comma");
4304 return false;
4305 }
4306
4307 // Parse the return register.
4308 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004309 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004310 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4311 reportParseError("expected return register");
4312 return false;
4313 }
4314
4315 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4316 if (!ReturnRegOpnd.isGPRAsmReg()) {
4317 reportParseError(ReturnRegOpnd.getStartLoc(),
4318 "expected general purpose register");
4319 return false;
4320 }
4321
4322 // If this is not the end of the statement, report an error.
4323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4324 reportParseError("unexpected token, expected end of statement");
4325 return false;
4326 }
4327
4328 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4329 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004330 return false;
4331 }
4332
Jack Carter07c818d2013-01-25 01:31:34 +00004333 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004334 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004335 }
4336
Daniel Sandersd97a6342014-08-13 10:07:34 +00004337 if (IDVal == ".mask" || IDVal == ".fmask") {
4338 // .mask bitmask, frame_offset
4339 // bitmask: One bit for each register used.
4340 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4341 // first register is expected to be saved.
4342 // Examples:
4343 // .mask 0x80000000, -4
4344 // .fmask 0x80000000, -4
4345 //
Jack Carterbe332172012-09-07 00:48:02 +00004346
Daniel Sandersd97a6342014-08-13 10:07:34 +00004347 // Parse the bitmask
4348 const MCExpr *BitMask;
4349 int64_t BitMaskVal;
4350
4351 if (Parser.parseExpression(BitMask)) {
4352 reportParseError("expected bitmask value");
4353 return false;
4354 }
4355
4356 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4357 reportParseError("bitmask not an absolute expression");
4358 return false;
4359 }
4360
4361 if (Parser.getTok().is(AsmToken::Comma))
4362 Parser.Lex();
4363 else {
4364 reportParseError("unexpected token, expected comma");
4365 return false;
4366 }
4367
4368 // Parse the frame_offset
4369 const MCExpr *FrameOffset;
4370 int64_t FrameOffsetVal;
4371
4372 if (Parser.parseExpression(FrameOffset)) {
4373 reportParseError("expected frame offset value");
4374 return false;
4375 }
4376
4377 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4378 reportParseError("frame offset not an absolute expression");
4379 return false;
4380 }
4381
4382 // If this is not the end of the statement, report an error.
4383 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4384 reportParseError("unexpected token, expected end of statement");
4385 return false;
4386 }
4387
4388 if (IDVal == ".mask")
4389 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4390 else
4391 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004392 return false;
4393 }
4394
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004395 if (IDVal == ".nan")
4396 return parseDirectiveNaN();
4397
Jack Carter07c818d2013-01-25 01:31:34 +00004398 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004399 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004400 return false;
4401 }
4402
Rafael Espindolab59fb732014-03-28 18:50:26 +00004403 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004404 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004405 return false;
4406 }
4407
Jack Carter07c818d2013-01-25 01:31:34 +00004408 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004409 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004410 return false;
4411 }
4412
Jack Carter0cd3c192014-01-06 23:27:31 +00004413 if (IDVal == ".option")
4414 return parseDirectiveOption();
4415
4416 if (IDVal == ".abicalls") {
4417 getTargetStreamer().emitDirectiveAbiCalls();
4418 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004419 Error(Parser.getTok().getLoc(),
4420 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004421 // Clear line
4422 Parser.eatToEndOfStatement();
4423 }
4424 return false;
4425 }
4426
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004427 if (IDVal == ".cpsetup")
4428 return parseDirectiveCPSetup();
4429
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004430 if (IDVal == ".module")
4431 return parseDirectiveModule();
4432
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004433 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4434 return parseInternalDirectiveReallowModule();
4435
Rafael Espindola870c4e92012-01-11 03:56:41 +00004436 return true;
4437}
4438
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004439bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4440 // If this is not the end of the statement, report an error.
4441 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4442 reportParseError("unexpected token, expected end of statement");
4443 return false;
4444 }
4445
4446 getTargetStreamer().reallowModuleDirective();
4447
4448 getParser().Lex(); // Eat EndOfStatement token.
4449 return false;
4450}
4451
Rafael Espindola870c4e92012-01-11 03:56:41 +00004452extern "C" void LLVMInitializeMipsAsmParser() {
4453 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4454 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4455 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4456 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4457}
Jack Carterb4dbc172012-09-05 23:34:03 +00004458
4459#define GET_REGISTER_MATCHER
4460#define GET_MATCHER_IMPLEMENTATION
4461#include "MipsGenAsmMatcher.inc"