blob: 5d704e655a83970a4dd3faf50cc5400fe9a58e39 [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 Espindola4a1a3602014-01-14 01:21:46 +000093 MCTargetStreamer &TS = *Parser.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;
98 MCAsmParser &Parser;
Toma Tabacu9db22db2014-09-09 10:15:38 +000099 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000100 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
101 // nullptr, which indicates that no function is currently
102 // selected. This usually happens after an '.end func'
103 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000104
Daniel Sandersef638fe2014-10-03 15:37:37 +0000105 // Print a warning along with its fix-it message at the given range.
106 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
107 SMRange Range, bool ShowColors = true);
108
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000109#define GET_ASSEMBLER_HEADER
110#include "MipsGenAsmMatcher.inc"
111
Matheus Almeida595fcab2014-06-11 15:05:56 +0000112 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
113
Chad Rosier49963552012-10-13 00:26:04 +0000114 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000115 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000116 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000117 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000118
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000119 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000120 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000121
Toma Tabacu13964452014-09-04 13:23:44 +0000122 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000123
Toma Tabacu13964452014-09-04 13:23:44 +0000124 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000125
David Blaikie960ea3f2014-06-08 16:18:35 +0000126 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
127 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000128
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
David Blaikie960ea3f2014-06-08 16:18:35 +0000131 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000132
133 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000134 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000136
Jack Carter873c7242013-01-12 01:03:14 +0000137 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000138 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000139
Toma Tabacu13964452014-09-04 13:23:44 +0000140 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000147
Toma Tabacu13964452014-09-04 13:23:44 +0000148 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000149
David Blaikie960ea3f2014-06-08 16:18:35 +0000150 bool searchSymbolAlias(OperandVector &Operands);
151
Toma Tabacu13964452014-09-04 13:23:44 +0000152 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000153
Jack Carter30a59822012-10-04 04:03:53 +0000154 bool needsExpansion(MCInst &Inst);
155
Matheus Almeida3813d572014-06-19 14:39:14 +0000156 // Expands assembly pseudo instructions.
157 // Returns false on success, true otherwise.
158 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000159 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000160
161 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000162 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000163
164 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000165 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000166
167 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000168 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000169
Toma Tabacu0d64b202014-08-14 10:29:17 +0000170 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
171 SmallVectorImpl<MCInst> &Instructions);
172
Jack Carter9e65aa32013-03-22 00:05:30 +0000173 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000174 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
175 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000176 bool reportParseError(Twine ErrorMsg);
177 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000178
Jack Carterb5cf5902013-04-17 00:18:04 +0000179 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000180 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000181
Vladimir Medic4c299852013-11-06 11:27:05 +0000182 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000183
184 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000185 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000186 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000187 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000188 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000189 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000190 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000191 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000192 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000193
194 bool parseSetAtDirective();
195 bool parseSetNoAtDirective();
196 bool parseSetMacroDirective();
197 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000198 bool parseSetMsaDirective();
199 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000200 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000201 bool parseSetReorderDirective();
202 bool parseSetNoReorderDirective();
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
Jack Carter873c7242013-01-12 01:03:14 +0000224 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000225
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000226 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000227
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000228 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000229
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000230 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000231
Jack Carter5dc8ac92013-09-25 23:50:44 +0000232 int matchMSA128RegisterName(StringRef Name);
233
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000234 int matchMSA128CtrlRegisterName(StringRef Name);
235
Jack Carterd0bd6422013-04-18 00:41:53 +0000236 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000237
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000238 unsigned getGPR(int RegNo);
239
Matheus Almeida7de68e72014-06-18 14:46:05 +0000240 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000241
242 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000243 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000244
245 // Helper function that checks if the value of a vector index is within the
246 // boundaries of accepted values for each RegisterKind
247 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
248 bool validateMSAIndex(int Val, int RegKind);
249
Daniel Sandersf0df2212014-08-04 12:20:00 +0000250 // Selects a new architecture by updating the FeatureBits with the necessary
251 // info including implied dependencies.
252 // Internally, it clears all the feature bits related to *any* architecture
253 // and selects the new one using the ToggleFeature functionality of the
254 // MCSubtargetInfo object that handles implied dependencies. The reason we
255 // clear all the arch related bits manually is because ToggleFeature only
256 // clears the features that imply the feature being cleared and not the
257 // features implied by the feature being cleared. This is easier to see
258 // with an example:
259 // --------------------------------------------------
260 // | Feature | Implies |
261 // | -------------------------------------------------|
262 // | FeatureMips1 | None |
263 // | FeatureMips2 | FeatureMips1 |
264 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
265 // | FeatureMips4 | FeatureMips3 |
266 // | ... | |
267 // --------------------------------------------------
268 //
269 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
270 // FeatureMipsGP64 | FeatureMips1)
271 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
272 void selectArch(StringRef ArchFeature) {
273 uint64_t FeatureBits = STI.getFeatureBits();
274 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
275 STI.setFeatureBits(FeatureBits);
276 setAvailableFeatures(
277 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000278 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000279 }
280
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000281 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000282 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000283 setAvailableFeatures(
284 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000285 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000286 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 }
288
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000289 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000291 setAvailableFeatures(
292 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000293 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000294 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
296
Rafael Espindola870c4e92012-01-11 03:56:41 +0000297public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000298 enum MipsMatchResultTy {
299 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
300#define GET_OPERAND_DIAGNOSTIC_TYPES
301#include "MipsGenAsmMatcher.inc"
302#undef GET_OPERAND_DIAGNOSTIC_TYPES
303
304 };
305
Joey Gouly0e76fa72013-09-12 10:28:05 +0000306 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000307 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000308 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000309 // Initialize the set of available features.
310 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000311
312 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000313 AssemblerOptions.push_back(
314 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000315
316 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000317 AssemblerOptions.push_back(
318 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000319
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000320 getTargetStreamer().updateABIInfo(*this);
321
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000322 // Assert exactly one ABI was chosen.
323 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
324 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
325 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
326 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000327
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000328 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000329 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000330
331 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000332 }
333
Jack Carterb4dbc172012-09-05 23:34:03 +0000334 MCAsmParser &getParser() const { return Parser; }
335 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000336
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000337 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
338 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
339
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000340 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
341 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
342 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
343 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
344 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000345 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000346
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000347 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000348 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
349 }
350
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000351 bool inMicroMipsMode() const {
352 return STI.getFeatureBits() & Mips::FeatureMicroMips;
353 }
354 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
355 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
356 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
357 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
358 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
359 bool hasMips32() const {
360 return (STI.getFeatureBits() & Mips::FeatureMips32);
361 }
362 bool hasMips64() const {
363 return (STI.getFeatureBits() & Mips::FeatureMips64);
364 }
365 bool hasMips32r2() const {
366 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
367 }
368 bool hasMips64r2() const {
369 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
370 }
371 bool hasMips32r6() const {
372 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
373 }
374 bool hasMips64r6() const {
375 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
376 }
377 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
378 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
379 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
380
381 bool inMips16Mode() const {
382 return STI.getFeatureBits() & Mips::FeatureMips16;
383 }
384 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000385 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000386
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000387 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000388 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000389};
390}
391
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000392namespace {
393
394/// MipsOperand - Instances of this class represent a parsed Mips machine
395/// instruction.
396class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000397public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000398 /// Broad categories of register classes
399 /// The exact class is finalized by the render method.
400 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000402 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000403 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000404 RegKind_FCC = 4, /// FCC
405 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
406 RegKind_MSACtrl = 16, /// MSA control registers
407 RegKind_COP2 = 32, /// COP2
408 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
409 /// context).
410 RegKind_CCR = 128, /// CCR
411 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000412 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000413
414 /// Potentially any (e.g. $1)
415 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
416 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000417 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000418 };
419
420private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000421 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000422 k_Immediate, /// An immediate (possibly involving symbol references)
423 k_Memory, /// Base + Offset Memory Address
424 k_PhysRegister, /// A physical register from the Mips namespace
425 k_RegisterIndex, /// A register index in one or more RegKind.
426 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000427 } Kind;
428
David Blaikie960ea3f2014-06-08 16:18:35 +0000429public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000430 MipsOperand(KindTy K, MipsAsmParser &Parser)
431 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
432
David Blaikie960ea3f2014-06-08 16:18:35 +0000433private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000434 /// For diagnostics, and checking the assembler temporary
435 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000436
Eric Christopher8996c5d2013-03-15 00:42:55 +0000437 struct Token {
438 const char *Data;
439 unsigned Length;
440 };
441
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000442 struct PhysRegOp {
443 unsigned Num; /// Register Number
444 };
445
446 struct RegIdxOp {
447 unsigned Index; /// Index into the register class
448 RegKind Kind; /// Bitfield of the kinds it could possibly be
449 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000450 };
451
452 struct ImmOp {
453 const MCExpr *Val;
454 };
455
456 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000457 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000458 const MCExpr *Off;
459 };
460
Jack Carterb4dbc172012-09-05 23:34:03 +0000461 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000462 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000463 struct PhysRegOp PhysReg;
464 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000465 struct ImmOp Imm;
466 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000467 };
468
469 SMLoc StartLoc, EndLoc;
470
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000471 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000472 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
473 const MCRegisterInfo *RegInfo,
474 SMLoc S, SMLoc E,
475 MipsAsmParser &Parser) {
476 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000477 Op->RegIdx.Index = Index;
478 Op->RegIdx.RegInfo = RegInfo;
479 Op->RegIdx.Kind = RegKind;
480 Op->StartLoc = S;
481 Op->EndLoc = E;
482 return Op;
483 }
484
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000485public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486 /// Coerce the register to GPR32 and return the real register for the current
487 /// target.
488 unsigned getGPR32Reg() const {
489 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000490 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 unsigned ClassID = Mips::GPR32RegClassID;
492 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000493 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000494
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000495 /// Coerce the register to GPR64 and return the real register for the current
496 /// target.
497 unsigned getGPR64Reg() const {
498 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
499 unsigned ClassID = Mips::GPR64RegClassID;
500 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000501 }
502
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000503private:
504 /// Coerce the register to AFGR64 and return the real register for the current
505 /// target.
506 unsigned getAFGR64Reg() const {
507 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
508 if (RegIdx.Index % 2 != 0)
509 AsmParser.Warning(StartLoc, "Float register should be even.");
510 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
511 .getRegister(RegIdx.Index / 2);
512 }
513
514 /// Coerce the register to FGR64 and return the real register for the current
515 /// target.
516 unsigned getFGR64Reg() const {
517 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
518 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
519 .getRegister(RegIdx.Index);
520 }
521
522 /// Coerce the register to FGR32 and return the real register for the current
523 /// target.
524 unsigned getFGR32Reg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
526 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
527 .getRegister(RegIdx.Index);
528 }
529
530 /// Coerce the register to FGRH32 and return the real register for the current
531 /// target.
532 unsigned getFGRH32Reg() const {
533 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
534 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
535 .getRegister(RegIdx.Index);
536 }
537
538 /// Coerce the register to FCC and return the real register for the current
539 /// target.
540 unsigned getFCCReg() const {
541 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
542 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
543 .getRegister(RegIdx.Index);
544 }
545
546 /// Coerce the register to MSA128 and return the real register for the current
547 /// target.
548 unsigned getMSA128Reg() const {
549 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
550 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
551 // identical
552 unsigned ClassID = Mips::MSA128BRegClassID;
553 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
554 }
555
556 /// Coerce the register to MSACtrl and return the real register for the
557 /// current target.
558 unsigned getMSACtrlReg() const {
559 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
560 unsigned ClassID = Mips::MSACtrlRegClassID;
561 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
562 }
563
564 /// Coerce the register to COP2 and return the real register for the
565 /// current target.
566 unsigned getCOP2Reg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
568 unsigned ClassID = Mips::COP2RegClassID;
569 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
570 }
571
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000572 /// Coerce the register to COP3 and return the real register for the
573 /// current target.
574 unsigned getCOP3Reg() const {
575 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
576 unsigned ClassID = Mips::COP3RegClassID;
577 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
578 }
579
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580 /// Coerce the register to ACC64DSP and return the real register for the
581 /// current target.
582 unsigned getACC64DSPReg() const {
583 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
584 unsigned ClassID = Mips::ACC64DSPRegClassID;
585 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
586 }
587
588 /// Coerce the register to HI32DSP and return the real register for the
589 /// current target.
590 unsigned getHI32DSPReg() const {
591 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
592 unsigned ClassID = Mips::HI32DSPRegClassID;
593 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
594 }
595
596 /// Coerce the register to LO32DSP and return the real register for the
597 /// current target.
598 unsigned getLO32DSPReg() const {
599 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
600 unsigned ClassID = Mips::LO32DSPRegClassID;
601 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
602 }
603
604 /// Coerce the register to CCR and return the real register for the
605 /// current target.
606 unsigned getCCRReg() const {
607 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
608 unsigned ClassID = Mips::CCRRegClassID;
609 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
610 }
611
612 /// Coerce the register to HWRegs and return the real register for the
613 /// current target.
614 unsigned getHWRegsReg() const {
615 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
616 unsigned ClassID = Mips::HWRegsRegClassID;
617 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
618 }
619
620public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000621 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000622 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000623 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000624 Inst.addOperand(MCOperand::CreateImm(0));
625 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
626 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
627 else
628 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000629 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000630
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 void addRegOperands(MCInst &Inst, unsigned N) const {
632 llvm_unreachable("Use a custom parser instead");
633 }
634
Daniel Sanders21bce302014-04-01 12:35:23 +0000635 /// Render the operand to an MCInst as a GPR32
636 /// Asserts if the wrong number of operands are requested, or the operand
637 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
639 assert(N == 1 && "Invalid number of operands!");
640 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
641 }
642
Daniel Sanders21bce302014-04-01 12:35:23 +0000643 /// Render the operand to an MCInst as a GPR64
644 /// Asserts if the wrong number of operands are requested, or the operand
645 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000646 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
647 assert(N == 1 && "Invalid number of operands!");
648 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
649 }
650
651 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
652 assert(N == 1 && "Invalid number of operands!");
653 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
654 }
655
656 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
657 assert(N == 1 && "Invalid number of operands!");
658 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
659 }
660
661 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
662 assert(N == 1 && "Invalid number of operands!");
663 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000664 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000665 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000666 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
667 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000668 }
669
670 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
673 }
674
675 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
676 assert(N == 1 && "Invalid number of operands!");
677 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
678 }
679
680 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
681 assert(N == 1 && "Invalid number of operands!");
682 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
683 }
684
685 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
686 assert(N == 1 && "Invalid number of operands!");
687 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
688 }
689
690 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
691 assert(N == 1 && "Invalid number of operands!");
692 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
693 }
694
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000695 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
696 assert(N == 1 && "Invalid number of operands!");
697 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
698 }
699
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
701 assert(N == 1 && "Invalid number of operands!");
702 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
703 }
704
705 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
706 assert(N == 1 && "Invalid number of operands!");
707 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
708 }
709
710 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
711 assert(N == 1 && "Invalid number of operands!");
712 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
713 }
714
715 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
717 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
718 }
719
720 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
722 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
723 }
724
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000725 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000726 assert(N == 1 && "Invalid number of operands!");
727 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000728 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000729 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000730
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000731 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000732 assert(N == 2 && "Invalid number of operands!");
733
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000735
736 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000737 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000738 }
739
Craig Topper56c590a2014-04-29 07:58:02 +0000740 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 // As a special case until we sort out the definition of div/divu, pretend
742 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
743 if (isGPRAsmReg() && RegIdx.Index == 0)
744 return true;
745
746 return Kind == k_PhysRegister;
747 }
748 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000749 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 bool isConstantImm() const {
751 return isImm() && dyn_cast<MCConstantExpr>(getImm());
752 }
Craig Topper56c590a2014-04-29 07:58:02 +0000753 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000754 // Note: It's not possible to pretend that other operand kinds are tokens.
755 // The matcher emitter checks tokens first.
756 return Kind == k_Token;
757 }
Craig Topper56c590a2014-04-29 07:58:02 +0000758 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000759 bool isConstantMemOff() const {
760 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
761 }
762 template <unsigned Bits> bool isMemWithSimmOffset() const {
763 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
764 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000765 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 bool isLSAImm() const {
767 if (!isConstantImm())
768 return false;
769 int64_t Val = getConstantImm();
770 return 1 <= Val && Val <= 4;
771 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000772
773 StringRef getToken() const {
774 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000775 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000776 }
777
Craig Topper56c590a2014-04-29 07:58:02 +0000778 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 // As a special case until we sort out the definition of div/divu, pretend
780 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
781 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
782 RegIdx.Kind & RegKind_GPR)
783 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000784
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 assert(Kind == k_PhysRegister && "Invalid access!");
786 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000787 }
788
Jack Carterb4dbc172012-09-05 23:34:03 +0000789 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000791 return Imm.Val;
792 }
793
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 int64_t getConstantImm() const {
795 const MCExpr *Val = getImm();
796 return static_cast<const MCConstantExpr *>(Val)->getValue();
797 }
798
799 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000800 assert((Kind == k_Memory) && "Invalid access!");
801 return Mem.Base;
802 }
803
804 const MCExpr *getMemOff() const {
805 assert((Kind == k_Memory) && "Invalid access!");
806 return Mem.Off;
807 }
808
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000809 int64_t getConstantMemOff() const {
810 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
811 }
812
David Blaikie960ea3f2014-06-08 16:18:35 +0000813 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
814 MipsAsmParser &Parser) {
815 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000816 Op->Tok.Data = Str.data();
817 Op->Tok.Length = Str.size();
818 Op->StartLoc = S;
819 Op->EndLoc = S;
820 return Op;
821 }
822
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 /// Create a numeric register (e.g. $1). The exact register remains
824 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000825 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000826 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000827 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000828 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000829 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000830 }
831
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000832 /// Create a register that is definitely a GPR.
833 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000834 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000835 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000836 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000838 }
839
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 /// Create a register that is definitely a FGR.
841 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000842 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000843 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000844 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
846 }
847
848 /// Create a register that is definitely an FCC.
849 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000850 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000851 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000852 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
854 }
855
856 /// Create a register that is definitely an ACC.
857 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000858 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000859 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000860 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
862 }
863
864 /// Create a register that is definitely an MSA128.
865 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000866 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000867 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000868 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
870 }
871
872 /// Create a register that is definitely an MSACtrl.
873 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000874 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000875 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000876 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
878 }
879
David Blaikie960ea3f2014-06-08 16:18:35 +0000880 static std::unique_ptr<MipsOperand>
881 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
882 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000883 Op->Imm.Val = Val;
884 Op->StartLoc = S;
885 Op->EndLoc = E;
886 return Op;
887 }
888
David Blaikie960ea3f2014-06-08 16:18:35 +0000889 static std::unique_ptr<MipsOperand>
890 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
891 SMLoc E, MipsAsmParser &Parser) {
892 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
893 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000894 Op->Mem.Off = Off;
895 Op->StartLoc = S;
896 Op->EndLoc = E;
897 return Op;
898 }
899
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000900 bool isGPRAsmReg() const {
901 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000902 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000903 bool isFGRAsmReg() const {
904 // AFGR64 is $0-$15 but we handle this in getAFGR64()
905 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000906 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 bool isHWRegsAsmReg() const {
908 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000909 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000910 bool isCCRAsmReg() const {
911 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000912 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000913 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000914 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
915 return false;
916 if (!AsmParser.hasEightFccRegisters())
917 return RegIdx.Index == 0;
918 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000919 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 bool isACCAsmReg() const {
921 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000922 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 bool isCOP2AsmReg() const {
924 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000925 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000926 bool isCOP3AsmReg() const {
927 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
928 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 bool isMSA128AsmReg() const {
930 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000931 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 bool isMSACtrlAsmReg() const {
933 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000934 }
935
Jack Carterb4dbc172012-09-05 23:34:03 +0000936 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000937 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000938 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000939 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000940
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000941 virtual ~MipsOperand() {
942 switch (Kind) {
943 case k_Immediate:
944 break;
945 case k_Memory:
946 delete Mem.Base;
947 break;
948 case k_PhysRegister:
949 case k_RegisterIndex:
950 case k_Token:
951 break;
952 }
953 }
954
Craig Topper56c590a2014-04-29 07:58:02 +0000955 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 switch (Kind) {
957 case k_Immediate:
958 OS << "Imm<";
959 Imm.Val->print(OS);
960 OS << ">";
961 break;
962 case k_Memory:
963 OS << "Mem<";
964 Mem.Base->print(OS);
965 OS << ", ";
966 Mem.Off->print(OS);
967 OS << ">";
968 break;
969 case k_PhysRegister:
970 OS << "PhysReg<" << PhysReg.Num << ">";
971 break;
972 case k_RegisterIndex:
973 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
974 break;
975 case k_Token:
976 OS << Tok.Data;
977 break;
978 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000979 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000980}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000981} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000982
Jack Carter9e65aa32013-03-22 00:05:30 +0000983namespace llvm {
984extern const MCInstrDesc MipsInsts[];
985}
986static const MCInstrDesc &getInstDesc(unsigned Opcode) {
987 return MipsInsts[Opcode];
988}
989
Zoran Jovanovicac9ef122014-09-12 13:43:41 +0000990static bool hasShortDelaySlot(unsigned Opcode) {
991 switch (Opcode) {
992 case Mips::JALS_MM:
993 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +0000994 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +0000995 case Mips::BGEZALS_MM:
996 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +0000997 return true;
998 default:
999 return false;
1000 }
1001}
1002
Jack Carter9e65aa32013-03-22 00:05:30 +00001003bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001004 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001005 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001006
Jack Carter9e65aa32013-03-22 00:05:30 +00001007 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001008
1009 if (MCID.isBranch() || MCID.isCall()) {
1010 const unsigned Opcode = Inst.getOpcode();
1011 MCOperand Offset;
1012
1013 switch (Opcode) {
1014 default:
1015 break;
1016 case Mips::BEQ:
1017 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 case Mips::BEQ_MM:
1019 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001020 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001021 Offset = Inst.getOperand(2);
1022 if (!Offset.isImm())
1023 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001024 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001025 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001026 if (OffsetToAlignment(Offset.getImm(),
1027 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001028 return Error(IDLoc, "branch to misaligned address");
1029 break;
1030 case Mips::BGEZ:
1031 case Mips::BGTZ:
1032 case Mips::BLEZ:
1033 case Mips::BLTZ:
1034 case Mips::BGEZAL:
1035 case Mips::BLTZAL:
1036 case Mips::BC1F:
1037 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001038 case Mips::BGEZ_MM:
1039 case Mips::BGTZ_MM:
1040 case Mips::BLEZ_MM:
1041 case Mips::BLTZ_MM:
1042 case Mips::BGEZAL_MM:
1043 case Mips::BLTZAL_MM:
1044 case Mips::BC1F_MM:
1045 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001046 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001047 Offset = Inst.getOperand(1);
1048 if (!Offset.isImm())
1049 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001050 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001051 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001052 if (OffsetToAlignment(Offset.getImm(),
1053 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001054 return Error(IDLoc, "branch to misaligned address");
1055 break;
1056 }
1057 }
1058
Daniel Sandersa84989a2014-06-16 13:25:35 +00001059 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1060 // We still accept it but it is a normal nop.
1061 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1062 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1063 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1064 "nop instruction");
1065 }
1066
Toma Tabacu9db22db2014-09-09 10:15:38 +00001067 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001068 // If this instruction has a delay slot and .set reorder is active,
1069 // emit a NOP after it.
1070 Instructions.push_back(Inst);
1071 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001072 if (hasShortDelaySlot(Inst.getOpcode())) {
1073 NopInst.setOpcode(Mips::MOVE16_MM);
1074 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1075 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1076 } else {
1077 NopInst.setOpcode(Mips::SLL);
1078 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1079 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1080 NopInst.addOperand(MCOperand::CreateImm(0));
1081 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001082 Instructions.push_back(NopInst);
1083 return false;
1084 }
1085
Jack Carter9e65aa32013-03-22 00:05:30 +00001086 if (MCID.mayLoad() || MCID.mayStore()) {
1087 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 // reference or immediate we may have to expand instructions.
1089 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001090 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001091 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1092 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001093 MCOperand &Op = Inst.getOperand(i);
1094 if (Op.isImm()) {
1095 int MemOffset = Op.getImm();
1096 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 // Offset can't exceed 16bit value.
1098 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001099 return false;
1100 }
1101 } else if (Op.isExpr()) {
1102 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001104 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001105 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001106 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001107 // Expand symbol.
1108 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001109 return false;
1110 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001111 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001112 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001113 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001114 }
1115 }
1116 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001117 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001118 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001119
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001120 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1121 if (inMicroMipsMode()) {
1122 MCOperand Opnd;
1123 int Imm;
1124
1125 switch (Inst.getOpcode()) {
1126 default:
1127 break;
1128 case Mips::ADDIUS5_MM:
1129 Opnd = Inst.getOperand(2);
1130 if (!Opnd.isImm())
1131 return Error(IDLoc, "expected immediate operand kind");
1132 Imm = Opnd.getImm();
1133 if (Imm < -8 || Imm > 7)
1134 return Error(IDLoc, "immediate operand value out of range");
1135 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001136 case Mips::ADDIUSP_MM:
1137 Opnd = Inst.getOperand(0);
1138 if (!Opnd.isImm())
1139 return Error(IDLoc, "expected immediate operand kind");
1140 Imm = Opnd.getImm();
1141 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1142 Imm % 4 != 0)
1143 return Error(IDLoc, "immediate operand value out of range");
1144 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001145 }
1146 }
1147
Jack Carter9e65aa32013-03-22 00:05:30 +00001148 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001149 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001150 else
1151 Instructions.push_back(Inst);
1152
1153 return false;
1154}
1155
Jack Carter30a59822012-10-04 04:03:53 +00001156bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1157
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 switch (Inst.getOpcode()) {
1159 case Mips::LoadImm32Reg:
1160 case Mips::LoadAddr32Imm:
1161 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001162 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001163 return true;
1164 default:
1165 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001166 }
1167}
Jack Carter92995f12012-10-06 00:53:28 +00001168
Matheus Almeida3813d572014-06-19 14:39:14 +00001169bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001170 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001172 default:
1173 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001174 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001175 case Mips::LoadImm32Reg:
1176 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001177 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001178 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001179 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001180 return true;
1181 }
1182 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 case Mips::LoadAddr32Imm:
1184 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1185 case Mips::LoadAddr32Reg:
1186 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1187 }
Jack Carter30a59822012-10-04 04:03:53 +00001188}
Jack Carter92995f12012-10-06 00:53:28 +00001189
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001190namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001191template <bool PerformShift>
1192void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001193 SmallVectorImpl<MCInst> &Instructions) {
1194 MCInst tmpInst;
1195 if (PerformShift) {
1196 tmpInst.setOpcode(Mips::DSLL);
1197 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1198 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1199 tmpInst.addOperand(MCOperand::CreateImm(16));
1200 tmpInst.setLoc(IDLoc);
1201 Instructions.push_back(tmpInst);
1202 tmpInst.clear();
1203 }
1204 tmpInst.setOpcode(Mips::ORi);
1205 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1206 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001207 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001208 tmpInst.setLoc(IDLoc);
1209 Instructions.push_back(tmpInst);
1210}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001211
1212template <int Shift, bool PerformShift>
1213void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1214 SmallVectorImpl<MCInst> &Instructions) {
1215 createShiftOr<PerformShift>(
1216 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1217 IDLoc, Instructions);
1218}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001219}
1220
Matheus Almeida3813d572014-06-19 14:39:14 +00001221bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001222 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001223 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001224 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001225 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001226 const MCOperand &RegOp = Inst.getOperand(0);
1227 assert(RegOp.isReg() && "expected register operand kind");
1228
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001229 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001230 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001231 // FIXME: gas has a special case for values that are 000...1111, which
1232 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001233 if (0 <= ImmValue && ImmValue <= 65535) {
1234 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001235 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001236 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001237 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001238 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001239 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001240 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001241 } else if (ImmValue < 0 && ImmValue >= -32768) {
1242 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001243 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001244 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001245 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001246 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001247 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001248 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001249 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1250 // For any value of j that is representable as a 32-bit integer, create
1251 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001252 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001253 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001254 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001255 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1256 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001257 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001258 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1259 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001260 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001261 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001262 return true;
1263 }
1264
1265 // <------- lo32 ------>
1266 // <------- hi32 ------>
1267 // <- hi16 -> <- lo16 ->
1268 // _________________________________
1269 // | | | |
1270 // | 16-bytes | 16-bytes | 16-bytes |
1271 // |__________|__________|__________|
1272 //
1273 // For any value of j that is representable as a 48-bit integer, create
1274 // a sequence of:
1275 // li d,j => lui d,hi16(j)
1276 // ori d,d,hi16(lo32(j))
1277 // dsll d,d,16
1278 // ori d,d,lo16(lo32(j))
1279 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001280 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001281 tmpInst.addOperand(
1282 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001283 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001284 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1285 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1286 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001287 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001288 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001289 return true;
1290 }
1291
1292 // <------- hi32 ------> <------- lo32 ------>
1293 // <- hi16 -> <- lo16 ->
1294 // ___________________________________________
1295 // | | | | |
1296 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1297 // |__________|__________|__________|__________|
1298 //
1299 // For any value of j that isn't representable as a 48-bit integer.
1300 // li d,j => lui d,hi16(j)
1301 // ori d,d,lo16(hi32(j))
1302 // dsll d,d,16
1303 // ori d,d,hi16(lo32(j))
1304 // dsll d,d,16
1305 // ori d,d,lo16(lo32(j))
1306 tmpInst.setOpcode(Mips::LUi);
1307 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1308 tmpInst.addOperand(
1309 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1310 Instructions.push_back(tmpInst);
1311 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1312 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1313 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001314 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001315 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001316}
Jack Carter92995f12012-10-06 00:53:28 +00001317
Matheus Almeida3813d572014-06-19 14:39:14 +00001318bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001319MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1320 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001321 MCInst tmpInst;
1322 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001323 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1324 "expected immediate operand kind");
1325 if (!ImmOp.isImm()) {
1326 expandLoadAddressSym(Inst, IDLoc, Instructions);
1327 return false;
1328 }
Jack Carter543fdf82012-10-09 23:29:45 +00001329 const MCOperand &SrcRegOp = Inst.getOperand(1);
1330 assert(SrcRegOp.isReg() && "expected register operand kind");
1331 const MCOperand &DstRegOp = Inst.getOperand(0);
1332 assert(DstRegOp.isReg() && "expected register operand kind");
1333 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001334 if (-32768 <= ImmValue && ImmValue <= 65535) {
1335 // For -32768 <= j <= 65535.
1336 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001337 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001338 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1339 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1340 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1341 Instructions.push_back(tmpInst);
1342 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001343 // For any other value of j that is representable as a 32-bit integer.
1344 // la d,j(s) => lui d,hi16(j)
1345 // ori d,d,lo16(j)
1346 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001347 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001348 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1349 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1350 Instructions.push_back(tmpInst);
1351 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001352 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001353 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1354 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1355 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1356 Instructions.push_back(tmpInst);
1357 tmpInst.clear();
1358 tmpInst.setOpcode(Mips::ADDu);
1359 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1360 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1361 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1362 Instructions.push_back(tmpInst);
1363 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001364 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001365}
1366
Matheus Almeida3813d572014-06-19 14:39:14 +00001367bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001368MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1369 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001370 MCInst tmpInst;
1371 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001372 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1373 "expected immediate operand kind");
1374 if (!ImmOp.isImm()) {
1375 expandLoadAddressSym(Inst, IDLoc, Instructions);
1376 return false;
1377 }
Jack Carter543fdf82012-10-09 23:29:45 +00001378 const MCOperand &RegOp = Inst.getOperand(0);
1379 assert(RegOp.isReg() && "expected register operand kind");
1380 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 if (-32768 <= ImmValue && ImmValue <= 65535) {
1382 // For -32768 <= j <= 65535.
1383 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001384 tmpInst.setOpcode(Mips::ADDiu);
1385 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001386 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001387 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1388 Instructions.push_back(tmpInst);
1389 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 // For any other value of j that is representable as a 32-bit integer.
1391 // la d,j => lui d,hi16(j)
1392 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001393 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001394 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1395 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1396 Instructions.push_back(tmpInst);
1397 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001398 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001399 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1400 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1401 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1402 Instructions.push_back(tmpInst);
1403 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001404 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001405}
1406
Toma Tabacu0d64b202014-08-14 10:29:17 +00001407void
1408MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1409 SmallVectorImpl<MCInst> &Instructions) {
1410 // FIXME: If we do have a valid at register to use, we should generate a
1411 // slightly shorter sequence here.
1412 MCInst tmpInst;
1413 int ExprOperandNo = 1;
1414 // Sometimes the assembly parser will get the immediate expression as
1415 // a $zero + an immediate.
1416 if (Inst.getNumOperands() == 3) {
1417 assert(Inst.getOperand(1).getReg() ==
1418 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1419 ExprOperandNo = 2;
1420 }
1421 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1422 assert(SymOp.isExpr() && "expected symbol operand kind");
1423 const MCOperand &RegOp = Inst.getOperand(0);
1424 unsigned RegNo = RegOp.getReg();
1425 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1426 const MCSymbolRefExpr *HiExpr =
1427 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1428 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1429 const MCSymbolRefExpr *LoExpr =
1430 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1431 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1432 if (isGP64bit()) {
1433 // If it's a 64-bit architecture, expand to:
1434 // la d,sym => lui d,highest(sym)
1435 // ori d,d,higher(sym)
1436 // dsll d,d,16
1437 // ori d,d,hi16(sym)
1438 // dsll d,d,16
1439 // ori d,d,lo16(sym)
1440 const MCSymbolRefExpr *HighestExpr =
1441 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1442 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1443 const MCSymbolRefExpr *HigherExpr =
1444 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1445 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1446
1447 tmpInst.setOpcode(Mips::LUi);
1448 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1449 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1450 Instructions.push_back(tmpInst);
1451
1452 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1453 Instructions);
1454 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1455 Instructions);
1456 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1457 Instructions);
1458 } else {
1459 // Otherwise, expand to:
1460 // la d,sym => lui d,hi16(sym)
1461 // ori d,d,lo16(sym)
1462 tmpInst.setOpcode(Mips::LUi);
1463 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1464 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1465 Instructions.push_back(tmpInst);
1466
1467 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1468 Instructions);
1469 }
1470}
1471
Jack Carter9e65aa32013-03-22 00:05:30 +00001472void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001473 SmallVectorImpl<MCInst> &Instructions,
1474 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001475 const MCSymbolRefExpr *SR;
1476 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001478 const MCExpr *ExprOffset;
1479 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001480 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001481 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1482 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001483 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001484 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1485 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001487 if (isImmOpnd) {
1488 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1489 ImmOffset = Inst.getOperand(2).getImm();
1490 LoOffset = ImmOffset & 0x0000ffff;
1491 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001492 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001493 if (LoOffset & 0x8000)
1494 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001495 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001496 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001497 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001498 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001499 // These are some of the types of expansions we perform here:
1500 // 1) lw $8, sym => lui $8, %hi(sym)
1501 // lw $8, %lo(sym)($8)
1502 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1503 // add $8, $8, $9
1504 // lw $8, %lo(offset)($9)
1505 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1506 // add $at, $at, $8
1507 // lw $8, %lo(offset)($at)
1508 // 4) sw $8, sym => lui $at, %hi(sym)
1509 // sw $8, %lo(sym)($at)
1510 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1511 // add $at, $at, $8
1512 // sw $8, %lo(offset)($at)
1513 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1514 // ldc1 $f0, %lo(sym)($at)
1515 //
1516 // For load instructions we can use the destination register as a temporary
1517 // if base and dst are different (examples 1 and 2) and if the base register
1518 // is general purpose otherwise we must use $at (example 6) and error if it's
1519 // not available. For stores we must use $at (examples 4 and 5) because we
1520 // must not clobber the source register setting up the offset.
1521 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1522 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1523 unsigned RegClassIDOp0 =
1524 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1525 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1526 (RegClassIDOp0 == Mips::GPR64RegClassID);
1527 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001528 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001529 else {
1530 int AT = getATReg(IDLoc);
1531 // At this point we need AT to perform the expansions and we exit if it is
1532 // not available.
1533 if (!AT)
1534 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001535 TmpRegNum = getReg(
1536 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001537 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001538
Jack Carter9e65aa32013-03-22 00:05:30 +00001539 TempInst.setOpcode(Mips::LUi);
1540 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1541 if (isImmOpnd)
1542 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1543 else {
1544 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001545 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001546 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1547 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1548 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001549 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001550 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001551 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001552 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001553 }
1554 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001555 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001556 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001558 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001559 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001560 TempInst.setOpcode(Mips::ADDu);
1561 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1562 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1563 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1564 Instructions.push_back(TempInst);
1565 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001566 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001567 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001568 TempInst.setOpcode(Inst.getOpcode());
1569 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1570 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1571 if (isImmOpnd)
1572 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1573 else {
1574 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001575 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1576 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1577 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001578 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001579 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001581 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001582 }
1583 }
1584 Instructions.push_back(TempInst);
1585 TempInst.clear();
1586}
1587
Matheus Almeida595fcab2014-06-11 15:05:56 +00001588unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1589 // As described by the Mips32r2 spec, the registers Rd and Rs for
1590 // jalr.hb must be different.
1591 unsigned Opcode = Inst.getOpcode();
1592
1593 if (Opcode == Mips::JALR_HB &&
1594 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1595 return Match_RequiresDifferentSrcAndDst;
1596
1597 return Match_Success;
1598}
1599
David Blaikie960ea3f2014-06-08 16:18:35 +00001600bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1601 OperandVector &Operands,
1602 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001603 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001604 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001605
Jack Carterb4dbc172012-09-05 23:34:03 +00001606 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001607 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001608 unsigned MatchResult =
1609 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001610
1611 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 default:
1613 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001614 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001616 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001617 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001618 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001619 return false;
1620 }
1621 case Match_MissingFeature:
1622 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1623 return true;
1624 case Match_InvalidOperand: {
1625 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001626 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001627 if (ErrorInfo >= Operands.size())
1628 return Error(IDLoc, "too few operands for instruction");
1629
David Blaikie960ea3f2014-06-08 16:18:35 +00001630 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 if (ErrorLoc == SMLoc())
1632 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001633 }
1634
1635 return Error(ErrorLoc, "invalid operand for instruction");
1636 }
1637 case Match_MnemonicFail:
1638 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001639 case Match_RequiresDifferentSrcAndDst:
1640 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001641 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001642 return true;
1643}
1644
Toma Tabacu13964452014-09-04 13:23:44 +00001645void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001646 if ((RegIndex != 0) &&
1647 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001648 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001649 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001650 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001651 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001652 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001653 }
1654}
1655
Daniel Sandersef638fe2014-10-03 15:37:37 +00001656void
1657MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1658 SMRange Range, bool ShowColors) {
1659 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001660 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001661 ShowColors);
1662}
1663
Jack Carter1ac53222013-02-20 23:11:17 +00001664int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001665 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001666
Vladimir Medic4c299852013-11-06 11:27:05 +00001667 CC = StringSwitch<unsigned>(Name)
1668 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001669 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001670 .Case("a0", 4)
1671 .Case("a1", 5)
1672 .Case("a2", 6)
1673 .Case("a3", 7)
1674 .Case("v0", 2)
1675 .Case("v1", 3)
1676 .Case("s0", 16)
1677 .Case("s1", 17)
1678 .Case("s2", 18)
1679 .Case("s3", 19)
1680 .Case("s4", 20)
1681 .Case("s5", 21)
1682 .Case("s6", 22)
1683 .Case("s7", 23)
1684 .Case("k0", 26)
1685 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001686 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001687 .Case("sp", 29)
1688 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001689 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001690 .Case("ra", 31)
1691 .Case("t0", 8)
1692 .Case("t1", 9)
1693 .Case("t2", 10)
1694 .Case("t3", 11)
1695 .Case("t4", 12)
1696 .Case("t5", 13)
1697 .Case("t6", 14)
1698 .Case("t7", 15)
1699 .Case("t8", 24)
1700 .Case("t9", 25)
1701 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001702
Toma Tabacufda445c2014-09-15 15:33:01 +00001703 if (!(isABI_N32() || isABI_N64()))
1704 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001705
Daniel Sandersef638fe2014-10-03 15:37:37 +00001706 if (12 <= CC && CC <= 15) {
1707 // Name is one of t4-t7
1708 AsmToken RegTok = getLexer().peekTok();
1709 SMRange RegRange = RegTok.getLocRange();
1710
1711 StringRef FixedName = StringSwitch<StringRef>(Name)
1712 .Case("t4", "t0")
1713 .Case("t5", "t1")
1714 .Case("t6", "t2")
1715 .Case("t7", "t3")
1716 .Default("");
1717 assert(FixedName != "" && "Register name is not one of t4-t7.");
1718
1719 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1720 "Did you mean $" + FixedName + "?", RegRange);
1721 }
1722
Toma Tabacufda445c2014-09-15 15:33:01 +00001723 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1724 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1725 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1726 if (8 <= CC && CC <= 11)
1727 CC += 4;
1728
1729 if (CC == -1)
1730 CC = StringSwitch<unsigned>(Name)
1731 .Case("a4", 8)
1732 .Case("a5", 9)
1733 .Case("a6", 10)
1734 .Case("a7", 11)
1735 .Case("kt0", 26)
1736 .Case("kt1", 27)
1737 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001738
1739 return CC;
1740}
Jack Carterd0bd6422013-04-18 00:41:53 +00001741
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001742int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001743
Jack Cartera63b16a2012-09-07 00:23:42 +00001744 if (Name[0] == 'f') {
1745 StringRef NumString = Name.substr(1);
1746 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001747 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001748 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001749 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001750 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001751 return IntVal;
1752 }
1753 return -1;
1754}
Jack Cartera63b16a2012-09-07 00:23:42 +00001755
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001756int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1757
1758 if (Name.startswith("fcc")) {
1759 StringRef NumString = Name.substr(3);
1760 unsigned IntVal;
1761 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001762 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001763 if (IntVal > 7) // There are only 8 fcc registers.
1764 return -1;
1765 return IntVal;
1766 }
1767 return -1;
1768}
1769
1770int MipsAsmParser::matchACRegisterName(StringRef Name) {
1771
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001772 if (Name.startswith("ac")) {
1773 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001774 unsigned IntVal;
1775 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001776 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001777 if (IntVal > 3) // There are only 3 acc registers.
1778 return -1;
1779 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001780 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001781 return -1;
1782}
Jack Carterd0bd6422013-04-18 00:41:53 +00001783
Jack Carter5dc8ac92013-09-25 23:50:44 +00001784int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1785 unsigned IntVal;
1786
1787 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1788 return -1;
1789
1790 if (IntVal > 31)
1791 return -1;
1792
1793 return IntVal;
1794}
1795
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001796int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1797 int CC;
1798
1799 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001800 .Case("msair", 0)
1801 .Case("msacsr", 1)
1802 .Case("msaaccess", 2)
1803 .Case("msasave", 3)
1804 .Case("msamodify", 4)
1805 .Case("msarequest", 5)
1806 .Case("msamap", 6)
1807 .Case("msaunmap", 7)
1808 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001809
1810 return CC;
1811}
1812
Jack Carter0b744b32012-10-04 02:29:46 +00001813bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1814 if (Reg > 31)
1815 return false;
1816
Toma Tabacu3c24b042014-09-05 15:43:21 +00001817 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001818 return true;
1819}
1820
Matheus Almeida7de68e72014-06-18 14:46:05 +00001821int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001822 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001823 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001824 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001825 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001826 return AT;
1827}
Jack Carter0b744b32012-10-04 02:29:46 +00001828
Jack Carterd0bd6422013-04-18 00:41:53 +00001829unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001830 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001831}
1832
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001833unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001834 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001835 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001836}
1837
Jack Carter873c7242013-01-12 01:03:14 +00001838int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001839 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001840 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001841 return -1;
1842
Jack Carter873c7242013-01-12 01:03:14 +00001843 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001844}
1845
Toma Tabacu13964452014-09-04 13:23:44 +00001846bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1847 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001848
Jack Carter30a59822012-10-04 04:03:53 +00001849 // Check if the current operand has a custom associated parser, if so, try to
1850 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001851 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1852 if (ResTy == MatchOperand_Success)
1853 return false;
1854 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1855 // there was a match, but an error occurred, in which case, just return that
1856 // the operand parsing failed.
1857 if (ResTy == MatchOperand_ParseFail)
1858 return true;
1859
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001860 DEBUG(dbgs() << ".. Generic Parser\n");
1861
Jack Carterb4dbc172012-09-05 23:34:03 +00001862 switch (getLexer().getKind()) {
1863 default:
1864 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1865 return true;
1866 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001867 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001868 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001869
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001870 // Almost all registers have been parsed by custom parsers. There is only
1871 // one exception to this. $zero (and it's alias $0) will reach this point
1872 // for div, divu, and similar instructions because it is not an operand
1873 // to the instruction definition but an explicit register. Special case
1874 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001875 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001876 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001877
Jack Carterd0bd6422013-04-18 00:41:53 +00001878 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001879 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001880 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001881 return true;
1882
Jack Carter873c7242013-01-12 01:03:14 +00001883 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001884 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001885 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001886 const MCExpr *Res =
1887 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001888
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001889 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001890 return false;
1891 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001892 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001893 case AsmToken::LParen:
1894 case AsmToken::Minus:
1895 case AsmToken::Plus:
1896 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001897 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001898 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001899 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001900 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001901 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001902 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001903 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001904 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001905 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001906 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001907 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001908 return true;
1909
Jack Carter873c7242013-01-12 01:03:14 +00001910 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1911
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001912 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001913 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001914 } // case AsmToken::Percent
1915 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001916 return true;
1917}
1918
Vladimir Medic4c299852013-11-06 11:27:05 +00001919const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001920 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001921 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001923 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001924 // It's a constant, evaluate reloc value.
1925 int16_t Val;
1926 switch (getVariantKind(RelocStr)) {
1927 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1928 // Get the 1st 16-bits.
1929 Val = MCE->getValue() & 0xffff;
1930 break;
1931 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1932 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1933 // 16 bits being negative.
1934 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1935 break;
1936 case MCSymbolRefExpr::VK_Mips_HIGHER:
1937 // Get the 3rd 16-bits.
1938 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1939 break;
1940 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1941 // Get the 4th 16-bits.
1942 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1943 break;
1944 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00001945 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001946 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001947 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001948 }
1949
Jack Carterb5cf5902013-04-17 00:18:04 +00001950 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001951 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001952 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001953 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001954 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001955 return Res;
1956 }
1957
1958 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001959 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1960
Sasa Stankovic06c47802014-04-03 10:37:45 +00001961 // Try to create target expression.
1962 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1963 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001964
Jack Carterd0bd6422013-04-18 00:41:53 +00001965 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1966 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001967 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1968 return Res;
1969 }
1970
1971 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001972 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1973 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1974 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001975 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001976 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001977 return Expr;
1978}
1979
1980bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1981
1982 switch (Expr->getKind()) {
1983 case MCExpr::Constant:
1984 return true;
1985 case MCExpr::SymbolRef:
1986 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1987 case MCExpr::Binary:
1988 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1989 if (!isEvaluated(BE->getLHS()))
1990 return false;
1991 return isEvaluated(BE->getRHS());
1992 }
1993 case MCExpr::Unary:
1994 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001995 case MCExpr::Target:
1996 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001997 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001998 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001999}
Jack Carterd0bd6422013-04-18 00:41:53 +00002000
Jack Carterb5cf5902013-04-17 00:18:04 +00002001bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002002 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002003 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002004 if (Tok.isNot(AsmToken::Identifier))
2005 return true;
2006
2007 std::string Str = Tok.getIdentifier().str();
2008
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 Parser.Lex(); // Eat the identifier.
2010 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002011 const MCExpr *IdVal;
2012 SMLoc EndLoc;
2013
2014 if (getLexer().getKind() == AsmToken::LParen) {
2015 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002016 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002017 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002018 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002019 const AsmToken &nextTok = Parser.getTok();
2020 if (nextTok.isNot(AsmToken::Identifier))
2021 return true;
2022 Str += "(%";
2023 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002024 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002025 if (getLexer().getKind() != AsmToken::LParen)
2026 return true;
2027 } else
2028 break;
2029 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002030 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002031 return true;
2032
2033 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002034 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002035
2036 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002037 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002038
Jack Carterd0bd6422013-04-18 00:41:53 +00002039 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002040 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002041}
2042
Jack Carterb4dbc172012-09-05 23:34:03 +00002043bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2044 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002045 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002046 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002047 if (ResTy == MatchOperand_Success) {
2048 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002049 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002050 StartLoc = Operand.getStartLoc();
2051 EndLoc = Operand.getEndLoc();
2052
2053 // AFAIK, we only support numeric registers and named GPR's in CFI
2054 // directives.
2055 // Don't worry about eating tokens before failing. Using an unrecognised
2056 // register is a parse error.
2057 if (Operand.isGPRAsmReg()) {
2058 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002059 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002060 }
2061
2062 return (RegNo == (unsigned)-1);
2063 }
2064
2065 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002066 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002067}
2068
Jack Carterb5cf5902013-04-17 00:18:04 +00002069bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00002070 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002071 bool Result = true;
2072
2073 while (getLexer().getKind() == AsmToken::LParen)
2074 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002075
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002077 default:
2078 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002080 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002081 case AsmToken::Integer:
2082 case AsmToken::Minus:
2083 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002084 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002086 else
2087 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002089 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002090 break;
Jack Carter873c7242013-01-12 01:03:14 +00002091 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002092 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002093 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002094 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002095}
2096
David Blaikie960ea3f2014-06-08 16:18:35 +00002097MipsAsmParser::OperandMatchResultTy
2098MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002099 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002100 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002101 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002102 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002103 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002105 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002106
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 if (getLexer().getKind() == AsmToken::LParen) {
2108 Parser.Lex();
2109 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002110 }
2111
Jack Carterb5cf5902013-04-17 00:18:04 +00002112 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002115
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002117 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002118 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2119 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002120 SMLoc E =
2121 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002122 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002123 return MatchOperand_Success;
2124 }
2125 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002126 SMLoc E =
2127 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002128
Jack Carterd0bd6422013-04-18 00:41:53 +00002129 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002130 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002131 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002132 S, E, *this);
2133 Operands.push_back(
2134 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002135 return MatchOperand_Success;
2136 }
2137 Error(Parser.getTok().getLoc(), "'(' expected");
2138 return MatchOperand_ParseFail;
2139 }
2140
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002142 }
2143
Toma Tabacu13964452014-09-04 13:23:44 +00002144 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002145 if (Res != MatchOperand_Success)
2146 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002147
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002148 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002149 Error(Parser.getTok().getLoc(), "')' expected");
2150 return MatchOperand_ParseFail;
2151 }
2152
Jack Carter873c7242013-01-12 01:03:14 +00002153 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2154
Jack Carterd0bd6422013-04-18 00:41:53 +00002155 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002156
Craig Topper062a2ba2014-04-25 05:30:21 +00002157 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002158 IdVal = MCConstantExpr::Create(0, getContext());
2159
Jack Carterd0bd6422013-04-18 00:41:53 +00002160 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002161 std::unique_ptr<MipsOperand> op(
2162 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002164 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002165 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002167 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2168 int64_t Imm;
2169 if (IdVal->EvaluateAsAbsolute(Imm))
2170 IdVal = MCConstantExpr::Create(Imm, getContext());
2171 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2172 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2173 getContext());
2174 }
2175
David Blaikie960ea3f2014-06-08 16:18:35 +00002176 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002177 return MatchOperand_Success;
2178}
2179
David Blaikie960ea3f2014-06-08 16:18:35 +00002180bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002181
Jack Carterd76b2372013-03-21 21:44:16 +00002182 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2183 if (Sym) {
2184 SMLoc S = Parser.getTok().getLoc();
2185 const MCExpr *Expr;
2186 if (Sym->isVariable())
2187 Expr = Sym->getVariableValue();
2188 else
2189 return false;
2190 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002191 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002192 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002193 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002194 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002195 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002196 if (ResTy == MatchOperand_Success) {
2197 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002198 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002199 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002200 llvm_unreachable("Should never ParseFail");
2201 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002202 }
2203 } else if (Expr->getKind() == MCExpr::Constant) {
2204 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002205 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002206 Operands.push_back(
2207 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002208 return true;
2209 }
2210 }
2211 return false;
2212}
Jack Carterd0bd6422013-04-18 00:41:53 +00002213
Jack Carter873c7242013-01-12 01:03:14 +00002214MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002215MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002216 StringRef Identifier,
2217 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002218 int Index = matchCPURegisterName(Identifier);
2219 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002220 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002221 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2222 return MatchOperand_Success;
2223 }
2224
2225 Index = matchFPURegisterName(Identifier);
2226 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002227 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002228 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2229 return MatchOperand_Success;
2230 }
2231
2232 Index = matchFCCRegisterName(Identifier);
2233 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002234 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002235 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2236 return MatchOperand_Success;
2237 }
2238
2239 Index = matchACRegisterName(Identifier);
2240 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002241 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002242 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2243 return MatchOperand_Success;
2244 }
2245
2246 Index = matchMSA128RegisterName(Identifier);
2247 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002248 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002249 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2250 return MatchOperand_Success;
2251 }
2252
2253 Index = matchMSA128CtrlRegisterName(Identifier);
2254 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002255 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002256 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2257 return MatchOperand_Success;
2258 }
2259
2260 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002261}
2262
2263MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002264MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002265 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002266
2267 if (Token.is(AsmToken::Identifier)) {
2268 DEBUG(dbgs() << ".. identifier\n");
2269 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002270 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002271 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002272 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002273 } else if (Token.is(AsmToken::Integer)) {
2274 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002275 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002276 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2277 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002278 return MatchOperand_Success;
2279 }
2280
2281 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2282
2283 return MatchOperand_NoMatch;
2284}
2285
David Blaikie960ea3f2014-06-08 16:18:35 +00002286MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002287MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2288 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002289
2290 auto Token = Parser.getTok();
2291
2292 SMLoc S = Token.getLoc();
2293
2294 if (Token.isNot(AsmToken::Dollar)) {
2295 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2296 if (Token.is(AsmToken::Identifier)) {
2297 if (searchSymbolAlias(Operands))
2298 return MatchOperand_Success;
2299 }
2300 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2301 return MatchOperand_NoMatch;
2302 }
2303 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002304
Toma Tabacu13964452014-09-04 13:23:44 +00002305 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002306 if (ResTy == MatchOperand_Success) {
2307 Parser.Lex(); // $
2308 Parser.Lex(); // identifier
2309 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002310 return ResTy;
2311}
2312
2313MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002314MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002315 switch (getLexer().getKind()) {
2316 default:
2317 return MatchOperand_NoMatch;
2318 case AsmToken::LParen:
2319 case AsmToken::Minus:
2320 case AsmToken::Plus:
2321 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002322 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002323 case AsmToken::String:
2324 break;
2325 }
2326
2327 const MCExpr *IdVal;
2328 SMLoc S = Parser.getTok().getLoc();
2329 if (getParser().parseExpression(IdVal))
2330 return MatchOperand_ParseFail;
2331
2332 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2333 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2334 return MatchOperand_Success;
2335}
2336
David Blaikie960ea3f2014-06-08 16:18:35 +00002337MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002338MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2339 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002340
2341 SMLoc S = getLexer().getLoc();
2342
2343 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002344 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002345 if (ResTy != MatchOperand_NoMatch)
2346 return ResTy;
2347
Daniel Sanders315386c2014-04-01 10:40:14 +00002348 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002349 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002350 if (ResTy != MatchOperand_NoMatch)
2351 return ResTy;
2352
Daniel Sandersffd84362014-04-01 10:41:48 +00002353 const MCExpr *Expr = nullptr;
2354 if (Parser.parseExpression(Expr)) {
2355 // We have no way of knowing if a symbol was consumed so we must ParseFail
2356 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002357 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002358 Operands.push_back(
2359 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002360 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002361}
2362
Vladimir Medic2b953d02013-10-01 09:48:56 +00002363MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002364MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002365 const MCExpr *IdVal;
2366 // If the first token is '$' we may have register operand.
2367 if (Parser.getTok().is(AsmToken::Dollar))
2368 return MatchOperand_NoMatch;
2369 SMLoc S = Parser.getTok().getLoc();
2370 if (getParser().parseExpression(IdVal))
2371 return MatchOperand_ParseFail;
2372 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002373 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002374 int64_t Val = MCE->getValue();
2375 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2376 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002377 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002378 return MatchOperand_Success;
2379}
2380
Matheus Almeida779c5932013-11-18 12:32:49 +00002381MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002382MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002383 switch (getLexer().getKind()) {
2384 default:
2385 return MatchOperand_NoMatch;
2386 case AsmToken::LParen:
2387 case AsmToken::Plus:
2388 case AsmToken::Minus:
2389 case AsmToken::Integer:
2390 break;
2391 }
2392
2393 const MCExpr *Expr;
2394 SMLoc S = Parser.getTok().getLoc();
2395
2396 if (getParser().parseExpression(Expr))
2397 return MatchOperand_ParseFail;
2398
2399 int64_t Val;
2400 if (!Expr->EvaluateAsAbsolute(Val)) {
2401 Error(S, "expected immediate value");
2402 return MatchOperand_ParseFail;
2403 }
2404
2405 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2406 // and because the CPU always adds one to the immediate field, the allowed
2407 // range becomes 1..4. We'll only check the range here and will deal
2408 // with the addition/subtraction when actually decoding/encoding
2409 // the instruction.
2410 if (Val < 1 || Val > 4) {
2411 Error(S, "immediate not in range (1..4)");
2412 return MatchOperand_ParseFail;
2413 }
2414
Jack Carter3b2c96e2014-01-22 23:31:38 +00002415 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002416 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002417 return MatchOperand_Success;
2418}
2419
Jack Carterdc1e35d2012-09-06 20:00:02 +00002420MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2421
Vladimir Medic4c299852013-11-06 11:27:05 +00002422 MCSymbolRefExpr::VariantKind VK =
2423 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2424 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2425 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2426 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2427 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2428 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2429 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2430 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2431 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2432 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2433 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2434 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2435 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2436 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2437 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2438 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2439 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2440 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002441 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2442 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2443 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2444 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2445 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2446 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002447 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2448 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002449 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002450
Matheus Almeida2852af82014-04-22 10:15:54 +00002451 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002452
Jack Carterdc1e35d2012-09-06 20:00:02 +00002453 return VK;
2454}
Jack Cartera63b16a2012-09-07 00:23:42 +00002455
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002456/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2457/// either this.
2458/// ::= '(', register, ')'
2459/// handle it before we iterate so we don't get tripped up by the lack of
2460/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002461bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462 if (getLexer().is(AsmToken::LParen)) {
2463 Operands.push_back(
2464 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2465 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002466 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002467 SMLoc Loc = getLexer().getLoc();
2468 Parser.eatToEndOfStatement();
2469 return Error(Loc, "unexpected token in argument list");
2470 }
2471 if (Parser.getTok().isNot(AsmToken::RParen)) {
2472 SMLoc Loc = getLexer().getLoc();
2473 Parser.eatToEndOfStatement();
2474 return Error(Loc, "unexpected token, expected ')'");
2475 }
2476 Operands.push_back(
2477 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2478 Parser.Lex();
2479 }
2480 return false;
2481}
2482
2483/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2484/// either one of these.
2485/// ::= '[', register, ']'
2486/// ::= '[', integer, ']'
2487/// handle it before we iterate so we don't get tripped up by the lack of
2488/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002489bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002490 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002491 if (getLexer().is(AsmToken::LBrac)) {
2492 Operands.push_back(
2493 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2494 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002495 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002496 SMLoc Loc = getLexer().getLoc();
2497 Parser.eatToEndOfStatement();
2498 return Error(Loc, "unexpected token in argument list");
2499 }
2500 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2501 SMLoc Loc = getLexer().getLoc();
2502 Parser.eatToEndOfStatement();
2503 return Error(Loc, "unexpected token, expected ']'");
2504 }
2505 Operands.push_back(
2506 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2507 Parser.Lex();
2508 }
2509 return false;
2510}
2511
David Blaikie960ea3f2014-06-08 16:18:35 +00002512bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2513 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002514 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002515
2516 // We have reached first instruction, module directive are now forbidden.
2517 getTargetStreamer().forbidModuleDirective();
2518
Vladimir Medic74593e62013-07-17 15:00:42 +00002519 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002520 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002521 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002522 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002523 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002524 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002525 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002526
2527 // Read the remaining operands.
2528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2529 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002530 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002531 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002532 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002533 return Error(Loc, "unexpected token in argument list");
2534 }
Toma Tabacu13964452014-09-04 13:23:44 +00002535 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002536 return true;
2537 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002538
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 while (getLexer().is(AsmToken::Comma)) {
2540 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002541 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002542 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002543 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002544 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002545 return Error(Loc, "unexpected token in argument list");
2546 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002547 // Parse bracket and parenthesis suffixes before we iterate
2548 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002549 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002550 return true;
2551 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002552 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002553 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002554 }
2555 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002556 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2557 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002558 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002559 return Error(Loc, "unexpected token in argument list");
2560 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002561 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002562 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002563}
2564
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002565bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002566 SMLoc Loc = getLexer().getLoc();
2567 Parser.eatToEndOfStatement();
2568 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002569}
2570
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002571bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002572 return Error(Loc, ErrorMsg);
2573}
2574
Jack Carter0b744b32012-10-04 02:29:46 +00002575bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 // Line should look like: ".set noat".
2577 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002578 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002579 // eat noat
2580 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002581 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002582 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002583 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002584 return false;
2585 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002587 return false;
2588}
Jack Carterd0bd6422013-04-18 00:41:53 +00002589
Jack Carter0b744b32012-10-04 02:29:46 +00002590bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002591 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002592 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002593 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002594 getParser().Lex();
2595 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002596 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002598 return false;
2599 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002600 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002601 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002602 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002603 return false;
2604 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002605 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002606 const AsmToken &Reg = Parser.getTok();
2607 if (Reg.is(AsmToken::Identifier)) {
2608 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2609 } else if (Reg.is(AsmToken::Integer)) {
2610 AtRegNo = Reg.getIntVal();
2611 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002612 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002613 return false;
2614 }
Jack Carter1ac53222013-02-20 23:11:17 +00002615
Daniel Sanders71a89d922014-03-25 13:01:06 +00002616 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002617 reportParseError("unexpected token in statement");
2618 return false;
2619 }
2620
Toma Tabacu9db22db2014-09-09 10:15:38 +00002621 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002622 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002623 return false;
2624 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002625 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002626
2627 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002628 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002629 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002630 }
2631 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002632 return false;
2633 } else {
2634 reportParseError("unexpected token in statement");
2635 return false;
2636 }
2637}
2638
2639bool MipsAsmParser::parseSetReorderDirective() {
2640 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002641 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002642 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002643 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002644 return false;
2645 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002646 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002647 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002648 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002649 return false;
2650}
2651
2652bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002653 Parser.Lex();
2654 // If this is not the end of the statement, report an error.
2655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002656 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002657 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002659 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002660 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002661 Parser.Lex(); // Consume the EndOfStatement.
2662 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002663}
2664
2665bool MipsAsmParser::parseSetMacroDirective() {
2666 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002667 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002668 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002669 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002670 return false;
2671 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002672 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002673 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002674 return false;
2675}
2676
2677bool MipsAsmParser::parseSetNoMacroDirective() {
2678 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002679 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002680 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002681 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002682 return false;
2683 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002684 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002685 reportParseError("`noreorder' must be set before `nomacro'");
2686 return false;
2687 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002688 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002689 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002690 return false;
2691}
Jack Carterd76b2372013-03-21 21:44:16 +00002692
Daniel Sanders44934432014-08-07 12:03:36 +00002693bool MipsAsmParser::parseSetMsaDirective() {
2694 Parser.Lex();
2695
2696 // If this is not the end of the statement, report an error.
2697 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002698 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002699
2700 setFeatureBits(Mips::FeatureMSA, "msa");
2701 getTargetStreamer().emitDirectiveSetMsa();
2702 return false;
2703}
2704
2705bool MipsAsmParser::parseSetNoMsaDirective() {
2706 Parser.Lex();
2707
2708 // If this is not the end of the statement, report an error.
2709 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002710 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002711
2712 clearFeatureBits(Mips::FeatureMSA, "msa");
2713 getTargetStreamer().emitDirectiveSetNoMsa();
2714 return false;
2715}
2716
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002717bool MipsAsmParser::parseSetNoDspDirective() {
2718 Parser.Lex(); // Eat "nodsp".
2719
2720 // If this is not the end of the statement, report an error.
2721 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2722 reportParseError("unexpected token, expected end of statement");
2723 return false;
2724 }
2725
2726 clearFeatureBits(Mips::FeatureDSP, "dsp");
2727 getTargetStreamer().emitDirectiveSetNoDsp();
2728 return false;
2729}
2730
Jack Carter39536722014-01-22 23:08:42 +00002731bool MipsAsmParser::parseSetNoMips16Directive() {
2732 Parser.Lex();
2733 // If this is not the end of the statement, report an error.
2734 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002735 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002736 return false;
2737 }
2738 // For now do nothing.
2739 Parser.Lex(); // Consume the EndOfStatement.
2740 return false;
2741}
2742
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002743bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002744 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002745 // Line can be: .set fp=32
2746 // .set fp=xx
2747 // .set fp=64
2748 Parser.Lex(); // Eat fp token
2749 AsmToken Tok = Parser.getTok();
2750 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002751 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002752 return false;
2753 }
2754 Parser.Lex(); // Eat '=' token.
2755 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002756
2757 if (!parseFpABIValue(FpAbiVal, ".set"))
2758 return false;
2759
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002761 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002762 return false;
2763 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002764 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002765 Parser.Lex(); // Consume the EndOfStatement.
2766 return false;
2767}
2768
Toma Tabacu9db22db2014-09-09 10:15:38 +00002769bool MipsAsmParser::parseSetPopDirective() {
2770 SMLoc Loc = getLexer().getLoc();
2771
2772 Parser.Lex();
2773 if (getLexer().isNot(AsmToken::EndOfStatement))
2774 return reportParseError("unexpected token, expected end of statement");
2775
2776 // Always keep an element on the options "stack" to prevent the user
2777 // from changing the initial options. This is how we remember them.
2778 if (AssemblerOptions.size() == 2)
2779 return reportParseError(Loc, ".set pop with no .set push");
2780
2781 AssemblerOptions.pop_back();
2782 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2783
2784 getTargetStreamer().emitDirectiveSetPop();
2785 return false;
2786}
2787
2788bool MipsAsmParser::parseSetPushDirective() {
2789 Parser.Lex();
2790 if (getLexer().isNot(AsmToken::EndOfStatement))
2791 return reportParseError("unexpected token, expected end of statement");
2792
2793 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002794 AssemblerOptions.push_back(
2795 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002796
2797 getTargetStreamer().emitDirectiveSetPush();
2798 return false;
2799}
2800
Jack Carterd76b2372013-03-21 21:44:16 +00002801bool MipsAsmParser::parseSetAssignment() {
2802 StringRef Name;
2803 const MCExpr *Value;
2804
2805 if (Parser.parseIdentifier(Name))
2806 reportParseError("expected identifier after .set");
2807
2808 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00002809 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00002810 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002811
Jack Carter3b2c96e2014-01-22 23:31:38 +00002812 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002813 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002814
Jack Carterd0bd6422013-04-18 00:41:53 +00002815 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002816 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002817 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002818 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002819 Sym = getContext().GetOrCreateSymbol(Name);
2820 Sym->setVariableValue(Value);
2821
2822 return false;
2823}
Jack Carterd0bd6422013-04-18 00:41:53 +00002824
Toma Tabacu26647792014-09-09 12:52:14 +00002825bool MipsAsmParser::parseSetMips0Directive() {
2826 Parser.Lex();
2827 if (getLexer().isNot(AsmToken::EndOfStatement))
2828 return reportParseError("unexpected token, expected end of statement");
2829
2830 // Reset assembler options to their initial values.
2831 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2832 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2833
2834 getTargetStreamer().emitDirectiveSetMips0();
2835 return false;
2836}
2837
Toma Tabacu85618b32014-08-19 14:22:52 +00002838bool MipsAsmParser::parseSetArchDirective() {
2839 Parser.Lex();
2840 if (getLexer().isNot(AsmToken::Equal))
2841 return reportParseError("unexpected token, expected equals sign");
2842
2843 Parser.Lex();
2844 StringRef Arch;
2845 if (Parser.parseIdentifier(Arch))
2846 return reportParseError("expected arch identifier");
2847
2848 StringRef ArchFeatureName =
2849 StringSwitch<StringRef>(Arch)
2850 .Case("mips1", "mips1")
2851 .Case("mips2", "mips2")
2852 .Case("mips3", "mips3")
2853 .Case("mips4", "mips4")
2854 .Case("mips5", "mips5")
2855 .Case("mips32", "mips32")
2856 .Case("mips32r2", "mips32r2")
2857 .Case("mips32r6", "mips32r6")
2858 .Case("mips64", "mips64")
2859 .Case("mips64r2", "mips64r2")
2860 .Case("mips64r6", "mips64r6")
2861 .Case("cnmips", "cnmips")
2862 .Case("r4000", "mips3") // This is an implementation of Mips3.
2863 .Default("");
2864
2865 if (ArchFeatureName.empty())
2866 return reportParseError("unsupported architecture");
2867
2868 selectArch(ArchFeatureName);
2869 getTargetStreamer().emitDirectiveSetArch(Arch);
2870 return false;
2871}
2872
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002873bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2874 Parser.Lex();
2875 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002876 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002877
Matheus Almeida2852af82014-04-22 10:15:54 +00002878 switch (Feature) {
2879 default:
2880 llvm_unreachable("Unimplemented feature");
2881 case Mips::FeatureDSP:
2882 setFeatureBits(Mips::FeatureDSP, "dsp");
2883 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002884 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002885 case Mips::FeatureMicroMips:
2886 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002887 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002888 case Mips::FeatureMips16:
2889 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002890 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002891 case Mips::FeatureMips1:
2892 selectArch("mips1");
2893 getTargetStreamer().emitDirectiveSetMips1();
2894 break;
2895 case Mips::FeatureMips2:
2896 selectArch("mips2");
2897 getTargetStreamer().emitDirectiveSetMips2();
2898 break;
2899 case Mips::FeatureMips3:
2900 selectArch("mips3");
2901 getTargetStreamer().emitDirectiveSetMips3();
2902 break;
2903 case Mips::FeatureMips4:
2904 selectArch("mips4");
2905 getTargetStreamer().emitDirectiveSetMips4();
2906 break;
2907 case Mips::FeatureMips5:
2908 selectArch("mips5");
2909 getTargetStreamer().emitDirectiveSetMips5();
2910 break;
2911 case Mips::FeatureMips32:
2912 selectArch("mips32");
2913 getTargetStreamer().emitDirectiveSetMips32();
2914 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002915 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002916 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002917 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002918 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002919 case Mips::FeatureMips32r6:
2920 selectArch("mips32r6");
2921 getTargetStreamer().emitDirectiveSetMips32R6();
2922 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002923 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002924 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002925 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002926 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002927 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002928 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002929 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002930 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002931 case Mips::FeatureMips64r6:
2932 selectArch("mips64r6");
2933 getTargetStreamer().emitDirectiveSetMips64R6();
2934 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002935 }
2936 return false;
2937}
2938
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002939bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2940 if (getLexer().isNot(AsmToken::Comma)) {
2941 SMLoc Loc = getLexer().getLoc();
2942 Parser.eatToEndOfStatement();
2943 return Error(Loc, ErrorStr);
2944 }
2945
Matheus Almeida2852af82014-04-22 10:15:54 +00002946 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002947 return true;
2948}
2949
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002950bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002951 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002952 Warning(Loc, ".cpload in reorder section");
2953
2954 // FIXME: Warn if cpload is used in Mips16 mode.
2955
David Blaikie960ea3f2014-06-08 16:18:35 +00002956 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002957 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002958 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2959 reportParseError("expected register containing function address");
2960 return false;
2961 }
2962
David Blaikie960ea3f2014-06-08 16:18:35 +00002963 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2964 if (!RegOpnd.isGPRAsmReg()) {
2965 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002966 return false;
2967 }
2968
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002969 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002970 return false;
2971}
2972
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002973bool MipsAsmParser::parseDirectiveCPSetup() {
2974 unsigned FuncReg;
2975 unsigned Save;
2976 bool SaveIsReg = true;
2977
Matheus Almeida7e815762014-06-18 13:08:59 +00002978 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002979 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002980 if (ResTy == MatchOperand_NoMatch) {
2981 reportParseError("expected register containing function address");
2982 Parser.eatToEndOfStatement();
2983 return false;
2984 }
2985
2986 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2987 if (!FuncRegOpnd.isGPRAsmReg()) {
2988 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2989 Parser.eatToEndOfStatement();
2990 return false;
2991 }
2992
2993 FuncReg = FuncRegOpnd.getGPR32Reg();
2994 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002995
Toma Tabacu65f10572014-09-16 15:00:52 +00002996 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002997 return true;
2998
Toma Tabacu13964452014-09-04 13:23:44 +00002999 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003000 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003001 const AsmToken &Tok = Parser.getTok();
3002 if (Tok.is(AsmToken::Integer)) {
3003 Save = Tok.getIntVal();
3004 SaveIsReg = false;
3005 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003006 } else {
3007 reportParseError("expected save register or stack offset");
3008 Parser.eatToEndOfStatement();
3009 return false;
3010 }
3011 } else {
3012 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3013 if (!SaveOpnd.isGPRAsmReg()) {
3014 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3015 Parser.eatToEndOfStatement();
3016 return false;
3017 }
3018 Save = SaveOpnd.getGPR32Reg();
3019 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003020
Toma Tabacu65f10572014-09-16 15:00:52 +00003021 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003022 return true;
3023
3024 StringRef Name;
3025 if (Parser.parseIdentifier(Name))
3026 reportParseError("expected identifier");
3027 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003028
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003029 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003030 return false;
3031}
3032
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003033bool MipsAsmParser::parseDirectiveNaN() {
3034 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3035 const AsmToken &Tok = Parser.getTok();
3036
3037 if (Tok.getString() == "2008") {
3038 Parser.Lex();
3039 getTargetStreamer().emitDirectiveNaN2008();
3040 return false;
3041 } else if (Tok.getString() == "legacy") {
3042 Parser.Lex();
3043 getTargetStreamer().emitDirectiveNaNLegacy();
3044 return false;
3045 }
3046 }
3047 // If we don't recognize the option passed to the .nan
3048 // directive (e.g. no option or unknown option), emit an error.
3049 reportParseError("invalid option in .nan directive");
3050 return false;
3051}
3052
Jack Carter0b744b32012-10-04 02:29:46 +00003053bool MipsAsmParser::parseDirectiveSet() {
3054
Jack Carterd0bd6422013-04-18 00:41:53 +00003055 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003056 const AsmToken &Tok = Parser.getTok();
3057
3058 if (Tok.getString() == "noat") {
3059 return parseSetNoAtDirective();
3060 } else if (Tok.getString() == "at") {
3061 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003062 } else if (Tok.getString() == "arch") {
3063 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003064 } else if (Tok.getString() == "fp") {
3065 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003066 } else if (Tok.getString() == "pop") {
3067 return parseSetPopDirective();
3068 } else if (Tok.getString() == "push") {
3069 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003070 } else if (Tok.getString() == "reorder") {
3071 return parseSetReorderDirective();
3072 } else if (Tok.getString() == "noreorder") {
3073 return parseSetNoReorderDirective();
3074 } else if (Tok.getString() == "macro") {
3075 return parseSetMacroDirective();
3076 } else if (Tok.getString() == "nomacro") {
3077 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003078 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003079 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00003080 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003081 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003082 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003083 getTargetStreamer().emitDirectiveSetNoMicroMips();
3084 Parser.eatToEndOfStatement();
3085 return false;
3086 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003087 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003088 } else if (Tok.getString() == "mips0") {
3089 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003090 } else if (Tok.getString() == "mips1") {
3091 return parseSetFeature(Mips::FeatureMips1);
3092 } else if (Tok.getString() == "mips2") {
3093 return parseSetFeature(Mips::FeatureMips2);
3094 } else if (Tok.getString() == "mips3") {
3095 return parseSetFeature(Mips::FeatureMips3);
3096 } else if (Tok.getString() == "mips4") {
3097 return parseSetFeature(Mips::FeatureMips4);
3098 } else if (Tok.getString() == "mips5") {
3099 return parseSetFeature(Mips::FeatureMips5);
3100 } else if (Tok.getString() == "mips32") {
3101 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003102 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003103 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003104 } else if (Tok.getString() == "mips32r6") {
3105 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003106 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003107 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003108 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003109 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003110 } else if (Tok.getString() == "mips64r6") {
3111 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003112 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003113 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003114 } else if (Tok.getString() == "nodsp") {
3115 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003116 } else if (Tok.getString() == "msa") {
3117 return parseSetMsaDirective();
3118 } else if (Tok.getString() == "nomsa") {
3119 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003120 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003121 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003122 parseSetAssignment();
3123 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003124 }
Jack Carter07c818d2013-01-25 01:31:34 +00003125
Jack Carter0b744b32012-10-04 02:29:46 +00003126 return true;
3127}
3128
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003129/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003130/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003131bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003132 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3133 for (;;) {
3134 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003135 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003136 return true;
3137
3138 getParser().getStreamer().EmitValue(Value, Size);
3139
3140 if (getLexer().is(AsmToken::EndOfStatement))
3141 break;
3142
Jack Carter07c818d2013-01-25 01:31:34 +00003143 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003144 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003145 Parser.Lex();
3146 }
3147 }
3148
3149 Parser.Lex();
3150 return false;
3151}
3152
Vladimir Medic4c299852013-11-06 11:27:05 +00003153/// parseDirectiveGpWord
3154/// ::= .gpword local_sym
3155bool MipsAsmParser::parseDirectiveGpWord() {
3156 const MCExpr *Value;
3157 // EmitGPRel32Value requires an expression, so we are using base class
3158 // method to evaluate the expression.
3159 if (getParser().parseExpression(Value))
3160 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003161 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003162
Vladimir Medice10c1122013-11-13 13:18:04 +00003163 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003164 return Error(getLexer().getLoc(),
3165 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003166 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003167 return false;
3168}
3169
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003170/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003171/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003172bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003173 const MCExpr *Value;
3174 // EmitGPRel64Value requires an expression, so we are using base class
3175 // method to evaluate the expression.
3176 if (getParser().parseExpression(Value))
3177 return true;
3178 getParser().getStreamer().EmitGPRel64Value(Value);
3179
3180 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003181 return Error(getLexer().getLoc(),
3182 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003183 Parser.Lex(); // Eat EndOfStatement token.
3184 return false;
3185}
3186
Jack Carter0cd3c192014-01-06 23:27:31 +00003187bool MipsAsmParser::parseDirectiveOption() {
3188 // Get the option token.
3189 AsmToken Tok = Parser.getTok();
3190 // At the moment only identifiers are supported.
3191 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003192 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003193 Parser.eatToEndOfStatement();
3194 return false;
3195 }
3196
3197 StringRef Option = Tok.getIdentifier();
3198
3199 if (Option == "pic0") {
3200 getTargetStreamer().emitDirectiveOptionPic0();
3201 Parser.Lex();
3202 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3203 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003204 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003205 Parser.eatToEndOfStatement();
3206 }
3207 return false;
3208 }
3209
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003210 if (Option == "pic2") {
3211 getTargetStreamer().emitDirectiveOptionPic2();
3212 Parser.Lex();
3213 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3214 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003215 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003216 Parser.eatToEndOfStatement();
3217 }
3218 return false;
3219 }
3220
Jack Carter0cd3c192014-01-06 23:27:31 +00003221 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003222 Warning(Parser.getTok().getLoc(),
3223 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003224 Parser.eatToEndOfStatement();
3225 return false;
3226}
3227
Daniel Sanders7e527422014-07-10 13:38:23 +00003228/// parseDirectiveModule
3229/// ::= .module oddspreg
3230/// ::= .module nooddspreg
3231/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003232bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003233 MCAsmLexer &Lexer = getLexer();
3234 SMLoc L = Lexer.getLoc();
3235
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003236 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003237 // TODO : get a better message.
3238 reportParseError(".module directive must appear before any code");
3239 return false;
3240 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003241
3242 if (Lexer.is(AsmToken::Identifier)) {
3243 StringRef Option = Parser.getTok().getString();
3244 Parser.Lex();
3245
3246 if (Option == "oddspreg") {
3247 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3248 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3249
3250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003251 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003252 return false;
3253 }
3254
3255 return false;
3256 } else if (Option == "nooddspreg") {
3257 if (!isABI_O32()) {
3258 Error(L, "'.module nooddspreg' requires the O32 ABI");
3259 return false;
3260 }
3261
3262 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3263 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3264
3265 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003266 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003267 return false;
3268 }
3269
3270 return false;
3271 } else if (Option == "fp") {
3272 return parseDirectiveModuleFP();
3273 }
3274
3275 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003276 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003277
3278 return false;
3279}
3280
3281/// parseDirectiveModuleFP
3282/// ::= =32
3283/// ::= =xx
3284/// ::= =64
3285bool MipsAsmParser::parseDirectiveModuleFP() {
3286 MCAsmLexer &Lexer = getLexer();
3287
3288 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003289 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003290 return false;
3291 }
3292 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003293
Daniel Sanders7e527422014-07-10 13:38:23 +00003294 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003295 if (!parseFpABIValue(FpABI, ".module"))
3296 return false;
3297
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003298 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003299 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003300 return false;
3301 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003302
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003303 // Emit appropriate flags.
3304 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003305 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003306 return false;
3307}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003308
Daniel Sanders7e527422014-07-10 13:38:23 +00003309bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003310 StringRef Directive) {
3311 MCAsmLexer &Lexer = getLexer();
3312
3313 if (Lexer.is(AsmToken::Identifier)) {
3314 StringRef Value = Parser.getTok().getString();
3315 Parser.Lex();
3316
3317 if (Value != "xx") {
3318 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3319 return false;
3320 }
3321
3322 if (!isABI_O32()) {
3323 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3324 return false;
3325 }
3326
Daniel Sanders7e527422014-07-10 13:38:23 +00003327 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003328 return true;
3329 }
3330
3331 if (Lexer.is(AsmToken::Integer)) {
3332 unsigned Value = Parser.getTok().getIntVal();
3333 Parser.Lex();
3334
3335 if (Value != 32 && Value != 64) {
3336 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3337 return false;
3338 }
3339
3340 if (Value == 32) {
3341 if (!isABI_O32()) {
3342 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3343 return false;
3344 }
3345
Daniel Sanders7e527422014-07-10 13:38:23 +00003346 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3347 } else
3348 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003349
Daniel Sanders7e527422014-07-10 13:38:23 +00003350 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003351 }
3352
3353 return false;
3354}
3355
Jack Carter0b744b32012-10-04 02:29:46 +00003356bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003357 StringRef IDVal = DirectiveID.getString();
3358
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003359 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003360 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003361 if (IDVal == ".dword") {
3362 parseDataDirective(8, DirectiveID.getLoc());
3363 return false;
3364 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003365 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003366 StringRef SymbolName;
3367
3368 if (Parser.parseIdentifier(SymbolName)) {
3369 reportParseError("expected identifier after .ent");
3370 return false;
3371 }
3372
3373 // There's an undocumented extension that allows an integer to
3374 // follow the name of the procedure which AFAICS is ignored by GAS.
3375 // Example: .ent foo,2
3376 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3377 if (getLexer().isNot(AsmToken::Comma)) {
3378 // Even though we accept this undocumented extension for compatibility
3379 // reasons, the additional integer argument does not actually change
3380 // the behaviour of the '.ent' directive, so we would like to discourage
3381 // its use. We do this by not referring to the extended version in
3382 // error messages which are not directly related to its use.
3383 reportParseError("unexpected token, expected end of statement");
3384 return false;
3385 }
3386 Parser.Lex(); // Eat the comma.
3387 const MCExpr *DummyNumber;
3388 int64_t DummyNumberVal;
3389 // If the user was explicitly trying to use the extended version,
3390 // we still give helpful extension-related error messages.
3391 if (Parser.parseExpression(DummyNumber)) {
3392 reportParseError("expected number after comma");
3393 return false;
3394 }
3395 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3396 reportParseError("expected an absolute expression after comma");
3397 return false;
3398 }
3399 }
3400
3401 // If this is not the end of the statement, report an error.
3402 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3403 reportParseError("unexpected token, expected end of statement");
3404 return false;
3405 }
3406
3407 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3408
3409 getTargetStreamer().emitDirectiveEnt(*Sym);
3410 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003411 return false;
3412 }
3413
Jack Carter07c818d2013-01-25 01:31:34 +00003414 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003415 StringRef SymbolName;
3416
3417 if (Parser.parseIdentifier(SymbolName)) {
3418 reportParseError("expected identifier after .end");
3419 return false;
3420 }
3421
3422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3423 reportParseError("unexpected token, expected end of statement");
3424 return false;
3425 }
3426
3427 if (CurrentFn == nullptr) {
3428 reportParseError(".end used without .ent");
3429 return false;
3430 }
3431
3432 if ((SymbolName != CurrentFn->getName())) {
3433 reportParseError(".end symbol does not match .ent symbol");
3434 return false;
3435 }
3436
3437 getTargetStreamer().emitDirectiveEnd(SymbolName);
3438 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003439 return false;
3440 }
3441
Jack Carter07c818d2013-01-25 01:31:34 +00003442 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003443 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3444 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003445 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003446 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3447 reportParseError("expected stack register");
3448 return false;
3449 }
3450
3451 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3452 if (!StackRegOpnd.isGPRAsmReg()) {
3453 reportParseError(StackRegOpnd.getStartLoc(),
3454 "expected general purpose register");
3455 return false;
3456 }
3457 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3458
3459 if (Parser.getTok().is(AsmToken::Comma))
3460 Parser.Lex();
3461 else {
3462 reportParseError("unexpected token, expected comma");
3463 return false;
3464 }
3465
3466 // Parse the frame size.
3467 const MCExpr *FrameSize;
3468 int64_t FrameSizeVal;
3469
3470 if (Parser.parseExpression(FrameSize)) {
3471 reportParseError("expected frame size value");
3472 return false;
3473 }
3474
3475 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3476 reportParseError("frame size not an absolute expression");
3477 return false;
3478 }
3479
3480 if (Parser.getTok().is(AsmToken::Comma))
3481 Parser.Lex();
3482 else {
3483 reportParseError("unexpected token, expected comma");
3484 return false;
3485 }
3486
3487 // Parse the return register.
3488 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003489 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003490 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3491 reportParseError("expected return register");
3492 return false;
3493 }
3494
3495 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3496 if (!ReturnRegOpnd.isGPRAsmReg()) {
3497 reportParseError(ReturnRegOpnd.getStartLoc(),
3498 "expected general purpose register");
3499 return false;
3500 }
3501
3502 // If this is not the end of the statement, report an error.
3503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3504 reportParseError("unexpected token, expected end of statement");
3505 return false;
3506 }
3507
3508 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3509 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003510 return false;
3511 }
3512
Jack Carter07c818d2013-01-25 01:31:34 +00003513 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003514 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003515 }
3516
Daniel Sandersd97a6342014-08-13 10:07:34 +00003517 if (IDVal == ".mask" || IDVal == ".fmask") {
3518 // .mask bitmask, frame_offset
3519 // bitmask: One bit for each register used.
3520 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3521 // first register is expected to be saved.
3522 // Examples:
3523 // .mask 0x80000000, -4
3524 // .fmask 0x80000000, -4
3525 //
Jack Carterbe332172012-09-07 00:48:02 +00003526
Daniel Sandersd97a6342014-08-13 10:07:34 +00003527 // Parse the bitmask
3528 const MCExpr *BitMask;
3529 int64_t BitMaskVal;
3530
3531 if (Parser.parseExpression(BitMask)) {
3532 reportParseError("expected bitmask value");
3533 return false;
3534 }
3535
3536 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3537 reportParseError("bitmask not an absolute expression");
3538 return false;
3539 }
3540
3541 if (Parser.getTok().is(AsmToken::Comma))
3542 Parser.Lex();
3543 else {
3544 reportParseError("unexpected token, expected comma");
3545 return false;
3546 }
3547
3548 // Parse the frame_offset
3549 const MCExpr *FrameOffset;
3550 int64_t FrameOffsetVal;
3551
3552 if (Parser.parseExpression(FrameOffset)) {
3553 reportParseError("expected frame offset value");
3554 return false;
3555 }
3556
3557 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3558 reportParseError("frame offset not an absolute expression");
3559 return false;
3560 }
3561
3562 // If this is not the end of the statement, report an error.
3563 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3564 reportParseError("unexpected token, expected end of statement");
3565 return false;
3566 }
3567
3568 if (IDVal == ".mask")
3569 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3570 else
3571 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003572 return false;
3573 }
3574
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003575 if (IDVal == ".nan")
3576 return parseDirectiveNaN();
3577
Jack Carter07c818d2013-01-25 01:31:34 +00003578 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003579 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003580 return false;
3581 }
3582
Rafael Espindolab59fb732014-03-28 18:50:26 +00003583 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003584 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003585 return false;
3586 }
3587
Jack Carter07c818d2013-01-25 01:31:34 +00003588 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003589 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003590 return false;
3591 }
3592
Jack Carter0cd3c192014-01-06 23:27:31 +00003593 if (IDVal == ".option")
3594 return parseDirectiveOption();
3595
3596 if (IDVal == ".abicalls") {
3597 getTargetStreamer().emitDirectiveAbiCalls();
3598 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003599 Error(Parser.getTok().getLoc(),
3600 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003601 // Clear line
3602 Parser.eatToEndOfStatement();
3603 }
3604 return false;
3605 }
3606
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003607 if (IDVal == ".cpsetup")
3608 return parseDirectiveCPSetup();
3609
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003610 if (IDVal == ".module")
3611 return parseDirectiveModule();
3612
Rafael Espindola870c4e92012-01-11 03:56:41 +00003613 return true;
3614}
3615
Rafael Espindola870c4e92012-01-11 03:56:41 +00003616extern "C" void LLVMInitializeMipsAsmParser() {
3617 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3618 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3619 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3620 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3621}
Jack Carterb4dbc172012-09-05 23:34:03 +00003622
3623#define GET_REGISTER_MATCHER
3624#define GET_MATCHER_IMPLEMENTATION
3625#include "MipsGenAsmMatcher.inc"