blob: a00e57953f96f4be2304d30d49a50b109e36eea2 [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
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000017#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000020#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCParser/MCAsmLexer.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000026#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000027#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000028#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000029#include "llvm/Support/TargetRegistry.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000031#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000032
33using namespace llvm;
34
Chandler Carruthe96dd892014-04-21 22:55:11 +000035#define DEBUG_TYPE "mips-asm-parser"
36
Joey Gouly0e76fa72013-09-12 10:28:05 +000037namespace llvm {
38class MCInstrInfo;
39}
40
Rafael Espindola870c4e92012-01-11 03:56:41 +000041namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000042class MipsAssemblerOptions {
43public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000044 MipsAssemblerOptions(uint64_t Features_) :
45 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000046
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48 ATReg = Opts->getATRegNum();
49 Reorder = Opts->isReorder();
50 Macro = Opts->isMacro();
51 Features = Opts->getFeatures();
52 }
53
54 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000055 bool setATReg(unsigned Reg);
56
Toma Tabacu9db22db2014-09-09 10:15:38 +000057 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000058 void setReorder() { Reorder = true; }
59 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000060
Toma Tabacu9db22db2014-09-09 10:15:38 +000061 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000062 void setMacro() { Macro = true; }
63 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 uint64_t getFeatures() const { return Features; }
66 void setFeatures(uint64_t Features_) { Features = Features_; }
67
Daniel Sandersf0df2212014-08-04 12:20:00 +000068 // Set of features that are either architecture features or referenced
69 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71 // The reason we need this mask is explained in the selectArch function.
72 // FIXME: Ideally we would like TableGen to generate this information.
73 static const uint64_t AllArchRelatedMask =
74 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81
Jack Carter0b744b32012-10-04 02:29:46 +000082private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000083 unsigned ATReg;
84 bool Reorder;
85 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000086 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000087};
88}
89
90namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000091class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000092 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +000093 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 return static_cast<MipsTargetStreamer &>(TS);
95 }
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 MCSubtargetInfo &STI;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Daniel Sandersef638fe2014-10-03 15:37:37 +0000104 // Print a warning along with its fix-it message at the given range.
105 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
106 SMRange Range, bool ShowColors = true);
107
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000108#define GET_ASSEMBLER_HEADER
109#include "MipsGenAsmMatcher.inc"
110
Matheus Almeida595fcab2014-06-11 15:05:56 +0000111 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
112
Chad Rosier49963552012-10-13 00:26:04 +0000113 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000114 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000115 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000116 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000117
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000119 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000120
Toma Tabacu13964452014-09-04 13:23:44 +0000121 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000122
Toma Tabacu13964452014-09-04 13:23:44 +0000123 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000124
David Blaikie960ea3f2014-06-08 16:18:35 +0000125 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
126 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Craig Topper56c590a2014-04-29 07:58:02 +0000128 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000135
Jack Carter873c7242013-01-12 01:03:14 +0000136 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000137 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000149 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000150 parseRegisterPair (OperandVector &Operands);
151
152 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000153 parseRegisterList (OperandVector &Operands);
154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 bool searchSymbolAlias(OperandVector &Operands);
156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000158
Jack Carter30a59822012-10-04 04:03:53 +0000159 bool needsExpansion(MCInst &Inst);
160
Matheus Almeida3813d572014-06-19 14:39:14 +0000161 // Expands assembly pseudo instructions.
162 // Returns false on success, true otherwise.
163 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000164 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000165
166 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000167 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000168
169 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
172 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000173 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000174
Toma Tabacu0d64b202014-08-14 10:29:17 +0000175 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
176 SmallVectorImpl<MCInst> &Instructions);
177
Jack Carter9e65aa32013-03-22 00:05:30 +0000178 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000179 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
180 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000181 bool reportParseError(Twine ErrorMsg);
182 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000183
Jack Carterb5cf5902013-04-17 00:18:04 +0000184 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000185 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000186
Vladimir Medic4c299852013-11-06 11:27:05 +0000187 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000188
189 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000190 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000191 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000192 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000193 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000194 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000195 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000196 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000197 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000198
199 bool parseSetAtDirective();
200 bool parseSetNoAtDirective();
201 bool parseSetMacroDirective();
202 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000203 bool parseSetMsaDirective();
204 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000205 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000206 bool parseSetReorderDirective();
207 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000208 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000209 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000210 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000211 bool parseSetPopDirective();
212 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000213
Jack Carterd76b2372013-03-21 21:44:16 +0000214 bool parseSetAssignment();
215
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000216 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000217 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000218 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000219 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000220 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000221 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
222 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000223
Jack Carterdc1e35d2012-09-06 20:00:02 +0000224 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000225
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000226 bool eatComma(StringRef ErrorStr);
227
Jack Carter1ac53222013-02-20 23:11:17 +0000228 int matchCPURegisterName(StringRef Symbol);
229
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000230 int matchHWRegsRegisterName(StringRef Symbol);
231
Jack Carter873c7242013-01-12 01:03:14 +0000232 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000233
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000234 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000235
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000236 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000237
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000238 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000239
Jack Carter5dc8ac92013-09-25 23:50:44 +0000240 int matchMSA128RegisterName(StringRef Name);
241
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000242 int matchMSA128CtrlRegisterName(StringRef Name);
243
Jack Carterd0bd6422013-04-18 00:41:53 +0000244 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000245
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000246 unsigned getGPR(int RegNo);
247
Matheus Almeida7de68e72014-06-18 14:46:05 +0000248 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000249
250 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000252
253 // Helper function that checks if the value of a vector index is within the
254 // boundaries of accepted values for each RegisterKind
255 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
256 bool validateMSAIndex(int Val, int RegKind);
257
Daniel Sandersf0df2212014-08-04 12:20:00 +0000258 // Selects a new architecture by updating the FeatureBits with the necessary
259 // info including implied dependencies.
260 // Internally, it clears all the feature bits related to *any* architecture
261 // and selects the new one using the ToggleFeature functionality of the
262 // MCSubtargetInfo object that handles implied dependencies. The reason we
263 // clear all the arch related bits manually is because ToggleFeature only
264 // clears the features that imply the feature being cleared and not the
265 // features implied by the feature being cleared. This is easier to see
266 // with an example:
267 // --------------------------------------------------
268 // | Feature | Implies |
269 // | -------------------------------------------------|
270 // | FeatureMips1 | None |
271 // | FeatureMips2 | FeatureMips1 |
272 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
273 // | FeatureMips4 | FeatureMips3 |
274 // | ... | |
275 // --------------------------------------------------
276 //
277 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
278 // FeatureMipsGP64 | FeatureMips1)
279 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
280 void selectArch(StringRef ArchFeature) {
281 uint64_t FeatureBits = STI.getFeatureBits();
282 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
283 STI.setFeatureBits(FeatureBits);
284 setAvailableFeatures(
285 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000286 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000287 }
288
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000289 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000291 setAvailableFeatures(
292 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000293 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000294 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
296
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000297 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000298 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000299 setAvailableFeatures(
300 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000301 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000302 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000303 }
304
Rafael Espindola870c4e92012-01-11 03:56:41 +0000305public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000306 enum MipsMatchResultTy {
307 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
308#define GET_OPERAND_DIAGNOSTIC_TYPES
309#include "MipsGenAsmMatcher.inc"
310#undef GET_OPERAND_DIAGNOSTIC_TYPES
311
312 };
313
Joey Gouly0e76fa72013-09-12 10:28:05 +0000314 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000315 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000316 : MCTargetAsmParser(), STI(sti) {
317 MCAsmParserExtension::Initialize(parser);
318
Jack Carterb4dbc172012-09-05 23:34:03 +0000319 // Initialize the set of available features.
320 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000321
322 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000323 AssemblerOptions.push_back(
324 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325
326 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000327 AssemblerOptions.push_back(
328 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000329
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000330 getTargetStreamer().updateABIInfo(*this);
331
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000332 // Assert exactly one ABI was chosen.
333 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
334 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
335 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
336 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000337
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000338 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000339 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000340
341 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000342 }
343
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000344 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
345 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
348 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
349 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
350 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
351 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000352 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000353
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000354 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000355 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
356 }
357
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000358 bool inMicroMipsMode() const {
359 return STI.getFeatureBits() & Mips::FeatureMicroMips;
360 }
361 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
362 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
363 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
364 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
365 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
366 bool hasMips32() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips32);
368 }
369 bool hasMips64() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips64);
371 }
372 bool hasMips32r2() const {
373 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
374 }
375 bool hasMips64r2() const {
376 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
377 }
378 bool hasMips32r6() const {
379 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
380 }
381 bool hasMips64r6() const {
382 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
383 }
384 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
385 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
386 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
387
388 bool inMips16Mode() const {
389 return STI.getFeatureBits() & Mips::FeatureMips16;
390 }
391 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000392 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000393
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000394 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000395 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000396};
397}
398
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000399namespace {
400
401/// MipsOperand - Instances of this class represent a parsed Mips machine
402/// instruction.
403class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000404public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000405 /// Broad categories of register classes
406 /// The exact class is finalized by the render method.
407 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000408 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000409 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000411 RegKind_FCC = 4, /// FCC
412 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
413 RegKind_MSACtrl = 16, /// MSA control registers
414 RegKind_COP2 = 32, /// COP2
415 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
416 /// context).
417 RegKind_CCR = 128, /// CCR
418 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000419 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000420
421 /// Potentially any (e.g. $1)
422 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
423 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000424 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000425 };
426
427private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000428 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000429 k_Immediate, /// An immediate (possibly involving symbol references)
430 k_Memory, /// Base + Offset Memory Address
431 k_PhysRegister, /// A physical register from the Mips namespace
432 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000433 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000434 k_RegList, /// A physical register list
435 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000436 } Kind;
437
David Blaikie960ea3f2014-06-08 16:18:35 +0000438public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000439 MipsOperand(KindTy K, MipsAsmParser &Parser)
440 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
441
David Blaikie960ea3f2014-06-08 16:18:35 +0000442private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 /// For diagnostics, and checking the assembler temporary
444 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000445
Eric Christopher8996c5d2013-03-15 00:42:55 +0000446 struct Token {
447 const char *Data;
448 unsigned Length;
449 };
450
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000451 struct PhysRegOp {
452 unsigned Num; /// Register Number
453 };
454
455 struct RegIdxOp {
456 unsigned Index; /// Index into the register class
457 RegKind Kind; /// Bitfield of the kinds it could possibly be
458 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000459 };
460
461 struct ImmOp {
462 const MCExpr *Val;
463 };
464
465 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000467 const MCExpr *Off;
468 };
469
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000470 struct RegListOp {
471 SmallVector<unsigned, 10> *List;
472 };
473
Jack Carterb4dbc172012-09-05 23:34:03 +0000474 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000475 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000476 struct PhysRegOp PhysReg;
477 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000478 struct ImmOp Imm;
479 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000480 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000481 };
482
483 SMLoc StartLoc, EndLoc;
484
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000485 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000486 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
487 const MCRegisterInfo *RegInfo,
488 SMLoc S, SMLoc E,
489 MipsAsmParser &Parser) {
490 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 Op->RegIdx.Index = Index;
492 Op->RegIdx.RegInfo = RegInfo;
493 Op->RegIdx.Kind = RegKind;
494 Op->StartLoc = S;
495 Op->EndLoc = E;
496 return Op;
497 }
498
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000499public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000500 /// Coerce the register to GPR32 and return the real register for the current
501 /// target.
502 unsigned getGPR32Reg() const {
503 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000504 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 unsigned ClassID = Mips::GPR32RegClassID;
506 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000507 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000508
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000509 /// Coerce the register to GPR32 and return the real register for the current
510 /// target.
511 unsigned getGPRMM16Reg() const {
512 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
513 unsigned ClassID = Mips::GPR32RegClassID;
514 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
515 }
516
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 /// Coerce the register to GPR64 and return the real register for the current
518 /// target.
519 unsigned getGPR64Reg() const {
520 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
521 unsigned ClassID = Mips::GPR64RegClassID;
522 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000523 }
524
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000525private:
526 /// Coerce the register to AFGR64 and return the real register for the current
527 /// target.
528 unsigned getAFGR64Reg() const {
529 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
530 if (RegIdx.Index % 2 != 0)
531 AsmParser.Warning(StartLoc, "Float register should be even.");
532 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
533 .getRegister(RegIdx.Index / 2);
534 }
535
536 /// Coerce the register to FGR64 and return the real register for the current
537 /// target.
538 unsigned getFGR64Reg() const {
539 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
540 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
541 .getRegister(RegIdx.Index);
542 }
543
544 /// Coerce the register to FGR32 and return the real register for the current
545 /// target.
546 unsigned getFGR32Reg() const {
547 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
548 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
549 .getRegister(RegIdx.Index);
550 }
551
552 /// Coerce the register to FGRH32 and return the real register for the current
553 /// target.
554 unsigned getFGRH32Reg() const {
555 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
556 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
557 .getRegister(RegIdx.Index);
558 }
559
560 /// Coerce the register to FCC and return the real register for the current
561 /// target.
562 unsigned getFCCReg() const {
563 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
564 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
565 .getRegister(RegIdx.Index);
566 }
567
568 /// Coerce the register to MSA128 and return the real register for the current
569 /// target.
570 unsigned getMSA128Reg() const {
571 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
572 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
573 // identical
574 unsigned ClassID = Mips::MSA128BRegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
576 }
577
578 /// Coerce the register to MSACtrl and return the real register for the
579 /// current target.
580 unsigned getMSACtrlReg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
582 unsigned ClassID = Mips::MSACtrlRegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584 }
585
586 /// Coerce the register to COP2 and return the real register for the
587 /// current target.
588 unsigned getCOP2Reg() const {
589 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
590 unsigned ClassID = Mips::COP2RegClassID;
591 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
592 }
593
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000594 /// Coerce the register to COP3 and return the real register for the
595 /// current target.
596 unsigned getCOP3Reg() const {
597 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
598 unsigned ClassID = Mips::COP3RegClassID;
599 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
600 }
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// Coerce the register to ACC64DSP and return the real register for the
603 /// current target.
604 unsigned getACC64DSPReg() const {
605 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
606 unsigned ClassID = Mips::ACC64DSPRegClassID;
607 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
608 }
609
610 /// Coerce the register to HI32DSP and return the real register for the
611 /// current target.
612 unsigned getHI32DSPReg() const {
613 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
614 unsigned ClassID = Mips::HI32DSPRegClassID;
615 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
616 }
617
618 /// Coerce the register to LO32DSP and return the real register for the
619 /// current target.
620 unsigned getLO32DSPReg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
622 unsigned ClassID = Mips::LO32DSPRegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
624 }
625
626 /// Coerce the register to CCR and return the real register for the
627 /// current target.
628 unsigned getCCRReg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
630 unsigned ClassID = Mips::CCRRegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
634 /// Coerce the register to HWRegs and return the real register for the
635 /// current target.
636 unsigned getHWRegsReg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
638 unsigned ClassID = Mips::HWRegsRegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
640 }
641
642public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000643 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000644 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000645 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 Inst.addOperand(MCOperand::CreateImm(0));
647 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
648 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
649 else
650 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000651 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000652
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 void addRegOperands(MCInst &Inst, unsigned N) const {
654 llvm_unreachable("Use a custom parser instead");
655 }
656
Daniel Sanders21bce302014-04-01 12:35:23 +0000657 /// Render the operand to an MCInst as a GPR32
658 /// Asserts if the wrong number of operands are requested, or the operand
659 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000660 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
661 assert(N == 1 && "Invalid number of operands!");
662 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
663 }
664
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000665 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
666 assert(N == 1 && "Invalid number of operands!");
667 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
668 }
669
Jozef Kolek1904fa22014-11-24 14:25:53 +0000670 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
673 }
674
Daniel Sanders21bce302014-04-01 12:35:23 +0000675 /// Render the operand to an MCInst as a GPR64
676 /// Asserts if the wrong number of operands are requested, or the operand
677 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
679 assert(N == 1 && "Invalid number of operands!");
680 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
681 }
682
683 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
684 assert(N == 1 && "Invalid number of operands!");
685 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
686 }
687
688 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
689 assert(N == 1 && "Invalid number of operands!");
690 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
691 }
692
693 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
694 assert(N == 1 && "Invalid number of operands!");
695 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000696 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000697 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000698 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
699 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 }
701
702 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
703 assert(N == 1 && "Invalid number of operands!");
704 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
705 }
706
707 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
708 assert(N == 1 && "Invalid number of operands!");
709 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
710 }
711
712 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
713 assert(N == 1 && "Invalid number of operands!");
714 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
715 }
716
717 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
718 assert(N == 1 && "Invalid number of operands!");
719 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
720 }
721
722 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
724 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
725 }
726
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000727 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
728 assert(N == 1 && "Invalid number of operands!");
729 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
730 }
731
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
733 assert(N == 1 && "Invalid number of operands!");
734 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
735 }
736
737 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
738 assert(N == 1 && "Invalid number of operands!");
739 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
740 }
741
742 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
743 assert(N == 1 && "Invalid number of operands!");
744 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
745 }
746
747 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
748 assert(N == 1 && "Invalid number of operands!");
749 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
750 }
751
752 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
754 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
755 }
756
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000758 assert(N == 1 && "Invalid number of operands!");
759 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000760 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000761 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000762
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000763 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000764 assert(N == 2 && "Invalid number of operands!");
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000767
768 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000769 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000770 }
771
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000772 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 2 && "Invalid number of operands!");
774
775 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
776
777 const MCExpr *Expr = getMemOff();
778 addExpr(Inst, Expr);
779 }
780
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000781 void addRegListOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
783
784 for (auto RegNo : getRegList())
785 Inst.addOperand(MCOperand::CreateReg(RegNo));
786 }
787
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000788 void addRegPairOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 2 && "Invalid number of operands!");
790 unsigned RegNo = getRegPair();
791 Inst.addOperand(MCOperand::CreateReg(RegNo++));
792 Inst.addOperand(MCOperand::CreateReg(RegNo));
793 }
794
Craig Topper56c590a2014-04-29 07:58:02 +0000795 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 // As a special case until we sort out the definition of div/divu, pretend
797 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
798 if (isGPRAsmReg() && RegIdx.Index == 0)
799 return true;
800
801 return Kind == k_PhysRegister;
802 }
803 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000804 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 bool isConstantImm() const {
806 return isImm() && dyn_cast<MCConstantExpr>(getImm());
807 }
Craig Topper56c590a2014-04-29 07:58:02 +0000808 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 // Note: It's not possible to pretend that other operand kinds are tokens.
810 // The matcher emitter checks tokens first.
811 return Kind == k_Token;
812 }
Craig Topper56c590a2014-04-29 07:58:02 +0000813 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000814 bool isConstantMemOff() const {
815 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
816 }
817 template <unsigned Bits> bool isMemWithSimmOffset() const {
818 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
819 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000820 bool isMemWithGRPMM16Base() const {
821 return isMem() && getMemBase()->isMM16AsmReg();
822 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000823 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
824 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
825 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
826 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000827 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
828 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
829 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
830 && (getMemBase()->getGPR32Reg() == Mips::SP);
831 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000832 bool isRegList16() const {
833 if (!isRegList())
834 return false;
835
836 int Size = RegList.List->size();
837 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
838 RegList.List->back() != Mips::RA)
839 return false;
840
841 int PrevReg = *RegList.List->begin();
842 for (int i = 1; i < Size - 1; i++) {
843 int Reg = (*(RegList.List))[i];
844 if ( Reg != PrevReg + 1)
845 return false;
846 PrevReg = Reg;
847 }
848
849 return true;
850 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000851 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000852 bool isLSAImm() const {
853 if (!isConstantImm())
854 return false;
855 int64_t Val = getConstantImm();
856 return 1 <= Val && Val <= 4;
857 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000858 bool isRegList() const { return Kind == k_RegList; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000859
860 StringRef getToken() const {
861 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000862 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000863 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000864 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000865
Craig Topper56c590a2014-04-29 07:58:02 +0000866 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 // As a special case until we sort out the definition of div/divu, pretend
868 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
869 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
870 RegIdx.Kind & RegKind_GPR)
871 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000872
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 assert(Kind == k_PhysRegister && "Invalid access!");
874 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000875 }
876
Jack Carterb4dbc172012-09-05 23:34:03 +0000877 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000879 return Imm.Val;
880 }
881
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 int64_t getConstantImm() const {
883 const MCExpr *Val = getImm();
884 return static_cast<const MCConstantExpr *>(Val)->getValue();
885 }
886
887 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000888 assert((Kind == k_Memory) && "Invalid access!");
889 return Mem.Base;
890 }
891
892 const MCExpr *getMemOff() const {
893 assert((Kind == k_Memory) && "Invalid access!");
894 return Mem.Off;
895 }
896
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000897 int64_t getConstantMemOff() const {
898 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
899 }
900
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 const SmallVectorImpl<unsigned> &getRegList() const {
902 assert((Kind == k_RegList) && "Invalid access!");
903 return *(RegList.List);
904 }
905
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000906 unsigned getRegPair() const {
907 assert((Kind == k_RegPair) && "Invalid access!");
908 return RegIdx.Index;
909 }
910
David Blaikie960ea3f2014-06-08 16:18:35 +0000911 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
912 MipsAsmParser &Parser) {
913 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000914 Op->Tok.Data = Str.data();
915 Op->Tok.Length = Str.size();
916 Op->StartLoc = S;
917 Op->EndLoc = S;
918 return Op;
919 }
920
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 /// Create a numeric register (e.g. $1). The exact register remains
922 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000923 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000924 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000925 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000926 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000928 }
929
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 /// Create a register that is definitely a GPR.
931 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000932 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000933 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000934 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000936 }
937
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 /// Create a register that is definitely a FGR.
939 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000940 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000941 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000942 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000943 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
944 }
945
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000946 /// Create a register that is definitely a HWReg.
947 /// This is typically only used for named registers such as $hwr_cpunum.
948 static std::unique_ptr<MipsOperand>
949 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
950 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
951 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
952 }
953
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000954 /// Create a register that is definitely an FCC.
955 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000956 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000957 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000958 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
960 }
961
962 /// Create a register that is definitely an ACC.
963 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000964 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000965 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000966 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000967 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
968 }
969
970 /// Create a register that is definitely an MSA128.
971 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000972 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000973 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000974 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
976 }
977
978 /// Create a register that is definitely an MSACtrl.
979 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000980 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000981 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000982 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000983 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
984 }
985
David Blaikie960ea3f2014-06-08 16:18:35 +0000986 static std::unique_ptr<MipsOperand>
987 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
988 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000989 Op->Imm.Val = Val;
990 Op->StartLoc = S;
991 Op->EndLoc = E;
992 return Op;
993 }
994
David Blaikie960ea3f2014-06-08 16:18:35 +0000995 static std::unique_ptr<MipsOperand>
996 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
997 SMLoc E, MipsAsmParser &Parser) {
998 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
999 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001000 Op->Mem.Off = Off;
1001 Op->StartLoc = S;
1002 Op->EndLoc = E;
1003 return Op;
1004 }
1005
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001006 static std::unique_ptr<MipsOperand>
1007 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1008 MipsAsmParser &Parser) {
1009 assert (Regs.size() > 0 && "Empty list not allowed");
1010
1011 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1012 Op->RegList.List = new SmallVector<unsigned, 10>();
1013 for (auto Reg : Regs)
1014 Op->RegList.List->push_back(Reg);
1015 Op->StartLoc = StartLoc;
1016 Op->EndLoc = EndLoc;
1017 return Op;
1018 }
1019
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001020 static std::unique_ptr<MipsOperand>
1021 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1022 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1023 Op->RegIdx.Index = RegNo;
1024 Op->StartLoc = S;
1025 Op->EndLoc = E;
1026 return Op;
1027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 bool isGPRAsmReg() const {
1030 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001031 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001032 bool isMM16AsmReg() const {
1033 if (!(isRegIdx() && RegIdx.Kind))
1034 return false;
1035 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1036 || RegIdx.Index == 16 || RegIdx.Index == 17);
1037 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001038 bool isMM16AsmRegZero() const {
1039 if (!(isRegIdx() && RegIdx.Kind))
1040 return false;
1041 return (RegIdx.Index == 0 ||
1042 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1043 RegIdx.Index == 17);
1044 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 bool isFGRAsmReg() const {
1046 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1047 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001048 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 bool isHWRegsAsmReg() const {
1050 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001051 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 bool isCCRAsmReg() const {
1053 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001054 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001056 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1057 return false;
1058 if (!AsmParser.hasEightFccRegisters())
1059 return RegIdx.Index == 0;
1060 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001061 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 bool isACCAsmReg() const {
1063 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001064 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 bool isCOP2AsmReg() const {
1066 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001067 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001068 bool isCOP3AsmReg() const {
1069 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1070 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 bool isMSA128AsmReg() const {
1072 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001073 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 bool isMSACtrlAsmReg() const {
1075 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001076 }
1077
Jack Carterb4dbc172012-09-05 23:34:03 +00001078 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001079 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001080 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001081 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001082
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001083 virtual ~MipsOperand() {
1084 switch (Kind) {
1085 case k_Immediate:
1086 break;
1087 case k_Memory:
1088 delete Mem.Base;
1089 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001090 case k_RegList:
1091 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001092 case k_PhysRegister:
1093 case k_RegisterIndex:
1094 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001095 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001096 break;
1097 }
1098 }
1099
Craig Topper56c590a2014-04-29 07:58:02 +00001100 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 switch (Kind) {
1102 case k_Immediate:
1103 OS << "Imm<";
1104 Imm.Val->print(OS);
1105 OS << ">";
1106 break;
1107 case k_Memory:
1108 OS << "Mem<";
1109 Mem.Base->print(OS);
1110 OS << ", ";
1111 Mem.Off->print(OS);
1112 OS << ">";
1113 break;
1114 case k_PhysRegister:
1115 OS << "PhysReg<" << PhysReg.Num << ">";
1116 break;
1117 case k_RegisterIndex:
1118 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1119 break;
1120 case k_Token:
1121 OS << Tok.Data;
1122 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001123 case k_RegList:
1124 OS << "RegList< ";
1125 for (auto Reg : (*RegList.List))
1126 OS << Reg << " ";
1127 OS << ">";
1128 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001129 case k_RegPair:
1130 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1131 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001133 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001134}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001135} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001136
Jack Carter9e65aa32013-03-22 00:05:30 +00001137namespace llvm {
1138extern const MCInstrDesc MipsInsts[];
1139}
1140static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1141 return MipsInsts[Opcode];
1142}
1143
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001144static bool hasShortDelaySlot(unsigned Opcode) {
1145 switch (Opcode) {
1146 case Mips::JALS_MM:
1147 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001148 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001149 case Mips::BGEZALS_MM:
1150 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001151 return true;
1152 default:
1153 return false;
1154 }
1155}
1156
Jack Carter9e65aa32013-03-22 00:05:30 +00001157bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001158 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001159 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001160
Jack Carter9e65aa32013-03-22 00:05:30 +00001161 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001162
1163 if (MCID.isBranch() || MCID.isCall()) {
1164 const unsigned Opcode = Inst.getOpcode();
1165 MCOperand Offset;
1166
1167 switch (Opcode) {
1168 default:
1169 break;
1170 case Mips::BEQ:
1171 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001172 case Mips::BEQ_MM:
1173 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001174 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001175 Offset = Inst.getOperand(2);
1176 if (!Offset.isImm())
1177 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001178 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001179 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001180 if (OffsetToAlignment(Offset.getImm(),
1181 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001182 return Error(IDLoc, "branch to misaligned address");
1183 break;
1184 case Mips::BGEZ:
1185 case Mips::BGTZ:
1186 case Mips::BLEZ:
1187 case Mips::BLTZ:
1188 case Mips::BGEZAL:
1189 case Mips::BLTZAL:
1190 case Mips::BC1F:
1191 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 case Mips::BGEZ_MM:
1193 case Mips::BGTZ_MM:
1194 case Mips::BLEZ_MM:
1195 case Mips::BLTZ_MM:
1196 case Mips::BGEZAL_MM:
1197 case Mips::BLTZAL_MM:
1198 case Mips::BC1F_MM:
1199 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001200 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001201 Offset = Inst.getOperand(1);
1202 if (!Offset.isImm())
1203 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001204 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001205 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001206 if (OffsetToAlignment(Offset.getImm(),
1207 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001208 return Error(IDLoc, "branch to misaligned address");
1209 break;
1210 }
1211 }
1212
Daniel Sandersa84989a2014-06-16 13:25:35 +00001213 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1214 // We still accept it but it is a normal nop.
1215 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1216 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1217 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1218 "nop instruction");
1219 }
1220
Toma Tabacu9db22db2014-09-09 10:15:38 +00001221 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001222 // If this instruction has a delay slot and .set reorder is active,
1223 // emit a NOP after it.
1224 Instructions.push_back(Inst);
1225 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001226 if (hasShortDelaySlot(Inst.getOpcode())) {
1227 NopInst.setOpcode(Mips::MOVE16_MM);
1228 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1229 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1230 } else {
1231 NopInst.setOpcode(Mips::SLL);
1232 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1233 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1234 NopInst.addOperand(MCOperand::CreateImm(0));
1235 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001236 Instructions.push_back(NopInst);
1237 return false;
1238 }
1239
Jack Carter9e65aa32013-03-22 00:05:30 +00001240 if (MCID.mayLoad() || MCID.mayStore()) {
1241 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001242 // reference or immediate we may have to expand instructions.
1243 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001244 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001245 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1246 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001247 MCOperand &Op = Inst.getOperand(i);
1248 if (Op.isImm()) {
1249 int MemOffset = Op.getImm();
1250 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001251 // Offset can't exceed 16bit value.
1252 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001253 return false;
1254 }
1255 } else if (Op.isExpr()) {
1256 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001257 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001258 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001259 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001260 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 // Expand symbol.
1262 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001263 return false;
1264 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001265 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001266 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001267 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001268 }
1269 }
1270 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001271 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001272 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001273
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001274 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1275 if (inMicroMipsMode()) {
1276 MCOperand Opnd;
1277 int Imm;
1278
1279 switch (Inst.getOpcode()) {
1280 default:
1281 break;
1282 case Mips::ADDIUS5_MM:
1283 Opnd = Inst.getOperand(2);
1284 if (!Opnd.isImm())
1285 return Error(IDLoc, "expected immediate operand kind");
1286 Imm = Opnd.getImm();
1287 if (Imm < -8 || Imm > 7)
1288 return Error(IDLoc, "immediate operand value out of range");
1289 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001290 case Mips::ADDIUSP_MM:
1291 Opnd = Inst.getOperand(0);
1292 if (!Opnd.isImm())
1293 return Error(IDLoc, "expected immediate operand kind");
1294 Imm = Opnd.getImm();
1295 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1296 Imm % 4 != 0)
1297 return Error(IDLoc, "immediate operand value out of range");
1298 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001299 case Mips::SLL16_MM:
1300 case Mips::SRL16_MM:
1301 Opnd = Inst.getOperand(2);
1302 if (!Opnd.isImm())
1303 return Error(IDLoc, "expected immediate operand kind");
1304 Imm = Opnd.getImm();
1305 if (Imm < 1 || Imm > 8)
1306 return Error(IDLoc, "immediate operand value out of range");
1307 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001308 case Mips::LI16_MM:
1309 Opnd = Inst.getOperand(1);
1310 if (!Opnd.isImm())
1311 return Error(IDLoc, "expected immediate operand kind");
1312 Imm = Opnd.getImm();
1313 if (Imm < -1 || Imm > 126)
1314 return Error(IDLoc, "immediate operand value out of range");
1315 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001316 case Mips::ADDIUR2_MM:
1317 Opnd = Inst.getOperand(2);
1318 if (!Opnd.isImm())
1319 return Error(IDLoc, "expected immediate operand kind");
1320 Imm = Opnd.getImm();
1321 if (!(Imm == 1 || Imm == -1 ||
1322 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1323 return Error(IDLoc, "immediate operand value out of range");
1324 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001325 case Mips::ADDIUR1SP_MM:
1326 Opnd = Inst.getOperand(1);
1327 if (!Opnd.isImm())
1328 return Error(IDLoc, "expected immediate operand kind");
1329 Imm = Opnd.getImm();
1330 if (OffsetToAlignment(Imm, 4LL))
1331 return Error(IDLoc, "misaligned immediate operand value");
1332 if (Imm < 0 || Imm > 255)
1333 return Error(IDLoc, "immediate operand value out of range");
1334 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001335 case Mips::ANDI16_MM:
1336 Opnd = Inst.getOperand(2);
1337 if (!Opnd.isImm())
1338 return Error(IDLoc, "expected immediate operand kind");
1339 Imm = Opnd.getImm();
1340 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1341 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1342 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1343 return Error(IDLoc, "immediate operand value out of range");
1344 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001345 case Mips::LBU16_MM:
1346 Opnd = Inst.getOperand(2);
1347 if (!Opnd.isImm())
1348 return Error(IDLoc, "expected immediate operand kind");
1349 Imm = Opnd.getImm();
1350 if (Imm < -1 || Imm > 14)
1351 return Error(IDLoc, "immediate operand value out of range");
1352 break;
1353 case Mips::SB16_MM:
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 > 15)
1359 return Error(IDLoc, "immediate operand value out of range");
1360 break;
1361 case Mips::LHU16_MM:
1362 case Mips::SH16_MM:
1363 Opnd = Inst.getOperand(2);
1364 if (!Opnd.isImm())
1365 return Error(IDLoc, "expected immediate operand kind");
1366 Imm = Opnd.getImm();
1367 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1368 return Error(IDLoc, "immediate operand value out of range");
1369 break;
1370 case Mips::LW16_MM:
1371 case Mips::SW16_MM:
1372 Opnd = Inst.getOperand(2);
1373 if (!Opnd.isImm())
1374 return Error(IDLoc, "expected immediate operand kind");
1375 Imm = Opnd.getImm();
1376 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1377 return Error(IDLoc, "immediate operand value out of range");
1378 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001379 }
1380 }
1381
Jack Carter9e65aa32013-03-22 00:05:30 +00001382 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001383 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001384 else
1385 Instructions.push_back(Inst);
1386
1387 return false;
1388}
1389
Jack Carter30a59822012-10-04 04:03:53 +00001390bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1391
Jack Carterd0bd6422013-04-18 00:41:53 +00001392 switch (Inst.getOpcode()) {
1393 case Mips::LoadImm32Reg:
1394 case Mips::LoadAddr32Imm:
1395 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001396 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 return true;
1398 default:
1399 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001400 }
1401}
Jack Carter92995f12012-10-06 00:53:28 +00001402
Matheus Almeida3813d572014-06-19 14:39:14 +00001403bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001404 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001406 default:
1407 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001408 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 case Mips::LoadImm32Reg:
1410 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001411 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001412 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001413 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001414 return true;
1415 }
1416 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 case Mips::LoadAddr32Imm:
1418 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1419 case Mips::LoadAddr32Reg:
1420 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1421 }
Jack Carter30a59822012-10-04 04:03:53 +00001422}
Jack Carter92995f12012-10-06 00:53:28 +00001423
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001424namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001425template <bool PerformShift>
1426void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001427 SmallVectorImpl<MCInst> &Instructions) {
1428 MCInst tmpInst;
1429 if (PerformShift) {
1430 tmpInst.setOpcode(Mips::DSLL);
1431 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1432 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1433 tmpInst.addOperand(MCOperand::CreateImm(16));
1434 tmpInst.setLoc(IDLoc);
1435 Instructions.push_back(tmpInst);
1436 tmpInst.clear();
1437 }
1438 tmpInst.setOpcode(Mips::ORi);
1439 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1440 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001441 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001442 tmpInst.setLoc(IDLoc);
1443 Instructions.push_back(tmpInst);
1444}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001445
1446template <int Shift, bool PerformShift>
1447void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1448 SmallVectorImpl<MCInst> &Instructions) {
1449 createShiftOr<PerformShift>(
1450 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1451 IDLoc, Instructions);
1452}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001453}
1454
Matheus Almeida3813d572014-06-19 14:39:14 +00001455bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001456 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001457 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001458 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001459 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001460 const MCOperand &RegOp = Inst.getOperand(0);
1461 assert(RegOp.isReg() && "expected register operand kind");
1462
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001463 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001464 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001465 // FIXME: gas has a special case for values that are 000...1111, which
1466 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 if (0 <= ImmValue && ImmValue <= 65535) {
1468 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001469 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001470 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001471 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001472 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001473 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001474 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001475 } else if (ImmValue < 0 && ImmValue >= -32768) {
1476 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001477 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001478 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001479 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001480 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001481 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001482 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001483 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1484 // For any value of j that is representable as a 32-bit integer, create
1485 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001486 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001487 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001488 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001489 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1490 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001491 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001492 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1493 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001494 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001495 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001496 return true;
1497 }
1498
1499 // <------- lo32 ------>
1500 // <------- hi32 ------>
1501 // <- hi16 -> <- lo16 ->
1502 // _________________________________
1503 // | | | |
1504 // | 16-bytes | 16-bytes | 16-bytes |
1505 // |__________|__________|__________|
1506 //
1507 // For any value of j that is representable as a 48-bit integer, create
1508 // a sequence of:
1509 // li d,j => lui d,hi16(j)
1510 // ori d,d,hi16(lo32(j))
1511 // dsll d,d,16
1512 // ori d,d,lo16(lo32(j))
1513 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001514 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001515 tmpInst.addOperand(
1516 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001517 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001518 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1519 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1520 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001521 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001522 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001523 return true;
1524 }
1525
1526 // <------- hi32 ------> <------- lo32 ------>
1527 // <- hi16 -> <- lo16 ->
1528 // ___________________________________________
1529 // | | | | |
1530 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1531 // |__________|__________|__________|__________|
1532 //
1533 // For any value of j that isn't representable as a 48-bit integer.
1534 // li d,j => lui d,hi16(j)
1535 // ori d,d,lo16(hi32(j))
1536 // dsll d,d,16
1537 // ori d,d,hi16(lo32(j))
1538 // dsll d,d,16
1539 // ori d,d,lo16(lo32(j))
1540 tmpInst.setOpcode(Mips::LUi);
1541 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1542 tmpInst.addOperand(
1543 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1544 Instructions.push_back(tmpInst);
1545 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1546 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1547 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001548 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001549 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001550}
Jack Carter92995f12012-10-06 00:53:28 +00001551
Matheus Almeida3813d572014-06-19 14:39:14 +00001552bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001553MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1554 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001555 MCInst tmpInst;
1556 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001557 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1558 "expected immediate operand kind");
1559 if (!ImmOp.isImm()) {
1560 expandLoadAddressSym(Inst, IDLoc, Instructions);
1561 return false;
1562 }
Jack Carter543fdf82012-10-09 23:29:45 +00001563 const MCOperand &SrcRegOp = Inst.getOperand(1);
1564 assert(SrcRegOp.isReg() && "expected register operand kind");
1565 const MCOperand &DstRegOp = Inst.getOperand(0);
1566 assert(DstRegOp.isReg() && "expected register operand kind");
1567 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001568 if (-32768 <= ImmValue && ImmValue <= 65535) {
1569 // For -32768 <= j <= 65535.
1570 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001571 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001572 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1573 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1574 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1575 Instructions.push_back(tmpInst);
1576 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001577 // For any other value of j that is representable as a 32-bit integer.
1578 // la d,j(s) => lui d,hi16(j)
1579 // ori d,d,lo16(j)
1580 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001581 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001582 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1583 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1584 Instructions.push_back(tmpInst);
1585 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001586 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001587 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1588 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1589 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1590 Instructions.push_back(tmpInst);
1591 tmpInst.clear();
1592 tmpInst.setOpcode(Mips::ADDu);
1593 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1594 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1595 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1596 Instructions.push_back(tmpInst);
1597 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001598 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001599}
1600
Matheus Almeida3813d572014-06-19 14:39:14 +00001601bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001602MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1603 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001604 MCInst tmpInst;
1605 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001606 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1607 "expected immediate operand kind");
1608 if (!ImmOp.isImm()) {
1609 expandLoadAddressSym(Inst, IDLoc, Instructions);
1610 return false;
1611 }
Jack Carter543fdf82012-10-09 23:29:45 +00001612 const MCOperand &RegOp = Inst.getOperand(0);
1613 assert(RegOp.isReg() && "expected register operand kind");
1614 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 if (-32768 <= ImmValue && ImmValue <= 65535) {
1616 // For -32768 <= j <= 65535.
1617 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001618 tmpInst.setOpcode(Mips::ADDiu);
1619 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001621 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1622 Instructions.push_back(tmpInst);
1623 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 // For any other value of j that is representable as a 32-bit integer.
1625 // la d,j => lui d,hi16(j)
1626 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001627 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001628 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1629 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1630 Instructions.push_back(tmpInst);
1631 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001632 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001633 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1634 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1635 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1636 Instructions.push_back(tmpInst);
1637 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001638 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001639}
1640
Toma Tabacu0d64b202014-08-14 10:29:17 +00001641void
1642MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1643 SmallVectorImpl<MCInst> &Instructions) {
1644 // FIXME: If we do have a valid at register to use, we should generate a
1645 // slightly shorter sequence here.
1646 MCInst tmpInst;
1647 int ExprOperandNo = 1;
1648 // Sometimes the assembly parser will get the immediate expression as
1649 // a $zero + an immediate.
1650 if (Inst.getNumOperands() == 3) {
1651 assert(Inst.getOperand(1).getReg() ==
1652 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1653 ExprOperandNo = 2;
1654 }
1655 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1656 assert(SymOp.isExpr() && "expected symbol operand kind");
1657 const MCOperand &RegOp = Inst.getOperand(0);
1658 unsigned RegNo = RegOp.getReg();
1659 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1660 const MCSymbolRefExpr *HiExpr =
1661 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1662 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1663 const MCSymbolRefExpr *LoExpr =
1664 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1665 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1666 if (isGP64bit()) {
1667 // If it's a 64-bit architecture, expand to:
1668 // la d,sym => lui d,highest(sym)
1669 // ori d,d,higher(sym)
1670 // dsll d,d,16
1671 // ori d,d,hi16(sym)
1672 // dsll d,d,16
1673 // ori d,d,lo16(sym)
1674 const MCSymbolRefExpr *HighestExpr =
1675 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1676 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1677 const MCSymbolRefExpr *HigherExpr =
1678 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1679 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1680
1681 tmpInst.setOpcode(Mips::LUi);
1682 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1683 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1684 Instructions.push_back(tmpInst);
1685
1686 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1687 Instructions);
1688 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1689 Instructions);
1690 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1691 Instructions);
1692 } else {
1693 // Otherwise, expand to:
1694 // la d,sym => lui d,hi16(sym)
1695 // ori d,d,lo16(sym)
1696 tmpInst.setOpcode(Mips::LUi);
1697 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1698 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1699 Instructions.push_back(tmpInst);
1700
1701 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1702 Instructions);
1703 }
1704}
1705
Jack Carter9e65aa32013-03-22 00:05:30 +00001706void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001707 SmallVectorImpl<MCInst> &Instructions,
1708 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001709 const MCSymbolRefExpr *SR;
1710 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001711 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001712 const MCExpr *ExprOffset;
1713 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001715 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1716 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001717 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001718 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1719 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001720 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001721 if (isImmOpnd) {
1722 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1723 ImmOffset = Inst.getOperand(2).getImm();
1724 LoOffset = ImmOffset & 0x0000ffff;
1725 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 if (LoOffset & 0x8000)
1728 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001730 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001731 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001733 // These are some of the types of expansions we perform here:
1734 // 1) lw $8, sym => lui $8, %hi(sym)
1735 // lw $8, %lo(sym)($8)
1736 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1737 // add $8, $8, $9
1738 // lw $8, %lo(offset)($9)
1739 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1740 // add $at, $at, $8
1741 // lw $8, %lo(offset)($at)
1742 // 4) sw $8, sym => lui $at, %hi(sym)
1743 // sw $8, %lo(sym)($at)
1744 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1745 // add $at, $at, $8
1746 // sw $8, %lo(offset)($at)
1747 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1748 // ldc1 $f0, %lo(sym)($at)
1749 //
1750 // For load instructions we can use the destination register as a temporary
1751 // if base and dst are different (examples 1 and 2) and if the base register
1752 // is general purpose otherwise we must use $at (example 6) and error if it's
1753 // not available. For stores we must use $at (examples 4 and 5) because we
1754 // must not clobber the source register setting up the offset.
1755 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1756 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1757 unsigned RegClassIDOp0 =
1758 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1759 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1760 (RegClassIDOp0 == Mips::GPR64RegClassID);
1761 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001762 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001763 else {
1764 int AT = getATReg(IDLoc);
1765 // At this point we need AT to perform the expansions and we exit if it is
1766 // not available.
1767 if (!AT)
1768 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001769 TmpRegNum = getReg(
1770 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001771 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001772
Jack Carter9e65aa32013-03-22 00:05:30 +00001773 TempInst.setOpcode(Mips::LUi);
1774 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1775 if (isImmOpnd)
1776 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1777 else {
1778 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001779 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1781 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1782 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001783 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001784 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001785 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001786 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001787 }
1788 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001789 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001790 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001791 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001792 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001793 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001794 TempInst.setOpcode(Mips::ADDu);
1795 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1796 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1797 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1798 Instructions.push_back(TempInst);
1799 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001800 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001801 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001802 TempInst.setOpcode(Inst.getOpcode());
1803 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1804 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1805 if (isImmOpnd)
1806 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1807 else {
1808 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001809 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1810 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1811 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001812 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001813 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001814 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001815 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001816 }
1817 }
1818 Instructions.push_back(TempInst);
1819 TempInst.clear();
1820}
1821
Matheus Almeida595fcab2014-06-11 15:05:56 +00001822unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1823 // As described by the Mips32r2 spec, the registers Rd and Rs for
1824 // jalr.hb must be different.
1825 unsigned Opcode = Inst.getOpcode();
1826
1827 if (Opcode == Mips::JALR_HB &&
1828 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1829 return Match_RequiresDifferentSrcAndDst;
1830
1831 return Match_Success;
1832}
1833
David Blaikie960ea3f2014-06-08 16:18:35 +00001834bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1835 OperandVector &Operands,
1836 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001837 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001838 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001839
Jack Carterb4dbc172012-09-05 23:34:03 +00001840 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001841 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001842 unsigned MatchResult =
1843 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001844
1845 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001846 default:
1847 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001848 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001849 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001850 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001851 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001852 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001853 return false;
1854 }
1855 case Match_MissingFeature:
1856 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1857 return true;
1858 case Match_InvalidOperand: {
1859 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001860 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001861 if (ErrorInfo >= Operands.size())
1862 return Error(IDLoc, "too few operands for instruction");
1863
David Blaikie960ea3f2014-06-08 16:18:35 +00001864 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001865 if (ErrorLoc == SMLoc())
1866 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001867 }
1868
1869 return Error(ErrorLoc, "invalid operand for instruction");
1870 }
1871 case Match_MnemonicFail:
1872 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001873 case Match_RequiresDifferentSrcAndDst:
1874 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001875 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001876 return true;
1877}
1878
Toma Tabacu13964452014-09-04 13:23:44 +00001879void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001880 if ((RegIndex != 0) &&
1881 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001882 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001883 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001884 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001885 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001886 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001887 }
1888}
1889
Daniel Sandersef638fe2014-10-03 15:37:37 +00001890void
1891MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1892 SMRange Range, bool ShowColors) {
1893 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001894 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001895 ShowColors);
1896}
1897
Jack Carter1ac53222013-02-20 23:11:17 +00001898int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001899 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001900
Vladimir Medic4c299852013-11-06 11:27:05 +00001901 CC = StringSwitch<unsigned>(Name)
1902 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001903 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001904 .Case("a0", 4)
1905 .Case("a1", 5)
1906 .Case("a2", 6)
1907 .Case("a3", 7)
1908 .Case("v0", 2)
1909 .Case("v1", 3)
1910 .Case("s0", 16)
1911 .Case("s1", 17)
1912 .Case("s2", 18)
1913 .Case("s3", 19)
1914 .Case("s4", 20)
1915 .Case("s5", 21)
1916 .Case("s6", 22)
1917 .Case("s7", 23)
1918 .Case("k0", 26)
1919 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001920 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001921 .Case("sp", 29)
1922 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001923 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001924 .Case("ra", 31)
1925 .Case("t0", 8)
1926 .Case("t1", 9)
1927 .Case("t2", 10)
1928 .Case("t3", 11)
1929 .Case("t4", 12)
1930 .Case("t5", 13)
1931 .Case("t6", 14)
1932 .Case("t7", 15)
1933 .Case("t8", 24)
1934 .Case("t9", 25)
1935 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001936
Toma Tabacufda445c2014-09-15 15:33:01 +00001937 if (!(isABI_N32() || isABI_N64()))
1938 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001939
Daniel Sandersef638fe2014-10-03 15:37:37 +00001940 if (12 <= CC && CC <= 15) {
1941 // Name is one of t4-t7
1942 AsmToken RegTok = getLexer().peekTok();
1943 SMRange RegRange = RegTok.getLocRange();
1944
1945 StringRef FixedName = StringSwitch<StringRef>(Name)
1946 .Case("t4", "t0")
1947 .Case("t5", "t1")
1948 .Case("t6", "t2")
1949 .Case("t7", "t3")
1950 .Default("");
1951 assert(FixedName != "" && "Register name is not one of t4-t7.");
1952
1953 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1954 "Did you mean $" + FixedName + "?", RegRange);
1955 }
1956
Toma Tabacufda445c2014-09-15 15:33:01 +00001957 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1958 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1959 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1960 if (8 <= CC && CC <= 11)
1961 CC += 4;
1962
1963 if (CC == -1)
1964 CC = StringSwitch<unsigned>(Name)
1965 .Case("a4", 8)
1966 .Case("a5", 9)
1967 .Case("a6", 10)
1968 .Case("a7", 11)
1969 .Case("kt0", 26)
1970 .Case("kt1", 27)
1971 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001972
1973 return CC;
1974}
Jack Carterd0bd6422013-04-18 00:41:53 +00001975
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001976int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1977 int CC;
1978
1979 CC = StringSwitch<unsigned>(Name)
1980 .Case("hwr_cpunum", 0)
1981 .Case("hwr_synci_step", 1)
1982 .Case("hwr_cc", 2)
1983 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001984 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001985 .Default(-1);
1986
1987 return CC;
1988}
1989
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001990int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001991
Jack Cartera63b16a2012-09-07 00:23:42 +00001992 if (Name[0] == 'f') {
1993 StringRef NumString = Name.substr(1);
1994 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001995 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001996 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001997 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001998 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001999 return IntVal;
2000 }
2001 return -1;
2002}
Jack Cartera63b16a2012-09-07 00:23:42 +00002003
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002004int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2005
2006 if (Name.startswith("fcc")) {
2007 StringRef NumString = Name.substr(3);
2008 unsigned IntVal;
2009 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002010 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002011 if (IntVal > 7) // There are only 8 fcc registers.
2012 return -1;
2013 return IntVal;
2014 }
2015 return -1;
2016}
2017
2018int MipsAsmParser::matchACRegisterName(StringRef Name) {
2019
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002020 if (Name.startswith("ac")) {
2021 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002022 unsigned IntVal;
2023 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002024 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002025 if (IntVal > 3) // There are only 3 acc registers.
2026 return -1;
2027 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002028 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002029 return -1;
2030}
Jack Carterd0bd6422013-04-18 00:41:53 +00002031
Jack Carter5dc8ac92013-09-25 23:50:44 +00002032int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2033 unsigned IntVal;
2034
2035 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2036 return -1;
2037
2038 if (IntVal > 31)
2039 return -1;
2040
2041 return IntVal;
2042}
2043
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002044int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2045 int CC;
2046
2047 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002048 .Case("msair", 0)
2049 .Case("msacsr", 1)
2050 .Case("msaaccess", 2)
2051 .Case("msasave", 3)
2052 .Case("msamodify", 4)
2053 .Case("msarequest", 5)
2054 .Case("msamap", 6)
2055 .Case("msaunmap", 7)
2056 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002057
2058 return CC;
2059}
2060
Jack Carter0b744b32012-10-04 02:29:46 +00002061bool MipsAssemblerOptions::setATReg(unsigned Reg) {
2062 if (Reg > 31)
2063 return false;
2064
Toma Tabacu3c24b042014-09-05 15:43:21 +00002065 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00002066 return true;
2067}
2068
Matheus Almeida7de68e72014-06-18 14:46:05 +00002069int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002070 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00002071 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002072 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002073 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00002074 return AT;
2075}
Jack Carter0b744b32012-10-04 02:29:46 +00002076
Jack Carterd0bd6422013-04-18 00:41:53 +00002077unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002078 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002079}
2080
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002081unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002082 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002083 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002084}
2085
Jack Carter873c7242013-01-12 01:03:14 +00002086int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002087 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002088 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002089 return -1;
2090
Jack Carter873c7242013-01-12 01:03:14 +00002091 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002092}
2093
Toma Tabacu13964452014-09-04 13:23:44 +00002094bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002095 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002096 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002097
Jack Carter30a59822012-10-04 04:03:53 +00002098 // Check if the current operand has a custom associated parser, if so, try to
2099 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002100 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2101 if (ResTy == MatchOperand_Success)
2102 return false;
2103 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2104 // there was a match, but an error occurred, in which case, just return that
2105 // the operand parsing failed.
2106 if (ResTy == MatchOperand_ParseFail)
2107 return true;
2108
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002109 DEBUG(dbgs() << ".. Generic Parser\n");
2110
Jack Carterb4dbc172012-09-05 23:34:03 +00002111 switch (getLexer().getKind()) {
2112 default:
2113 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2114 return true;
2115 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002117 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002118
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002119 // Almost all registers have been parsed by custom parsers. There is only
2120 // one exception to this. $zero (and it's alias $0) will reach this point
2121 // for div, divu, and similar instructions because it is not an operand
2122 // to the instruction definition but an explicit register. Special case
2123 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002124 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002125 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002126
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002128 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002129 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002130 return true;
2131
Jack Carter873c7242013-01-12 01:03:14 +00002132 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002133 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002134 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002135 const MCExpr *Res =
2136 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002137
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002138 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002139 return false;
2140 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002141 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002142 case AsmToken::LParen:
2143 case AsmToken::Minus:
2144 case AsmToken::Plus:
2145 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002146 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002147 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002148 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002149 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002150 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002151 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002152 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002153 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002154 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002155 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002156 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002157 return true;
2158
Jack Carter873c7242013-01-12 01:03:14 +00002159 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2160
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002161 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002162 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002163 } // case AsmToken::Percent
2164 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002165 return true;
2166}
2167
Vladimir Medic4c299852013-11-06 11:27:05 +00002168const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002169 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002170 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002171 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002172 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002173 // It's a constant, evaluate reloc value.
2174 int16_t Val;
2175 switch (getVariantKind(RelocStr)) {
2176 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2177 // Get the 1st 16-bits.
2178 Val = MCE->getValue() & 0xffff;
2179 break;
2180 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2181 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2182 // 16 bits being negative.
2183 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2184 break;
2185 case MCSymbolRefExpr::VK_Mips_HIGHER:
2186 // Get the 3rd 16-bits.
2187 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2188 break;
2189 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2190 // Get the 4th 16-bits.
2191 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2192 break;
2193 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002194 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002195 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002196 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002197 }
2198
Jack Carterb5cf5902013-04-17 00:18:04 +00002199 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002200 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002201 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002202 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002203 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002204 return Res;
2205 }
2206
2207 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002208 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2209
Sasa Stankovic06c47802014-04-03 10:37:45 +00002210 // Try to create target expression.
2211 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2212 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002213
Jack Carterd0bd6422013-04-18 00:41:53 +00002214 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2215 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002216 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2217 return Res;
2218 }
2219
2220 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002221 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2222 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2223 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002224 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002226 return Expr;
2227}
2228
2229bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2230
2231 switch (Expr->getKind()) {
2232 case MCExpr::Constant:
2233 return true;
2234 case MCExpr::SymbolRef:
2235 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2236 case MCExpr::Binary:
2237 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2238 if (!isEvaluated(BE->getLHS()))
2239 return false;
2240 return isEvaluated(BE->getRHS());
2241 }
2242 case MCExpr::Unary:
2243 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002244 case MCExpr::Target:
2245 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002246 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002247 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002248}
Jack Carterd0bd6422013-04-18 00:41:53 +00002249
Jack Carterb5cf5902013-04-17 00:18:04 +00002250bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002251 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002252 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002253 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002254 if (Tok.isNot(AsmToken::Identifier))
2255 return true;
2256
2257 std::string Str = Tok.getIdentifier().str();
2258
Jack Carterd0bd6422013-04-18 00:41:53 +00002259 Parser.Lex(); // Eat the identifier.
2260 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002261 const MCExpr *IdVal;
2262 SMLoc EndLoc;
2263
2264 if (getLexer().getKind() == AsmToken::LParen) {
2265 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002266 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002267 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002268 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002269 const AsmToken &nextTok = Parser.getTok();
2270 if (nextTok.isNot(AsmToken::Identifier))
2271 return true;
2272 Str += "(%";
2273 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002274 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002275 if (getLexer().getKind() != AsmToken::LParen)
2276 return true;
2277 } else
2278 break;
2279 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002280 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002281 return true;
2282
2283 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002284 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002285
2286 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002287 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002288
Jack Carterd0bd6422013-04-18 00:41:53 +00002289 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002290 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002291}
2292
Jack Carterb4dbc172012-09-05 23:34:03 +00002293bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2294 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002295 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002296 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002297 if (ResTy == MatchOperand_Success) {
2298 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002299 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002300 StartLoc = Operand.getStartLoc();
2301 EndLoc = Operand.getEndLoc();
2302
2303 // AFAIK, we only support numeric registers and named GPR's in CFI
2304 // directives.
2305 // Don't worry about eating tokens before failing. Using an unrecognised
2306 // register is a parse error.
2307 if (Operand.isGPRAsmReg()) {
2308 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002309 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002310 }
2311
2312 return (RegNo == (unsigned)-1);
2313 }
2314
2315 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002316 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002317}
2318
Jack Carterb5cf5902013-04-17 00:18:04 +00002319bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002320 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002321 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002322 bool Result = true;
2323
2324 while (getLexer().getKind() == AsmToken::LParen)
2325 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002326
Jack Carterd0bd6422013-04-18 00:41:53 +00002327 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002328 default:
2329 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002330 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002331 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002332 case AsmToken::Integer:
2333 case AsmToken::Minus:
2334 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002335 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002336 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002337 else
2338 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002339 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002340 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 break;
Jack Carter873c7242013-01-12 01:03:14 +00002342 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002343 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002344 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002345 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002346}
2347
David Blaikie960ea3f2014-06-08 16:18:35 +00002348MipsAsmParser::OperandMatchResultTy
2349MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002350 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002351 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002352 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002353 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002354 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002355 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002356 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002357 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002358
Jack Carterb5cf5902013-04-17 00:18:04 +00002359 if (getLexer().getKind() == AsmToken::LParen) {
2360 Parser.Lex();
2361 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002362 }
2363
Jack Carterb5cf5902013-04-17 00:18:04 +00002364 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002365 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002366 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002367
Jack Carterd0bd6422013-04-18 00:41:53 +00002368 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002369 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002370 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2371 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002372 SMLoc E =
2373 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002374 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002375 return MatchOperand_Success;
2376 }
2377 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002378 SMLoc E =
2379 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002380
Jack Carterd0bd6422013-04-18 00:41:53 +00002381 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002382 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002383 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002384 S, E, *this);
2385 Operands.push_back(
2386 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002387 return MatchOperand_Success;
2388 }
2389 Error(Parser.getTok().getLoc(), "'(' expected");
2390 return MatchOperand_ParseFail;
2391 }
2392
Jack Carterd0bd6422013-04-18 00:41:53 +00002393 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002394 }
2395
Toma Tabacu13964452014-09-04 13:23:44 +00002396 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002397 if (Res != MatchOperand_Success)
2398 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002399
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002400 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002401 Error(Parser.getTok().getLoc(), "')' expected");
2402 return MatchOperand_ParseFail;
2403 }
2404
Jack Carter873c7242013-01-12 01:03:14 +00002405 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2406
Jack Carterd0bd6422013-04-18 00:41:53 +00002407 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002408
Craig Topper062a2ba2014-04-25 05:30:21 +00002409 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002410 IdVal = MCConstantExpr::Create(0, getContext());
2411
Jack Carterd0bd6422013-04-18 00:41:53 +00002412 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002413 std::unique_ptr<MipsOperand> op(
2414 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002415 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002416 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002417 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002418 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002419 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2420 int64_t Imm;
2421 if (IdVal->EvaluateAsAbsolute(Imm))
2422 IdVal = MCConstantExpr::Create(Imm, getContext());
2423 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2424 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2425 getContext());
2426 }
2427
David Blaikie960ea3f2014-06-08 16:18:35 +00002428 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002429 return MatchOperand_Success;
2430}
2431
David Blaikie960ea3f2014-06-08 16:18:35 +00002432bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002433 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002434 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2435 if (Sym) {
2436 SMLoc S = Parser.getTok().getLoc();
2437 const MCExpr *Expr;
2438 if (Sym->isVariable())
2439 Expr = Sym->getVariableValue();
2440 else
2441 return false;
2442 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002443 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002444 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002445 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002446 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002447 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002448 if (ResTy == MatchOperand_Success) {
2449 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002450 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002451 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002452 llvm_unreachable("Should never ParseFail");
2453 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002454 }
2455 } else if (Expr->getKind() == MCExpr::Constant) {
2456 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002457 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002458 Operands.push_back(
2459 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002460 return true;
2461 }
2462 }
2463 return false;
2464}
Jack Carterd0bd6422013-04-18 00:41:53 +00002465
Jack Carter873c7242013-01-12 01:03:14 +00002466MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002467MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002468 StringRef Identifier,
2469 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002470 int Index = matchCPURegisterName(Identifier);
2471 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002472 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2474 return MatchOperand_Success;
2475 }
2476
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002477 Index = matchHWRegsRegisterName(Identifier);
2478 if (Index != -1) {
2479 Operands.push_back(MipsOperand::createHWRegsReg(
2480 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2481 return MatchOperand_Success;
2482 }
2483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002484 Index = matchFPURegisterName(Identifier);
2485 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002486 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002487 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2488 return MatchOperand_Success;
2489 }
2490
2491 Index = matchFCCRegisterName(Identifier);
2492 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002493 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002494 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2495 return MatchOperand_Success;
2496 }
2497
2498 Index = matchACRegisterName(Identifier);
2499 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002500 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002501 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2502 return MatchOperand_Success;
2503 }
2504
2505 Index = matchMSA128RegisterName(Identifier);
2506 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002507 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002508 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2509 return MatchOperand_Success;
2510 }
2511
2512 Index = matchMSA128CtrlRegisterName(Identifier);
2513 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002514 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002515 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2516 return MatchOperand_Success;
2517 }
2518
2519 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002520}
2521
2522MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002523MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002524 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002525 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002526
2527 if (Token.is(AsmToken::Identifier)) {
2528 DEBUG(dbgs() << ".. identifier\n");
2529 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002530 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002531 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002532 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002533 } else if (Token.is(AsmToken::Integer)) {
2534 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002535 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002536 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2537 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002538 return MatchOperand_Success;
2539 }
2540
2541 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2542
2543 return MatchOperand_NoMatch;
2544}
2545
David Blaikie960ea3f2014-06-08 16:18:35 +00002546MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002547MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002548 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002549 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002550
2551 auto Token = Parser.getTok();
2552
2553 SMLoc S = Token.getLoc();
2554
2555 if (Token.isNot(AsmToken::Dollar)) {
2556 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2557 if (Token.is(AsmToken::Identifier)) {
2558 if (searchSymbolAlias(Operands))
2559 return MatchOperand_Success;
2560 }
2561 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2562 return MatchOperand_NoMatch;
2563 }
2564 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002565
Toma Tabacu13964452014-09-04 13:23:44 +00002566 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002567 if (ResTy == MatchOperand_Success) {
2568 Parser.Lex(); // $
2569 Parser.Lex(); // identifier
2570 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002571 return ResTy;
2572}
2573
2574MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002575MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002576 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002577 switch (getLexer().getKind()) {
2578 default:
2579 return MatchOperand_NoMatch;
2580 case AsmToken::LParen:
2581 case AsmToken::Minus:
2582 case AsmToken::Plus:
2583 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002584 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002585 case AsmToken::String:
2586 break;
2587 }
2588
2589 const MCExpr *IdVal;
2590 SMLoc S = Parser.getTok().getLoc();
2591 if (getParser().parseExpression(IdVal))
2592 return MatchOperand_ParseFail;
2593
2594 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2595 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2596 return MatchOperand_Success;
2597}
2598
David Blaikie960ea3f2014-06-08 16:18:35 +00002599MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002600MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002601 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002602 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002603
2604 SMLoc S = getLexer().getLoc();
2605
2606 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002607 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002608 if (ResTy != MatchOperand_NoMatch)
2609 return ResTy;
2610
Daniel Sanders315386c2014-04-01 10:40:14 +00002611 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002612 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002613 if (ResTy != MatchOperand_NoMatch)
2614 return ResTy;
2615
Daniel Sandersffd84362014-04-01 10:41:48 +00002616 const MCExpr *Expr = nullptr;
2617 if (Parser.parseExpression(Expr)) {
2618 // We have no way of knowing if a symbol was consumed so we must ParseFail
2619 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002620 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002621 Operands.push_back(
2622 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002623 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002624}
2625
Vladimir Medic2b953d02013-10-01 09:48:56 +00002626MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002627MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002628 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002629 const MCExpr *IdVal;
2630 // If the first token is '$' we may have register operand.
2631 if (Parser.getTok().is(AsmToken::Dollar))
2632 return MatchOperand_NoMatch;
2633 SMLoc S = Parser.getTok().getLoc();
2634 if (getParser().parseExpression(IdVal))
2635 return MatchOperand_ParseFail;
2636 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002637 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002638 int64_t Val = MCE->getValue();
2639 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2640 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002641 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002642 return MatchOperand_Success;
2643}
2644
Matheus Almeida779c5932013-11-18 12:32:49 +00002645MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002646MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002647 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002648 switch (getLexer().getKind()) {
2649 default:
2650 return MatchOperand_NoMatch;
2651 case AsmToken::LParen:
2652 case AsmToken::Plus:
2653 case AsmToken::Minus:
2654 case AsmToken::Integer:
2655 break;
2656 }
2657
2658 const MCExpr *Expr;
2659 SMLoc S = Parser.getTok().getLoc();
2660
2661 if (getParser().parseExpression(Expr))
2662 return MatchOperand_ParseFail;
2663
2664 int64_t Val;
2665 if (!Expr->EvaluateAsAbsolute(Val)) {
2666 Error(S, "expected immediate value");
2667 return MatchOperand_ParseFail;
2668 }
2669
2670 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2671 // and because the CPU always adds one to the immediate field, the allowed
2672 // range becomes 1..4. We'll only check the range here and will deal
2673 // with the addition/subtraction when actually decoding/encoding
2674 // the instruction.
2675 if (Val < 1 || Val > 4) {
2676 Error(S, "immediate not in range (1..4)");
2677 return MatchOperand_ParseFail;
2678 }
2679
Jack Carter3b2c96e2014-01-22 23:31:38 +00002680 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002681 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002682 return MatchOperand_Success;
2683}
2684
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00002685MipsAsmParser::OperandMatchResultTy
2686MipsAsmParser::parseRegisterList(OperandVector &Operands) {
2687 MCAsmParser &Parser = getParser();
2688 SmallVector<unsigned, 10> Regs;
2689 unsigned RegNo;
2690 unsigned PrevReg = Mips::NoRegister;
2691 bool RegRange = false;
2692 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
2693
2694 if (Parser.getTok().isNot(AsmToken::Dollar))
2695 return MatchOperand_ParseFail;
2696
2697 SMLoc S = Parser.getTok().getLoc();
2698 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
2699 SMLoc E = getLexer().getLoc();
2700 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
2701 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
2702 if (RegRange) {
2703 // Remove last register operand because registers from register range
2704 // should be inserted first.
2705 if (RegNo == Mips::RA) {
2706 Regs.push_back(RegNo);
2707 } else {
2708 unsigned TmpReg = PrevReg + 1;
2709 while (TmpReg <= RegNo) {
2710 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
2711 Error(E, "invalid register operand");
2712 return MatchOperand_ParseFail;
2713 }
2714
2715 PrevReg = TmpReg;
2716 Regs.push_back(TmpReg++);
2717 }
2718 }
2719
2720 RegRange = false;
2721 } else {
2722 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
2723 (RegNo != Mips::RA)) {
2724 Error(E, "$16 or $31 expected");
2725 return MatchOperand_ParseFail;
2726 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
2727 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2728 Error(E, "invalid register operand");
2729 return MatchOperand_ParseFail;
2730 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
2731 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
2732 Error(E, "consecutive register numbers expected");
2733 return MatchOperand_ParseFail;
2734 }
2735
2736 Regs.push_back(RegNo);
2737 }
2738
2739 if (Parser.getTok().is(AsmToken::Minus))
2740 RegRange = true;
2741
2742 if (!Parser.getTok().isNot(AsmToken::Minus) &&
2743 !Parser.getTok().isNot(AsmToken::Comma)) {
2744 Error(E, "',' or '-' expected");
2745 return MatchOperand_ParseFail;
2746 }
2747
2748 Lex(); // Consume comma or minus
2749 if (Parser.getTok().isNot(AsmToken::Dollar))
2750 break;
2751
2752 PrevReg = RegNo;
2753 }
2754
2755 SMLoc E = Parser.getTok().getLoc();
2756 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
2757 parseMemOperand(Operands);
2758 return MatchOperand_Success;
2759}
2760
Zoran Jovanovic2deca342014-12-16 14:59:10 +00002761MipsAsmParser::OperandMatchResultTy
2762MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
2763 MCAsmParser &Parser = getParser();
2764
2765 SMLoc S = Parser.getTok().getLoc();
2766 if (parseAnyRegister(Operands) != MatchOperand_Success)
2767 return MatchOperand_ParseFail;
2768
2769 SMLoc E = Parser.getTok().getLoc();
2770 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
2771 unsigned Reg = Op.getGPR32Reg();
2772 Operands.pop_back();
2773 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
2774 return MatchOperand_Success;
2775}
2776
Jack Carterdc1e35d2012-09-06 20:00:02 +00002777MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2778
Vladimir Medic4c299852013-11-06 11:27:05 +00002779 MCSymbolRefExpr::VariantKind VK =
2780 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2781 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2782 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2783 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2784 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2785 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2786 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2787 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2788 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2789 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2790 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2791 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2792 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2793 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2794 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2795 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2796 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2797 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002798 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2799 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2800 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2801 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2802 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2803 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002804 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2805 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002806 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002807
Matheus Almeida2852af82014-04-22 10:15:54 +00002808 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002809
Jack Carterdc1e35d2012-09-06 20:00:02 +00002810 return VK;
2811}
Jack Cartera63b16a2012-09-07 00:23:42 +00002812
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002813/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2814/// either this.
2815/// ::= '(', register, ')'
2816/// handle it before we iterate so we don't get tripped up by the lack of
2817/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002818bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002819 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 if (getLexer().is(AsmToken::LParen)) {
2821 Operands.push_back(
2822 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2823 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002824 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002825 SMLoc Loc = getLexer().getLoc();
2826 Parser.eatToEndOfStatement();
2827 return Error(Loc, "unexpected token in argument list");
2828 }
2829 if (Parser.getTok().isNot(AsmToken::RParen)) {
2830 SMLoc Loc = getLexer().getLoc();
2831 Parser.eatToEndOfStatement();
2832 return Error(Loc, "unexpected token, expected ')'");
2833 }
2834 Operands.push_back(
2835 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2836 Parser.Lex();
2837 }
2838 return false;
2839}
2840
2841/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2842/// either one of these.
2843/// ::= '[', register, ']'
2844/// ::= '[', integer, ']'
2845/// handle it before we iterate so we don't get tripped up by the lack of
2846/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002847bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002848 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002849 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 if (getLexer().is(AsmToken::LBrac)) {
2851 Operands.push_back(
2852 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2853 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002854 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 SMLoc Loc = getLexer().getLoc();
2856 Parser.eatToEndOfStatement();
2857 return Error(Loc, "unexpected token in argument list");
2858 }
2859 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2860 SMLoc Loc = getLexer().getLoc();
2861 Parser.eatToEndOfStatement();
2862 return Error(Loc, "unexpected token, expected ']'");
2863 }
2864 Operands.push_back(
2865 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2866 Parser.Lex();
2867 }
2868 return false;
2869}
2870
David Blaikie960ea3f2014-06-08 16:18:35 +00002871bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2872 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002873 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002874 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002875
2876 // We have reached first instruction, module directive are now forbidden.
2877 getTargetStreamer().forbidModuleDirective();
2878
Vladimir Medic74593e62013-07-17 15:00:42 +00002879 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002880 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002881 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002882 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002883 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002884 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002885 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002886
2887 // Read the remaining operands.
2888 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2889 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002890 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002891 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002892 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002893 return Error(Loc, "unexpected token in argument list");
2894 }
Toma Tabacu13964452014-09-04 13:23:44 +00002895 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002896 return true;
2897 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002898
Jack Carterd0bd6422013-04-18 00:41:53 +00002899 while (getLexer().is(AsmToken::Comma)) {
2900 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002901 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002902 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002903 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002904 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002905 return Error(Loc, "unexpected token in argument list");
2906 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002907 // Parse bracket and parenthesis suffixes before we iterate
2908 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002909 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002910 return true;
2911 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002912 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002913 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002914 }
2915 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002916 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2917 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002918 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002919 return Error(Loc, "unexpected token in argument list");
2920 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002921 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002922 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002923}
2924
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002925bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002926 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002927 SMLoc Loc = getLexer().getLoc();
2928 Parser.eatToEndOfStatement();
2929 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002930}
2931
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002932bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002933 return Error(Loc, ErrorMsg);
2934}
2935
Jack Carter0b744b32012-10-04 02:29:46 +00002936bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002937 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002938 // Line should look like: ".set noat".
2939 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002940 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002941 // eat noat
2942 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002943 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002944 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002945 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002946 return false;
2947 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002948 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002949 return false;
2950}
Jack Carterd0bd6422013-04-18 00:41:53 +00002951
Jack Carter0b744b32012-10-04 02:29:46 +00002952bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002953 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002954 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002955 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002956 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002957 getParser().Lex();
2958 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002959 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002960 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002961 return false;
2962 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002963 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002964 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002965 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002966 return false;
2967 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002968 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002969 const AsmToken &Reg = Parser.getTok();
2970 if (Reg.is(AsmToken::Identifier)) {
2971 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2972 } else if (Reg.is(AsmToken::Integer)) {
2973 AtRegNo = Reg.getIntVal();
2974 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002975 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002976 return false;
2977 }
Jack Carter1ac53222013-02-20 23:11:17 +00002978
Daniel Sanders71a89d922014-03-25 13:01:06 +00002979 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002980 reportParseError("unexpected token in statement");
2981 return false;
2982 }
2983
Toma Tabacu9db22db2014-09-09 10:15:38 +00002984 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002985 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002986 return false;
2987 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002988 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002989
2990 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002991 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002992 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002993 }
2994 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002995 return false;
2996 } else {
2997 reportParseError("unexpected token in statement");
2998 return false;
2999 }
3000}
3001
3002bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003003 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003004 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003005 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003006 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003007 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003008 return false;
3009 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003010 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003011 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003012 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003013 return false;
3014}
3015
3016bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003017 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003018 Parser.Lex();
3019 // If this is not the end of the statement, report an error.
3020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003021 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003022 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003023 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003024 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003025 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003026 Parser.Lex(); // Consume the EndOfStatement.
3027 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003028}
3029
3030bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003031 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003032 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003033 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003034 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003035 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003036 return false;
3037 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003038 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003039 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003040 return false;
3041}
3042
3043bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003044 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003045 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003046 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003048 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003049 return false;
3050 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003051 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003052 reportParseError("`noreorder' must be set before `nomacro'");
3053 return false;
3054 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003055 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003056 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003057 return false;
3058}
Jack Carterd76b2372013-03-21 21:44:16 +00003059
Daniel Sanders44934432014-08-07 12:03:36 +00003060bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003061 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003062 Parser.Lex();
3063
3064 // If this is not the end of the statement, report an error.
3065 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003066 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003067
3068 setFeatureBits(Mips::FeatureMSA, "msa");
3069 getTargetStreamer().emitDirectiveSetMsa();
3070 return false;
3071}
3072
3073bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003074 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003075 Parser.Lex();
3076
3077 // If this is not the end of the statement, report an error.
3078 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003079 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003080
3081 clearFeatureBits(Mips::FeatureMSA, "msa");
3082 getTargetStreamer().emitDirectiveSetNoMsa();
3083 return false;
3084}
3085
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003086bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003087 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003088 Parser.Lex(); // Eat "nodsp".
3089
3090 // If this is not the end of the statement, report an error.
3091 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3092 reportParseError("unexpected token, expected end of statement");
3093 return false;
3094 }
3095
3096 clearFeatureBits(Mips::FeatureDSP, "dsp");
3097 getTargetStreamer().emitDirectiveSetNoDsp();
3098 return false;
3099}
3100
Toma Tabacucc2502d2014-11-04 17:18:07 +00003101bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003102 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003103 Parser.Lex(); // Eat "mips16".
3104
Jack Carter39536722014-01-22 23:08:42 +00003105 // If this is not the end of the statement, report an error.
3106 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003107 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003108 return false;
3109 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003110
3111 setFeatureBits(Mips::FeatureMips16, "mips16");
3112 getTargetStreamer().emitDirectiveSetMips16();
3113 Parser.Lex(); // Consume the EndOfStatement.
3114 return false;
3115}
3116
3117bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003118 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003119 Parser.Lex(); // Eat "nomips16".
3120
3121 // If this is not the end of the statement, report an error.
3122 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3123 reportParseError("unexpected token, expected end of statement");
3124 return false;
3125 }
3126
3127 clearFeatureBits(Mips::FeatureMips16, "mips16");
3128 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003129 Parser.Lex(); // Consume the EndOfStatement.
3130 return false;
3131}
3132
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003133bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003134 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003135 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003136 // Line can be: .set fp=32
3137 // .set fp=xx
3138 // .set fp=64
3139 Parser.Lex(); // Eat fp token
3140 AsmToken Tok = Parser.getTok();
3141 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003142 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003143 return false;
3144 }
3145 Parser.Lex(); // Eat '=' token.
3146 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003147
3148 if (!parseFpABIValue(FpAbiVal, ".set"))
3149 return false;
3150
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003151 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003152 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003153 return false;
3154 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003155 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003156 Parser.Lex(); // Consume the EndOfStatement.
3157 return false;
3158}
3159
Toma Tabacu9db22db2014-09-09 10:15:38 +00003160bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003161 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003162 SMLoc Loc = getLexer().getLoc();
3163
3164 Parser.Lex();
3165 if (getLexer().isNot(AsmToken::EndOfStatement))
3166 return reportParseError("unexpected token, expected end of statement");
3167
3168 // Always keep an element on the options "stack" to prevent the user
3169 // from changing the initial options. This is how we remember them.
3170 if (AssemblerOptions.size() == 2)
3171 return reportParseError(Loc, ".set pop with no .set push");
3172
3173 AssemblerOptions.pop_back();
3174 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3175
3176 getTargetStreamer().emitDirectiveSetPop();
3177 return false;
3178}
3179
3180bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003181 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003182 Parser.Lex();
3183 if (getLexer().isNot(AsmToken::EndOfStatement))
3184 return reportParseError("unexpected token, expected end of statement");
3185
3186 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003187 AssemblerOptions.push_back(
3188 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003189
3190 getTargetStreamer().emitDirectiveSetPush();
3191 return false;
3192}
3193
Jack Carterd76b2372013-03-21 21:44:16 +00003194bool MipsAsmParser::parseSetAssignment() {
3195 StringRef Name;
3196 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003197 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003198
3199 if (Parser.parseIdentifier(Name))
3200 reportParseError("expected identifier after .set");
3201
3202 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003203 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003204 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003205
Jack Carter3b2c96e2014-01-22 23:31:38 +00003206 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003207 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003208
Jack Carterd0bd6422013-04-18 00:41:53 +00003209 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00003210 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00003211 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00003212 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00003213 Sym = getContext().GetOrCreateSymbol(Name);
3214 Sym->setVariableValue(Value);
3215
3216 return false;
3217}
Jack Carterd0bd6422013-04-18 00:41:53 +00003218
Toma Tabacu26647792014-09-09 12:52:14 +00003219bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003220 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003221 Parser.Lex();
3222 if (getLexer().isNot(AsmToken::EndOfStatement))
3223 return reportParseError("unexpected token, expected end of statement");
3224
3225 // Reset assembler options to their initial values.
3226 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3227 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3228
3229 getTargetStreamer().emitDirectiveSetMips0();
3230 return false;
3231}
3232
Toma Tabacu85618b32014-08-19 14:22:52 +00003233bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003234 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003235 Parser.Lex();
3236 if (getLexer().isNot(AsmToken::Equal))
3237 return reportParseError("unexpected token, expected equals sign");
3238
3239 Parser.Lex();
3240 StringRef Arch;
3241 if (Parser.parseIdentifier(Arch))
3242 return reportParseError("expected arch identifier");
3243
3244 StringRef ArchFeatureName =
3245 StringSwitch<StringRef>(Arch)
3246 .Case("mips1", "mips1")
3247 .Case("mips2", "mips2")
3248 .Case("mips3", "mips3")
3249 .Case("mips4", "mips4")
3250 .Case("mips5", "mips5")
3251 .Case("mips32", "mips32")
3252 .Case("mips32r2", "mips32r2")
3253 .Case("mips32r6", "mips32r6")
3254 .Case("mips64", "mips64")
3255 .Case("mips64r2", "mips64r2")
3256 .Case("mips64r6", "mips64r6")
3257 .Case("cnmips", "cnmips")
3258 .Case("r4000", "mips3") // This is an implementation of Mips3.
3259 .Default("");
3260
3261 if (ArchFeatureName.empty())
3262 return reportParseError("unsupported architecture");
3263
3264 selectArch(ArchFeatureName);
3265 getTargetStreamer().emitDirectiveSetArch(Arch);
3266 return false;
3267}
3268
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003269bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003270 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003271 Parser.Lex();
3272 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003273 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003274
Matheus Almeida2852af82014-04-22 10:15:54 +00003275 switch (Feature) {
3276 default:
3277 llvm_unreachable("Unimplemented feature");
3278 case Mips::FeatureDSP:
3279 setFeatureBits(Mips::FeatureDSP, "dsp");
3280 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003281 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003282 case Mips::FeatureMicroMips:
3283 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003284 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003285 case Mips::FeatureMips1:
3286 selectArch("mips1");
3287 getTargetStreamer().emitDirectiveSetMips1();
3288 break;
3289 case Mips::FeatureMips2:
3290 selectArch("mips2");
3291 getTargetStreamer().emitDirectiveSetMips2();
3292 break;
3293 case Mips::FeatureMips3:
3294 selectArch("mips3");
3295 getTargetStreamer().emitDirectiveSetMips3();
3296 break;
3297 case Mips::FeatureMips4:
3298 selectArch("mips4");
3299 getTargetStreamer().emitDirectiveSetMips4();
3300 break;
3301 case Mips::FeatureMips5:
3302 selectArch("mips5");
3303 getTargetStreamer().emitDirectiveSetMips5();
3304 break;
3305 case Mips::FeatureMips32:
3306 selectArch("mips32");
3307 getTargetStreamer().emitDirectiveSetMips32();
3308 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003309 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003310 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003311 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003312 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003313 case Mips::FeatureMips32r6:
3314 selectArch("mips32r6");
3315 getTargetStreamer().emitDirectiveSetMips32R6();
3316 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003317 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003318 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003319 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003320 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003321 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003322 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003323 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003324 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003325 case Mips::FeatureMips64r6:
3326 selectArch("mips64r6");
3327 getTargetStreamer().emitDirectiveSetMips64R6();
3328 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003329 }
3330 return false;
3331}
3332
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003333bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003334 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003335 if (getLexer().isNot(AsmToken::Comma)) {
3336 SMLoc Loc = getLexer().getLoc();
3337 Parser.eatToEndOfStatement();
3338 return Error(Loc, ErrorStr);
3339 }
3340
Matheus Almeida2852af82014-04-22 10:15:54 +00003341 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003342 return true;
3343}
3344
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003345bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003346 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003347 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003348
Toma Tabacudde4c462014-11-06 10:02:45 +00003349 if (inMips16Mode()) {
3350 reportParseError(".cpload is not supported in Mips16 mode");
3351 return false;
3352 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003353
David Blaikie960ea3f2014-06-08 16:18:35 +00003354 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003355 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003356 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3357 reportParseError("expected register containing function address");
3358 return false;
3359 }
3360
David Blaikie960ea3f2014-06-08 16:18:35 +00003361 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3362 if (!RegOpnd.isGPRAsmReg()) {
3363 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003364 return false;
3365 }
3366
Toma Tabacudde4c462014-11-06 10:02:45 +00003367 // If this is not the end of the statement, report an error.
3368 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3369 reportParseError("unexpected token, expected end of statement");
3370 return false;
3371 }
3372
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003373 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003374 return false;
3375}
3376
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003377bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003378 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003379 unsigned FuncReg;
3380 unsigned Save;
3381 bool SaveIsReg = true;
3382
Matheus Almeida7e815762014-06-18 13:08:59 +00003383 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003384 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003385 if (ResTy == MatchOperand_NoMatch) {
3386 reportParseError("expected register containing function address");
3387 Parser.eatToEndOfStatement();
3388 return false;
3389 }
3390
3391 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3392 if (!FuncRegOpnd.isGPRAsmReg()) {
3393 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3394 Parser.eatToEndOfStatement();
3395 return false;
3396 }
3397
3398 FuncReg = FuncRegOpnd.getGPR32Reg();
3399 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003400
Toma Tabacu65f10572014-09-16 15:00:52 +00003401 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003402 return true;
3403
Toma Tabacu13964452014-09-04 13:23:44 +00003404 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003405 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003406 const AsmToken &Tok = Parser.getTok();
3407 if (Tok.is(AsmToken::Integer)) {
3408 Save = Tok.getIntVal();
3409 SaveIsReg = false;
3410 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003411 } else {
3412 reportParseError("expected save register or stack offset");
3413 Parser.eatToEndOfStatement();
3414 return false;
3415 }
3416 } else {
3417 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3418 if (!SaveOpnd.isGPRAsmReg()) {
3419 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3420 Parser.eatToEndOfStatement();
3421 return false;
3422 }
3423 Save = SaveOpnd.getGPR32Reg();
3424 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003425
Toma Tabacu65f10572014-09-16 15:00:52 +00003426 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003427 return true;
3428
3429 StringRef Name;
3430 if (Parser.parseIdentifier(Name))
3431 reportParseError("expected identifier");
3432 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003433
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003434 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003435 return false;
3436}
3437
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003438bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003439 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3441 const AsmToken &Tok = Parser.getTok();
3442
3443 if (Tok.getString() == "2008") {
3444 Parser.Lex();
3445 getTargetStreamer().emitDirectiveNaN2008();
3446 return false;
3447 } else if (Tok.getString() == "legacy") {
3448 Parser.Lex();
3449 getTargetStreamer().emitDirectiveNaNLegacy();
3450 return false;
3451 }
3452 }
3453 // If we don't recognize the option passed to the .nan
3454 // directive (e.g. no option or unknown option), emit an error.
3455 reportParseError("invalid option in .nan directive");
3456 return false;
3457}
3458
Jack Carter0b744b32012-10-04 02:29:46 +00003459bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003460 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003461 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003462 const AsmToken &Tok = Parser.getTok();
3463
3464 if (Tok.getString() == "noat") {
3465 return parseSetNoAtDirective();
3466 } else if (Tok.getString() == "at") {
3467 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003468 } else if (Tok.getString() == "arch") {
3469 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003470 } else if (Tok.getString() == "fp") {
3471 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003472 } else if (Tok.getString() == "pop") {
3473 return parseSetPopDirective();
3474 } else if (Tok.getString() == "push") {
3475 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003476 } else if (Tok.getString() == "reorder") {
3477 return parseSetReorderDirective();
3478 } else if (Tok.getString() == "noreorder") {
3479 return parseSetNoReorderDirective();
3480 } else if (Tok.getString() == "macro") {
3481 return parseSetMacroDirective();
3482 } else if (Tok.getString() == "nomacro") {
3483 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003484 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003485 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003486 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003487 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003488 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003489 getTargetStreamer().emitDirectiveSetNoMicroMips();
3490 Parser.eatToEndOfStatement();
3491 return false;
3492 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003493 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003494 } else if (Tok.getString() == "mips0") {
3495 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003496 } else if (Tok.getString() == "mips1") {
3497 return parseSetFeature(Mips::FeatureMips1);
3498 } else if (Tok.getString() == "mips2") {
3499 return parseSetFeature(Mips::FeatureMips2);
3500 } else if (Tok.getString() == "mips3") {
3501 return parseSetFeature(Mips::FeatureMips3);
3502 } else if (Tok.getString() == "mips4") {
3503 return parseSetFeature(Mips::FeatureMips4);
3504 } else if (Tok.getString() == "mips5") {
3505 return parseSetFeature(Mips::FeatureMips5);
3506 } else if (Tok.getString() == "mips32") {
3507 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003508 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003509 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003510 } else if (Tok.getString() == "mips32r6") {
3511 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003512 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003513 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003514 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003515 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003516 } else if (Tok.getString() == "mips64r6") {
3517 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003518 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003519 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003520 } else if (Tok.getString() == "nodsp") {
3521 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003522 } else if (Tok.getString() == "msa") {
3523 return parseSetMsaDirective();
3524 } else if (Tok.getString() == "nomsa") {
3525 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003526 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003527 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003528 parseSetAssignment();
3529 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003530 }
Jack Carter07c818d2013-01-25 01:31:34 +00003531
Jack Carter0b744b32012-10-04 02:29:46 +00003532 return true;
3533}
3534
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003535/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003536/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003537bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003538 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003539 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3540 for (;;) {
3541 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003542 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003543 return true;
3544
3545 getParser().getStreamer().EmitValue(Value, Size);
3546
3547 if (getLexer().is(AsmToken::EndOfStatement))
3548 break;
3549
Jack Carter07c818d2013-01-25 01:31:34 +00003550 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003551 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003552 Parser.Lex();
3553 }
3554 }
3555
3556 Parser.Lex();
3557 return false;
3558}
3559
Vladimir Medic4c299852013-11-06 11:27:05 +00003560/// parseDirectiveGpWord
3561/// ::= .gpword local_sym
3562bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003563 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003564 const MCExpr *Value;
3565 // EmitGPRel32Value requires an expression, so we are using base class
3566 // method to evaluate the expression.
3567 if (getParser().parseExpression(Value))
3568 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003569 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003570
Vladimir Medice10c1122013-11-13 13:18:04 +00003571 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003572 return Error(getLexer().getLoc(),
3573 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003574 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003575 return false;
3576}
3577
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003578/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003579/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003580bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003581 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003582 const MCExpr *Value;
3583 // EmitGPRel64Value requires an expression, so we are using base class
3584 // method to evaluate the expression.
3585 if (getParser().parseExpression(Value))
3586 return true;
3587 getParser().getStreamer().EmitGPRel64Value(Value);
3588
3589 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003590 return Error(getLexer().getLoc(),
3591 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003592 Parser.Lex(); // Eat EndOfStatement token.
3593 return false;
3594}
3595
Jack Carter0cd3c192014-01-06 23:27:31 +00003596bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003597 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003598 // Get the option token.
3599 AsmToken Tok = Parser.getTok();
3600 // At the moment only identifiers are supported.
3601 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003602 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003603 Parser.eatToEndOfStatement();
3604 return false;
3605 }
3606
3607 StringRef Option = Tok.getIdentifier();
3608
3609 if (Option == "pic0") {
3610 getTargetStreamer().emitDirectiveOptionPic0();
3611 Parser.Lex();
3612 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3613 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003614 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003615 Parser.eatToEndOfStatement();
3616 }
3617 return false;
3618 }
3619
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003620 if (Option == "pic2") {
3621 getTargetStreamer().emitDirectiveOptionPic2();
3622 Parser.Lex();
3623 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3624 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003625 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003626 Parser.eatToEndOfStatement();
3627 }
3628 return false;
3629 }
3630
Jack Carter0cd3c192014-01-06 23:27:31 +00003631 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003632 Warning(Parser.getTok().getLoc(),
3633 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003634 Parser.eatToEndOfStatement();
3635 return false;
3636}
3637
Daniel Sanders7e527422014-07-10 13:38:23 +00003638/// parseDirectiveModule
3639/// ::= .module oddspreg
3640/// ::= .module nooddspreg
3641/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003642bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003643 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003644 MCAsmLexer &Lexer = getLexer();
3645 SMLoc L = Lexer.getLoc();
3646
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003647 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003648 // TODO : get a better message.
3649 reportParseError(".module directive must appear before any code");
3650 return false;
3651 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003652
3653 if (Lexer.is(AsmToken::Identifier)) {
3654 StringRef Option = Parser.getTok().getString();
3655 Parser.Lex();
3656
3657 if (Option == "oddspreg") {
3658 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3659 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3660
3661 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003662 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003663 return false;
3664 }
3665
3666 return false;
3667 } else if (Option == "nooddspreg") {
3668 if (!isABI_O32()) {
3669 Error(L, "'.module nooddspreg' requires the O32 ABI");
3670 return false;
3671 }
3672
3673 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3674 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3675
3676 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003677 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003678 return false;
3679 }
3680
3681 return false;
3682 } else if (Option == "fp") {
3683 return parseDirectiveModuleFP();
3684 }
3685
3686 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003687 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003688
3689 return false;
3690}
3691
3692/// parseDirectiveModuleFP
3693/// ::= =32
3694/// ::= =xx
3695/// ::= =64
3696bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003697 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003698 MCAsmLexer &Lexer = getLexer();
3699
3700 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003701 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003702 return false;
3703 }
3704 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003705
Daniel Sanders7e527422014-07-10 13:38:23 +00003706 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003707 if (!parseFpABIValue(FpABI, ".module"))
3708 return false;
3709
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003710 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003711 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003712 return false;
3713 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003714
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003715 // Emit appropriate flags.
3716 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003717 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003718 return false;
3719}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003720
Daniel Sanders7e527422014-07-10 13:38:23 +00003721bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003722 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003723 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003724 MCAsmLexer &Lexer = getLexer();
3725
3726 if (Lexer.is(AsmToken::Identifier)) {
3727 StringRef Value = Parser.getTok().getString();
3728 Parser.Lex();
3729
3730 if (Value != "xx") {
3731 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3732 return false;
3733 }
3734
3735 if (!isABI_O32()) {
3736 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3737 return false;
3738 }
3739
Daniel Sanders7e527422014-07-10 13:38:23 +00003740 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003741 return true;
3742 }
3743
3744 if (Lexer.is(AsmToken::Integer)) {
3745 unsigned Value = Parser.getTok().getIntVal();
3746 Parser.Lex();
3747
3748 if (Value != 32 && Value != 64) {
3749 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3750 return false;
3751 }
3752
3753 if (Value == 32) {
3754 if (!isABI_O32()) {
3755 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3756 return false;
3757 }
3758
Daniel Sanders7e527422014-07-10 13:38:23 +00003759 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3760 } else
3761 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003762
Daniel Sanders7e527422014-07-10 13:38:23 +00003763 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003764 }
3765
3766 return false;
3767}
3768
Jack Carter0b744b32012-10-04 02:29:46 +00003769bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003770 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003771 StringRef IDVal = DirectiveID.getString();
3772
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003773 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003774 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003775 if (IDVal == ".dword") {
3776 parseDataDirective(8, DirectiveID.getLoc());
3777 return false;
3778 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003779 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003780 StringRef SymbolName;
3781
3782 if (Parser.parseIdentifier(SymbolName)) {
3783 reportParseError("expected identifier after .ent");
3784 return false;
3785 }
3786
3787 // There's an undocumented extension that allows an integer to
3788 // follow the name of the procedure which AFAICS is ignored by GAS.
3789 // Example: .ent foo,2
3790 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3791 if (getLexer().isNot(AsmToken::Comma)) {
3792 // Even though we accept this undocumented extension for compatibility
3793 // reasons, the additional integer argument does not actually change
3794 // the behaviour of the '.ent' directive, so we would like to discourage
3795 // its use. We do this by not referring to the extended version in
3796 // error messages which are not directly related to its use.
3797 reportParseError("unexpected token, expected end of statement");
3798 return false;
3799 }
3800 Parser.Lex(); // Eat the comma.
3801 const MCExpr *DummyNumber;
3802 int64_t DummyNumberVal;
3803 // If the user was explicitly trying to use the extended version,
3804 // we still give helpful extension-related error messages.
3805 if (Parser.parseExpression(DummyNumber)) {
3806 reportParseError("expected number after comma");
3807 return false;
3808 }
3809 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3810 reportParseError("expected an absolute expression after comma");
3811 return false;
3812 }
3813 }
3814
3815 // If this is not the end of the statement, report an error.
3816 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3817 reportParseError("unexpected token, expected end of statement");
3818 return false;
3819 }
3820
3821 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3822
3823 getTargetStreamer().emitDirectiveEnt(*Sym);
3824 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003825 return false;
3826 }
3827
Jack Carter07c818d2013-01-25 01:31:34 +00003828 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003829 StringRef SymbolName;
3830
3831 if (Parser.parseIdentifier(SymbolName)) {
3832 reportParseError("expected identifier after .end");
3833 return false;
3834 }
3835
3836 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3837 reportParseError("unexpected token, expected end of statement");
3838 return false;
3839 }
3840
3841 if (CurrentFn == nullptr) {
3842 reportParseError(".end used without .ent");
3843 return false;
3844 }
3845
3846 if ((SymbolName != CurrentFn->getName())) {
3847 reportParseError(".end symbol does not match .ent symbol");
3848 return false;
3849 }
3850
3851 getTargetStreamer().emitDirectiveEnd(SymbolName);
3852 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003853 return false;
3854 }
3855
Jack Carter07c818d2013-01-25 01:31:34 +00003856 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003857 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3858 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003859 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003860 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3861 reportParseError("expected stack register");
3862 return false;
3863 }
3864
3865 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3866 if (!StackRegOpnd.isGPRAsmReg()) {
3867 reportParseError(StackRegOpnd.getStartLoc(),
3868 "expected general purpose register");
3869 return false;
3870 }
3871 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3872
3873 if (Parser.getTok().is(AsmToken::Comma))
3874 Parser.Lex();
3875 else {
3876 reportParseError("unexpected token, expected comma");
3877 return false;
3878 }
3879
3880 // Parse the frame size.
3881 const MCExpr *FrameSize;
3882 int64_t FrameSizeVal;
3883
3884 if (Parser.parseExpression(FrameSize)) {
3885 reportParseError("expected frame size value");
3886 return false;
3887 }
3888
3889 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3890 reportParseError("frame size not an absolute expression");
3891 return false;
3892 }
3893
3894 if (Parser.getTok().is(AsmToken::Comma))
3895 Parser.Lex();
3896 else {
3897 reportParseError("unexpected token, expected comma");
3898 return false;
3899 }
3900
3901 // Parse the return register.
3902 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003903 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003904 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3905 reportParseError("expected return register");
3906 return false;
3907 }
3908
3909 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3910 if (!ReturnRegOpnd.isGPRAsmReg()) {
3911 reportParseError(ReturnRegOpnd.getStartLoc(),
3912 "expected general purpose register");
3913 return false;
3914 }
3915
3916 // If this is not the end of the statement, report an error.
3917 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3918 reportParseError("unexpected token, expected end of statement");
3919 return false;
3920 }
3921
3922 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3923 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003924 return false;
3925 }
3926
Jack Carter07c818d2013-01-25 01:31:34 +00003927 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003928 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003929 }
3930
Daniel Sandersd97a6342014-08-13 10:07:34 +00003931 if (IDVal == ".mask" || IDVal == ".fmask") {
3932 // .mask bitmask, frame_offset
3933 // bitmask: One bit for each register used.
3934 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3935 // first register is expected to be saved.
3936 // Examples:
3937 // .mask 0x80000000, -4
3938 // .fmask 0x80000000, -4
3939 //
Jack Carterbe332172012-09-07 00:48:02 +00003940
Daniel Sandersd97a6342014-08-13 10:07:34 +00003941 // Parse the bitmask
3942 const MCExpr *BitMask;
3943 int64_t BitMaskVal;
3944
3945 if (Parser.parseExpression(BitMask)) {
3946 reportParseError("expected bitmask value");
3947 return false;
3948 }
3949
3950 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3951 reportParseError("bitmask not an absolute expression");
3952 return false;
3953 }
3954
3955 if (Parser.getTok().is(AsmToken::Comma))
3956 Parser.Lex();
3957 else {
3958 reportParseError("unexpected token, expected comma");
3959 return false;
3960 }
3961
3962 // Parse the frame_offset
3963 const MCExpr *FrameOffset;
3964 int64_t FrameOffsetVal;
3965
3966 if (Parser.parseExpression(FrameOffset)) {
3967 reportParseError("expected frame offset value");
3968 return false;
3969 }
3970
3971 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3972 reportParseError("frame offset not an absolute expression");
3973 return false;
3974 }
3975
3976 // If this is not the end of the statement, report an error.
3977 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3978 reportParseError("unexpected token, expected end of statement");
3979 return false;
3980 }
3981
3982 if (IDVal == ".mask")
3983 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3984 else
3985 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003986 return false;
3987 }
3988
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003989 if (IDVal == ".nan")
3990 return parseDirectiveNaN();
3991
Jack Carter07c818d2013-01-25 01:31:34 +00003992 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003993 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003994 return false;
3995 }
3996
Rafael Espindolab59fb732014-03-28 18:50:26 +00003997 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003998 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003999 return false;
4000 }
4001
Jack Carter07c818d2013-01-25 01:31:34 +00004002 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004003 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004004 return false;
4005 }
4006
Jack Carter0cd3c192014-01-06 23:27:31 +00004007 if (IDVal == ".option")
4008 return parseDirectiveOption();
4009
4010 if (IDVal == ".abicalls") {
4011 getTargetStreamer().emitDirectiveAbiCalls();
4012 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004013 Error(Parser.getTok().getLoc(),
4014 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004015 // Clear line
4016 Parser.eatToEndOfStatement();
4017 }
4018 return false;
4019 }
4020
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004021 if (IDVal == ".cpsetup")
4022 return parseDirectiveCPSetup();
4023
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004024 if (IDVal == ".module")
4025 return parseDirectiveModule();
4026
Rafael Espindola870c4e92012-01-11 03:56:41 +00004027 return true;
4028}
4029
Rafael Espindola870c4e92012-01-11 03:56:41 +00004030extern "C" void LLVMInitializeMipsAsmParser() {
4031 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4032 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4033 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4034 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4035}
Jack Carterb4dbc172012-09-05 23:34:03 +00004036
4037#define GET_REGISTER_MATCHER
4038#define GET_MATCHER_IMPLEMENTATION
4039#include "MipsGenAsmMatcher.inc"