blob: e53d3c7e29b398b803b91a2cabe245bdc5f1c08b [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
David Blaikie960ea3f2014-06-08 16:18:35 +0000149 bool searchSymbolAlias(OperandVector &Operands);
150
Toma Tabacu13964452014-09-04 13:23:44 +0000151 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000152
Jack Carter30a59822012-10-04 04:03:53 +0000153 bool needsExpansion(MCInst &Inst);
154
Matheus Almeida3813d572014-06-19 14:39:14 +0000155 // Expands assembly pseudo instructions.
156 // Returns false on success, true otherwise.
157 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000158 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000159
160 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000161 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000162
163 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000164 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000165
166 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000167 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000168
Toma Tabacu0d64b202014-08-14 10:29:17 +0000169 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
170 SmallVectorImpl<MCInst> &Instructions);
171
Jack Carter9e65aa32013-03-22 00:05:30 +0000172 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000173 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
174 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000175 bool reportParseError(Twine ErrorMsg);
176 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000177
Jack Carterb5cf5902013-04-17 00:18:04 +0000178 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000179 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000180
Vladimir Medic4c299852013-11-06 11:27:05 +0000181 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000182
183 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000184 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000185 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000186 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000187 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000188 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000189 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000190 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000191 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000192
193 bool parseSetAtDirective();
194 bool parseSetNoAtDirective();
195 bool parseSetMacroDirective();
196 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000197 bool parseSetMsaDirective();
198 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000199 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000200 bool parseSetReorderDirective();
201 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000202 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000203 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000204 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000205 bool parseSetPopDirective();
206 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000207
Jack Carterd76b2372013-03-21 21:44:16 +0000208 bool parseSetAssignment();
209
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000210 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000211 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000212 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000213 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000214 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000215 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
216 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000217
Jack Carterdc1e35d2012-09-06 20:00:02 +0000218 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000219
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000220 bool eatComma(StringRef ErrorStr);
221
Jack Carter1ac53222013-02-20 23:11:17 +0000222 int matchCPURegisterName(StringRef Symbol);
223
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000224 int matchHWRegsRegisterName(StringRef Symbol);
225
Jack Carter873c7242013-01-12 01:03:14 +0000226 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000227
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000228 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000229
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000230 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000231
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000232 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000233
Jack Carter5dc8ac92013-09-25 23:50:44 +0000234 int matchMSA128RegisterName(StringRef Name);
235
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000236 int matchMSA128CtrlRegisterName(StringRef Name);
237
Jack Carterd0bd6422013-04-18 00:41:53 +0000238 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000239
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000240 unsigned getGPR(int RegNo);
241
Matheus Almeida7de68e72014-06-18 14:46:05 +0000242 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000243
244 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000245 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000246
247 // Helper function that checks if the value of a vector index is within the
248 // boundaries of accepted values for each RegisterKind
249 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
250 bool validateMSAIndex(int Val, int RegKind);
251
Daniel Sandersf0df2212014-08-04 12:20:00 +0000252 // Selects a new architecture by updating the FeatureBits with the necessary
253 // info including implied dependencies.
254 // Internally, it clears all the feature bits related to *any* architecture
255 // and selects the new one using the ToggleFeature functionality of the
256 // MCSubtargetInfo object that handles implied dependencies. The reason we
257 // clear all the arch related bits manually is because ToggleFeature only
258 // clears the features that imply the feature being cleared and not the
259 // features implied by the feature being cleared. This is easier to see
260 // with an example:
261 // --------------------------------------------------
262 // | Feature | Implies |
263 // | -------------------------------------------------|
264 // | FeatureMips1 | None |
265 // | FeatureMips2 | FeatureMips1 |
266 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
267 // | FeatureMips4 | FeatureMips3 |
268 // | ... | |
269 // --------------------------------------------------
270 //
271 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
272 // FeatureMipsGP64 | FeatureMips1)
273 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
274 void selectArch(StringRef ArchFeature) {
275 uint64_t FeatureBits = STI.getFeatureBits();
276 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
277 STI.setFeatureBits(FeatureBits);
278 setAvailableFeatures(
279 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000280 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000281 }
282
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000283 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000284 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000285 setAvailableFeatures(
286 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000288 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000289 }
290
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000291 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000292 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000293 setAvailableFeatures(
294 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000296 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000297 }
298
Rafael Espindola870c4e92012-01-11 03:56:41 +0000299public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000300 enum MipsMatchResultTy {
301 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
302#define GET_OPERAND_DIAGNOSTIC_TYPES
303#include "MipsGenAsmMatcher.inc"
304#undef GET_OPERAND_DIAGNOSTIC_TYPES
305
306 };
307
Joey Gouly0e76fa72013-09-12 10:28:05 +0000308 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000309 const MCInstrInfo &MII, const MCTargetOptions &Options)
Rafael Espindola961d4692014-11-11 05:18:41 +0000310 : MCTargetAsmParser(), STI(sti) {
311 MCAsmParserExtension::Initialize(parser);
312
Jack Carterb4dbc172012-09-05 23:34:03 +0000313 // Initialize the set of available features.
314 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000315
316 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000317 AssemblerOptions.push_back(
318 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000319
320 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000321 AssemblerOptions.push_back(
322 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000323
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000324 getTargetStreamer().updateABIInfo(*this);
325
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000326 // Assert exactly one ABI was chosen.
327 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
328 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
329 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
330 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000331
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000332 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000333 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000334
335 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000336 }
337
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000338 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
339 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
340
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000341 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
342 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
343 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
344 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
345 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000346 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000348 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000349 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
350 }
351
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000352 bool inMicroMipsMode() const {
353 return STI.getFeatureBits() & Mips::FeatureMicroMips;
354 }
355 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
356 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
357 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
358 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
359 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
360 bool hasMips32() const {
361 return (STI.getFeatureBits() & Mips::FeatureMips32);
362 }
363 bool hasMips64() const {
364 return (STI.getFeatureBits() & Mips::FeatureMips64);
365 }
366 bool hasMips32r2() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
368 }
369 bool hasMips64r2() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
371 }
372 bool hasMips32r6() const {
373 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
374 }
375 bool hasMips64r6() const {
376 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
377 }
378 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
379 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
380 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
381
382 bool inMips16Mode() const {
383 return STI.getFeatureBits() & Mips::FeatureMips16;
384 }
385 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000386 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000387
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000388 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000389 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000390};
391}
392
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000393namespace {
394
395/// MipsOperand - Instances of this class represent a parsed Mips machine
396/// instruction.
397class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000398public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000399 /// Broad categories of register classes
400 /// The exact class is finalized by the render method.
401 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000402 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000403 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000405 RegKind_FCC = 4, /// FCC
406 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
407 RegKind_MSACtrl = 16, /// MSA control registers
408 RegKind_COP2 = 32, /// COP2
409 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
410 /// context).
411 RegKind_CCR = 128, /// CCR
412 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000413 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000414
415 /// Potentially any (e.g. $1)
416 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
417 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000418 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000419 };
420
421private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000422 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000423 k_Immediate, /// An immediate (possibly involving symbol references)
424 k_Memory, /// Base + Offset Memory Address
425 k_PhysRegister, /// A physical register from the Mips namespace
426 k_RegisterIndex, /// A register index in one or more RegKind.
427 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000428 } Kind;
429
David Blaikie960ea3f2014-06-08 16:18:35 +0000430public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000431 MipsOperand(KindTy K, MipsAsmParser &Parser)
432 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
433
David Blaikie960ea3f2014-06-08 16:18:35 +0000434private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000435 /// For diagnostics, and checking the assembler temporary
436 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000437
Eric Christopher8996c5d2013-03-15 00:42:55 +0000438 struct Token {
439 const char *Data;
440 unsigned Length;
441 };
442
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 struct PhysRegOp {
444 unsigned Num; /// Register Number
445 };
446
447 struct RegIdxOp {
448 unsigned Index; /// Index into the register class
449 RegKind Kind; /// Bitfield of the kinds it could possibly be
450 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000451 };
452
453 struct ImmOp {
454 const MCExpr *Val;
455 };
456
457 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000458 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000459 const MCExpr *Off;
460 };
461
Jack Carterb4dbc172012-09-05 23:34:03 +0000462 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000463 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000464 struct PhysRegOp PhysReg;
465 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000466 struct ImmOp Imm;
467 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000468 };
469
470 SMLoc StartLoc, EndLoc;
471
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000472 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000473 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
474 const MCRegisterInfo *RegInfo,
475 SMLoc S, SMLoc E,
476 MipsAsmParser &Parser) {
477 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000478 Op->RegIdx.Index = Index;
479 Op->RegIdx.RegInfo = RegInfo;
480 Op->RegIdx.Kind = RegKind;
481 Op->StartLoc = S;
482 Op->EndLoc = E;
483 return Op;
484 }
485
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000486public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000487 /// Coerce the register to GPR32 and return the real register for the current
488 /// target.
489 unsigned getGPR32Reg() const {
490 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000491 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000492 unsigned ClassID = Mips::GPR32RegClassID;
493 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000494 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000495
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000496 /// Coerce the register to GPR32 and return the real register for the current
497 /// target.
498 unsigned getGPRMM16Reg() const {
499 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
500 unsigned ClassID = Mips::GPR32RegClassID;
501 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
502 }
503
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000504 /// Coerce the register to GPR64 and return the real register for the current
505 /// target.
506 unsigned getGPR64Reg() const {
507 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
508 unsigned ClassID = Mips::GPR64RegClassID;
509 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000510 }
511
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000512private:
513 /// Coerce the register to AFGR64 and return the real register for the current
514 /// target.
515 unsigned getAFGR64Reg() const {
516 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
517 if (RegIdx.Index % 2 != 0)
518 AsmParser.Warning(StartLoc, "Float register should be even.");
519 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
520 .getRegister(RegIdx.Index / 2);
521 }
522
523 /// Coerce the register to FGR64 and return the real register for the current
524 /// target.
525 unsigned getFGR64Reg() const {
526 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
527 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
528 .getRegister(RegIdx.Index);
529 }
530
531 /// Coerce the register to FGR32 and return the real register for the current
532 /// target.
533 unsigned getFGR32Reg() const {
534 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
535 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
536 .getRegister(RegIdx.Index);
537 }
538
539 /// Coerce the register to FGRH32 and return the real register for the current
540 /// target.
541 unsigned getFGRH32Reg() const {
542 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
543 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
544 .getRegister(RegIdx.Index);
545 }
546
547 /// Coerce the register to FCC and return the real register for the current
548 /// target.
549 unsigned getFCCReg() const {
550 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
551 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
552 .getRegister(RegIdx.Index);
553 }
554
555 /// Coerce the register to MSA128 and return the real register for the current
556 /// target.
557 unsigned getMSA128Reg() const {
558 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
559 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
560 // identical
561 unsigned ClassID = Mips::MSA128BRegClassID;
562 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
563 }
564
565 /// Coerce the register to MSACtrl and return the real register for the
566 /// current target.
567 unsigned getMSACtrlReg() const {
568 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
569 unsigned ClassID = Mips::MSACtrlRegClassID;
570 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
571 }
572
573 /// Coerce the register to COP2 and return the real register for the
574 /// current target.
575 unsigned getCOP2Reg() const {
576 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
577 unsigned ClassID = Mips::COP2RegClassID;
578 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
579 }
580
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000581 /// Coerce the register to COP3 and return the real register for the
582 /// current target.
583 unsigned getCOP3Reg() const {
584 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
585 unsigned ClassID = Mips::COP3RegClassID;
586 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
587 }
588
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000589 /// Coerce the register to ACC64DSP and return the real register for the
590 /// current target.
591 unsigned getACC64DSPReg() const {
592 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
593 unsigned ClassID = Mips::ACC64DSPRegClassID;
594 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
595 }
596
597 /// Coerce the register to HI32DSP and return the real register for the
598 /// current target.
599 unsigned getHI32DSPReg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
601 unsigned ClassID = Mips::HI32DSPRegClassID;
602 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
603 }
604
605 /// Coerce the register to LO32DSP and return the real register for the
606 /// current target.
607 unsigned getLO32DSPReg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
609 unsigned ClassID = Mips::LO32DSPRegClassID;
610 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to CCR and return the real register for the
614 /// current target.
615 unsigned getCCRReg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
617 unsigned ClassID = Mips::CCRRegClassID;
618 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
619 }
620
621 /// Coerce the register to HWRegs and return the real register for the
622 /// current target.
623 unsigned getHWRegsReg() const {
624 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
625 unsigned ClassID = Mips::HWRegsRegClassID;
626 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
627 }
628
629public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000630 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000631 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000632 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000633 Inst.addOperand(MCOperand::CreateImm(0));
634 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
635 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
636 else
637 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000638 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000639
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 void addRegOperands(MCInst &Inst, unsigned N) const {
641 llvm_unreachable("Use a custom parser instead");
642 }
643
Daniel Sanders21bce302014-04-01 12:35:23 +0000644 /// Render the operand to an MCInst as a GPR32
645 /// Asserts if the wrong number of operands are requested, or the operand
646 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
648 assert(N == 1 && "Invalid number of operands!");
649 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
650 }
651
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000652 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
653 assert(N == 1 && "Invalid number of operands!");
654 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
655 }
656
Daniel Sanders21bce302014-04-01 12:35:23 +0000657 /// Render the operand to an MCInst as a GPR64
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 addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
661 assert(N == 1 && "Invalid number of operands!");
662 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
663 }
664
665 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
666 assert(N == 1 && "Invalid number of operands!");
667 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
668 }
669
670 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
673 }
674
675 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
676 assert(N == 1 && "Invalid number of operands!");
677 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000678 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000679 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000680 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
681 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 }
683
684 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
685 assert(N == 1 && "Invalid number of operands!");
686 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
687 }
688
689 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
690 assert(N == 1 && "Invalid number of operands!");
691 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
692 }
693
694 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
695 assert(N == 1 && "Invalid number of operands!");
696 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
697 }
698
699 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
700 assert(N == 1 && "Invalid number of operands!");
701 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
702 }
703
704 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
705 assert(N == 1 && "Invalid number of operands!");
706 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
707 }
708
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000709 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
710 assert(N == 1 && "Invalid number of operands!");
711 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
712 }
713
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000714 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
715 assert(N == 1 && "Invalid number of operands!");
716 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
717 }
718
719 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
720 assert(N == 1 && "Invalid number of operands!");
721 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
722 }
723
724 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
725 assert(N == 1 && "Invalid number of operands!");
726 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
727 }
728
729 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
730 assert(N == 1 && "Invalid number of operands!");
731 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
732 }
733
734 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
735 assert(N == 1 && "Invalid number of operands!");
736 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
737 }
738
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000739 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000740 assert(N == 1 && "Invalid number of operands!");
741 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000742 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000743 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000744
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000745 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000746 assert(N == 2 && "Invalid number of operands!");
747
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000749
750 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000751 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000752 }
753
Craig Topper56c590a2014-04-29 07:58:02 +0000754 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 // As a special case until we sort out the definition of div/divu, pretend
756 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
757 if (isGPRAsmReg() && RegIdx.Index == 0)
758 return true;
759
760 return Kind == k_PhysRegister;
761 }
762 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000763 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000764 bool isConstantImm() const {
765 return isImm() && dyn_cast<MCConstantExpr>(getImm());
766 }
Craig Topper56c590a2014-04-29 07:58:02 +0000767 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 // Note: It's not possible to pretend that other operand kinds are tokens.
769 // The matcher emitter checks tokens first.
770 return Kind == k_Token;
771 }
Craig Topper56c590a2014-04-29 07:58:02 +0000772 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000773 bool isConstantMemOff() const {
774 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
775 }
776 template <unsigned Bits> bool isMemWithSimmOffset() const {
777 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
778 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000779 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 bool isLSAImm() const {
781 if (!isConstantImm())
782 return false;
783 int64_t Val = getConstantImm();
784 return 1 <= Val && Val <= 4;
785 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000786
787 StringRef getToken() const {
788 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000789 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000790 }
791
Craig Topper56c590a2014-04-29 07:58:02 +0000792 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 // As a special case until we sort out the definition of div/divu, pretend
794 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
795 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
796 RegIdx.Kind & RegKind_GPR)
797 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000798
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 assert(Kind == k_PhysRegister && "Invalid access!");
800 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000801 }
802
Jack Carterb4dbc172012-09-05 23:34:03 +0000803 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000805 return Imm.Val;
806 }
807
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 int64_t getConstantImm() const {
809 const MCExpr *Val = getImm();
810 return static_cast<const MCConstantExpr *>(Val)->getValue();
811 }
812
813 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000814 assert((Kind == k_Memory) && "Invalid access!");
815 return Mem.Base;
816 }
817
818 const MCExpr *getMemOff() const {
819 assert((Kind == k_Memory) && "Invalid access!");
820 return Mem.Off;
821 }
822
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000823 int64_t getConstantMemOff() const {
824 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
825 }
826
David Blaikie960ea3f2014-06-08 16:18:35 +0000827 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
828 MipsAsmParser &Parser) {
829 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000830 Op->Tok.Data = Str.data();
831 Op->Tok.Length = Str.size();
832 Op->StartLoc = S;
833 Op->EndLoc = S;
834 return Op;
835 }
836
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 /// Create a numeric register (e.g. $1). The exact register remains
838 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000839 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000840 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000841 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000842 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000844 }
845
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 /// Create a register that is definitely a GPR.
847 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000848 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000849 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000850 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000851 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000852 }
853
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 /// Create a register that is definitely a FGR.
855 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000856 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000857 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000858 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
860 }
861
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000862 /// Create a register that is definitely a HWReg.
863 /// This is typically only used for named registers such as $hwr_cpunum.
864 static std::unique_ptr<MipsOperand>
865 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
866 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
867 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
868 }
869
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 /// Create a register that is definitely an FCC.
871 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000872 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000873 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000874 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
876 }
877
878 /// Create a register that is definitely an ACC.
879 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000880 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000881 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000882 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
884 }
885
886 /// Create a register that is definitely an MSA128.
887 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000888 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000889 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000890 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000891 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
892 }
893
894 /// Create a register that is definitely an MSACtrl.
895 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000896 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000897 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000898 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
900 }
901
David Blaikie960ea3f2014-06-08 16:18:35 +0000902 static std::unique_ptr<MipsOperand>
903 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
904 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000905 Op->Imm.Val = Val;
906 Op->StartLoc = S;
907 Op->EndLoc = E;
908 return Op;
909 }
910
David Blaikie960ea3f2014-06-08 16:18:35 +0000911 static std::unique_ptr<MipsOperand>
912 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
913 SMLoc E, MipsAsmParser &Parser) {
914 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
915 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000916 Op->Mem.Off = Off;
917 Op->StartLoc = S;
918 Op->EndLoc = E;
919 return Op;
920 }
921
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 bool isGPRAsmReg() const {
923 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000924 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000925 bool isMM16AsmReg() const {
926 if (!(isRegIdx() && RegIdx.Kind))
927 return false;
928 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
929 || RegIdx.Index == 16 || RegIdx.Index == 17);
930 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000931 bool isFGRAsmReg() const {
932 // AFGR64 is $0-$15 but we handle this in getAFGR64()
933 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000934 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 bool isHWRegsAsmReg() const {
936 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000937 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 bool isCCRAsmReg() const {
939 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000940 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000941 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000942 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
943 return false;
944 if (!AsmParser.hasEightFccRegisters())
945 return RegIdx.Index == 0;
946 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000947 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 bool isACCAsmReg() const {
949 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000950 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 bool isCOP2AsmReg() const {
952 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000953 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000954 bool isCOP3AsmReg() const {
955 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
956 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000957 bool isMSA128AsmReg() const {
958 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000959 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000960 bool isMSACtrlAsmReg() const {
961 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000962 }
963
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000965 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000967 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000968
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000969 virtual ~MipsOperand() {
970 switch (Kind) {
971 case k_Immediate:
972 break;
973 case k_Memory:
974 delete Mem.Base;
975 break;
976 case k_PhysRegister:
977 case k_RegisterIndex:
978 case k_Token:
979 break;
980 }
981 }
982
Craig Topper56c590a2014-04-29 07:58:02 +0000983 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 switch (Kind) {
985 case k_Immediate:
986 OS << "Imm<";
987 Imm.Val->print(OS);
988 OS << ">";
989 break;
990 case k_Memory:
991 OS << "Mem<";
992 Mem.Base->print(OS);
993 OS << ", ";
994 Mem.Off->print(OS);
995 OS << ">";
996 break;
997 case k_PhysRegister:
998 OS << "PhysReg<" << PhysReg.Num << ">";
999 break;
1000 case k_RegisterIndex:
1001 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1002 break;
1003 case k_Token:
1004 OS << Tok.Data;
1005 break;
1006 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001007 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001008}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001009} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001010
Jack Carter9e65aa32013-03-22 00:05:30 +00001011namespace llvm {
1012extern const MCInstrDesc MipsInsts[];
1013}
1014static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1015 return MipsInsts[Opcode];
1016}
1017
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001018static bool hasShortDelaySlot(unsigned Opcode) {
1019 switch (Opcode) {
1020 case Mips::JALS_MM:
1021 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001022 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001023 case Mips::BGEZALS_MM:
1024 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001025 return true;
1026 default:
1027 return false;
1028 }
1029}
1030
Jack Carter9e65aa32013-03-22 00:05:30 +00001031bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001032 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001033 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001034
Jack Carter9e65aa32013-03-22 00:05:30 +00001035 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001036
1037 if (MCID.isBranch() || MCID.isCall()) {
1038 const unsigned Opcode = Inst.getOpcode();
1039 MCOperand Offset;
1040
1041 switch (Opcode) {
1042 default:
1043 break;
1044 case Mips::BEQ:
1045 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 case Mips::BEQ_MM:
1047 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001048 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001049 Offset = Inst.getOperand(2);
1050 if (!Offset.isImm())
1051 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001052 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001053 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001054 if (OffsetToAlignment(Offset.getImm(),
1055 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001056 return Error(IDLoc, "branch to misaligned address");
1057 break;
1058 case Mips::BGEZ:
1059 case Mips::BGTZ:
1060 case Mips::BLEZ:
1061 case Mips::BLTZ:
1062 case Mips::BGEZAL:
1063 case Mips::BLTZAL:
1064 case Mips::BC1F:
1065 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 case Mips::BGEZ_MM:
1067 case Mips::BGTZ_MM:
1068 case Mips::BLEZ_MM:
1069 case Mips::BLTZ_MM:
1070 case Mips::BGEZAL_MM:
1071 case Mips::BLTZAL_MM:
1072 case Mips::BC1F_MM:
1073 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001074 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001075 Offset = Inst.getOperand(1);
1076 if (!Offset.isImm())
1077 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001078 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001079 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001080 if (OffsetToAlignment(Offset.getImm(),
1081 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001082 return Error(IDLoc, "branch to misaligned address");
1083 break;
1084 }
1085 }
1086
Daniel Sandersa84989a2014-06-16 13:25:35 +00001087 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1088 // We still accept it but it is a normal nop.
1089 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1090 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1091 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1092 "nop instruction");
1093 }
1094
Toma Tabacu9db22db2014-09-09 10:15:38 +00001095 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001096 // If this instruction has a delay slot and .set reorder is active,
1097 // emit a NOP after it.
1098 Instructions.push_back(Inst);
1099 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001100 if (hasShortDelaySlot(Inst.getOpcode())) {
1101 NopInst.setOpcode(Mips::MOVE16_MM);
1102 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1103 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1104 } else {
1105 NopInst.setOpcode(Mips::SLL);
1106 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1107 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1108 NopInst.addOperand(MCOperand::CreateImm(0));
1109 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001110 Instructions.push_back(NopInst);
1111 return false;
1112 }
1113
Jack Carter9e65aa32013-03-22 00:05:30 +00001114 if (MCID.mayLoad() || MCID.mayStore()) {
1115 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 // reference or immediate we may have to expand instructions.
1117 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001118 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001119 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1120 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001121 MCOperand &Op = Inst.getOperand(i);
1122 if (Op.isImm()) {
1123 int MemOffset = Op.getImm();
1124 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001125 // Offset can't exceed 16bit value.
1126 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001127 return false;
1128 }
1129 } else if (Op.isExpr()) {
1130 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001132 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001133 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001134 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001135 // Expand symbol.
1136 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001137 return false;
1138 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001139 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001141 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001142 }
1143 }
1144 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001146 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001147
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001148 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1149 if (inMicroMipsMode()) {
1150 MCOperand Opnd;
1151 int Imm;
1152
1153 switch (Inst.getOpcode()) {
1154 default:
1155 break;
1156 case Mips::ADDIUS5_MM:
1157 Opnd = Inst.getOperand(2);
1158 if (!Opnd.isImm())
1159 return Error(IDLoc, "expected immediate operand kind");
1160 Imm = Opnd.getImm();
1161 if (Imm < -8 || Imm > 7)
1162 return Error(IDLoc, "immediate operand value out of range");
1163 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001164 case Mips::ADDIUSP_MM:
1165 Opnd = Inst.getOperand(0);
1166 if (!Opnd.isImm())
1167 return Error(IDLoc, "expected immediate operand kind");
1168 Imm = Opnd.getImm();
1169 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1170 Imm % 4 != 0)
1171 return Error(IDLoc, "immediate operand value out of range");
1172 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001173 case Mips::SLL16_MM:
1174 case Mips::SRL16_MM:
1175 Opnd = Inst.getOperand(2);
1176 if (!Opnd.isImm())
1177 return Error(IDLoc, "expected immediate operand kind");
1178 Imm = Opnd.getImm();
1179 if (Imm < 1 || Imm > 8)
1180 return Error(IDLoc, "immediate operand value out of range");
1181 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001182 case Mips::LI16_MM:
1183 Opnd = Inst.getOperand(1);
1184 if (!Opnd.isImm())
1185 return Error(IDLoc, "expected immediate operand kind");
1186 Imm = Opnd.getImm();
1187 if (Imm < -1 || Imm > 126)
1188 return Error(IDLoc, "immediate operand value out of range");
1189 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001190 case Mips::ADDIUR2_MM:
1191 Opnd = Inst.getOperand(2);
1192 if (!Opnd.isImm())
1193 return Error(IDLoc, "expected immediate operand kind");
1194 Imm = Opnd.getImm();
1195 if (!(Imm == 1 || Imm == -1 ||
1196 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1197 return Error(IDLoc, "immediate operand value out of range");
1198 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001199 case Mips::ADDIUR1SP_MM:
1200 Opnd = Inst.getOperand(1);
1201 if (!Opnd.isImm())
1202 return Error(IDLoc, "expected immediate operand kind");
1203 Imm = Opnd.getImm();
1204 if (OffsetToAlignment(Imm, 4LL))
1205 return Error(IDLoc, "misaligned immediate operand value");
1206 if (Imm < 0 || Imm > 255)
1207 return Error(IDLoc, "immediate operand value out of range");
1208 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001209 case Mips::ANDI16_MM:
1210 Opnd = Inst.getOperand(2);
1211 if (!Opnd.isImm())
1212 return Error(IDLoc, "expected immediate operand kind");
1213 Imm = Opnd.getImm();
1214 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1215 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1216 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1217 return Error(IDLoc, "immediate operand value out of range");
1218 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001219 }
1220 }
1221
Jack Carter9e65aa32013-03-22 00:05:30 +00001222 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001223 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001224 else
1225 Instructions.push_back(Inst);
1226
1227 return false;
1228}
1229
Jack Carter30a59822012-10-04 04:03:53 +00001230bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1231
Jack Carterd0bd6422013-04-18 00:41:53 +00001232 switch (Inst.getOpcode()) {
1233 case Mips::LoadImm32Reg:
1234 case Mips::LoadAddr32Imm:
1235 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001236 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001237 return true;
1238 default:
1239 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001240 }
1241}
Jack Carter92995f12012-10-06 00:53:28 +00001242
Matheus Almeida3813d572014-06-19 14:39:14 +00001243bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001244 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001245 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001246 default:
1247 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001248 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001249 case Mips::LoadImm32Reg:
1250 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001251 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001252 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001253 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001254 return true;
1255 }
1256 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001257 case Mips::LoadAddr32Imm:
1258 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1259 case Mips::LoadAddr32Reg:
1260 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1261 }
Jack Carter30a59822012-10-04 04:03:53 +00001262}
Jack Carter92995f12012-10-06 00:53:28 +00001263
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001264namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001265template <bool PerformShift>
1266void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001267 SmallVectorImpl<MCInst> &Instructions) {
1268 MCInst tmpInst;
1269 if (PerformShift) {
1270 tmpInst.setOpcode(Mips::DSLL);
1271 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1272 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1273 tmpInst.addOperand(MCOperand::CreateImm(16));
1274 tmpInst.setLoc(IDLoc);
1275 Instructions.push_back(tmpInst);
1276 tmpInst.clear();
1277 }
1278 tmpInst.setOpcode(Mips::ORi);
1279 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1280 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001281 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001282 tmpInst.setLoc(IDLoc);
1283 Instructions.push_back(tmpInst);
1284}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001285
1286template <int Shift, bool PerformShift>
1287void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1288 SmallVectorImpl<MCInst> &Instructions) {
1289 createShiftOr<PerformShift>(
1290 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1291 IDLoc, Instructions);
1292}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001293}
1294
Matheus Almeida3813d572014-06-19 14:39:14 +00001295bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001296 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001297 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001298 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001299 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001300 const MCOperand &RegOp = Inst.getOperand(0);
1301 assert(RegOp.isReg() && "expected register operand kind");
1302
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001303 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001304 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001305 // FIXME: gas has a special case for values that are 000...1111, which
1306 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001307 if (0 <= ImmValue && ImmValue <= 65535) {
1308 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001309 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001310 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001311 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001312 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001313 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001314 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001315 } else if (ImmValue < 0 && ImmValue >= -32768) {
1316 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001317 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001318 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001319 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001320 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001321 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001322 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001323 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1324 // For any value of j that is representable as a 32-bit integer, create
1325 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001326 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001327 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001328 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001329 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1330 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001331 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001332 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1333 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001334 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001335 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001336 return true;
1337 }
1338
1339 // <------- lo32 ------>
1340 // <------- hi32 ------>
1341 // <- hi16 -> <- lo16 ->
1342 // _________________________________
1343 // | | | |
1344 // | 16-bytes | 16-bytes | 16-bytes |
1345 // |__________|__________|__________|
1346 //
1347 // For any value of j that is representable as a 48-bit integer, create
1348 // a sequence of:
1349 // li d,j => lui d,hi16(j)
1350 // ori d,d,hi16(lo32(j))
1351 // dsll d,d,16
1352 // ori d,d,lo16(lo32(j))
1353 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001354 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001355 tmpInst.addOperand(
1356 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001357 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001358 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1359 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1360 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001361 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001362 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001363 return true;
1364 }
1365
1366 // <------- hi32 ------> <------- lo32 ------>
1367 // <- hi16 -> <- lo16 ->
1368 // ___________________________________________
1369 // | | | | |
1370 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1371 // |__________|__________|__________|__________|
1372 //
1373 // For any value of j that isn't representable as a 48-bit integer.
1374 // li d,j => lui d,hi16(j)
1375 // ori d,d,lo16(hi32(j))
1376 // dsll d,d,16
1377 // ori d,d,hi16(lo32(j))
1378 // dsll d,d,16
1379 // ori d,d,lo16(lo32(j))
1380 tmpInst.setOpcode(Mips::LUi);
1381 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1382 tmpInst.addOperand(
1383 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1384 Instructions.push_back(tmpInst);
1385 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1386 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1387 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001388 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001389 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001390}
Jack Carter92995f12012-10-06 00:53:28 +00001391
Matheus Almeida3813d572014-06-19 14:39:14 +00001392bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001393MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1394 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001395 MCInst tmpInst;
1396 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001397 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1398 "expected immediate operand kind");
1399 if (!ImmOp.isImm()) {
1400 expandLoadAddressSym(Inst, IDLoc, Instructions);
1401 return false;
1402 }
Jack Carter543fdf82012-10-09 23:29:45 +00001403 const MCOperand &SrcRegOp = Inst.getOperand(1);
1404 assert(SrcRegOp.isReg() && "expected register operand kind");
1405 const MCOperand &DstRegOp = Inst.getOperand(0);
1406 assert(DstRegOp.isReg() && "expected register operand kind");
1407 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001408 if (-32768 <= ImmValue && ImmValue <= 65535) {
1409 // For -32768 <= j <= 65535.
1410 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001411 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001412 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1413 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1414 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1415 Instructions.push_back(tmpInst);
1416 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 // For any other value of j that is representable as a 32-bit integer.
1418 // la d,j(s) => lui d,hi16(j)
1419 // ori d,d,lo16(j)
1420 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001421 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001422 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1423 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1424 Instructions.push_back(tmpInst);
1425 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001426 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001427 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1428 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1429 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1430 Instructions.push_back(tmpInst);
1431 tmpInst.clear();
1432 tmpInst.setOpcode(Mips::ADDu);
1433 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1434 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1435 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1436 Instructions.push_back(tmpInst);
1437 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001438 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001439}
1440
Matheus Almeida3813d572014-06-19 14:39:14 +00001441bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001442MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1443 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001444 MCInst tmpInst;
1445 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001446 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1447 "expected immediate operand kind");
1448 if (!ImmOp.isImm()) {
1449 expandLoadAddressSym(Inst, IDLoc, Instructions);
1450 return false;
1451 }
Jack Carter543fdf82012-10-09 23:29:45 +00001452 const MCOperand &RegOp = Inst.getOperand(0);
1453 assert(RegOp.isReg() && "expected register operand kind");
1454 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001455 if (-32768 <= ImmValue && ImmValue <= 65535) {
1456 // For -32768 <= j <= 65535.
1457 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001458 tmpInst.setOpcode(Mips::ADDiu);
1459 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001460 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001461 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1462 Instructions.push_back(tmpInst);
1463 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 // For any other value of j that is representable as a 32-bit integer.
1465 // la d,j => lui d,hi16(j)
1466 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001467 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001468 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1469 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1470 Instructions.push_back(tmpInst);
1471 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001472 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001473 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1474 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1475 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1476 Instructions.push_back(tmpInst);
1477 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001478 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001479}
1480
Toma Tabacu0d64b202014-08-14 10:29:17 +00001481void
1482MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1483 SmallVectorImpl<MCInst> &Instructions) {
1484 // FIXME: If we do have a valid at register to use, we should generate a
1485 // slightly shorter sequence here.
1486 MCInst tmpInst;
1487 int ExprOperandNo = 1;
1488 // Sometimes the assembly parser will get the immediate expression as
1489 // a $zero + an immediate.
1490 if (Inst.getNumOperands() == 3) {
1491 assert(Inst.getOperand(1).getReg() ==
1492 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1493 ExprOperandNo = 2;
1494 }
1495 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1496 assert(SymOp.isExpr() && "expected symbol operand kind");
1497 const MCOperand &RegOp = Inst.getOperand(0);
1498 unsigned RegNo = RegOp.getReg();
1499 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1500 const MCSymbolRefExpr *HiExpr =
1501 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1502 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1503 const MCSymbolRefExpr *LoExpr =
1504 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1505 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1506 if (isGP64bit()) {
1507 // If it's a 64-bit architecture, expand to:
1508 // la d,sym => lui d,highest(sym)
1509 // ori d,d,higher(sym)
1510 // dsll d,d,16
1511 // ori d,d,hi16(sym)
1512 // dsll d,d,16
1513 // ori d,d,lo16(sym)
1514 const MCSymbolRefExpr *HighestExpr =
1515 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1516 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1517 const MCSymbolRefExpr *HigherExpr =
1518 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1519 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1520
1521 tmpInst.setOpcode(Mips::LUi);
1522 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1523 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1524 Instructions.push_back(tmpInst);
1525
1526 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1527 Instructions);
1528 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1529 Instructions);
1530 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1531 Instructions);
1532 } else {
1533 // Otherwise, expand to:
1534 // la d,sym => lui d,hi16(sym)
1535 // ori d,d,lo16(sym)
1536 tmpInst.setOpcode(Mips::LUi);
1537 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1538 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1539 Instructions.push_back(tmpInst);
1540
1541 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1542 Instructions);
1543 }
1544}
1545
Jack Carter9e65aa32013-03-22 00:05:30 +00001546void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001547 SmallVectorImpl<MCInst> &Instructions,
1548 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001549 const MCSymbolRefExpr *SR;
1550 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001551 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001552 const MCExpr *ExprOffset;
1553 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001554 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001555 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1556 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001558 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1559 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001560 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001561 if (isImmOpnd) {
1562 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1563 ImmOffset = Inst.getOperand(2).getImm();
1564 LoOffset = ImmOffset & 0x0000ffff;
1565 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001566 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001567 if (LoOffset & 0x8000)
1568 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001569 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001570 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001571 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001572 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001573 // These are some of the types of expansions we perform here:
1574 // 1) lw $8, sym => lui $8, %hi(sym)
1575 // lw $8, %lo(sym)($8)
1576 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1577 // add $8, $8, $9
1578 // lw $8, %lo(offset)($9)
1579 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1580 // add $at, $at, $8
1581 // lw $8, %lo(offset)($at)
1582 // 4) sw $8, sym => lui $at, %hi(sym)
1583 // sw $8, %lo(sym)($at)
1584 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1585 // add $at, $at, $8
1586 // sw $8, %lo(offset)($at)
1587 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1588 // ldc1 $f0, %lo(sym)($at)
1589 //
1590 // For load instructions we can use the destination register as a temporary
1591 // if base and dst are different (examples 1 and 2) and if the base register
1592 // is general purpose otherwise we must use $at (example 6) and error if it's
1593 // not available. For stores we must use $at (examples 4 and 5) because we
1594 // must not clobber the source register setting up the offset.
1595 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1596 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1597 unsigned RegClassIDOp0 =
1598 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1599 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1600 (RegClassIDOp0 == Mips::GPR64RegClassID);
1601 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001602 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001603 else {
1604 int AT = getATReg(IDLoc);
1605 // At this point we need AT to perform the expansions and we exit if it is
1606 // not available.
1607 if (!AT)
1608 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001609 TmpRegNum = getReg(
1610 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001611 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001612
Jack Carter9e65aa32013-03-22 00:05:30 +00001613 TempInst.setOpcode(Mips::LUi);
1614 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1615 if (isImmOpnd)
1616 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1617 else {
1618 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001619 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1621 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1622 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001623 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001624 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001625 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001626 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001627 }
1628 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001630 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001632 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001634 TempInst.setOpcode(Mips::ADDu);
1635 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1636 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1637 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1638 Instructions.push_back(TempInst);
1639 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001640 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001641 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001642 TempInst.setOpcode(Inst.getOpcode());
1643 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1644 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1645 if (isImmOpnd)
1646 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1647 else {
1648 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001649 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1650 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1651 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001652 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001653 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001654 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001655 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001656 }
1657 }
1658 Instructions.push_back(TempInst);
1659 TempInst.clear();
1660}
1661
Matheus Almeida595fcab2014-06-11 15:05:56 +00001662unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1663 // As described by the Mips32r2 spec, the registers Rd and Rs for
1664 // jalr.hb must be different.
1665 unsigned Opcode = Inst.getOpcode();
1666
1667 if (Opcode == Mips::JALR_HB &&
1668 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1669 return Match_RequiresDifferentSrcAndDst;
1670
1671 return Match_Success;
1672}
1673
David Blaikie960ea3f2014-06-08 16:18:35 +00001674bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1675 OperandVector &Operands,
1676 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001677 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001678 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001679
Jack Carterb4dbc172012-09-05 23:34:03 +00001680 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001681 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001682 unsigned MatchResult =
1683 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001684
1685 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001686 default:
1687 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001688 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001689 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001690 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001691 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001692 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001693 return false;
1694 }
1695 case Match_MissingFeature:
1696 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1697 return true;
1698 case Match_InvalidOperand: {
1699 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001700 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001701 if (ErrorInfo >= Operands.size())
1702 return Error(IDLoc, "too few operands for instruction");
1703
David Blaikie960ea3f2014-06-08 16:18:35 +00001704 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 if (ErrorLoc == SMLoc())
1706 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001707 }
1708
1709 return Error(ErrorLoc, "invalid operand for instruction");
1710 }
1711 case Match_MnemonicFail:
1712 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001713 case Match_RequiresDifferentSrcAndDst:
1714 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001715 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001716 return true;
1717}
1718
Toma Tabacu13964452014-09-04 13:23:44 +00001719void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001720 if ((RegIndex != 0) &&
1721 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001722 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001723 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001724 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001725 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001726 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001727 }
1728}
1729
Daniel Sandersef638fe2014-10-03 15:37:37 +00001730void
1731MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1732 SMRange Range, bool ShowColors) {
1733 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001734 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001735 ShowColors);
1736}
1737
Jack Carter1ac53222013-02-20 23:11:17 +00001738int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001739 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001740
Vladimir Medic4c299852013-11-06 11:27:05 +00001741 CC = StringSwitch<unsigned>(Name)
1742 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001743 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001744 .Case("a0", 4)
1745 .Case("a1", 5)
1746 .Case("a2", 6)
1747 .Case("a3", 7)
1748 .Case("v0", 2)
1749 .Case("v1", 3)
1750 .Case("s0", 16)
1751 .Case("s1", 17)
1752 .Case("s2", 18)
1753 .Case("s3", 19)
1754 .Case("s4", 20)
1755 .Case("s5", 21)
1756 .Case("s6", 22)
1757 .Case("s7", 23)
1758 .Case("k0", 26)
1759 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001760 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001761 .Case("sp", 29)
1762 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001763 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001764 .Case("ra", 31)
1765 .Case("t0", 8)
1766 .Case("t1", 9)
1767 .Case("t2", 10)
1768 .Case("t3", 11)
1769 .Case("t4", 12)
1770 .Case("t5", 13)
1771 .Case("t6", 14)
1772 .Case("t7", 15)
1773 .Case("t8", 24)
1774 .Case("t9", 25)
1775 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001776
Toma Tabacufda445c2014-09-15 15:33:01 +00001777 if (!(isABI_N32() || isABI_N64()))
1778 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001779
Daniel Sandersef638fe2014-10-03 15:37:37 +00001780 if (12 <= CC && CC <= 15) {
1781 // Name is one of t4-t7
1782 AsmToken RegTok = getLexer().peekTok();
1783 SMRange RegRange = RegTok.getLocRange();
1784
1785 StringRef FixedName = StringSwitch<StringRef>(Name)
1786 .Case("t4", "t0")
1787 .Case("t5", "t1")
1788 .Case("t6", "t2")
1789 .Case("t7", "t3")
1790 .Default("");
1791 assert(FixedName != "" && "Register name is not one of t4-t7.");
1792
1793 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1794 "Did you mean $" + FixedName + "?", RegRange);
1795 }
1796
Toma Tabacufda445c2014-09-15 15:33:01 +00001797 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1798 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1799 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1800 if (8 <= CC && CC <= 11)
1801 CC += 4;
1802
1803 if (CC == -1)
1804 CC = StringSwitch<unsigned>(Name)
1805 .Case("a4", 8)
1806 .Case("a5", 9)
1807 .Case("a6", 10)
1808 .Case("a7", 11)
1809 .Case("kt0", 26)
1810 .Case("kt1", 27)
1811 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001812
1813 return CC;
1814}
Jack Carterd0bd6422013-04-18 00:41:53 +00001815
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001816int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
1817 int CC;
1818
1819 CC = StringSwitch<unsigned>(Name)
1820 .Case("hwr_cpunum", 0)
1821 .Case("hwr_synci_step", 1)
1822 .Case("hwr_cc", 2)
1823 .Case("hwr_ccres", 3)
1824 .Default(-1);
1825
1826 return CC;
1827}
1828
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001829int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001830
Jack Cartera63b16a2012-09-07 00:23:42 +00001831 if (Name[0] == 'f') {
1832 StringRef NumString = Name.substr(1);
1833 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001834 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001835 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001836 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001837 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001838 return IntVal;
1839 }
1840 return -1;
1841}
Jack Cartera63b16a2012-09-07 00:23:42 +00001842
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001843int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1844
1845 if (Name.startswith("fcc")) {
1846 StringRef NumString = Name.substr(3);
1847 unsigned IntVal;
1848 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001849 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001850 if (IntVal > 7) // There are only 8 fcc registers.
1851 return -1;
1852 return IntVal;
1853 }
1854 return -1;
1855}
1856
1857int MipsAsmParser::matchACRegisterName(StringRef Name) {
1858
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001859 if (Name.startswith("ac")) {
1860 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001861 unsigned IntVal;
1862 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001863 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001864 if (IntVal > 3) // There are only 3 acc registers.
1865 return -1;
1866 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001867 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001868 return -1;
1869}
Jack Carterd0bd6422013-04-18 00:41:53 +00001870
Jack Carter5dc8ac92013-09-25 23:50:44 +00001871int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1872 unsigned IntVal;
1873
1874 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1875 return -1;
1876
1877 if (IntVal > 31)
1878 return -1;
1879
1880 return IntVal;
1881}
1882
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001883int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1884 int CC;
1885
1886 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001887 .Case("msair", 0)
1888 .Case("msacsr", 1)
1889 .Case("msaaccess", 2)
1890 .Case("msasave", 3)
1891 .Case("msamodify", 4)
1892 .Case("msarequest", 5)
1893 .Case("msamap", 6)
1894 .Case("msaunmap", 7)
1895 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001896
1897 return CC;
1898}
1899
Jack Carter0b744b32012-10-04 02:29:46 +00001900bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1901 if (Reg > 31)
1902 return false;
1903
Toma Tabacu3c24b042014-09-05 15:43:21 +00001904 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001905 return true;
1906}
1907
Matheus Almeida7de68e72014-06-18 14:46:05 +00001908int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001909 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001910 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001911 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001912 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001913 return AT;
1914}
Jack Carter0b744b32012-10-04 02:29:46 +00001915
Jack Carterd0bd6422013-04-18 00:41:53 +00001916unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001917 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001918}
1919
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001920unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001921 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001922 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001923}
1924
Jack Carter873c7242013-01-12 01:03:14 +00001925int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001926 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001927 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001928 return -1;
1929
Jack Carter873c7242013-01-12 01:03:14 +00001930 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001931}
1932
Toma Tabacu13964452014-09-04 13:23:44 +00001933bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001934 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00001935 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001936
Jack Carter30a59822012-10-04 04:03:53 +00001937 // Check if the current operand has a custom associated parser, if so, try to
1938 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001939 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1940 if (ResTy == MatchOperand_Success)
1941 return false;
1942 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1943 // there was a match, but an error occurred, in which case, just return that
1944 // the operand parsing failed.
1945 if (ResTy == MatchOperand_ParseFail)
1946 return true;
1947
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001948 DEBUG(dbgs() << ".. Generic Parser\n");
1949
Jack Carterb4dbc172012-09-05 23:34:03 +00001950 switch (getLexer().getKind()) {
1951 default:
1952 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1953 return true;
1954 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001955 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001956 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001957
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001958 // Almost all registers have been parsed by custom parsers. There is only
1959 // one exception to this. $zero (and it's alias $0) will reach this point
1960 // for div, divu, and similar instructions because it is not an operand
1961 // to the instruction definition but an explicit register. Special case
1962 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001963 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001964 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001965
Jack Carterd0bd6422013-04-18 00:41:53 +00001966 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001967 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001968 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001969 return true;
1970
Jack Carter873c7242013-01-12 01:03:14 +00001971 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001972 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001973 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001974 const MCExpr *Res =
1975 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001976
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001977 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001978 return false;
1979 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001980 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001981 case AsmToken::LParen:
1982 case AsmToken::Minus:
1983 case AsmToken::Plus:
1984 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001985 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001986 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001987 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001988 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001989 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001990 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001991 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001992 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001993 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001994 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001995 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001996 return true;
1997
Jack Carter873c7242013-01-12 01:03:14 +00001998 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1999
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002000 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002001 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002002 } // case AsmToken::Percent
2003 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002004 return true;
2005}
2006
Vladimir Medic4c299852013-11-06 11:27:05 +00002007const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002008 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002009 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002010 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002011 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002012 // It's a constant, evaluate reloc value.
2013 int16_t Val;
2014 switch (getVariantKind(RelocStr)) {
2015 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2016 // Get the 1st 16-bits.
2017 Val = MCE->getValue() & 0xffff;
2018 break;
2019 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2020 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2021 // 16 bits being negative.
2022 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2023 break;
2024 case MCSymbolRefExpr::VK_Mips_HIGHER:
2025 // Get the 3rd 16-bits.
2026 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2027 break;
2028 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2029 // Get the 4th 16-bits.
2030 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2031 break;
2032 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002033 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002034 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002035 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002036 }
2037
Jack Carterb5cf5902013-04-17 00:18:04 +00002038 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002039 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002040 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002041 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002042 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002043 return Res;
2044 }
2045
2046 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002047 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2048
Sasa Stankovic06c47802014-04-03 10:37:45 +00002049 // Try to create target expression.
2050 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2051 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002052
Jack Carterd0bd6422013-04-18 00:41:53 +00002053 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2054 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002055 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2056 return Res;
2057 }
2058
2059 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002060 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2061 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2062 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002063 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002064 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002065 return Expr;
2066}
2067
2068bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2069
2070 switch (Expr->getKind()) {
2071 case MCExpr::Constant:
2072 return true;
2073 case MCExpr::SymbolRef:
2074 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2075 case MCExpr::Binary:
2076 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2077 if (!isEvaluated(BE->getLHS()))
2078 return false;
2079 return isEvaluated(BE->getRHS());
2080 }
2081 case MCExpr::Unary:
2082 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002083 case MCExpr::Target:
2084 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002085 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002086 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002087}
Jack Carterd0bd6422013-04-18 00:41:53 +00002088
Jack Carterb5cf5902013-04-17 00:18:04 +00002089bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002090 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002091 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002092 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002093 if (Tok.isNot(AsmToken::Identifier))
2094 return true;
2095
2096 std::string Str = Tok.getIdentifier().str();
2097
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 Parser.Lex(); // Eat the identifier.
2099 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002100 const MCExpr *IdVal;
2101 SMLoc EndLoc;
2102
2103 if (getLexer().getKind() == AsmToken::LParen) {
2104 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002105 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002106 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002108 const AsmToken &nextTok = Parser.getTok();
2109 if (nextTok.isNot(AsmToken::Identifier))
2110 return true;
2111 Str += "(%";
2112 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 if (getLexer().getKind() != AsmToken::LParen)
2115 return true;
2116 } else
2117 break;
2118 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002120 return true;
2121
2122 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002124
2125 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002126 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002127
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002129 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002130}
2131
Jack Carterb4dbc172012-09-05 23:34:03 +00002132bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2133 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002134 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002135 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002136 if (ResTy == MatchOperand_Success) {
2137 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002138 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002139 StartLoc = Operand.getStartLoc();
2140 EndLoc = Operand.getEndLoc();
2141
2142 // AFAIK, we only support numeric registers and named GPR's in CFI
2143 // directives.
2144 // Don't worry about eating tokens before failing. Using an unrecognised
2145 // register is a parse error.
2146 if (Operand.isGPRAsmReg()) {
2147 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002148 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002149 }
2150
2151 return (RegNo == (unsigned)-1);
2152 }
2153
2154 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002155 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002156}
2157
Jack Carterb5cf5902013-04-17 00:18:04 +00002158bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002159 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002160 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002161 bool Result = true;
2162
2163 while (getLexer().getKind() == AsmToken::LParen)
2164 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002165
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002167 default:
2168 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002169 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002170 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002171 case AsmToken::Integer:
2172 case AsmToken::Minus:
2173 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002174 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002175 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002176 else
2177 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002179 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 break;
Jack Carter873c7242013-01-12 01:03:14 +00002181 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002182 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002183 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002184 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002185}
2186
David Blaikie960ea3f2014-06-08 16:18:35 +00002187MipsAsmParser::OperandMatchResultTy
2188MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002189 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002190 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002191 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002192 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002193 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002194 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002196 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002197
Jack Carterb5cf5902013-04-17 00:18:04 +00002198 if (getLexer().getKind() == AsmToken::LParen) {
2199 Parser.Lex();
2200 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002201 }
2202
Jack Carterb5cf5902013-04-17 00:18:04 +00002203 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002204 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002205 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002206
Jack Carterd0bd6422013-04-18 00:41:53 +00002207 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002208 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002209 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2210 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002211 SMLoc E =
2212 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002213 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002214 return MatchOperand_Success;
2215 }
2216 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002217 SMLoc E =
2218 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002219
Jack Carterd0bd6422013-04-18 00:41:53 +00002220 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002221 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002222 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002223 S, E, *this);
2224 Operands.push_back(
2225 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002226 return MatchOperand_Success;
2227 }
2228 Error(Parser.getTok().getLoc(), "'(' expected");
2229 return MatchOperand_ParseFail;
2230 }
2231
Jack Carterd0bd6422013-04-18 00:41:53 +00002232 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002233 }
2234
Toma Tabacu13964452014-09-04 13:23:44 +00002235 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002236 if (Res != MatchOperand_Success)
2237 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002238
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002239 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002240 Error(Parser.getTok().getLoc(), "')' expected");
2241 return MatchOperand_ParseFail;
2242 }
2243
Jack Carter873c7242013-01-12 01:03:14 +00002244 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2245
Jack Carterd0bd6422013-04-18 00:41:53 +00002246 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002247
Craig Topper062a2ba2014-04-25 05:30:21 +00002248 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002249 IdVal = MCConstantExpr::Create(0, getContext());
2250
Jack Carterd0bd6422013-04-18 00:41:53 +00002251 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002252 std::unique_ptr<MipsOperand> op(
2253 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002254 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002255 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002256 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002257 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002258 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2259 int64_t Imm;
2260 if (IdVal->EvaluateAsAbsolute(Imm))
2261 IdVal = MCConstantExpr::Create(Imm, getContext());
2262 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2263 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2264 getContext());
2265 }
2266
David Blaikie960ea3f2014-06-08 16:18:35 +00002267 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002268 return MatchOperand_Success;
2269}
2270
David Blaikie960ea3f2014-06-08 16:18:35 +00002271bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002272 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002273 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2274 if (Sym) {
2275 SMLoc S = Parser.getTok().getLoc();
2276 const MCExpr *Expr;
2277 if (Sym->isVariable())
2278 Expr = Sym->getVariableValue();
2279 else
2280 return false;
2281 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002282 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002283 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002284 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002285 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002286 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002287 if (ResTy == MatchOperand_Success) {
2288 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002289 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002290 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002291 llvm_unreachable("Should never ParseFail");
2292 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002293 }
2294 } else if (Expr->getKind() == MCExpr::Constant) {
2295 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002296 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002297 Operands.push_back(
2298 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002299 return true;
2300 }
2301 }
2302 return false;
2303}
Jack Carterd0bd6422013-04-18 00:41:53 +00002304
Jack Carter873c7242013-01-12 01:03:14 +00002305MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002306MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002307 StringRef Identifier,
2308 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002309 int Index = matchCPURegisterName(Identifier);
2310 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002311 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002312 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2313 return MatchOperand_Success;
2314 }
2315
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002316 Index = matchHWRegsRegisterName(Identifier);
2317 if (Index != -1) {
2318 Operands.push_back(MipsOperand::createHWRegsReg(
2319 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2320 return MatchOperand_Success;
2321 }
2322
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002323 Index = matchFPURegisterName(Identifier);
2324 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002325 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002326 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2327 return MatchOperand_Success;
2328 }
2329
2330 Index = matchFCCRegisterName(Identifier);
2331 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002332 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002333 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2334 return MatchOperand_Success;
2335 }
2336
2337 Index = matchACRegisterName(Identifier);
2338 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002339 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002340 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2341 return MatchOperand_Success;
2342 }
2343
2344 Index = matchMSA128RegisterName(Identifier);
2345 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002346 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002347 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2348 return MatchOperand_Success;
2349 }
2350
2351 Index = matchMSA128CtrlRegisterName(Identifier);
2352 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002353 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002354 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2355 return MatchOperand_Success;
2356 }
2357
2358 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002359}
2360
2361MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002362MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002363 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002364 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002365
2366 if (Token.is(AsmToken::Identifier)) {
2367 DEBUG(dbgs() << ".. identifier\n");
2368 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002369 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002370 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002371 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002372 } else if (Token.is(AsmToken::Integer)) {
2373 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002374 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002375 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2376 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002377 return MatchOperand_Success;
2378 }
2379
2380 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2381
2382 return MatchOperand_NoMatch;
2383}
2384
David Blaikie960ea3f2014-06-08 16:18:35 +00002385MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002386MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002387 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002388 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002389
2390 auto Token = Parser.getTok();
2391
2392 SMLoc S = Token.getLoc();
2393
2394 if (Token.isNot(AsmToken::Dollar)) {
2395 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2396 if (Token.is(AsmToken::Identifier)) {
2397 if (searchSymbolAlias(Operands))
2398 return MatchOperand_Success;
2399 }
2400 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2401 return MatchOperand_NoMatch;
2402 }
2403 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002404
Toma Tabacu13964452014-09-04 13:23:44 +00002405 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002406 if (ResTy == MatchOperand_Success) {
2407 Parser.Lex(); // $
2408 Parser.Lex(); // identifier
2409 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002410 return ResTy;
2411}
2412
2413MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002414MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002415 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002416 switch (getLexer().getKind()) {
2417 default:
2418 return MatchOperand_NoMatch;
2419 case AsmToken::LParen:
2420 case AsmToken::Minus:
2421 case AsmToken::Plus:
2422 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002423 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002424 case AsmToken::String:
2425 break;
2426 }
2427
2428 const MCExpr *IdVal;
2429 SMLoc S = Parser.getTok().getLoc();
2430 if (getParser().parseExpression(IdVal))
2431 return MatchOperand_ParseFail;
2432
2433 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2434 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2435 return MatchOperand_Success;
2436}
2437
David Blaikie960ea3f2014-06-08 16:18:35 +00002438MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002439MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002440 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002441 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002442
2443 SMLoc S = getLexer().getLoc();
2444
2445 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002446 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447 if (ResTy != MatchOperand_NoMatch)
2448 return ResTy;
2449
Daniel Sanders315386c2014-04-01 10:40:14 +00002450 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002451 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002452 if (ResTy != MatchOperand_NoMatch)
2453 return ResTy;
2454
Daniel Sandersffd84362014-04-01 10:41:48 +00002455 const MCExpr *Expr = nullptr;
2456 if (Parser.parseExpression(Expr)) {
2457 // We have no way of knowing if a symbol was consumed so we must ParseFail
2458 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002459 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002460 Operands.push_back(
2461 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002463}
2464
Vladimir Medic2b953d02013-10-01 09:48:56 +00002465MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002466MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002467 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002468 const MCExpr *IdVal;
2469 // If the first token is '$' we may have register operand.
2470 if (Parser.getTok().is(AsmToken::Dollar))
2471 return MatchOperand_NoMatch;
2472 SMLoc S = Parser.getTok().getLoc();
2473 if (getParser().parseExpression(IdVal))
2474 return MatchOperand_ParseFail;
2475 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002476 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002477 int64_t Val = MCE->getValue();
2478 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2479 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002481 return MatchOperand_Success;
2482}
2483
Matheus Almeida779c5932013-11-18 12:32:49 +00002484MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002485MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002486 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002487 switch (getLexer().getKind()) {
2488 default:
2489 return MatchOperand_NoMatch;
2490 case AsmToken::LParen:
2491 case AsmToken::Plus:
2492 case AsmToken::Minus:
2493 case AsmToken::Integer:
2494 break;
2495 }
2496
2497 const MCExpr *Expr;
2498 SMLoc S = Parser.getTok().getLoc();
2499
2500 if (getParser().parseExpression(Expr))
2501 return MatchOperand_ParseFail;
2502
2503 int64_t Val;
2504 if (!Expr->EvaluateAsAbsolute(Val)) {
2505 Error(S, "expected immediate value");
2506 return MatchOperand_ParseFail;
2507 }
2508
2509 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2510 // and because the CPU always adds one to the immediate field, the allowed
2511 // range becomes 1..4. We'll only check the range here and will deal
2512 // with the addition/subtraction when actually decoding/encoding
2513 // the instruction.
2514 if (Val < 1 || Val > 4) {
2515 Error(S, "immediate not in range (1..4)");
2516 return MatchOperand_ParseFail;
2517 }
2518
Jack Carter3b2c96e2014-01-22 23:31:38 +00002519 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002520 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002521 return MatchOperand_Success;
2522}
2523
Jack Carterdc1e35d2012-09-06 20:00:02 +00002524MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2525
Vladimir Medic4c299852013-11-06 11:27:05 +00002526 MCSymbolRefExpr::VariantKind VK =
2527 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2528 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2529 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2530 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2531 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2532 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2533 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2534 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2535 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2536 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2537 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2538 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2539 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2540 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2541 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2542 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2543 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2544 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002545 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2546 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2547 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2548 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2549 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2550 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002551 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2552 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002553 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002554
Matheus Almeida2852af82014-04-22 10:15:54 +00002555 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002556
Jack Carterdc1e35d2012-09-06 20:00:02 +00002557 return VK;
2558}
Jack Cartera63b16a2012-09-07 00:23:42 +00002559
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002560/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2561/// either this.
2562/// ::= '(', register, ')'
2563/// handle it before we iterate so we don't get tripped up by the lack of
2564/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002565bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002566 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002567 if (getLexer().is(AsmToken::LParen)) {
2568 Operands.push_back(
2569 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2570 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002571 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002572 SMLoc Loc = getLexer().getLoc();
2573 Parser.eatToEndOfStatement();
2574 return Error(Loc, "unexpected token in argument list");
2575 }
2576 if (Parser.getTok().isNot(AsmToken::RParen)) {
2577 SMLoc Loc = getLexer().getLoc();
2578 Parser.eatToEndOfStatement();
2579 return Error(Loc, "unexpected token, expected ')'");
2580 }
2581 Operands.push_back(
2582 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2583 Parser.Lex();
2584 }
2585 return false;
2586}
2587
2588/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2589/// either one of these.
2590/// ::= '[', register, ']'
2591/// ::= '[', integer, ']'
2592/// handle it before we iterate so we don't get tripped up by the lack of
2593/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002594bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002595 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002596 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002597 if (getLexer().is(AsmToken::LBrac)) {
2598 Operands.push_back(
2599 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2600 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002601 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002602 SMLoc Loc = getLexer().getLoc();
2603 Parser.eatToEndOfStatement();
2604 return Error(Loc, "unexpected token in argument list");
2605 }
2606 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2607 SMLoc Loc = getLexer().getLoc();
2608 Parser.eatToEndOfStatement();
2609 return Error(Loc, "unexpected token, expected ']'");
2610 }
2611 Operands.push_back(
2612 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2613 Parser.Lex();
2614 }
2615 return false;
2616}
2617
David Blaikie960ea3f2014-06-08 16:18:35 +00002618bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2619 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002620 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002621 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002622
2623 // We have reached first instruction, module directive are now forbidden.
2624 getTargetStreamer().forbidModuleDirective();
2625
Vladimir Medic74593e62013-07-17 15:00:42 +00002626 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002627 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002628 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002629 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002630 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002631 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002632 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002633
2634 // Read the remaining operands.
2635 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2636 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002637 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002638 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002639 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002640 return Error(Loc, "unexpected token in argument list");
2641 }
Toma Tabacu13964452014-09-04 13:23:44 +00002642 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002643 return true;
2644 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002645
Jack Carterd0bd6422013-04-18 00:41:53 +00002646 while (getLexer().is(AsmToken::Comma)) {
2647 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002648 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002649 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002650 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002651 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002652 return Error(Loc, "unexpected token in argument list");
2653 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002654 // Parse bracket and parenthesis suffixes before we iterate
2655 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002656 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002657 return true;
2658 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002659 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002660 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002661 }
2662 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002663 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2664 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002665 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002666 return Error(Loc, "unexpected token in argument list");
2667 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002668 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002669 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002670}
2671
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002672bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002673 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002674 SMLoc Loc = getLexer().getLoc();
2675 Parser.eatToEndOfStatement();
2676 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002677}
2678
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002679bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002680 return Error(Loc, ErrorMsg);
2681}
2682
Jack Carter0b744b32012-10-04 02:29:46 +00002683bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002684 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002685 // Line should look like: ".set noat".
2686 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002687 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002688 // eat noat
2689 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002690 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002691 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002692 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002693 return false;
2694 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002695 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002696 return false;
2697}
Jack Carterd0bd6422013-04-18 00:41:53 +00002698
Jack Carter0b744b32012-10-04 02:29:46 +00002699bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002700 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002701 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002702 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002703 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002704 getParser().Lex();
2705 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002706 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002707 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002708 return false;
2709 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002710 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002711 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002712 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002713 return false;
2714 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002715 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002716 const AsmToken &Reg = Parser.getTok();
2717 if (Reg.is(AsmToken::Identifier)) {
2718 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2719 } else if (Reg.is(AsmToken::Integer)) {
2720 AtRegNo = Reg.getIntVal();
2721 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002722 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002723 return false;
2724 }
Jack Carter1ac53222013-02-20 23:11:17 +00002725
Daniel Sanders71a89d922014-03-25 13:01:06 +00002726 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002727 reportParseError("unexpected token in statement");
2728 return false;
2729 }
2730
Toma Tabacu9db22db2014-09-09 10:15:38 +00002731 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002732 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002733 return false;
2734 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002735 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002736
2737 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002738 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002739 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002740 }
2741 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002742 return false;
2743 } else {
2744 reportParseError("unexpected token in statement");
2745 return false;
2746 }
2747}
2748
2749bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002750 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002751 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002752 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002753 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002754 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002755 return false;
2756 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002757 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002758 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002759 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002760 return false;
2761}
2762
2763bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002764 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002765 Parser.Lex();
2766 // If this is not the end of the statement, report an error.
2767 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002768 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002769 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002770 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002771 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002772 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002773 Parser.Lex(); // Consume the EndOfStatement.
2774 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002775}
2776
2777bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002778 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002779 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002780 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002781 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002782 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002783 return false;
2784 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002785 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002786 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002787 return false;
2788}
2789
2790bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002791 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002792 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002793 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002795 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002796 return false;
2797 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002798 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002799 reportParseError("`noreorder' must be set before `nomacro'");
2800 return false;
2801 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002802 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002803 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002804 return false;
2805}
Jack Carterd76b2372013-03-21 21:44:16 +00002806
Daniel Sanders44934432014-08-07 12:03:36 +00002807bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002808 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002809 Parser.Lex();
2810
2811 // If this is not the end of the statement, report an error.
2812 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002813 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002814
2815 setFeatureBits(Mips::FeatureMSA, "msa");
2816 getTargetStreamer().emitDirectiveSetMsa();
2817 return false;
2818}
2819
2820bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002821 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002822 Parser.Lex();
2823
2824 // If this is not the end of the statement, report an error.
2825 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002826 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002827
2828 clearFeatureBits(Mips::FeatureMSA, "msa");
2829 getTargetStreamer().emitDirectiveSetNoMsa();
2830 return false;
2831}
2832
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002833bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002834 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002835 Parser.Lex(); // Eat "nodsp".
2836
2837 // If this is not the end of the statement, report an error.
2838 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2839 reportParseError("unexpected token, expected end of statement");
2840 return false;
2841 }
2842
2843 clearFeatureBits(Mips::FeatureDSP, "dsp");
2844 getTargetStreamer().emitDirectiveSetNoDsp();
2845 return false;
2846}
2847
Toma Tabacucc2502d2014-11-04 17:18:07 +00002848bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002849 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00002850 Parser.Lex(); // Eat "mips16".
2851
Jack Carter39536722014-01-22 23:08:42 +00002852 // If this is not the end of the statement, report an error.
2853 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002854 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002855 return false;
2856 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00002857
2858 setFeatureBits(Mips::FeatureMips16, "mips16");
2859 getTargetStreamer().emitDirectiveSetMips16();
2860 Parser.Lex(); // Consume the EndOfStatement.
2861 return false;
2862}
2863
2864bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002865 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00002866 Parser.Lex(); // Eat "nomips16".
2867
2868 // If this is not the end of the statement, report an error.
2869 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2870 reportParseError("unexpected token, expected end of statement");
2871 return false;
2872 }
2873
2874 clearFeatureBits(Mips::FeatureMips16, "mips16");
2875 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00002876 Parser.Lex(); // Consume the EndOfStatement.
2877 return false;
2878}
2879
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002880bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002881 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00002882 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002883 // Line can be: .set fp=32
2884 // .set fp=xx
2885 // .set fp=64
2886 Parser.Lex(); // Eat fp token
2887 AsmToken Tok = Parser.getTok();
2888 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002889 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002890 return false;
2891 }
2892 Parser.Lex(); // Eat '=' token.
2893 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002894
2895 if (!parseFpABIValue(FpAbiVal, ".set"))
2896 return false;
2897
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002899 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002900 return false;
2901 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002902 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002903 Parser.Lex(); // Consume the EndOfStatement.
2904 return false;
2905}
2906
Toma Tabacu9db22db2014-09-09 10:15:38 +00002907bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002908 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002909 SMLoc Loc = getLexer().getLoc();
2910
2911 Parser.Lex();
2912 if (getLexer().isNot(AsmToken::EndOfStatement))
2913 return reportParseError("unexpected token, expected end of statement");
2914
2915 // Always keep an element on the options "stack" to prevent the user
2916 // from changing the initial options. This is how we remember them.
2917 if (AssemblerOptions.size() == 2)
2918 return reportParseError(Loc, ".set pop with no .set push");
2919
2920 AssemblerOptions.pop_back();
2921 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2922
2923 getTargetStreamer().emitDirectiveSetPop();
2924 return false;
2925}
2926
2927bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002928 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002929 Parser.Lex();
2930 if (getLexer().isNot(AsmToken::EndOfStatement))
2931 return reportParseError("unexpected token, expected end of statement");
2932
2933 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002934 AssemblerOptions.push_back(
2935 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002936
2937 getTargetStreamer().emitDirectiveSetPush();
2938 return false;
2939}
2940
Jack Carterd76b2372013-03-21 21:44:16 +00002941bool MipsAsmParser::parseSetAssignment() {
2942 StringRef Name;
2943 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00002944 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002945
2946 if (Parser.parseIdentifier(Name))
2947 reportParseError("expected identifier after .set");
2948
2949 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00002950 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00002951 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002952
Jack Carter3b2c96e2014-01-22 23:31:38 +00002953 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002954 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002955
Jack Carterd0bd6422013-04-18 00:41:53 +00002956 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002957 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002958 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002959 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002960 Sym = getContext().GetOrCreateSymbol(Name);
2961 Sym->setVariableValue(Value);
2962
2963 return false;
2964}
Jack Carterd0bd6422013-04-18 00:41:53 +00002965
Toma Tabacu26647792014-09-09 12:52:14 +00002966bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002967 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00002968 Parser.Lex();
2969 if (getLexer().isNot(AsmToken::EndOfStatement))
2970 return reportParseError("unexpected token, expected end of statement");
2971
2972 // Reset assembler options to their initial values.
2973 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2974 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2975
2976 getTargetStreamer().emitDirectiveSetMips0();
2977 return false;
2978}
2979
Toma Tabacu85618b32014-08-19 14:22:52 +00002980bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002981 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00002982 Parser.Lex();
2983 if (getLexer().isNot(AsmToken::Equal))
2984 return reportParseError("unexpected token, expected equals sign");
2985
2986 Parser.Lex();
2987 StringRef Arch;
2988 if (Parser.parseIdentifier(Arch))
2989 return reportParseError("expected arch identifier");
2990
2991 StringRef ArchFeatureName =
2992 StringSwitch<StringRef>(Arch)
2993 .Case("mips1", "mips1")
2994 .Case("mips2", "mips2")
2995 .Case("mips3", "mips3")
2996 .Case("mips4", "mips4")
2997 .Case("mips5", "mips5")
2998 .Case("mips32", "mips32")
2999 .Case("mips32r2", "mips32r2")
3000 .Case("mips32r6", "mips32r6")
3001 .Case("mips64", "mips64")
3002 .Case("mips64r2", "mips64r2")
3003 .Case("mips64r6", "mips64r6")
3004 .Case("cnmips", "cnmips")
3005 .Case("r4000", "mips3") // This is an implementation of Mips3.
3006 .Default("");
3007
3008 if (ArchFeatureName.empty())
3009 return reportParseError("unsupported architecture");
3010
3011 selectArch(ArchFeatureName);
3012 getTargetStreamer().emitDirectiveSetArch(Arch);
3013 return false;
3014}
3015
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003016bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003017 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003018 Parser.Lex();
3019 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003020 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003021
Matheus Almeida2852af82014-04-22 10:15:54 +00003022 switch (Feature) {
3023 default:
3024 llvm_unreachable("Unimplemented feature");
3025 case Mips::FeatureDSP:
3026 setFeatureBits(Mips::FeatureDSP, "dsp");
3027 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003028 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003029 case Mips::FeatureMicroMips:
3030 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003031 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003032 case Mips::FeatureMips1:
3033 selectArch("mips1");
3034 getTargetStreamer().emitDirectiveSetMips1();
3035 break;
3036 case Mips::FeatureMips2:
3037 selectArch("mips2");
3038 getTargetStreamer().emitDirectiveSetMips2();
3039 break;
3040 case Mips::FeatureMips3:
3041 selectArch("mips3");
3042 getTargetStreamer().emitDirectiveSetMips3();
3043 break;
3044 case Mips::FeatureMips4:
3045 selectArch("mips4");
3046 getTargetStreamer().emitDirectiveSetMips4();
3047 break;
3048 case Mips::FeatureMips5:
3049 selectArch("mips5");
3050 getTargetStreamer().emitDirectiveSetMips5();
3051 break;
3052 case Mips::FeatureMips32:
3053 selectArch("mips32");
3054 getTargetStreamer().emitDirectiveSetMips32();
3055 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003056 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003057 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003058 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003059 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003060 case Mips::FeatureMips32r6:
3061 selectArch("mips32r6");
3062 getTargetStreamer().emitDirectiveSetMips32R6();
3063 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003064 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003065 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003066 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003067 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003068 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003069 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003070 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003071 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003072 case Mips::FeatureMips64r6:
3073 selectArch("mips64r6");
3074 getTargetStreamer().emitDirectiveSetMips64R6();
3075 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003076 }
3077 return false;
3078}
3079
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003080bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003081 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003082 if (getLexer().isNot(AsmToken::Comma)) {
3083 SMLoc Loc = getLexer().getLoc();
3084 Parser.eatToEndOfStatement();
3085 return Error(Loc, ErrorStr);
3086 }
3087
Matheus Almeida2852af82014-04-22 10:15:54 +00003088 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003089 return true;
3090}
3091
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003092bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003093 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003094 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003095
Toma Tabacudde4c462014-11-06 10:02:45 +00003096 if (inMips16Mode()) {
3097 reportParseError(".cpload is not supported in Mips16 mode");
3098 return false;
3099 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003100
David Blaikie960ea3f2014-06-08 16:18:35 +00003101 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003102 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003103 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3104 reportParseError("expected register containing function address");
3105 return false;
3106 }
3107
David Blaikie960ea3f2014-06-08 16:18:35 +00003108 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3109 if (!RegOpnd.isGPRAsmReg()) {
3110 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003111 return false;
3112 }
3113
Toma Tabacudde4c462014-11-06 10:02:45 +00003114 // If this is not the end of the statement, report an error.
3115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3116 reportParseError("unexpected token, expected end of statement");
3117 return false;
3118 }
3119
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003120 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003121 return false;
3122}
3123
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003124bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003125 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003126 unsigned FuncReg;
3127 unsigned Save;
3128 bool SaveIsReg = true;
3129
Matheus Almeida7e815762014-06-18 13:08:59 +00003130 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003131 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003132 if (ResTy == MatchOperand_NoMatch) {
3133 reportParseError("expected register containing function address");
3134 Parser.eatToEndOfStatement();
3135 return false;
3136 }
3137
3138 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3139 if (!FuncRegOpnd.isGPRAsmReg()) {
3140 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3141 Parser.eatToEndOfStatement();
3142 return false;
3143 }
3144
3145 FuncReg = FuncRegOpnd.getGPR32Reg();
3146 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003147
Toma Tabacu65f10572014-09-16 15:00:52 +00003148 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003149 return true;
3150
Toma Tabacu13964452014-09-04 13:23:44 +00003151 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003152 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003153 const AsmToken &Tok = Parser.getTok();
3154 if (Tok.is(AsmToken::Integer)) {
3155 Save = Tok.getIntVal();
3156 SaveIsReg = false;
3157 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003158 } else {
3159 reportParseError("expected save register or stack offset");
3160 Parser.eatToEndOfStatement();
3161 return false;
3162 }
3163 } else {
3164 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3165 if (!SaveOpnd.isGPRAsmReg()) {
3166 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3167 Parser.eatToEndOfStatement();
3168 return false;
3169 }
3170 Save = SaveOpnd.getGPR32Reg();
3171 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003172
Toma Tabacu65f10572014-09-16 15:00:52 +00003173 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003174 return true;
3175
3176 StringRef Name;
3177 if (Parser.parseIdentifier(Name))
3178 reportParseError("expected identifier");
3179 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003180
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003181 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003182 return false;
3183}
3184
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003185bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003186 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3188 const AsmToken &Tok = Parser.getTok();
3189
3190 if (Tok.getString() == "2008") {
3191 Parser.Lex();
3192 getTargetStreamer().emitDirectiveNaN2008();
3193 return false;
3194 } else if (Tok.getString() == "legacy") {
3195 Parser.Lex();
3196 getTargetStreamer().emitDirectiveNaNLegacy();
3197 return false;
3198 }
3199 }
3200 // If we don't recognize the option passed to the .nan
3201 // directive (e.g. no option or unknown option), emit an error.
3202 reportParseError("invalid option in .nan directive");
3203 return false;
3204}
3205
Jack Carter0b744b32012-10-04 02:29:46 +00003206bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003207 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003208 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003209 const AsmToken &Tok = Parser.getTok();
3210
3211 if (Tok.getString() == "noat") {
3212 return parseSetNoAtDirective();
3213 } else if (Tok.getString() == "at") {
3214 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003215 } else if (Tok.getString() == "arch") {
3216 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003217 } else if (Tok.getString() == "fp") {
3218 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003219 } else if (Tok.getString() == "pop") {
3220 return parseSetPopDirective();
3221 } else if (Tok.getString() == "push") {
3222 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003223 } else if (Tok.getString() == "reorder") {
3224 return parseSetReorderDirective();
3225 } else if (Tok.getString() == "noreorder") {
3226 return parseSetNoReorderDirective();
3227 } else if (Tok.getString() == "macro") {
3228 return parseSetMacroDirective();
3229 } else if (Tok.getString() == "nomacro") {
3230 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003231 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003232 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003233 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003234 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003235 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003236 getTargetStreamer().emitDirectiveSetNoMicroMips();
3237 Parser.eatToEndOfStatement();
3238 return false;
3239 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003240 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003241 } else if (Tok.getString() == "mips0") {
3242 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003243 } else if (Tok.getString() == "mips1") {
3244 return parseSetFeature(Mips::FeatureMips1);
3245 } else if (Tok.getString() == "mips2") {
3246 return parseSetFeature(Mips::FeatureMips2);
3247 } else if (Tok.getString() == "mips3") {
3248 return parseSetFeature(Mips::FeatureMips3);
3249 } else if (Tok.getString() == "mips4") {
3250 return parseSetFeature(Mips::FeatureMips4);
3251 } else if (Tok.getString() == "mips5") {
3252 return parseSetFeature(Mips::FeatureMips5);
3253 } else if (Tok.getString() == "mips32") {
3254 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003255 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003256 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003257 } else if (Tok.getString() == "mips32r6") {
3258 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003259 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003260 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003261 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003262 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003263 } else if (Tok.getString() == "mips64r6") {
3264 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003265 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003266 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003267 } else if (Tok.getString() == "nodsp") {
3268 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003269 } else if (Tok.getString() == "msa") {
3270 return parseSetMsaDirective();
3271 } else if (Tok.getString() == "nomsa") {
3272 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003273 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003274 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003275 parseSetAssignment();
3276 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003277 }
Jack Carter07c818d2013-01-25 01:31:34 +00003278
Jack Carter0b744b32012-10-04 02:29:46 +00003279 return true;
3280}
3281
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003282/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003283/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003284bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003285 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003286 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3287 for (;;) {
3288 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003289 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003290 return true;
3291
3292 getParser().getStreamer().EmitValue(Value, Size);
3293
3294 if (getLexer().is(AsmToken::EndOfStatement))
3295 break;
3296
Jack Carter07c818d2013-01-25 01:31:34 +00003297 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003298 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003299 Parser.Lex();
3300 }
3301 }
3302
3303 Parser.Lex();
3304 return false;
3305}
3306
Vladimir Medic4c299852013-11-06 11:27:05 +00003307/// parseDirectiveGpWord
3308/// ::= .gpword local_sym
3309bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003310 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003311 const MCExpr *Value;
3312 // EmitGPRel32Value requires an expression, so we are using base class
3313 // method to evaluate the expression.
3314 if (getParser().parseExpression(Value))
3315 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003316 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003317
Vladimir Medice10c1122013-11-13 13:18:04 +00003318 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003319 return Error(getLexer().getLoc(),
3320 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003321 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003322 return false;
3323}
3324
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003325/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003326/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003327bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003328 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003329 const MCExpr *Value;
3330 // EmitGPRel64Value requires an expression, so we are using base class
3331 // method to evaluate the expression.
3332 if (getParser().parseExpression(Value))
3333 return true;
3334 getParser().getStreamer().EmitGPRel64Value(Value);
3335
3336 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003337 return Error(getLexer().getLoc(),
3338 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003339 Parser.Lex(); // Eat EndOfStatement token.
3340 return false;
3341}
3342
Jack Carter0cd3c192014-01-06 23:27:31 +00003343bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003344 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003345 // Get the option token.
3346 AsmToken Tok = Parser.getTok();
3347 // At the moment only identifiers are supported.
3348 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003349 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003350 Parser.eatToEndOfStatement();
3351 return false;
3352 }
3353
3354 StringRef Option = Tok.getIdentifier();
3355
3356 if (Option == "pic0") {
3357 getTargetStreamer().emitDirectiveOptionPic0();
3358 Parser.Lex();
3359 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3360 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003361 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003362 Parser.eatToEndOfStatement();
3363 }
3364 return false;
3365 }
3366
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003367 if (Option == "pic2") {
3368 getTargetStreamer().emitDirectiveOptionPic2();
3369 Parser.Lex();
3370 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3371 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003372 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003373 Parser.eatToEndOfStatement();
3374 }
3375 return false;
3376 }
3377
Jack Carter0cd3c192014-01-06 23:27:31 +00003378 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003379 Warning(Parser.getTok().getLoc(),
3380 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003381 Parser.eatToEndOfStatement();
3382 return false;
3383}
3384
Daniel Sanders7e527422014-07-10 13:38:23 +00003385/// parseDirectiveModule
3386/// ::= .module oddspreg
3387/// ::= .module nooddspreg
3388/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003389bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003390 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003391 MCAsmLexer &Lexer = getLexer();
3392 SMLoc L = Lexer.getLoc();
3393
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003394 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003395 // TODO : get a better message.
3396 reportParseError(".module directive must appear before any code");
3397 return false;
3398 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003399
3400 if (Lexer.is(AsmToken::Identifier)) {
3401 StringRef Option = Parser.getTok().getString();
3402 Parser.Lex();
3403
3404 if (Option == "oddspreg") {
3405 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3406 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3407
3408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003409 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003410 return false;
3411 }
3412
3413 return false;
3414 } else if (Option == "nooddspreg") {
3415 if (!isABI_O32()) {
3416 Error(L, "'.module nooddspreg' requires the O32 ABI");
3417 return false;
3418 }
3419
3420 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3421 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3422
3423 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003424 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003425 return false;
3426 }
3427
3428 return false;
3429 } else if (Option == "fp") {
3430 return parseDirectiveModuleFP();
3431 }
3432
3433 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003434 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003435
3436 return false;
3437}
3438
3439/// parseDirectiveModuleFP
3440/// ::= =32
3441/// ::= =xx
3442/// ::= =64
3443bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003444 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003445 MCAsmLexer &Lexer = getLexer();
3446
3447 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003448 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003449 return false;
3450 }
3451 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003452
Daniel Sanders7e527422014-07-10 13:38:23 +00003453 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003454 if (!parseFpABIValue(FpABI, ".module"))
3455 return false;
3456
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003458 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003459 return false;
3460 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003461
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003462 // Emit appropriate flags.
3463 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003464 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003465 return false;
3466}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003467
Daniel Sanders7e527422014-07-10 13:38:23 +00003468bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003469 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003470 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003471 MCAsmLexer &Lexer = getLexer();
3472
3473 if (Lexer.is(AsmToken::Identifier)) {
3474 StringRef Value = Parser.getTok().getString();
3475 Parser.Lex();
3476
3477 if (Value != "xx") {
3478 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3479 return false;
3480 }
3481
3482 if (!isABI_O32()) {
3483 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3484 return false;
3485 }
3486
Daniel Sanders7e527422014-07-10 13:38:23 +00003487 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003488 return true;
3489 }
3490
3491 if (Lexer.is(AsmToken::Integer)) {
3492 unsigned Value = Parser.getTok().getIntVal();
3493 Parser.Lex();
3494
3495 if (Value != 32 && Value != 64) {
3496 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3497 return false;
3498 }
3499
3500 if (Value == 32) {
3501 if (!isABI_O32()) {
3502 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3503 return false;
3504 }
3505
Daniel Sanders7e527422014-07-10 13:38:23 +00003506 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3507 } else
3508 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003509
Daniel Sanders7e527422014-07-10 13:38:23 +00003510 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003511 }
3512
3513 return false;
3514}
3515
Jack Carter0b744b32012-10-04 02:29:46 +00003516bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003517 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003518 StringRef IDVal = DirectiveID.getString();
3519
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003520 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003521 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003522 if (IDVal == ".dword") {
3523 parseDataDirective(8, DirectiveID.getLoc());
3524 return false;
3525 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003526 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003527 StringRef SymbolName;
3528
3529 if (Parser.parseIdentifier(SymbolName)) {
3530 reportParseError("expected identifier after .ent");
3531 return false;
3532 }
3533
3534 // There's an undocumented extension that allows an integer to
3535 // follow the name of the procedure which AFAICS is ignored by GAS.
3536 // Example: .ent foo,2
3537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3538 if (getLexer().isNot(AsmToken::Comma)) {
3539 // Even though we accept this undocumented extension for compatibility
3540 // reasons, the additional integer argument does not actually change
3541 // the behaviour of the '.ent' directive, so we would like to discourage
3542 // its use. We do this by not referring to the extended version in
3543 // error messages which are not directly related to its use.
3544 reportParseError("unexpected token, expected end of statement");
3545 return false;
3546 }
3547 Parser.Lex(); // Eat the comma.
3548 const MCExpr *DummyNumber;
3549 int64_t DummyNumberVal;
3550 // If the user was explicitly trying to use the extended version,
3551 // we still give helpful extension-related error messages.
3552 if (Parser.parseExpression(DummyNumber)) {
3553 reportParseError("expected number after comma");
3554 return false;
3555 }
3556 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3557 reportParseError("expected an absolute expression after comma");
3558 return false;
3559 }
3560 }
3561
3562 // If this is not the end of the statement, report an error.
3563 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3564 reportParseError("unexpected token, expected end of statement");
3565 return false;
3566 }
3567
3568 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3569
3570 getTargetStreamer().emitDirectiveEnt(*Sym);
3571 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003572 return false;
3573 }
3574
Jack Carter07c818d2013-01-25 01:31:34 +00003575 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003576 StringRef SymbolName;
3577
3578 if (Parser.parseIdentifier(SymbolName)) {
3579 reportParseError("expected identifier after .end");
3580 return false;
3581 }
3582
3583 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3584 reportParseError("unexpected token, expected end of statement");
3585 return false;
3586 }
3587
3588 if (CurrentFn == nullptr) {
3589 reportParseError(".end used without .ent");
3590 return false;
3591 }
3592
3593 if ((SymbolName != CurrentFn->getName())) {
3594 reportParseError(".end symbol does not match .ent symbol");
3595 return false;
3596 }
3597
3598 getTargetStreamer().emitDirectiveEnd(SymbolName);
3599 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003600 return false;
3601 }
3602
Jack Carter07c818d2013-01-25 01:31:34 +00003603 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003604 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3605 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003606 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003607 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3608 reportParseError("expected stack register");
3609 return false;
3610 }
3611
3612 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3613 if (!StackRegOpnd.isGPRAsmReg()) {
3614 reportParseError(StackRegOpnd.getStartLoc(),
3615 "expected general purpose register");
3616 return false;
3617 }
3618 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3619
3620 if (Parser.getTok().is(AsmToken::Comma))
3621 Parser.Lex();
3622 else {
3623 reportParseError("unexpected token, expected comma");
3624 return false;
3625 }
3626
3627 // Parse the frame size.
3628 const MCExpr *FrameSize;
3629 int64_t FrameSizeVal;
3630
3631 if (Parser.parseExpression(FrameSize)) {
3632 reportParseError("expected frame size value");
3633 return false;
3634 }
3635
3636 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3637 reportParseError("frame size not an absolute expression");
3638 return false;
3639 }
3640
3641 if (Parser.getTok().is(AsmToken::Comma))
3642 Parser.Lex();
3643 else {
3644 reportParseError("unexpected token, expected comma");
3645 return false;
3646 }
3647
3648 // Parse the return register.
3649 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003650 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003651 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3652 reportParseError("expected return register");
3653 return false;
3654 }
3655
3656 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3657 if (!ReturnRegOpnd.isGPRAsmReg()) {
3658 reportParseError(ReturnRegOpnd.getStartLoc(),
3659 "expected general purpose register");
3660 return false;
3661 }
3662
3663 // If this is not the end of the statement, report an error.
3664 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3665 reportParseError("unexpected token, expected end of statement");
3666 return false;
3667 }
3668
3669 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3670 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003671 return false;
3672 }
3673
Jack Carter07c818d2013-01-25 01:31:34 +00003674 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003675 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003676 }
3677
Daniel Sandersd97a6342014-08-13 10:07:34 +00003678 if (IDVal == ".mask" || IDVal == ".fmask") {
3679 // .mask bitmask, frame_offset
3680 // bitmask: One bit for each register used.
3681 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3682 // first register is expected to be saved.
3683 // Examples:
3684 // .mask 0x80000000, -4
3685 // .fmask 0x80000000, -4
3686 //
Jack Carterbe332172012-09-07 00:48:02 +00003687
Daniel Sandersd97a6342014-08-13 10:07:34 +00003688 // Parse the bitmask
3689 const MCExpr *BitMask;
3690 int64_t BitMaskVal;
3691
3692 if (Parser.parseExpression(BitMask)) {
3693 reportParseError("expected bitmask value");
3694 return false;
3695 }
3696
3697 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3698 reportParseError("bitmask not an absolute expression");
3699 return false;
3700 }
3701
3702 if (Parser.getTok().is(AsmToken::Comma))
3703 Parser.Lex();
3704 else {
3705 reportParseError("unexpected token, expected comma");
3706 return false;
3707 }
3708
3709 // Parse the frame_offset
3710 const MCExpr *FrameOffset;
3711 int64_t FrameOffsetVal;
3712
3713 if (Parser.parseExpression(FrameOffset)) {
3714 reportParseError("expected frame offset value");
3715 return false;
3716 }
3717
3718 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3719 reportParseError("frame offset not an absolute expression");
3720 return false;
3721 }
3722
3723 // If this is not the end of the statement, report an error.
3724 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3725 reportParseError("unexpected token, expected end of statement");
3726 return false;
3727 }
3728
3729 if (IDVal == ".mask")
3730 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3731 else
3732 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003733 return false;
3734 }
3735
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003736 if (IDVal == ".nan")
3737 return parseDirectiveNaN();
3738
Jack Carter07c818d2013-01-25 01:31:34 +00003739 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003740 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003741 return false;
3742 }
3743
Rafael Espindolab59fb732014-03-28 18:50:26 +00003744 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003745 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003746 return false;
3747 }
3748
Jack Carter07c818d2013-01-25 01:31:34 +00003749 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003750 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003751 return false;
3752 }
3753
Jack Carter0cd3c192014-01-06 23:27:31 +00003754 if (IDVal == ".option")
3755 return parseDirectiveOption();
3756
3757 if (IDVal == ".abicalls") {
3758 getTargetStreamer().emitDirectiveAbiCalls();
3759 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003760 Error(Parser.getTok().getLoc(),
3761 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003762 // Clear line
3763 Parser.eatToEndOfStatement();
3764 }
3765 return false;
3766 }
3767
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003768 if (IDVal == ".cpsetup")
3769 return parseDirectiveCPSetup();
3770
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003771 if (IDVal == ".module")
3772 return parseDirectiveModule();
3773
Rafael Espindola870c4e92012-01-11 03:56:41 +00003774 return true;
3775}
3776
Rafael Espindola870c4e92012-01-11 03:56:41 +00003777extern "C" void LLVMInitializeMipsAsmParser() {
3778 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3779 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3780 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3781 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3782}
Jack Carterb4dbc172012-09-05 23:34:03 +00003783
3784#define GET_REGISTER_MATCHER
3785#define GET_MATCHER_IMPLEMENTATION
3786#include "MipsGenAsmMatcher.inc"