blob: 1efbc05c34b4f75823a5465aab262103aa579e8e [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)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00001824 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001825 .Default(-1);
1826
1827 return CC;
1828}
1829
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001830int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001831
Jack Cartera63b16a2012-09-07 00:23:42 +00001832 if (Name[0] == 'f') {
1833 StringRef NumString = Name.substr(1);
1834 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001835 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001836 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001837 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001838 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001839 return IntVal;
1840 }
1841 return -1;
1842}
Jack Cartera63b16a2012-09-07 00:23:42 +00001843
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001844int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1845
1846 if (Name.startswith("fcc")) {
1847 StringRef NumString = Name.substr(3);
1848 unsigned IntVal;
1849 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001850 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001851 if (IntVal > 7) // There are only 8 fcc registers.
1852 return -1;
1853 return IntVal;
1854 }
1855 return -1;
1856}
1857
1858int MipsAsmParser::matchACRegisterName(StringRef Name) {
1859
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001860 if (Name.startswith("ac")) {
1861 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001862 unsigned IntVal;
1863 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001864 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001865 if (IntVal > 3) // There are only 3 acc registers.
1866 return -1;
1867 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001868 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001869 return -1;
1870}
Jack Carterd0bd6422013-04-18 00:41:53 +00001871
Jack Carter5dc8ac92013-09-25 23:50:44 +00001872int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1873 unsigned IntVal;
1874
1875 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1876 return -1;
1877
1878 if (IntVal > 31)
1879 return -1;
1880
1881 return IntVal;
1882}
1883
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001884int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1885 int CC;
1886
1887 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001888 .Case("msair", 0)
1889 .Case("msacsr", 1)
1890 .Case("msaaccess", 2)
1891 .Case("msasave", 3)
1892 .Case("msamodify", 4)
1893 .Case("msarequest", 5)
1894 .Case("msamap", 6)
1895 .Case("msaunmap", 7)
1896 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001897
1898 return CC;
1899}
1900
Jack Carter0b744b32012-10-04 02:29:46 +00001901bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1902 if (Reg > 31)
1903 return false;
1904
Toma Tabacu3c24b042014-09-05 15:43:21 +00001905 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001906 return true;
1907}
1908
Matheus Almeida7de68e72014-06-18 14:46:05 +00001909int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001910 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001911 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001912 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001913 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001914 return AT;
1915}
Jack Carter0b744b32012-10-04 02:29:46 +00001916
Jack Carterd0bd6422013-04-18 00:41:53 +00001917unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001918 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001919}
1920
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001921unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001922 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001923 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001924}
1925
Jack Carter873c7242013-01-12 01:03:14 +00001926int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001927 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001928 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001929 return -1;
1930
Jack Carter873c7242013-01-12 01:03:14 +00001931 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001932}
1933
Toma Tabacu13964452014-09-04 13:23:44 +00001934bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001935 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00001936 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001937
Jack Carter30a59822012-10-04 04:03:53 +00001938 // Check if the current operand has a custom associated parser, if so, try to
1939 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001940 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1941 if (ResTy == MatchOperand_Success)
1942 return false;
1943 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1944 // there was a match, but an error occurred, in which case, just return that
1945 // the operand parsing failed.
1946 if (ResTy == MatchOperand_ParseFail)
1947 return true;
1948
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001949 DEBUG(dbgs() << ".. Generic Parser\n");
1950
Jack Carterb4dbc172012-09-05 23:34:03 +00001951 switch (getLexer().getKind()) {
1952 default:
1953 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1954 return true;
1955 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001956 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001957 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001958
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001959 // Almost all registers have been parsed by custom parsers. There is only
1960 // one exception to this. $zero (and it's alias $0) will reach this point
1961 // for div, divu, and similar instructions because it is not an operand
1962 // to the instruction definition but an explicit register. Special case
1963 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001964 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001965 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001966
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001968 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001969 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001970 return true;
1971
Jack Carter873c7242013-01-12 01:03:14 +00001972 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001973 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001974 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001975 const MCExpr *Res =
1976 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001977
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001978 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001979 return false;
1980 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001981 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001982 case AsmToken::LParen:
1983 case AsmToken::Minus:
1984 case AsmToken::Plus:
1985 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001986 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001987 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001988 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001989 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001990 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001991 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001992 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001993 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001994 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001995 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001996 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001997 return true;
1998
Jack Carter873c7242013-01-12 01:03:14 +00001999 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2000
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002001 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002002 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002003 } // case AsmToken::Percent
2004 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002005 return true;
2006}
2007
Vladimir Medic4c299852013-11-06 11:27:05 +00002008const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002009 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002010 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002012 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002013 // It's a constant, evaluate reloc value.
2014 int16_t Val;
2015 switch (getVariantKind(RelocStr)) {
2016 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2017 // Get the 1st 16-bits.
2018 Val = MCE->getValue() & 0xffff;
2019 break;
2020 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2021 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2022 // 16 bits being negative.
2023 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2024 break;
2025 case MCSymbolRefExpr::VK_Mips_HIGHER:
2026 // Get the 3rd 16-bits.
2027 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2028 break;
2029 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2030 // Get the 4th 16-bits.
2031 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2032 break;
2033 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002034 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002035 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002036 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002037 }
2038
Jack Carterb5cf5902013-04-17 00:18:04 +00002039 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002040 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002041 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002042 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002043 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002044 return Res;
2045 }
2046
2047 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002048 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2049
Sasa Stankovic06c47802014-04-03 10:37:45 +00002050 // Try to create target expression.
2051 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2052 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002053
Jack Carterd0bd6422013-04-18 00:41:53 +00002054 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2055 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002056 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2057 return Res;
2058 }
2059
2060 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002061 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2062 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2063 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002064 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002065 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002066 return Expr;
2067}
2068
2069bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2070
2071 switch (Expr->getKind()) {
2072 case MCExpr::Constant:
2073 return true;
2074 case MCExpr::SymbolRef:
2075 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2076 case MCExpr::Binary:
2077 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2078 if (!isEvaluated(BE->getLHS()))
2079 return false;
2080 return isEvaluated(BE->getRHS());
2081 }
2082 case MCExpr::Unary:
2083 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002084 case MCExpr::Target:
2085 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002086 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002087 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002088}
Jack Carterd0bd6422013-04-18 00:41:53 +00002089
Jack Carterb5cf5902013-04-17 00:18:04 +00002090bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002091 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002092 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002094 if (Tok.isNot(AsmToken::Identifier))
2095 return true;
2096
2097 std::string Str = Tok.getIdentifier().str();
2098
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 Parser.Lex(); // Eat the identifier.
2100 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002101 const MCExpr *IdVal;
2102 SMLoc EndLoc;
2103
2104 if (getLexer().getKind() == AsmToken::LParen) {
2105 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002109 const AsmToken &nextTok = Parser.getTok();
2110 if (nextTok.isNot(AsmToken::Identifier))
2111 return true;
2112 Str += "(%";
2113 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002115 if (getLexer().getKind() != AsmToken::LParen)
2116 return true;
2117 } else
2118 break;
2119 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002121 return true;
2122
2123 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002124 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002125
2126 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002128
Jack Carterd0bd6422013-04-18 00:41:53 +00002129 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002130 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002131}
2132
Jack Carterb4dbc172012-09-05 23:34:03 +00002133bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2134 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002135 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002136 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002137 if (ResTy == MatchOperand_Success) {
2138 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002139 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002140 StartLoc = Operand.getStartLoc();
2141 EndLoc = Operand.getEndLoc();
2142
2143 // AFAIK, we only support numeric registers and named GPR's in CFI
2144 // directives.
2145 // Don't worry about eating tokens before failing. Using an unrecognised
2146 // register is a parse error.
2147 if (Operand.isGPRAsmReg()) {
2148 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002149 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002150 }
2151
2152 return (RegNo == (unsigned)-1);
2153 }
2154
2155 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002156 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002157}
2158
Jack Carterb5cf5902013-04-17 00:18:04 +00002159bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002160 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002161 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002162 bool Result = true;
2163
2164 while (getLexer().getKind() == AsmToken::LParen)
2165 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002166
Jack Carterd0bd6422013-04-18 00:41:53 +00002167 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002168 default:
2169 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002170 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002171 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002172 case AsmToken::Integer:
2173 case AsmToken::Minus:
2174 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002175 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002177 else
2178 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002179 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002180 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002181 break;
Jack Carter873c7242013-01-12 01:03:14 +00002182 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002183 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002184 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002185 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002186}
2187
David Blaikie960ea3f2014-06-08 16:18:35 +00002188MipsAsmParser::OperandMatchResultTy
2189MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002190 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002191 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002192 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002193 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002194 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002195 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002196 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002197 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002198
Jack Carterb5cf5902013-04-17 00:18:04 +00002199 if (getLexer().getKind() == AsmToken::LParen) {
2200 Parser.Lex();
2201 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002202 }
2203
Jack Carterb5cf5902013-04-17 00:18:04 +00002204 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002206 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002207
Jack Carterd0bd6422013-04-18 00:41:53 +00002208 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002209 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002210 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2211 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002212 SMLoc E =
2213 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002214 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002215 return MatchOperand_Success;
2216 }
2217 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002218 SMLoc E =
2219 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002220
Jack Carterd0bd6422013-04-18 00:41:53 +00002221 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002222 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002223 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002224 S, E, *this);
2225 Operands.push_back(
2226 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002227 return MatchOperand_Success;
2228 }
2229 Error(Parser.getTok().getLoc(), "'(' expected");
2230 return MatchOperand_ParseFail;
2231 }
2232
Jack Carterd0bd6422013-04-18 00:41:53 +00002233 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002234 }
2235
Toma Tabacu13964452014-09-04 13:23:44 +00002236 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002237 if (Res != MatchOperand_Success)
2238 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002239
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002240 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002241 Error(Parser.getTok().getLoc(), "')' expected");
2242 return MatchOperand_ParseFail;
2243 }
2244
Jack Carter873c7242013-01-12 01:03:14 +00002245 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2246
Jack Carterd0bd6422013-04-18 00:41:53 +00002247 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002248
Craig Topper062a2ba2014-04-25 05:30:21 +00002249 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002250 IdVal = MCConstantExpr::Create(0, getContext());
2251
Jack Carterd0bd6422013-04-18 00:41:53 +00002252 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002253 std::unique_ptr<MipsOperand> op(
2254 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002255 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002256 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002257 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002258 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002259 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2260 int64_t Imm;
2261 if (IdVal->EvaluateAsAbsolute(Imm))
2262 IdVal = MCConstantExpr::Create(Imm, getContext());
2263 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2264 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2265 getContext());
2266 }
2267
David Blaikie960ea3f2014-06-08 16:18:35 +00002268 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002269 return MatchOperand_Success;
2270}
2271
David Blaikie960ea3f2014-06-08 16:18:35 +00002272bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002273 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002274 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2275 if (Sym) {
2276 SMLoc S = Parser.getTok().getLoc();
2277 const MCExpr *Expr;
2278 if (Sym->isVariable())
2279 Expr = Sym->getVariableValue();
2280 else
2281 return false;
2282 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002283 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002284 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002285 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002286 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002287 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002288 if (ResTy == MatchOperand_Success) {
2289 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002290 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002291 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002292 llvm_unreachable("Should never ParseFail");
2293 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002294 }
2295 } else if (Expr->getKind() == MCExpr::Constant) {
2296 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002297 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002298 Operands.push_back(
2299 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002300 return true;
2301 }
2302 }
2303 return false;
2304}
Jack Carterd0bd6422013-04-18 00:41:53 +00002305
Jack Carter873c7242013-01-12 01:03:14 +00002306MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002307MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002308 StringRef Identifier,
2309 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002310 int Index = matchCPURegisterName(Identifier);
2311 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002312 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002313 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2314 return MatchOperand_Success;
2315 }
2316
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002317 Index = matchHWRegsRegisterName(Identifier);
2318 if (Index != -1) {
2319 Operands.push_back(MipsOperand::createHWRegsReg(
2320 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2321 return MatchOperand_Success;
2322 }
2323
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002324 Index = matchFPURegisterName(Identifier);
2325 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002326 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002327 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2328 return MatchOperand_Success;
2329 }
2330
2331 Index = matchFCCRegisterName(Identifier);
2332 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002333 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002334 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2335 return MatchOperand_Success;
2336 }
2337
2338 Index = matchACRegisterName(Identifier);
2339 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002340 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002341 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2342 return MatchOperand_Success;
2343 }
2344
2345 Index = matchMSA128RegisterName(Identifier);
2346 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002347 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002348 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2349 return MatchOperand_Success;
2350 }
2351
2352 Index = matchMSA128CtrlRegisterName(Identifier);
2353 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002354 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002355 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2356 return MatchOperand_Success;
2357 }
2358
2359 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002360}
2361
2362MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002363MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002364 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002365 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002366
2367 if (Token.is(AsmToken::Identifier)) {
2368 DEBUG(dbgs() << ".. identifier\n");
2369 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002370 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002371 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002372 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002373 } else if (Token.is(AsmToken::Integer)) {
2374 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002375 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002376 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2377 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002378 return MatchOperand_Success;
2379 }
2380
2381 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2382
2383 return MatchOperand_NoMatch;
2384}
2385
David Blaikie960ea3f2014-06-08 16:18:35 +00002386MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002387MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002388 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002389 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002390
2391 auto Token = Parser.getTok();
2392
2393 SMLoc S = Token.getLoc();
2394
2395 if (Token.isNot(AsmToken::Dollar)) {
2396 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2397 if (Token.is(AsmToken::Identifier)) {
2398 if (searchSymbolAlias(Operands))
2399 return MatchOperand_Success;
2400 }
2401 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2402 return MatchOperand_NoMatch;
2403 }
2404 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002405
Toma Tabacu13964452014-09-04 13:23:44 +00002406 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002407 if (ResTy == MatchOperand_Success) {
2408 Parser.Lex(); // $
2409 Parser.Lex(); // identifier
2410 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002411 return ResTy;
2412}
2413
2414MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002415MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002416 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002417 switch (getLexer().getKind()) {
2418 default:
2419 return MatchOperand_NoMatch;
2420 case AsmToken::LParen:
2421 case AsmToken::Minus:
2422 case AsmToken::Plus:
2423 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002424 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002425 case AsmToken::String:
2426 break;
2427 }
2428
2429 const MCExpr *IdVal;
2430 SMLoc S = Parser.getTok().getLoc();
2431 if (getParser().parseExpression(IdVal))
2432 return MatchOperand_ParseFail;
2433
2434 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2435 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2436 return MatchOperand_Success;
2437}
2438
David Blaikie960ea3f2014-06-08 16:18:35 +00002439MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002440MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002441 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002442 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002443
2444 SMLoc S = getLexer().getLoc();
2445
2446 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002447 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002448 if (ResTy != MatchOperand_NoMatch)
2449 return ResTy;
2450
Daniel Sanders315386c2014-04-01 10:40:14 +00002451 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002452 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002453 if (ResTy != MatchOperand_NoMatch)
2454 return ResTy;
2455
Daniel Sandersffd84362014-04-01 10:41:48 +00002456 const MCExpr *Expr = nullptr;
2457 if (Parser.parseExpression(Expr)) {
2458 // We have no way of knowing if a symbol was consumed so we must ParseFail
2459 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002460 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002461 Operands.push_back(
2462 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002463 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002464}
2465
Vladimir Medic2b953d02013-10-01 09:48:56 +00002466MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002467MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002468 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002469 const MCExpr *IdVal;
2470 // If the first token is '$' we may have register operand.
2471 if (Parser.getTok().is(AsmToken::Dollar))
2472 return MatchOperand_NoMatch;
2473 SMLoc S = Parser.getTok().getLoc();
2474 if (getParser().parseExpression(IdVal))
2475 return MatchOperand_ParseFail;
2476 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002477 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002478 int64_t Val = MCE->getValue();
2479 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2480 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002481 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002482 return MatchOperand_Success;
2483}
2484
Matheus Almeida779c5932013-11-18 12:32:49 +00002485MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002486MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002487 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002488 switch (getLexer().getKind()) {
2489 default:
2490 return MatchOperand_NoMatch;
2491 case AsmToken::LParen:
2492 case AsmToken::Plus:
2493 case AsmToken::Minus:
2494 case AsmToken::Integer:
2495 break;
2496 }
2497
2498 const MCExpr *Expr;
2499 SMLoc S = Parser.getTok().getLoc();
2500
2501 if (getParser().parseExpression(Expr))
2502 return MatchOperand_ParseFail;
2503
2504 int64_t Val;
2505 if (!Expr->EvaluateAsAbsolute(Val)) {
2506 Error(S, "expected immediate value");
2507 return MatchOperand_ParseFail;
2508 }
2509
2510 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2511 // and because the CPU always adds one to the immediate field, the allowed
2512 // range becomes 1..4. We'll only check the range here and will deal
2513 // with the addition/subtraction when actually decoding/encoding
2514 // the instruction.
2515 if (Val < 1 || Val > 4) {
2516 Error(S, "immediate not in range (1..4)");
2517 return MatchOperand_ParseFail;
2518 }
2519
Jack Carter3b2c96e2014-01-22 23:31:38 +00002520 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002521 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002522 return MatchOperand_Success;
2523}
2524
Jack Carterdc1e35d2012-09-06 20:00:02 +00002525MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2526
Vladimir Medic4c299852013-11-06 11:27:05 +00002527 MCSymbolRefExpr::VariantKind VK =
2528 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2529 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2530 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2531 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2532 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2533 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2534 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2535 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2536 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2537 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2538 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2539 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2540 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2541 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2542 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2543 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2544 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2545 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002546 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2547 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2548 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2549 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2550 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2551 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002552 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2553 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002554 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002555
Matheus Almeida2852af82014-04-22 10:15:54 +00002556 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002557
Jack Carterdc1e35d2012-09-06 20:00:02 +00002558 return VK;
2559}
Jack Cartera63b16a2012-09-07 00:23:42 +00002560
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002561/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2562/// either this.
2563/// ::= '(', register, ')'
2564/// handle it before we iterate so we don't get tripped up by the lack of
2565/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002566bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002567 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002568 if (getLexer().is(AsmToken::LParen)) {
2569 Operands.push_back(
2570 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2571 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002572 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002573 SMLoc Loc = getLexer().getLoc();
2574 Parser.eatToEndOfStatement();
2575 return Error(Loc, "unexpected token in argument list");
2576 }
2577 if (Parser.getTok().isNot(AsmToken::RParen)) {
2578 SMLoc Loc = getLexer().getLoc();
2579 Parser.eatToEndOfStatement();
2580 return Error(Loc, "unexpected token, expected ')'");
2581 }
2582 Operands.push_back(
2583 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2584 Parser.Lex();
2585 }
2586 return false;
2587}
2588
2589/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2590/// either one of these.
2591/// ::= '[', register, ']'
2592/// ::= '[', integer, ']'
2593/// handle it before we iterate so we don't get tripped up by the lack of
2594/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002595bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002596 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002597 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002598 if (getLexer().is(AsmToken::LBrac)) {
2599 Operands.push_back(
2600 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2601 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002602 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002603 SMLoc Loc = getLexer().getLoc();
2604 Parser.eatToEndOfStatement();
2605 return Error(Loc, "unexpected token in argument list");
2606 }
2607 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2608 SMLoc Loc = getLexer().getLoc();
2609 Parser.eatToEndOfStatement();
2610 return Error(Loc, "unexpected token, expected ']'");
2611 }
2612 Operands.push_back(
2613 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2614 Parser.Lex();
2615 }
2616 return false;
2617}
2618
David Blaikie960ea3f2014-06-08 16:18:35 +00002619bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2620 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002621 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002622 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002623
2624 // We have reached first instruction, module directive are now forbidden.
2625 getTargetStreamer().forbidModuleDirective();
2626
Vladimir Medic74593e62013-07-17 15:00:42 +00002627 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002628 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002629 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002630 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002631 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002632 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002633 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002634
2635 // Read the remaining operands.
2636 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2637 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002638 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002639 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002640 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002641 return Error(Loc, "unexpected token in argument list");
2642 }
Toma Tabacu13964452014-09-04 13:23:44 +00002643 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002644 return true;
2645 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002646
Jack Carterd0bd6422013-04-18 00:41:53 +00002647 while (getLexer().is(AsmToken::Comma)) {
2648 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002649 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002650 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002651 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002652 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002653 return Error(Loc, "unexpected token in argument list");
2654 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002655 // Parse bracket and parenthesis suffixes before we iterate
2656 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002657 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002658 return true;
2659 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002660 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002661 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002662 }
2663 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002664 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2665 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002666 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002667 return Error(Loc, "unexpected token in argument list");
2668 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002669 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002670 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002671}
2672
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002673bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002674 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002675 SMLoc Loc = getLexer().getLoc();
2676 Parser.eatToEndOfStatement();
2677 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002678}
2679
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002680bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002681 return Error(Loc, ErrorMsg);
2682}
2683
Jack Carter0b744b32012-10-04 02:29:46 +00002684bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002685 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002686 // Line should look like: ".set noat".
2687 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002688 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002689 // eat noat
2690 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002691 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002693 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002694 return false;
2695 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002696 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002697 return false;
2698}
Jack Carterd0bd6422013-04-18 00:41:53 +00002699
Jack Carter0b744b32012-10-04 02:29:46 +00002700bool MipsAsmParser::parseSetAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002701 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002702 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002703 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002704 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002705 getParser().Lex();
2706 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002707 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002708 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002709 return false;
2710 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002712 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002713 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002714 return false;
2715 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002716 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002717 const AsmToken &Reg = Parser.getTok();
2718 if (Reg.is(AsmToken::Identifier)) {
2719 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2720 } else if (Reg.is(AsmToken::Integer)) {
2721 AtRegNo = Reg.getIntVal();
2722 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002723 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002724 return false;
2725 }
Jack Carter1ac53222013-02-20 23:11:17 +00002726
Daniel Sanders71a89d922014-03-25 13:01:06 +00002727 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002728 reportParseError("unexpected token in statement");
2729 return false;
2730 }
2731
Toma Tabacu9db22db2014-09-09 10:15:38 +00002732 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002733 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002734 return false;
2735 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002736 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002737
2738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002739 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002740 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002741 }
2742 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002743 return false;
2744 } else {
2745 reportParseError("unexpected token in statement");
2746 return false;
2747 }
2748}
2749
2750bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002751 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002752 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002753 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002754 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002755 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002756 return false;
2757 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002758 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002759 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002760 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002761 return false;
2762}
2763
2764bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002765 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00002766 Parser.Lex();
2767 // If this is not the end of the statement, report an error.
2768 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002769 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002770 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002771 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002772 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002773 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002774 Parser.Lex(); // Consume the EndOfStatement.
2775 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002776}
2777
2778bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002779 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002780 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002781 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002782 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002783 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002784 return false;
2785 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002786 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002787 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002788 return false;
2789}
2790
2791bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002792 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00002793 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002794 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002795 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002796 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002797 return false;
2798 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002799 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002800 reportParseError("`noreorder' must be set before `nomacro'");
2801 return false;
2802 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002803 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002804 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002805 return false;
2806}
Jack Carterd76b2372013-03-21 21:44:16 +00002807
Daniel Sanders44934432014-08-07 12:03:36 +00002808bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002809 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002810 Parser.Lex();
2811
2812 // If this is not the end of the statement, report an error.
2813 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002814 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002815
2816 setFeatureBits(Mips::FeatureMSA, "msa");
2817 getTargetStreamer().emitDirectiveSetMsa();
2818 return false;
2819}
2820
2821bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002822 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00002823 Parser.Lex();
2824
2825 // If this is not the end of the statement, report an error.
2826 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002827 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002828
2829 clearFeatureBits(Mips::FeatureMSA, "msa");
2830 getTargetStreamer().emitDirectiveSetNoMsa();
2831 return false;
2832}
2833
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002834bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002835 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002836 Parser.Lex(); // Eat "nodsp".
2837
2838 // If this is not the end of the statement, report an error.
2839 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2840 reportParseError("unexpected token, expected end of statement");
2841 return false;
2842 }
2843
2844 clearFeatureBits(Mips::FeatureDSP, "dsp");
2845 getTargetStreamer().emitDirectiveSetNoDsp();
2846 return false;
2847}
2848
Toma Tabacucc2502d2014-11-04 17:18:07 +00002849bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002850 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00002851 Parser.Lex(); // Eat "mips16".
2852
Jack Carter39536722014-01-22 23:08:42 +00002853 // If this is not the end of the statement, report an error.
2854 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002855 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002856 return false;
2857 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00002858
2859 setFeatureBits(Mips::FeatureMips16, "mips16");
2860 getTargetStreamer().emitDirectiveSetMips16();
2861 Parser.Lex(); // Consume the EndOfStatement.
2862 return false;
2863}
2864
2865bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002866 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00002867 Parser.Lex(); // Eat "nomips16".
2868
2869 // If this is not the end of the statement, report an error.
2870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2871 reportParseError("unexpected token, expected end of statement");
2872 return false;
2873 }
2874
2875 clearFeatureBits(Mips::FeatureMips16, "mips16");
2876 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00002877 Parser.Lex(); // Consume the EndOfStatement.
2878 return false;
2879}
2880
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002881bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002882 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00002883 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002884 // Line can be: .set fp=32
2885 // .set fp=xx
2886 // .set fp=64
2887 Parser.Lex(); // Eat fp token
2888 AsmToken Tok = Parser.getTok();
2889 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002890 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002891 return false;
2892 }
2893 Parser.Lex(); // Eat '=' token.
2894 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002895
2896 if (!parseFpABIValue(FpAbiVal, ".set"))
2897 return false;
2898
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002899 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002900 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002901 return false;
2902 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002903 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002904 Parser.Lex(); // Consume the EndOfStatement.
2905 return false;
2906}
2907
Toma Tabacu9db22db2014-09-09 10:15:38 +00002908bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002909 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002910 SMLoc Loc = getLexer().getLoc();
2911
2912 Parser.Lex();
2913 if (getLexer().isNot(AsmToken::EndOfStatement))
2914 return reportParseError("unexpected token, expected end of statement");
2915
2916 // Always keep an element on the options "stack" to prevent the user
2917 // from changing the initial options. This is how we remember them.
2918 if (AssemblerOptions.size() == 2)
2919 return reportParseError(Loc, ".set pop with no .set push");
2920
2921 AssemblerOptions.pop_back();
2922 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2923
2924 getTargetStreamer().emitDirectiveSetPop();
2925 return false;
2926}
2927
2928bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002929 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002930 Parser.Lex();
2931 if (getLexer().isNot(AsmToken::EndOfStatement))
2932 return reportParseError("unexpected token, expected end of statement");
2933
2934 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002935 AssemblerOptions.push_back(
2936 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002937
2938 getTargetStreamer().emitDirectiveSetPush();
2939 return false;
2940}
2941
Jack Carterd76b2372013-03-21 21:44:16 +00002942bool MipsAsmParser::parseSetAssignment() {
2943 StringRef Name;
2944 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00002945 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002946
2947 if (Parser.parseIdentifier(Name))
2948 reportParseError("expected identifier after .set");
2949
2950 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00002951 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00002952 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002953
Jack Carter3b2c96e2014-01-22 23:31:38 +00002954 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002955 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002956
Jack Carterd0bd6422013-04-18 00:41:53 +00002957 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002958 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002959 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002960 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002961 Sym = getContext().GetOrCreateSymbol(Name);
2962 Sym->setVariableValue(Value);
2963
2964 return false;
2965}
Jack Carterd0bd6422013-04-18 00:41:53 +00002966
Toma Tabacu26647792014-09-09 12:52:14 +00002967bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002968 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00002969 Parser.Lex();
2970 if (getLexer().isNot(AsmToken::EndOfStatement))
2971 return reportParseError("unexpected token, expected end of statement");
2972
2973 // Reset assembler options to their initial values.
2974 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2975 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2976
2977 getTargetStreamer().emitDirectiveSetMips0();
2978 return false;
2979}
2980
Toma Tabacu85618b32014-08-19 14:22:52 +00002981bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002982 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00002983 Parser.Lex();
2984 if (getLexer().isNot(AsmToken::Equal))
2985 return reportParseError("unexpected token, expected equals sign");
2986
2987 Parser.Lex();
2988 StringRef Arch;
2989 if (Parser.parseIdentifier(Arch))
2990 return reportParseError("expected arch identifier");
2991
2992 StringRef ArchFeatureName =
2993 StringSwitch<StringRef>(Arch)
2994 .Case("mips1", "mips1")
2995 .Case("mips2", "mips2")
2996 .Case("mips3", "mips3")
2997 .Case("mips4", "mips4")
2998 .Case("mips5", "mips5")
2999 .Case("mips32", "mips32")
3000 .Case("mips32r2", "mips32r2")
3001 .Case("mips32r6", "mips32r6")
3002 .Case("mips64", "mips64")
3003 .Case("mips64r2", "mips64r2")
3004 .Case("mips64r6", "mips64r6")
3005 .Case("cnmips", "cnmips")
3006 .Case("r4000", "mips3") // This is an implementation of Mips3.
3007 .Default("");
3008
3009 if (ArchFeatureName.empty())
3010 return reportParseError("unsupported architecture");
3011
3012 selectArch(ArchFeatureName);
3013 getTargetStreamer().emitDirectiveSetArch(Arch);
3014 return false;
3015}
3016
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003017bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003018 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003019 Parser.Lex();
3020 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003021 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003022
Matheus Almeida2852af82014-04-22 10:15:54 +00003023 switch (Feature) {
3024 default:
3025 llvm_unreachable("Unimplemented feature");
3026 case Mips::FeatureDSP:
3027 setFeatureBits(Mips::FeatureDSP, "dsp");
3028 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003029 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003030 case Mips::FeatureMicroMips:
3031 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003032 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003033 case Mips::FeatureMips1:
3034 selectArch("mips1");
3035 getTargetStreamer().emitDirectiveSetMips1();
3036 break;
3037 case Mips::FeatureMips2:
3038 selectArch("mips2");
3039 getTargetStreamer().emitDirectiveSetMips2();
3040 break;
3041 case Mips::FeatureMips3:
3042 selectArch("mips3");
3043 getTargetStreamer().emitDirectiveSetMips3();
3044 break;
3045 case Mips::FeatureMips4:
3046 selectArch("mips4");
3047 getTargetStreamer().emitDirectiveSetMips4();
3048 break;
3049 case Mips::FeatureMips5:
3050 selectArch("mips5");
3051 getTargetStreamer().emitDirectiveSetMips5();
3052 break;
3053 case Mips::FeatureMips32:
3054 selectArch("mips32");
3055 getTargetStreamer().emitDirectiveSetMips32();
3056 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003057 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003058 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003059 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003060 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003061 case Mips::FeatureMips32r6:
3062 selectArch("mips32r6");
3063 getTargetStreamer().emitDirectiveSetMips32R6();
3064 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003065 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003066 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003067 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003068 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003069 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003070 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003071 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003072 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003073 case Mips::FeatureMips64r6:
3074 selectArch("mips64r6");
3075 getTargetStreamer().emitDirectiveSetMips64R6();
3076 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003077 }
3078 return false;
3079}
3080
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003081bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003082 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003083 if (getLexer().isNot(AsmToken::Comma)) {
3084 SMLoc Loc = getLexer().getLoc();
3085 Parser.eatToEndOfStatement();
3086 return Error(Loc, ErrorStr);
3087 }
3088
Matheus Almeida2852af82014-04-22 10:15:54 +00003089 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003090 return true;
3091}
3092
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003093bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003094 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003095 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003096
Toma Tabacudde4c462014-11-06 10:02:45 +00003097 if (inMips16Mode()) {
3098 reportParseError(".cpload is not supported in Mips16 mode");
3099 return false;
3100 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003101
David Blaikie960ea3f2014-06-08 16:18:35 +00003102 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003103 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003104 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3105 reportParseError("expected register containing function address");
3106 return false;
3107 }
3108
David Blaikie960ea3f2014-06-08 16:18:35 +00003109 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3110 if (!RegOpnd.isGPRAsmReg()) {
3111 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003112 return false;
3113 }
3114
Toma Tabacudde4c462014-11-06 10:02:45 +00003115 // If this is not the end of the statement, report an error.
3116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3117 reportParseError("unexpected token, expected end of statement");
3118 return false;
3119 }
3120
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003121 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003122 return false;
3123}
3124
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003125bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003126 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003127 unsigned FuncReg;
3128 unsigned Save;
3129 bool SaveIsReg = true;
3130
Matheus Almeida7e815762014-06-18 13:08:59 +00003131 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003132 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003133 if (ResTy == MatchOperand_NoMatch) {
3134 reportParseError("expected register containing function address");
3135 Parser.eatToEndOfStatement();
3136 return false;
3137 }
3138
3139 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3140 if (!FuncRegOpnd.isGPRAsmReg()) {
3141 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3142 Parser.eatToEndOfStatement();
3143 return false;
3144 }
3145
3146 FuncReg = FuncRegOpnd.getGPR32Reg();
3147 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003148
Toma Tabacu65f10572014-09-16 15:00:52 +00003149 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003150 return true;
3151
Toma Tabacu13964452014-09-04 13:23:44 +00003152 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003153 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003154 const AsmToken &Tok = Parser.getTok();
3155 if (Tok.is(AsmToken::Integer)) {
3156 Save = Tok.getIntVal();
3157 SaveIsReg = false;
3158 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003159 } else {
3160 reportParseError("expected save register or stack offset");
3161 Parser.eatToEndOfStatement();
3162 return false;
3163 }
3164 } else {
3165 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3166 if (!SaveOpnd.isGPRAsmReg()) {
3167 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3168 Parser.eatToEndOfStatement();
3169 return false;
3170 }
3171 Save = SaveOpnd.getGPR32Reg();
3172 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003173
Toma Tabacu65f10572014-09-16 15:00:52 +00003174 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003175 return true;
3176
3177 StringRef Name;
3178 if (Parser.parseIdentifier(Name))
3179 reportParseError("expected identifier");
3180 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003181
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003182 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003183 return false;
3184}
3185
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003186bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003187 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3189 const AsmToken &Tok = Parser.getTok();
3190
3191 if (Tok.getString() == "2008") {
3192 Parser.Lex();
3193 getTargetStreamer().emitDirectiveNaN2008();
3194 return false;
3195 } else if (Tok.getString() == "legacy") {
3196 Parser.Lex();
3197 getTargetStreamer().emitDirectiveNaNLegacy();
3198 return false;
3199 }
3200 }
3201 // If we don't recognize the option passed to the .nan
3202 // directive (e.g. no option or unknown option), emit an error.
3203 reportParseError("invalid option in .nan directive");
3204 return false;
3205}
3206
Jack Carter0b744b32012-10-04 02:29:46 +00003207bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003208 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003209 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003210 const AsmToken &Tok = Parser.getTok();
3211
3212 if (Tok.getString() == "noat") {
3213 return parseSetNoAtDirective();
3214 } else if (Tok.getString() == "at") {
3215 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003216 } else if (Tok.getString() == "arch") {
3217 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003218 } else if (Tok.getString() == "fp") {
3219 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003220 } else if (Tok.getString() == "pop") {
3221 return parseSetPopDirective();
3222 } else if (Tok.getString() == "push") {
3223 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003224 } else if (Tok.getString() == "reorder") {
3225 return parseSetReorderDirective();
3226 } else if (Tok.getString() == "noreorder") {
3227 return parseSetNoReorderDirective();
3228 } else if (Tok.getString() == "macro") {
3229 return parseSetMacroDirective();
3230 } else if (Tok.getString() == "nomacro") {
3231 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003232 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003233 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003234 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003235 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003236 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003237 getTargetStreamer().emitDirectiveSetNoMicroMips();
3238 Parser.eatToEndOfStatement();
3239 return false;
3240 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003241 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003242 } else if (Tok.getString() == "mips0") {
3243 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003244 } else if (Tok.getString() == "mips1") {
3245 return parseSetFeature(Mips::FeatureMips1);
3246 } else if (Tok.getString() == "mips2") {
3247 return parseSetFeature(Mips::FeatureMips2);
3248 } else if (Tok.getString() == "mips3") {
3249 return parseSetFeature(Mips::FeatureMips3);
3250 } else if (Tok.getString() == "mips4") {
3251 return parseSetFeature(Mips::FeatureMips4);
3252 } else if (Tok.getString() == "mips5") {
3253 return parseSetFeature(Mips::FeatureMips5);
3254 } else if (Tok.getString() == "mips32") {
3255 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003256 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003257 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003258 } else if (Tok.getString() == "mips32r6") {
3259 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003260 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003261 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003262 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003263 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003264 } else if (Tok.getString() == "mips64r6") {
3265 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003266 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003267 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003268 } else if (Tok.getString() == "nodsp") {
3269 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003270 } else if (Tok.getString() == "msa") {
3271 return parseSetMsaDirective();
3272 } else if (Tok.getString() == "nomsa") {
3273 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003274 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003275 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003276 parseSetAssignment();
3277 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003278 }
Jack Carter07c818d2013-01-25 01:31:34 +00003279
Jack Carter0b744b32012-10-04 02:29:46 +00003280 return true;
3281}
3282
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003283/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003284/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003285bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003286 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003287 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3288 for (;;) {
3289 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003290 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003291 return true;
3292
3293 getParser().getStreamer().EmitValue(Value, Size);
3294
3295 if (getLexer().is(AsmToken::EndOfStatement))
3296 break;
3297
Jack Carter07c818d2013-01-25 01:31:34 +00003298 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003299 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003300 Parser.Lex();
3301 }
3302 }
3303
3304 Parser.Lex();
3305 return false;
3306}
3307
Vladimir Medic4c299852013-11-06 11:27:05 +00003308/// parseDirectiveGpWord
3309/// ::= .gpword local_sym
3310bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003311 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003312 const MCExpr *Value;
3313 // EmitGPRel32Value requires an expression, so we are using base class
3314 // method to evaluate the expression.
3315 if (getParser().parseExpression(Value))
3316 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003317 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003318
Vladimir Medice10c1122013-11-13 13:18:04 +00003319 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003320 return Error(getLexer().getLoc(),
3321 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003322 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003323 return false;
3324}
3325
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003326/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003327/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003328bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003329 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003330 const MCExpr *Value;
3331 // EmitGPRel64Value requires an expression, so we are using base class
3332 // method to evaluate the expression.
3333 if (getParser().parseExpression(Value))
3334 return true;
3335 getParser().getStreamer().EmitGPRel64Value(Value);
3336
3337 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003338 return Error(getLexer().getLoc(),
3339 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003340 Parser.Lex(); // Eat EndOfStatement token.
3341 return false;
3342}
3343
Jack Carter0cd3c192014-01-06 23:27:31 +00003344bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003345 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00003346 // Get the option token.
3347 AsmToken Tok = Parser.getTok();
3348 // At the moment only identifiers are supported.
3349 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003350 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003351 Parser.eatToEndOfStatement();
3352 return false;
3353 }
3354
3355 StringRef Option = Tok.getIdentifier();
3356
3357 if (Option == "pic0") {
3358 getTargetStreamer().emitDirectiveOptionPic0();
3359 Parser.Lex();
3360 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3361 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003362 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003363 Parser.eatToEndOfStatement();
3364 }
3365 return false;
3366 }
3367
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003368 if (Option == "pic2") {
3369 getTargetStreamer().emitDirectiveOptionPic2();
3370 Parser.Lex();
3371 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3372 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003373 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003374 Parser.eatToEndOfStatement();
3375 }
3376 return false;
3377 }
3378
Jack Carter0cd3c192014-01-06 23:27:31 +00003379 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003380 Warning(Parser.getTok().getLoc(),
3381 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003382 Parser.eatToEndOfStatement();
3383 return false;
3384}
3385
Daniel Sanders7e527422014-07-10 13:38:23 +00003386/// parseDirectiveModule
3387/// ::= .module oddspreg
3388/// ::= .module nooddspreg
3389/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003390bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003391 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003392 MCAsmLexer &Lexer = getLexer();
3393 SMLoc L = Lexer.getLoc();
3394
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003395 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003396 // TODO : get a better message.
3397 reportParseError(".module directive must appear before any code");
3398 return false;
3399 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003400
3401 if (Lexer.is(AsmToken::Identifier)) {
3402 StringRef Option = Parser.getTok().getString();
3403 Parser.Lex();
3404
3405 if (Option == "oddspreg") {
3406 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3407 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3408
3409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003410 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003411 return false;
3412 }
3413
3414 return false;
3415 } else if (Option == "nooddspreg") {
3416 if (!isABI_O32()) {
3417 Error(L, "'.module nooddspreg' requires the O32 ABI");
3418 return false;
3419 }
3420
3421 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3422 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3423
3424 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003425 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003426 return false;
3427 }
3428
3429 return false;
3430 } else if (Option == "fp") {
3431 return parseDirectiveModuleFP();
3432 }
3433
3434 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003435 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003436
3437 return false;
3438}
3439
3440/// parseDirectiveModuleFP
3441/// ::= =32
3442/// ::= =xx
3443/// ::= =64
3444bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003445 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003446 MCAsmLexer &Lexer = getLexer();
3447
3448 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003449 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003450 return false;
3451 }
3452 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003453
Daniel Sanders7e527422014-07-10 13:38:23 +00003454 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003455 if (!parseFpABIValue(FpABI, ".module"))
3456 return false;
3457
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003458 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003459 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003460 return false;
3461 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003462
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003463 // Emit appropriate flags.
3464 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003465 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003466 return false;
3467}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003468
Daniel Sanders7e527422014-07-10 13:38:23 +00003469bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003470 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003471 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003472 MCAsmLexer &Lexer = getLexer();
3473
3474 if (Lexer.is(AsmToken::Identifier)) {
3475 StringRef Value = Parser.getTok().getString();
3476 Parser.Lex();
3477
3478 if (Value != "xx") {
3479 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3480 return false;
3481 }
3482
3483 if (!isABI_O32()) {
3484 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3485 return false;
3486 }
3487
Daniel Sanders7e527422014-07-10 13:38:23 +00003488 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003489 return true;
3490 }
3491
3492 if (Lexer.is(AsmToken::Integer)) {
3493 unsigned Value = Parser.getTok().getIntVal();
3494 Parser.Lex();
3495
3496 if (Value != 32 && Value != 64) {
3497 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3498 return false;
3499 }
3500
3501 if (Value == 32) {
3502 if (!isABI_O32()) {
3503 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3504 return false;
3505 }
3506
Daniel Sanders7e527422014-07-10 13:38:23 +00003507 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3508 } else
3509 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003510
Daniel Sanders7e527422014-07-10 13:38:23 +00003511 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003512 }
3513
3514 return false;
3515}
3516
Jack Carter0b744b32012-10-04 02:29:46 +00003517bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003518 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003519 StringRef IDVal = DirectiveID.getString();
3520
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003521 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003522 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003523 if (IDVal == ".dword") {
3524 parseDataDirective(8, DirectiveID.getLoc());
3525 return false;
3526 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003527 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003528 StringRef SymbolName;
3529
3530 if (Parser.parseIdentifier(SymbolName)) {
3531 reportParseError("expected identifier after .ent");
3532 return false;
3533 }
3534
3535 // There's an undocumented extension that allows an integer to
3536 // follow the name of the procedure which AFAICS is ignored by GAS.
3537 // Example: .ent foo,2
3538 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3539 if (getLexer().isNot(AsmToken::Comma)) {
3540 // Even though we accept this undocumented extension for compatibility
3541 // reasons, the additional integer argument does not actually change
3542 // the behaviour of the '.ent' directive, so we would like to discourage
3543 // its use. We do this by not referring to the extended version in
3544 // error messages which are not directly related to its use.
3545 reportParseError("unexpected token, expected end of statement");
3546 return false;
3547 }
3548 Parser.Lex(); // Eat the comma.
3549 const MCExpr *DummyNumber;
3550 int64_t DummyNumberVal;
3551 // If the user was explicitly trying to use the extended version,
3552 // we still give helpful extension-related error messages.
3553 if (Parser.parseExpression(DummyNumber)) {
3554 reportParseError("expected number after comma");
3555 return false;
3556 }
3557 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3558 reportParseError("expected an absolute expression after comma");
3559 return false;
3560 }
3561 }
3562
3563 // If this is not the end of the statement, report an error.
3564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3565 reportParseError("unexpected token, expected end of statement");
3566 return false;
3567 }
3568
3569 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3570
3571 getTargetStreamer().emitDirectiveEnt(*Sym);
3572 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003573 return false;
3574 }
3575
Jack Carter07c818d2013-01-25 01:31:34 +00003576 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003577 StringRef SymbolName;
3578
3579 if (Parser.parseIdentifier(SymbolName)) {
3580 reportParseError("expected identifier after .end");
3581 return false;
3582 }
3583
3584 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3585 reportParseError("unexpected token, expected end of statement");
3586 return false;
3587 }
3588
3589 if (CurrentFn == nullptr) {
3590 reportParseError(".end used without .ent");
3591 return false;
3592 }
3593
3594 if ((SymbolName != CurrentFn->getName())) {
3595 reportParseError(".end symbol does not match .ent symbol");
3596 return false;
3597 }
3598
3599 getTargetStreamer().emitDirectiveEnd(SymbolName);
3600 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003601 return false;
3602 }
3603
Jack Carter07c818d2013-01-25 01:31:34 +00003604 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003605 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3606 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003607 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003608 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3609 reportParseError("expected stack register");
3610 return false;
3611 }
3612
3613 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3614 if (!StackRegOpnd.isGPRAsmReg()) {
3615 reportParseError(StackRegOpnd.getStartLoc(),
3616 "expected general purpose register");
3617 return false;
3618 }
3619 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3620
3621 if (Parser.getTok().is(AsmToken::Comma))
3622 Parser.Lex();
3623 else {
3624 reportParseError("unexpected token, expected comma");
3625 return false;
3626 }
3627
3628 // Parse the frame size.
3629 const MCExpr *FrameSize;
3630 int64_t FrameSizeVal;
3631
3632 if (Parser.parseExpression(FrameSize)) {
3633 reportParseError("expected frame size value");
3634 return false;
3635 }
3636
3637 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3638 reportParseError("frame size not an absolute expression");
3639 return false;
3640 }
3641
3642 if (Parser.getTok().is(AsmToken::Comma))
3643 Parser.Lex();
3644 else {
3645 reportParseError("unexpected token, expected comma");
3646 return false;
3647 }
3648
3649 // Parse the return register.
3650 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003651 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003652 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3653 reportParseError("expected return register");
3654 return false;
3655 }
3656
3657 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3658 if (!ReturnRegOpnd.isGPRAsmReg()) {
3659 reportParseError(ReturnRegOpnd.getStartLoc(),
3660 "expected general purpose register");
3661 return false;
3662 }
3663
3664 // If this is not the end of the statement, report an error.
3665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3666 reportParseError("unexpected token, expected end of statement");
3667 return false;
3668 }
3669
3670 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3671 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003672 return false;
3673 }
3674
Jack Carter07c818d2013-01-25 01:31:34 +00003675 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003676 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003677 }
3678
Daniel Sandersd97a6342014-08-13 10:07:34 +00003679 if (IDVal == ".mask" || IDVal == ".fmask") {
3680 // .mask bitmask, frame_offset
3681 // bitmask: One bit for each register used.
3682 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3683 // first register is expected to be saved.
3684 // Examples:
3685 // .mask 0x80000000, -4
3686 // .fmask 0x80000000, -4
3687 //
Jack Carterbe332172012-09-07 00:48:02 +00003688
Daniel Sandersd97a6342014-08-13 10:07:34 +00003689 // Parse the bitmask
3690 const MCExpr *BitMask;
3691 int64_t BitMaskVal;
3692
3693 if (Parser.parseExpression(BitMask)) {
3694 reportParseError("expected bitmask value");
3695 return false;
3696 }
3697
3698 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3699 reportParseError("bitmask not an absolute expression");
3700 return false;
3701 }
3702
3703 if (Parser.getTok().is(AsmToken::Comma))
3704 Parser.Lex();
3705 else {
3706 reportParseError("unexpected token, expected comma");
3707 return false;
3708 }
3709
3710 // Parse the frame_offset
3711 const MCExpr *FrameOffset;
3712 int64_t FrameOffsetVal;
3713
3714 if (Parser.parseExpression(FrameOffset)) {
3715 reportParseError("expected frame offset value");
3716 return false;
3717 }
3718
3719 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3720 reportParseError("frame offset not an absolute expression");
3721 return false;
3722 }
3723
3724 // If this is not the end of the statement, report an error.
3725 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3726 reportParseError("unexpected token, expected end of statement");
3727 return false;
3728 }
3729
3730 if (IDVal == ".mask")
3731 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3732 else
3733 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003734 return false;
3735 }
3736
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003737 if (IDVal == ".nan")
3738 return parseDirectiveNaN();
3739
Jack Carter07c818d2013-01-25 01:31:34 +00003740 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003741 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003742 return false;
3743 }
3744
Rafael Espindolab59fb732014-03-28 18:50:26 +00003745 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003746 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003747 return false;
3748 }
3749
Jack Carter07c818d2013-01-25 01:31:34 +00003750 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003751 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003752 return false;
3753 }
3754
Jack Carter0cd3c192014-01-06 23:27:31 +00003755 if (IDVal == ".option")
3756 return parseDirectiveOption();
3757
3758 if (IDVal == ".abicalls") {
3759 getTargetStreamer().emitDirectiveAbiCalls();
3760 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003761 Error(Parser.getTok().getLoc(),
3762 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003763 // Clear line
3764 Parser.eatToEndOfStatement();
3765 }
3766 return false;
3767 }
3768
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003769 if (IDVal == ".cpsetup")
3770 return parseDirectiveCPSetup();
3771
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003772 if (IDVal == ".module")
3773 return parseDirectiveModule();
3774
Rafael Espindola870c4e92012-01-11 03:56:41 +00003775 return true;
3776}
3777
Rafael Espindola870c4e92012-01-11 03:56:41 +00003778extern "C" void LLVMInitializeMipsAsmParser() {
3779 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3780 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3781 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3782 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3783}
Jack Carterb4dbc172012-09-05 23:34:03 +00003784
3785#define GET_REGISTER_MATCHER
3786#define GET_MATCHER_IMPLEMENTATION
3787#include "MipsGenAsmMatcher.inc"